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
[-- Attachment #1 --]
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 ---------------------->
[-- Attachment #2 --]
#!/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 :
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020203112327.A685>
