################################################################################ # # File: updcksum # # Purpose: Set the cksum value in a file so Lawson lasetup will not attempt to overwrite # solely based on cksum, but rather on version number ONLY # # Syntax: # perl $GENDIR/bin/updcksum Productline Directory Filename # or %GENDIR%/bin/... for windows # # Example (Unix): # updcksum test803 pdlib OEOIL # # Description: This perl script will use the cksum algirithem defined by Lawson's # lasetup script to set the cksum value in the header of a customized # lawson file. # # Productline is the product line in which the file resides # Directory is the directory under the product line in which the file exists # For Example: pdlib or apsrc # DO NOT include any slashes # Filename is the actual file name to check and set the cksum if needed. # # None of the parameters are case sensitive. This program will convert case # as needed following these rules: # 1. Productline will be converted to both upper and lower case to be used # in validation of the product line # 2. Directory will be converted to lower case - ALWAYS # 3. Filename will be converted to UPPER case and if the filename contains # and extension (i.e., ".scr") the extension will be converted to # lower case. # # Notes: # THIS PROGRAM REQUIRES PERL 5 (5.004) OR GREATER. # Written by Todd Kastle, Kastle Consulting on 5/13/2004 # Based on the logic in $GENDIR/bin/lasetup # # Update Notes: # If the cksum does not convert properly and the lasetup program continues # to notice that the file has been changed even after you have run this # script and changed the cksum then look in $GENDIR/bin/lasetup for the # cksum function and compare the settings in that file. They should never # change, but you never know what Lawson will do... # ################################################################################ ################################################################################ # Validate version of Perl, GENDIR and LAWDIR are set, and point to $GENDIR/bin ################################################################################ BEGIN { die "\nThis program requires Perl version 5 (5.004) or greater. Your version is $].\nPlease update your version of perl.\n\n" if $] < 5.004; die "You must first set the environment variables GENDIR and LAWDIR.\n\n" unless $ENV{GENDIR} and $ENV{LAWDIR}; push(@INC, "$ENV{GENDIR}/bin"); } use File::Basename; use File::Path; use File::Find; use File::Copy; use FileHandle; use Config; use Cwd; #use strict; sub quit; sub Log; ########################Build_Hash Variables########################################## my $file_header; my $header_cksum; my $header_file_name; my $header_version; my $nocheck_header; my $file_array; my $top_line; my $true_cksum32; my $true_cksum64; ############################## Get starting time ############################### gettime(); $starttime = "$mon/$mday/$year $hr:$min:$sec"; ################## Global static variables ##################################### ### Directory paths ### $GENDIR = join '/', split /\\/, $ENV{GENDIR}; # Microsoft compatability $LAWDIR = join '/', split /\\/, $ENV{LAWDIR}; # Microsoft compatability ### Determine OS Type ### if($ENV{OS} eq "Windows_NT"){ $OS = "NT"; } ### Usage text ### #------------------------------------------------------------------------------- $Usage = " Syntax: updcksum Productline Directory Filename Example: updcksum test803 pdlib OEOIL "; #------------------------------------------------------------------------------- ######################### Process Command Line Arguments ####################### ### capture command line ### @CmdLine = @ARGV; unshift @CmdLine, $0; ### print Usage if incorrect number of arguments ### if ( @ARGV != 3 ) { quit("\nYou must supply command line arguments.\n" . $Usage , "SILENT", "SCREEN"); } ($Productline, $Directory, $Filename) = @ARGV; ##################### Validate LAWDIR and GENDIR ############################### ### Validate $LAWDIR and $GENDIR/bin directory ### unless (defined $LAWDIR and $LAWDIR ne "") { quit("LAWDIR environment variable is not defined.\n", "SILENT", "SCREEN"); } unless (-d "$LAWDIR") { quit("LAWDIR directory ($LAWDIR) does not exist.\n", "SILENT", "SCREEN"); } unless (defined $GENDIR and $GENDIR ne "") { quit("GENDIR environment variable is not defined.\n", "SILENT", "SCREEN"); } unless (-d "$GENDIR") { quit("GENDIR directory ($GENDIR) does not exist.\n", "SILENT", "LOGSCREEN"); } unless (-d "$GENDIR/bin") { quit("\$GENDIR/bin directory ($GENDIR/bin) does not exist.\n", "SILENT", "LOGSCREEN"); } ########################### Examine Productline ############################### $Productline = lc $Productline; # Productline usually must be lowercase $ProdlineCaps = uc $Productline; # Productline must be all caps for rngdbdump $ProdDir = "$LAWDIR/$Productline"; $Directory = lc $Directory; # Directory usually must be lowercase $FileDir = "$LAWDIR/$Productline/$Directory"; $AdminDir = "$ProdDir/Admin"; ### Don't allow "gen" or a beginning digit for a productline ### if ( $Productline eq "gen" ) { quit("Please do not use 'gen' as your Productline.\n", "SILENT", "SCREEN"); } if ( $Productline =~ /^\d/ ) { quit("First character of Productline may not be numeric (0-9).\n", "SILENT", "SCREEN"); } ### Find out if Productline exists as a directory or in GEN ### $PLDirExists = -d $ProdDir; @GenPL = `rngdbdump -n gen prodline -f productline -v productline=$ProdlineCaps`; unless ($? == 0) { quit("ERROR - 'rngdbdump' failed while querying GEN for Productline - make sure ladb is running.\n", "ERROR", "LOGSCREEN"); } $PLGenExists = ( scalar(@GenPL) and ($GenPL[0] =~ /^\s*$ProdlineCaps\s*$/) ); $FileDirExists = -d $FileDir; if ( ! $PLDirExists and ! $PLGenExists ) { quit("ERROR - Productline $ProdlineCaps not found.\n", "SILENT", "LOGSCREEN"); } if ( ! $FileDirExists ) { quit("ERROR - The directory $FileDir not found.\n", "SILENT", "LOGSCREEN"); } $Filename = uc $Filename; $LCFilename = lc $Filename; $pos = index($Filename, "."); if ($pos > -1) { $Filename = substr($Filename,0,($pos+1)) . substr($LCFilename,($pos+1),3); } $FullFilename = $FileDir."/".$Filename; $FileExists = -f $FullFilename; if ( ! $FileExists ) { quit("ERROR - The file $Filename not found.\n", "SILENT", "LOGSCREEN"); } if ((-B $FullFilename) || (-z $FullFilename)) { quit("ERROR - The file $Filename is binary and cannot be processed.\n", "SILENT", "LOGSCREEN"); } ######################################################################################## # Open file and check header ######################################################################################## unless (open (FILE, "<$FullFilename")) { print "ERROR: Unable to read file \"$FullFilename\": $!\n"; exit 1; } $top_line = ; chomp $top_line; close(FILE); if ($top_line =~ /\*{7} ([\w-+=:]+(?:\.[\w-+=:]+)*) (\d+(?:\.\d+)*) +\<(\d+)\>/) { $header_file_name = $1; if ($header_file_name ne $Filename) { print "ERROR: file \"$FullFilename\" has bad header:\n"; exit 1; } } else { print "ERROR: file \"$FullFilename\" has bad header:\n"; exit 1; } unless (open (FILE, "<$FullFilename")) { print "ERROR: Unable to read file \"$FullFilename\": $!\n"; exit 1; } @file_array = (); @file_array = ; close(FILE); $file_header = $file_array[0]; ### Check for detectable local modifications ### if ($file_header =~ /\*{7} ([\w-+=:]+(?:\.[\w-+=:]+)*) (\d+(?:\.\d+)*) +\<(\d+)\>/) { $header_file_name = $1; $header_version = $2; $header_cksum = $3; ### Check for detectable local modifications ### $nocheck_header = return_header($file_header); shift @file_array; chomp($nocheck_header); unshift @file_array, $nocheck_header . "\n"; $true_cksum32 = cksum(\@file_array, $true_cksum64); if ("$header_cksum" eq "$true_cksum32" || "$header_cksum" eq "$true_cksum64") { print "cksum does not need to be changed\n"; exit; } else { print "\nFor the file: $FullFilename *******************\n"; print " cksum value in header of file: $header_cksum\n"; print " cksum value calculated for file: $true_cksum64\n"; print "\nDo you want to update the file with the calculated cksum? (y/n) "; $answer = ; chomp $answer; if (yes($answer)) { print "Updating file header...\n"; unless (open (FILE, ">$FullFilename")) { print "ERROR: Unable to write to file \"$FullFilename\": $!\n"; exit 1; } shift @file_array; unshift @file_array, $nocheck_header . " <" . $true_cksum64. ">\n"; foreach $x (@file_array) { print FILE $x; } } else { print "File Header NOT Changed\n"; } } } exit; ################################################################################ ########################### Subroutines ######################################## ################################################################################ ################################################################################ # Function: quit(msg, exitType, output) # Purpose: log message and an exit condition, then quit program. # Example: quit("Failed to extract install files. Exiting...", "ERROR", "LOGSCREEN"); # will output the message string along with an abnormal termination message to # both the log file and the screen, then exit. # Arguments: # string : any string the user wants to output (uses Log() to output). # exitType : a string indicating the type of exit (uses Log() to output). # "DONE" = installation is complete # "PREVIEW" = preview is complete # "ERROR" = installation terminating abnormally # "SILENT" = don't log any exit condition # output : tells Log() where to log messages (logfile, stdout, or both). ################################################################################ ############################################################################################### sub quit { ############################################################################################### (my $msg, my $exitType, my $output) = @_; if ($msg =~ /.+/) { Log($msg, $output); } unless ( $exitType eq "SILENT" ) { gettime(); $endtime = "$mon/$mday/$year $hr:$min:$sec"; if ( $exitType eq "DONE" ) { Log("Installation ${RelID}complete (start = $starttime, stop = $endtime).\n\n", $output); } elsif ( $exitType eq "PREVIEW" ) { Log("Installation preview ${RelID}complete (start = $starttime, stop = $endtime).\n\n", $output); } elsif ( $exitType eq "ERROR" ) { Log("Installation ${RelID}terminated abnormally (start = $starttime, stop = $endtime).\n\n", $output); } } exit; } ################################################################################ # Function: Log(msg, output) # Purpose: log a message to the logfile, to the screen, or both. # Example: Log("Can't find file. Exiting...", "LOGSCREEN"); # will print message to both the logfile and the screen (stdout). # Arguments: # msg : a string containing the message to log. # output : a string indicating where to send the message. # "LOGFILE" = output message to logfile only. # "SCREEN" = output message to screen only. # "LOGSCREEN" = output message to logfile and screen. # Caveats: # 1. a timestamp will be prepended to the message. # 2. newlines/carriage returns are NOT added to the message. ################################################################################ ############################################################################################### sub Log { ############################################################################################### (my $msg, my $output, my $nostamp) = @_; gettime(); $logtime = "$mon/$mday/$year $hr:$min:$sec"; if ( $nostamp ) { $logmsg = $msg; } else { $logmsg = "$logtime $msg"; } if ( $output eq "SCREEN" or $output eq "LOGSCREEN" ) { print STDOUT $msg; } } ############################################################################################### sub gettime { ############################################################################################### ### Reads current time into appropriate variables. ($sec,$min,$hr,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); if ($mday < 10) { $mday = "0" . $mday; } $mon++; if ($mon < 10) { $mon = "0" . $mon; } $year += 1900; $yr = substr("$year", 2, 2); $yday++; if ($sec < 10) { $sec = "0" . $sec; } if ($min < 10) { $min = "0" . $min; } } ############################################################################################### sub return_header { ############################################################################################### my ($line) = $_[0]; if ($line =~ /(\*{7} [\w-+=:]+(?:\.[\w-+=:]+)* \d+(?:\.\d+)*) +\<(\d+)\>/) { $header = $1; $checkSum = $2; return $header."\n"; } else { return ""; #not a correct version string } } ############################################################################################### sub cksum { ############################################################################################### my $file = $_[0]; my $crc; my @crctab; my @line; @crctab = ( 0x0, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 ); $crc = 0; for ($index = 0; $index <= $#{$file}; $index++) { @line = split //, ${$file}[$index]; foreach $char (@line) { $crc = ($crc << 8) ^ $crctab[(($crc >>24) ^ ord($char)) & 0xFF]; } } $bytes_read = $#{$file} + 1; while ($bytes_read > 0) { $crc = ($crc << 8) ^ $crctab[(($crc >>24) ^ $bytes_read) & 0xFF]; $bytes_read >>=8; } $_[1] = $crc; #Returns native or 64 bit to 2nd argument $crc = $crc & 0xffffffff; #Forces function to always return 32 bit return $crc; } ############################################################################################### # sub yes returns 1 for a "yes" answer returns 0 for a "no" answer. ############################################################################################### sub yes { my $in = $_[0]; while (1) { if ( ($in =~ m/^y$/i) || ($in =~ m/^yes$/i) ) { return 1; } elsif ( ($in =~ m/^n$/i) || ($in =~ m/^no$/i) ) { return 0; } else { print STDOUT "Please type \"y\" or \"n\" and press return. "; $in = ; chomp $in; } } } ##############################################################################################