--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/evalid/EvalidMD5.pm Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,499 @@
+#
+# Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the License "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# This module implements the MD5 version of the Evalid's compare
+#
+
+package EvalidMD5;
+
+use strict;
+use Carp;
+use File::Find;
+use IO::File;
+use Sys::Hostname;
+
+use FindBin;
+use lib "$FindBin::Bin";
+require Exporter;
+use File::Basename;
+
+use vars qw($VERSION );
+$VERSION = 0.02;
+
+use EvalidCompare;
+
+# Public
+
+# MD5Generate
+#
+# Inputs
+# $iLeftDir - Left side directory or File containing listing of left side
+# $iResultsFile - Name of file to write the list of files and MD5 checksum to
+# $iExclude - Reference to array of regular expression patterns to exclude
+# $iInclude - Reference to array of regular expression patterns to include
+# $iListFile - Filename to read for list of files from [Optional]
+# $iDumpDir - Directory to generate dump of comparison data [Optional]
+#
+# Outputs
+#
+# Description
+# This function generates the MD5 checksum file
+
+sub MD5Generate
+{
+ my ($iLeftDir, $iResultsFile, $iExclude, $iInclude, $iListFile, $iDumpDir) = @_;
+
+ my (@iLeftFiles);
+
+ # This should have been check before getting here but to be on the safe side
+ # check again, as it should never overwrite or append to the file
+ croak "$iResultsFile already exists" if (-e $iResultsFile);
+ croak "$iListFile does exist" if ((defined($iListFile) && (!-e $iListFile)));
+
+ if (-d $iLeftDir){
+ # Make sure all the \ are / for the RegEx
+ $iLeftDir =~ s/\\/\//g;
+ # Make sure it does not have a / on the end
+ $iLeftDir =~ s/\/$//;
+ # If $iFileList is defined then use the filelist to generate @iLeftFiles
+ if (defined($iListFile))
+ {
+ # Generate list of files
+ @iLeftFiles = &FilterDir($iLeftDir,$iExclude,$iInclude, $iListFile);
+ } else {
+ # Generate the the directory listing
+ @iLeftFiles = &FilterDir($iLeftDir,$iExclude,$iInclude);
+ }
+ } else {
+ croak "$iLeftDir is not a directory";
+ }
+
+ # Open the results file for writing
+ my ($fResultsFile) = new IO::File;
+ croak "Cannot for $iResultsFile for writing" unless ($fResultsFile->open("> $iResultsFile"));
+
+ # Write headers to the file
+ print $fResultsFile "Host:".&hostname()."\n";
+ print $fResultsFile "Username:".$ENV{'USERNAME'}."\n";
+ print $fResultsFile "Date-Time:".scalar(localtime)."\n";
+ print $fResultsFile "Version:".$VERSION."\n";
+ print $fResultsFile "Directory:".$iLeftDir."\n";
+ print $fResultsFile "FileList:".$iListFile."\n" if (defined($iListFile));
+ print $fResultsFile "Exclusion(s):";
+ foreach my $iExc (sort @$iExclude)
+ {
+ print $fResultsFile "$iExc ";
+ }
+ print $fResultsFile "\n";
+
+ print $fResultsFile "Inclusion(s):";
+ foreach my $iInc (@$iInclude)
+ {
+ print $fResultsFile "$iInc ";
+ }
+ print $fResultsFile "\n";
+
+ print $fResultsFile "----------------\n";
+
+ # Write out sorted list of files with MD5 Checksums
+ foreach my $iFile (sort @iLeftFiles)
+ {
+ my ($MD5, $type) = &EvalidCompare::GenerateSignature($iLeftDir."/".$iFile, $iDumpDir);
+ print $fResultsFile $iFile." TYPE=".$type." MD5=".$MD5."\n";
+ }
+
+ $fResultsFile->close;
+}
+
+
+# MD5Compare
+#
+# Inputs
+# $iLeftFile - Left side File containing listing and MD5 of left side
+# $iRightFile - Right side File containing listing and MD5 of right side
+# $iVerbose - Verbose Flag
+# $iLog - Logfile name
+#
+# Outputs
+# %iCommon - hash relative filenames with values of file type that are in both directories and Compare results/types
+# %iDiff - hash relative filenames with values of file type and directory side infomation
+#
+# Description
+
+sub MD5Compare
+{
+ my ($iLeftFile) = shift;
+ my ($iRightFile) = shift;
+ my ($iVerbose) = defined($_[0]) ? shift : 0;
+ my ($iLog) = defined($_[0]) ? shift : *STDOUT;
+
+ my (%iCommon, %iDiff);
+
+ my (%iLeftFiles, %iRightFiles);
+ my (%iLeftHeaders, %iRightHeaders);
+
+ # Backup check the files are available to read.
+ croak "$iLeftFile is not a file" unless (-f $iLeftFile);
+ croak "$iRightFile is not a file" unless(-f $iRightFile);
+
+ #Read the files
+ &ReadMD5File($iLeftFile, \%iLeftFiles, \%iLeftHeaders);
+ &ReadMD5File($iRightFile, \%iRightFiles, \%iRightHeaders);
+
+ # Check Critical headers
+ foreach my $iHeader (sort keys %iLeftHeaders)
+ {
+ # Warning is certain headers are not identical
+ if ($iHeader =~ /^Version|Exclusion\(s\)|Inclusion\(s\)/)
+ {
+ print $iLog "WARNING:$iHeader is different\n" if ($iLeftHeaders{$iHeader} ne $iRightHeaders{$iHeader});
+ }
+ }
+
+ # A Hash is used to combine the two directory listing using the filename as the key
+ my %iCombinedFiles;
+
+ # Enter the files from the left side listing and check the right side critical header are the same
+ # Note all filenames are turned to lower case as this is designed to only wotk on Windows
+ foreach my $iFile (sort keys %iLeftFiles)
+ {
+ $iCombinedFiles{$iFile} = "Left";
+ }
+
+ # Enter the files from the right side listing
+ # Note all filenames are turned to lower case as this is designed to only wotk on Windows
+ foreach my $iFile (sort keys %iRightFiles)
+ {
+ # Check to see if any entry for this file exists on the left side
+ if ((defined ($iCombinedFiles{$iFile})) && ( $iCombinedFiles{$iFile} eq "Left"))
+ {
+ # Yes, so add to the Common set
+ # Check if the MD5 checksum matches
+ # The [0] element is the file type
+ if ($iLeftFiles{$iFile}[0] ne $iRightFiles{$iFile}[0])
+ {
+ $iCommon{$iFile} = [$iLeftFiles{$iFile}[0]." to ".$iRightFiles{$iFile}[0], "Type Changed"];
+ } elsif ($iLeftFiles{$iFile}[1] eq $iRightFiles{$iFile}[1]) {
+ $iCommon{$iFile} = [$iLeftFiles{$iFile}[0],"OK"];
+ } else {
+ $iCommon{$iFile} = [$iLeftFiles{$iFile}[0],"Different"];
+ }
+ # The filename key is not needed any more as both sides have been processed, so delete the hash entry
+ delete $iCombinedFiles{$iFile};
+ } elsif (!defined($iCombinedFiles{$iFile})) {
+ # No, the key is not defined, so this filename is only in the right side
+ $iDiff{$iFile} = [$iRightFiles{$iFile}[0],"Right"];
+ # The filename key is not needed any more as both sides have been processed, so delete the hash entry
+ delete $iCombinedFiles{$iFile};
+ }
+ }
+
+ # Add the files left in the hash to the Left side only list
+ foreach my $iFile (sort keys %iCombinedFiles)
+ {
+ $iDiff{$iFile} = [$iLeftFiles{$iFile}[0],"Left"];
+ }
+
+ # Return References to the Arrays
+ return (\%iCommon, \%iLeftHeaders, \%iRightHeaders, \%iDiff);
+}
+
+# FilterDir
+#
+# Inputs
+# $iDir - Directory to process
+# $iExclude - Reference to array of regular expression patterns to exclude
+# $iInclude - Reference to array of regular expression patterns to include
+# $iListFile - Filename to read for list of files from [Optional]
+#
+# Outputs
+# @iFinalFileList - Filtered list relative filenames
+#
+# Description
+# This function produces a filtered list of filenames in the specified directory or from file
+
+sub FilterDir
+{
+ my ($iDir,$iExclude,$iInclude, $iListFile) = @_;
+
+ my (@iFileList, @iFinalFileList, $iFileName);
+
+ if(defined($iListFile))
+ {
+ open LIST, "$iListFile" or croak "Cannot open $iListFile\n";
+ while(<LIST>)
+ {
+ next if /^\s+$/; # skip blank lines
+ my $iFileName = $iDir."/".$_;
+ chomp $iFileName; # Remove new line
+ if(-e $iFileName)
+ {
+ # The listed file exists add to the @iFileList
+ push @iFileList, $iFileName;
+ } else {
+ print "Warning: Cannot find $iFileName\n";
+ }
+ }
+ close LIST;
+ } else {
+ # Produce full filelist listing without directory names
+ find sub { push @iFileList, $File::Find::name if (!-d) ;}, $iDir;
+ }
+
+ foreach my $iFile ( @iFileList)
+ {
+ my $iExcludeFile = 0;
+
+ # Remove the specified directory path from the front of the filename
+ $iFile =~ s#^$iDir/##;
+
+ # Process all Exclude RegEx to see if this file matches
+ foreach my $iExcludeRegEx (@$iExclude)
+ {
+ if ($iFile =~ /$iExcludeRegEx/i)
+ {
+ # Mark this file to be excluded from the final list
+ $iExcludeFile = 1;
+ }
+ }
+
+ # Process all Include RegEx to see if this file matches
+ foreach my $iIncludeRegEx (@$iInclude)
+ {
+ if ($iFile =~ /$iIncludeRegEx/i)
+ {
+ # Mark this file to be Included in the final list
+ $iExcludeFile = 0;
+ }
+ }
+
+ # Added the file to the final list based on the flag
+ push @iFinalFileList, lc($iFile) unless $iExcludeFile;
+ }
+
+ return @iFinalFileList;
+
+}
+
+# MD5ComparePrint
+#
+# Inputs
+# $iCommon - Reference to Hash of common file names and the result the comparision
+# $iLeftHeaders - Reference to Hash contain the left side
+# $iRightHeaders - Reference to Hash contain the right side
+# $iDiff - Reference to Hash of relative filenames with values of file type and left/right directory side
+# $iLog - Logfile name
+#
+# Outputs
+#
+# Description
+# This function prints the output of a Compare
+sub MD5ComparePrint
+{
+ my ($iCommon) = shift;
+ my ($iLeftHeaders) = shift;
+ my ($iRightHeaders) = shift;
+ my ($iDiff) = shift;
+ my ($iLog) = shift;
+
+ my ($iFailed) = 0; # Count of the failed comparisions
+ my ($iPassed) = 0; # Count of the Passed comparisions
+ my ($iLeft) = 0; # Count of the Passed comparisions
+ my ($iRight) = 0; # Count of the Passed comparisions
+
+
+ my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
+ printf $iLog "\n----------------\n%02d:%02d %02d/%02d/%04d\n", $hour, $min, $mday, $mon+1, $year+1900;
+ print $iLog "evalid\nLeft Side=$ARGV[0]\nRight Side=$ARGV[1]\n";
+ print $iLog "\nLeft side information\n";
+ foreach my $iHeader (sort keys %$iLeftHeaders)
+ {
+ print $iLog $iHeader.":".$$iLeftHeaders{$iHeader}."\n";
+ }
+ print $iLog "\nRight side information\n";
+ foreach my $iHeader (sort keys %$iRightHeaders)
+ {
+ print $iLog $iHeader.":".$$iRightHeaders{$iHeader}."\n";
+ }
+ print $iLog "\n";
+
+ foreach my $iFile (sort keys %$iCommon)
+ {
+ if ($$iCommon{$iFile}[1] eq "OK")
+ {
+ print $iLog "Passed:$iFile (".$$iCommon{$iFile}[0].")\n";
+ $iPassed++;
+ }
+ }
+ print $iLog "\n";
+
+ foreach my $iFile (sort keys %$iCommon)
+ {
+ if ($$iCommon{$iFile}[1] eq "Type Changed")
+ {
+ print $iLog "Type Changed:$iFile (".$$iCommon{$iFile}[0].")\n";
+ $iFailed++;
+ }
+ }
+ print $iLog "\n";
+
+ foreach my $iFile (sort keys %$iCommon)
+ {
+ if ($$iCommon{$iFile}[1] eq "Different")
+ {
+ print $iLog "Failed:$iFile (".$$iCommon{$iFile}[0].")\n";
+ $iFailed++;
+ }
+ }
+ print $iLog "\n";
+
+ foreach my $iFile (sort keys %$iDiff)
+ {
+ if ($$iDiff{$iFile}[1] eq "Left")
+ {
+ print $iLog "Missing Left:$iFile (".$$iDiff{$iFile}[0].")\n";
+ $iLeft++;
+ }
+ }
+ print $iLog "\n";
+
+ foreach my $iFile (sort keys %$iDiff)
+ {
+ if ($$iDiff{$iFile}[1] eq "Right")
+ {
+ print $iLog "Missing Right:$iFile (".$$iDiff{$iFile}[0].")\n";
+ $iRight++;
+ }
+ }
+
+ print $iLog "\n\nSummary\n";
+ print $iLog "Total files processed=".($iPassed+$iFailed+$iRight+$iLeft)."\n";
+ print $iLog "Files Passed=$iPassed\n";
+ print $iLog "Files Failed=$iFailed\n";
+ print $iLog "Missing Files in Left=".$iRight."\n";
+ print $iLog "Missing Files in Right=".$iLeft."\n";
+
+ return ($iFailed);
+}
+# NameOnly
+#
+# Inputs
+# $filename - may contain path and file extension
+#
+# Outputs
+# $nameOnly - filename without extension and path
+#
+# Description
+# This routine is used to extract the name of the file
+# only from a filename that may include a path and file extension
+#
+sub NameOnly
+{
+ my ($filename) = @_;
+ my $nameOnly = basename($filename);
+ $nameOnly =~ s/(\w+.*)\.\w+$/$1/;
+ return $nameOnly;
+}
+
+# MD5CompareZipDel
+#
+# Inputs
+# $iCommon - Reference to Hash of common file names and the result the comparision
+# $iDiff - Reference to Hash of relative filenames with values of file type and left/right directory side
+# $iLeft - filename of Left side directory
+# $iRight - filename of Right side directory
+#
+# Outputs
+#
+# Description
+# This function prints the output of a Compare results in a format ready for creating the a
+# Zip and batch file to upgrade the left side to the equivalent of the right side.
+sub MD5CompareZipDel
+{
+ my ($iCommon) = shift;
+ my ($iDiff) = shift;
+ my ($iLeft) = shift;
+ my ($iRight) = shift;
+
+ # Build a suitable name for outputfiles based on input filenames
+ $iLeft = NameOnly($iLeft);
+ $iRight = NameOnly($iRight);
+ my ($iBasename) = $iLeft."_to_".$iRight;
+
+ open DELLIST, ">del_$iBasename.bat";
+ open ZIPLIST, ">zip_$iBasename.log";
+ open ZIPBAT, ">zip_$iBasename.bat";
+
+ foreach my $iFile (sort keys %$iCommon)
+ {
+ if (($$iCommon{$iFile}[1] eq "Different") || ($$iCommon{$iFile}[1] eq "Type Changed"))
+ {
+ print ZIPLIST "$iFile\n";
+ }
+ }
+
+ foreach my $iFile (sort keys %$iDiff)
+ {
+ if ($$iDiff{$iFile}[1] eq "Right")
+ {
+ print ZIPLIST "$iFile\n";
+ } else {
+ # DEL needs the / to be \
+ $iFile =~ s/\//\\/g;
+ print DELLIST "del /F $iFile\n";
+ }
+ }
+
+ print ZIPBAT "zip $iBasename.zip -@<zip_$iBasename.log\n";
+
+ close DELLIST;
+ close ZIPLIST;
+ close ZIPBAT;
+
+}
+
+
+# Private
+
+# ReadMD5File
+#
+# Inputs
+# $iResultsFile - Results filename to process
+# $iResults - Reference to Results Hash
+# $iHeaders - Reference to Headers Hash
+#
+# Outputs
+#
+# Description
+# This function reads the conntent of the MD5 File in to a Hash
+sub ReadMD5File
+{
+ my ($iResultsFile, $iResults, $iHeaders) = @_;
+
+ # Open the results file for reading
+ open (INPUT, "$iResultsFile") or croak "Cannot for $iResultsFile for reading";
+ while (<INPUT>)
+ {
+ if (/^(\S+?):(.*)/)
+ {
+ $$iHeaders{$1} = $2;
+ } elsif (/^(\S+?)\sTYPE=(.*?)\sMD5=(.*)/){
+ $$iResults{$1} = [$2,$3];
+ }
+ }
+ close INPUT;
+
+}
+
+1;