Date: Sun, 3 Feb 2002 11:23:27 +0100 From: Rogier Steehouder <r.j.s@gmx.net> To: jaime aguirre <jaimea@3web.net> Cc: questions@FreeBSD.org Subject: Re: checksum verifying. Message-ID: <20020203112327.A685@localhost> In-Reply-To: <000801c1ac1a$bc9b3520$a8bafea9@jim>; from jaimea@3web.net on Sat, Feb 02, 2002 at 01:52:15PM -0500 References: <000801c1ac1a$bc9b3520$a8bafea9@jim>
next in thread | previous in thread | raw e-mail | index | archive | help
--GvXjxJ+pjyke8COw Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On 02-02-2002 13:52 (-0500), jaime aguirre wrote: > I downloaded to a windows box the 4.5 mini-iso of FreeBSD. > Is there a way to verify the checksum before it is burn into a cd? I started learning perl around the time 4.3 came out, so I solved it by writing a small script. Of course this would require you to install perl on windows. With kind regards, Rogier Steehouder PS. This was a programming exercise. No guarantees whatsoever. -- ___ _ -O_\ // | / Rogier Steehouder //\ / \ r.j.s@gmx.net // \ <---------------------- 25m ----------------------> --GvXjxJ+pjyke8COw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="checksum.pl" #!/usr/bin/perl -w use strict; use Cwd; use Getopt::Std; use Digest::MD5; # Basic program help is provided in pod format below. sub Help { exec("perldoc $0"); } #+-------------------------------------------------------------------+ #| Main Program | #+-------------------------------------------------------------------+ my(%cmdopts, $sumfile, @dirlist, $origdir); # Process options getopts('cf:hrR', \%cmdopts); if ($cmdopts{'h'}) { &Help; } unless ($sumfile = $cmdopts{'f'}) { $sumfile = 'CHECKSUM.MD5'; } # List of all files/dirs to be checked @dirlist = @ARGV; unless ($dirlist[0]) { $dirlist[0] = '.'; } # Current directory $origdir = getcwd; # Loop through all files/dirs foreach my $dir (@dirlist) { my(%checksums); # Directory: scan all files if (-d $dir) { chdir($dir) or next; if (-r $sumfile) { %checksums = &ReadSumfile($sumfile); } # Read filenames in directory opendir(DIR, '.') or die("Could not open directory $dir"); my @files = readdir(DIR); closedir(DIR); # Join existing filenames and filenames from checksum file push(@files, keys(%checksums)); @files = &uniq(@files); # Check each file foreach my $file (@files) { # Ignore . and .. next if ($file =~ m/^\.\.?$/); # Ignore dirs, but if -r, add to dirlist if (-d $file) { if ($cmdopts{'r'}) { push(@dirlist, "$dir/$file"); } next; } # Ignore checksum file next if ($file eq $sumfile); # File does not exist: GONE or REMOVED if (! -e $file) { if ($cmdopts{'R'}) { delete($checksums{$file}); print("REMOVED\t$dir/$file\n"); } else { print("GONE\t$dir/$file\n"); } } # If exists but cannot be read: UNREAD or Ignore elsif (! -r $file) { if ($checksums{$file}) { print("UNREAD\t$dir/$file\n"); } else { next; } } # If checksum not present: NEW elsif (! $checksums{$file}) { # Ignore if -c next if ($cmdopts{'c'}); $checksums{$file} = &CalcSum($file); print("NEW\t$dir/$file\n"); } # If checksum matches: OK elsif ($checksums{$file} eq &CalcSum($file)) { print("OK\t$dir/$file\n"); } # No match: ERROR or CHANGED else { if ($cmdopts{'R'}) { $checksums{$file} = &CalcSum($file); print("CHANGED\t$dir/$file\n"); } else { print("ERROR\t$dir/$file\n"); } } } # Write new checksum file unless -c unless ($cmdopts{'c'}) { &WriteSumfile($sumfile, %checksums); } chdir($origdir); # File: scan file if exists } elsif (-e $dir) { print("Specifying files on the command line is yet unsupported. Stick to directories.\n"); # Ignore non-existing files } else { print("$dir does not exist.\n"); next; } } #+-------------------------------------------------------------------+ #| Subroutines | #+-------------------------------------------------------------------+ #+-----------------------------------------------------------+ #| Read checksums from checksum file | #+-----------------------------------------------------------+ sub ReadSumfile { my($filename) = shift; my(%checksums); open(FH, "< $filename") or die("Could not read from $filename"); while (<FH>) { chomp; if (m/^MD5 \(([^\)]*)\) = (.*)$/) { $checksums{$1} = $2; } } close(FH); return(%checksums); } #+-----------------------------------------------------------+ #| Write checksums to checksum file | #+-----------------------------------------------------------+ sub WriteSumfile { my($filename) = shift; my(%checksums) = @_; open(FH, "> $filename") or die("Could not write to $filename"); foreach my $file (sort(keys(%checksums))) { print(FH "MD5 ($file) = ", $checksums{$file}, "\n"); } close(FH); } #+-----------------------------------------------------------+ #| Calculate the checksum of a given file | #+-----------------------------------------------------------+ sub CalcSum { my($filename) = shift; my($sum); open(DATA, "< $filename") or die("Could not read from $filename"); binmode(DATA); $sum = Digest::MD5->new->addfile(*DATA)->hexdigest; close(DATA); return($sum); } #+-----------------------------------------------------------+ #| Remove duplicates from an array | #+-----------------------------------------------------------+ sub uniq { # @list -> @list my(@list) = @_; my(%list); map { $list{$_} = 1 } @list; return(sort(keys(%list))); } __END__ =pod =head1 NAME checksum - check and/or generate checksums for files in directories =head1 SYNOPSIS B<checksum> [I<options>] <I<files or dirs>> =head1 DESCRIPTION B<checksum> checks and/or generates checksums for each file in a directory. The checksums are stored in a file, by default CHECKSUM.MD5 By default, the program will scan all files in the directory, report files that are okay, missing or changed and adds new files to the checksum file. =head1 OPTIONS =over 4 =item B<-c> Check only. Do not alter checksum file(s). =item B<-f> <I<filename>> Specify checksum file name. Default: 'CHECKSUM.MD5'. =item B<-h> Print help. =item B<-r> Recurse into subdirectories. Every subdirectory has its own checksum file. =item B<-R> Replace checksum file. Assume all files are valid and update sums that do not match. =back If no files or directories are specified on the command line, the current directory is checked. =head1 OUTPUT In the output, files can be labelled: =over 4 =item B<OK> No problem. =item B<NEW> No checksum recorded. Checksum is added to checksum file unless -c is set. =item B<GONE> Checksum is present, but the file is not. =item B<REMOVED> Checksum is present, but the file is not. The checksum has been removed from the checksum file. (See -R) =item B<ERROR> Checksum did not match. The file has been altered. =item B<CHANGED> Checksum did not match. The checksum has been updated in the checksum file. (See -R) =item B<UNREAD> Checksum could not be verified, because the file is no longer readable. =back Files that cannot be read from and have no previous checksum are ignored. =head1 BUGS No wildcards are accepted. Usually this is handled fine by the shell. Currently only works with directories. The program will not accept filenames on the command line, only directories. =head1 AUTHOR Rogier Steehouder <r.j.s@gmx.net> =cut # vim: set ts=4 sw=4 et : --GvXjxJ+pjyke8COw-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020203112327.A685>