#!/usr/bin/perl
#
# my_md5sum
#
# Script to clone the 'md5sum' command found on modern systems, since that
# command is not always found on all systems.
#
# Use the "--help" option for more info!
#
# Written by Matt Wagner <matt@mysql.com>
#
use strict;

#
# Use local perl libraries first. 'unshift' adds to the front of @INC
# The local perl library dir hidden is $HOME/.perllibs on each build host
#
BEGIN
{
        my $homedir= $ENV{HOME};
        unshift (@INC, "$homedir/.perllibs");
}

use Digest::MD5;
use Getopt::Long;

my $VER= "1.3";
my $EXIT= 0;

#
# Strip the leading path info off the program name ($0). We want 'my_md5sum'
# not './my_md5sum'.
#
$0=~ s/^.*\/(.+)$/$1/;

my ($opt_check, $opt_help)= undef;

GetOptions(
	"check|c" => \$opt_check,
	"help|h" => \$opt_help,
	) || usage(); 

#
# Put all the [file1 file2 file3 ...]'s into an array
#
my @files = @ARGV;

#
# Give the "--help" text if:
#  - "--help|-h" was specified
#  - The number of files given as arguments is nil
#  - The "--check|-c" option is used with more than one [file] argument
#
usage() if $opt_help || $#files == -1 || ($opt_check && $#files > 0);

# If "--check|-c", then go into checking
if ($opt_check)
{
	open (CHECKFILE, $files[0]) or die "$files[0]: $!";

	while (<CHECKFILE>)
	{
		#
		# Goto the next line in the file if it does not match a typical
		# digest line like:
		#
		# f1007efa2c72daa693981ec764cdeaca  Bootstrap
		#
		next if $_!~ m/^([a-z0-9]{32})\s+(.+)$/;

		# Collect the trappings from the above regex
		my $checksum= $1;
		my $checkfile= $2;

		# Generate a fresh MD5 for the file in question
		my $digest= &mkmd5($checkfile);

		# Check the fresh MD5 against what is recorded in the file
		# Print an error message if they don't match, else print OK
		print "$checkfile: FAILED\n" if $digest ne $checksum;
		print "$checkfile: OK\n" if $digest eq $checksum;

                # Set the exit() status to non-zero if FAILED
                $EXIT= 1 if $digest ne $checksum;
	}
}
# Else generate the MD5 digest to STDOUT
else
{
	foreach my $file (@files)
	{
		my $digest= &mkmd5($file);

		print "$digest  $file\n";
	}
}

exit($EXIT);


#
# This routine generates the MD5 digest of a file
#
sub mkmd5
{
	my $file= shift;

	open (FILE, $file) or die "$file: $!";
	binmode(FILE);

	my $digest= Digest::MD5->new->addfile(*FILE)->hexdigest;

	close FILE;

	return $digest;
}

#
# Print the help text
#
sub usage
{
	print <<EOF;

$0 version $VER by Matt Wagner <matt\@mysql.com>

Usage:
$0 [-c [file]] |  [file1...]
Generates or checks MD5 message digests.

Options:
-c, --check	Check message digests (default is generate)
-h, --help	Display this text and exit

The input for -c should be the list of message digests and file names that is
printed on STDOUT by this program when it generates digests.

EOF

	exit(0);
}
