home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / trojan_p / filetest.arc / FILECOMP.PAS < prev    next >
Pascal/Delphi Source File  |  1988-03-13  |  17KB  |  544 lines

  1. {  PROGRAM TO COMPARE THE CRC'S OF THE FILE LISTS IN  }
  2. {   FILETEST.NEW AND FILETEST.OLD                      }
  3.  
  4. {$G512,P512,U+,R+ }
  5. Program Compare;
  6.  
  7. TYPE
  8.   string255 = string[255];
  9.   string64 = string[64];
  10.   string12 = string[12];
  11.  
  12.   Registers = record
  13.                 ax, bx, cx, dx, bp, si, di, ds, es, flags : integer;
  14.               end;
  15.   Months = array [1..12] of string[3];
  16.  
  17.   Directory_record = record
  18.                        directory : string64;
  19.                        FileNum   : integer;
  20.                      end;
  21.  
  22.   File_Rec = record
  23.                name                : string12;
  24.                time_of_day, date   : integer;
  25.                low_size,high_size  : integer;
  26.                attribute           : byte;
  27.                crc                 : integer;
  28.                found               : boolean;
  29.              end;
  30.  
  31.  
  32. CONST
  33.   month : Months = ('JAN','FEB','MAR','APR','MAY','JUN',
  34.                     'JUL','AUG','SEP','OCT','NOV','DEC');
  35.   Version = 3.00;
  36.   Version_Date = '03/11/88';
  37.   diagnostics = false;      {turn on for diagnostic prints}
  38.  
  39. VAR
  40.  
  41.   {  File Creation time and date  }
  42.   TimeOfDay, FileDate : integer;
  43.   directory_number, file_number : integer;
  44.   {  Number of files in each category  }
  45.   old_file, new_file, OK_file, Update_file, Mod_file : integer;
  46.   i : integer;
  47.   old_filename, new_filename : string64;
  48.   infile : TEXT[$0800];  { file for reading file lists }
  49.   tempfile : file; { used in renaming files }
  50.   found_file1,found_file2:boolean;
  51.   yesno : char;
  52.   CRC_value : Integer;
  53.   filesize : real;
  54.   filename : string12;
  55.   Name_of_File, CRC_string, instring : string255;
  56.  
  57.   attribute : byte;
  58.   lowsize, highsize : integer;
  59.   new, new_dir : boolean;
  60.  
  61.   number_directories, direct_count : integer;
  62.  
  63.   this_directory, current_directory : string64;
  64.  
  65.   directories : array [1..200] of directory_record;
  66.   fileinfo : array [1..1800] of file_rec;
  67.  
  68.  
  69. function get_string  : string255;
  70. {
  71.   This function returns a string up to the first space from infile
  72. }
  73. var
  74.   inchar : char;
  75.   temp_string : string255;
  76.  
  77. begin
  78.   {  Ignore any leading blanks  }
  79.   Repeat
  80.     read(infile, inchar);
  81.   Until inchar <> ' ';
  82.  
  83.   temp_string := '';
  84.  
  85.   {  Now, add on to temp_string until a blank is found  }
  86.   Repeat
  87.     temp_string := temp_string + inchar;
  88.     read(infile, inchar);
  89.   Until inchar = ' ';
  90.  
  91.   get_string := temp_string;
  92.  
  93. end;
  94.  
  95. procedure read_old_file;
  96. {
  97.   Procedure to read in the old list of files and set up the list of
  98.   directories (variable directories), and the list of files along with
  99.   the various data (variable fileinfo).
  100.   On return,
  101.   old_file has the number of files in the list and
  102.   number_directories has the number of directories.
  103.  
  104.   The variables directories and fileinfo have the following information:
  105.   directories  directory : Name of the directory (up to 64 characters)
  106.                FileNum   : Number of the name in fileinfo that contains
  107.                            the information for the first file in this
  108.                            directory.
  109.  
  110.   fileinfo     name        : Name of the file
  111.                time_of_day : Time of day in DOS format
  112.                date        : Date in DOS format
  113.                low_size    : Low byte of the file size
  114.                high_size   : High byte of the file size
  115.                attribute   : Attribute of the file
  116.                crc         : CRC of the file
  117.                found       : has file been matched
  118.  
  119. }
  120.  
  121. begin
  122.   {$I-}
  123.   Reset (infile);  {  See if the file already exists  }
  124.   {$I+}
  125.   if IOresult =0 then found_file1 := true;
  126.   old_file := 0;  {  Number of files in the list  }
  127.   number_directories := 0;  {  Number of directories in the list  }
  128.   While found_file1 and not eof(infile) do
  129.   begin
  130.     old_file := old_file + 1;  {  Another file  }
  131.     this_directory := get_string;  {  Get the directory name  }
  132.     fileinfo[old_file].name := get_string;  {  Get the file name  }
  133.     fileinfo[old_file].found := false;
  134.     if this_directory <> current_directory then
  135.     begin
  136.       current_directory := this_directory;
  137.       number_directories := number_directories + 1;
  138.       directories[number_directories].directory := this_directory;
  139.       directories[number_directories].FileNum := old_file;
  140.     end;
  141.     With fileinfo[old_file] do
  142.       Readln(infile,attribute, Time_of_day, date, low_size, high_size, crc);
  143.   end;
  144.   directories[number_directories + 1].FileNum := old_file + 1;
  145.   Close (infile);
  146. end;
  147.  
  148. procedure strup(var temp:string64);
  149.   {
  150.   this procedure changes strings like ' 1' to '01'.
  151.   }
  152.   begin
  153.   if copy(temp,1,1) = ' ' then
  154.     temp := '0'+copy(temp,2,1);
  155.   end;
  156.  
  157.  
  158. function get_time(date1,date2 : integer) : string64;
  159. {
  160.   This function returns the time and date of file creation.
  161.   date1 is the time of day in DOS format
  162.   date2 is the date of creation in DOS format
  163.  
  164.   get_time is a string with the time and date (e.g., 14:31:42  8 AUG 1986)
  165. }
  166.  
  167. var
  168.   hour, minute, second : integer;
  169.   temp, time : string64;
  170.   year, n_month, day : integer;
  171.  
  172. begin
  173.  
  174.   if date2 <> 0 then
  175.   begin
  176.     hour := date1 shr 11;
  177.     minute := (date1 shr 5) - (hour shl 6);
  178.     second := (date1 - (minute shl 5) - (hour shl 11))*2;
  179.     year := date2 shr 9;
  180.     n_month := (date2 shr 5) - (year shl 4);
  181.     day := date2 - (n_month shl 5) - (year shl 9);
  182.     Str(day:2,temp);
  183.     time := temp + ' ' + month[n_month] + ' ';
  184.     Str(year + 1980:4,temp);
  185.     time := time + temp + '  ';
  186.     Str(hour:2,temp);
  187.     strup(temp);
  188.     time := time + temp + ':';
  189.     Str(minute:2,temp);
  190.     strup(temp);
  191.     time := time + temp + ':';
  192.     Str(second:2,temp);
  193.     strup(temp);
  194.     time := time + temp;
  195.     get_time := time;
  196.   end
  197.   else
  198.     get_time := '                      ';
  199.  
  200. end;
  201.  
  202. procedure write_old_file ( file_number : integer);
  203. {
  204.   Procedure to write the attribute, size and CRC for a file from
  205.   the old list
  206.  
  207.   file_number is the number of the file name
  208.  
  209. }
  210.  
  211. begin
  212.   with fileinfo[file_number] do
  213.   begin
  214.     if low_size < 0 then
  215.       filesize := int(high_size)*65536.0 + 32768.0 + int(low_size and $7FFF)
  216.     else
  217.       filesize := int(high_size)*65536.0 + int(low_size);
  218.     Write ('  Attribute = ',attribute:3,', Size = ',filesize:10:0);
  219.     Writeln(', CRC = ',CRC);
  220.   end;
  221. end;
  222.  
  223.  
  224. procedure write_new_file;
  225. {
  226.   Procedure to write the attribute, size and CRC for a file from
  227.   the new list
  228.  
  229. }
  230.  
  231. begin
  232.   if lowsize < 0 then
  233.     filesize := int(highsize)*65536.0 + 32768.0 + int(lowsize and $7FFF)
  234.   else
  235.     filesize := int(highsize)*65536.0 + int(lowsize);
  236.   Write ('  Attribute = ',attribute:3,', Size = ',filesize:10:0);
  237.   Writeln(', CRC = ', CRC_value)
  238. end;
  239.  
  240.  
  241. procedure find_directory( var number : integer; var newdir : boolean);
  242. {
  243.   Procedure to the the directory from the old list that matches the
  244.   directory name from the new list
  245.  
  246.   If the directory name is the same as the current directory, then
  247.   number and newdir are unchanged.
  248.  
  249.   If the directory name is not the same, and it exists on the old list,
  250.   number will be the number of the old directory, and newdir is FALSE.
  251.   The current directory will be updated.
  252.  
  253.   If the directory name is not the same, and it does not exist on the
  254.   old list, newdir is FALSE.  Number is number of directories + 1, but
  255.   is never used.
  256.  
  257. }
  258. begin
  259.   {  If the directory is the same, then the status of number and newdir  }
  260.   {  will not change                                                     }
  261.   if this_directory <> current_directory then
  262.   begin  {  search from the beginning  --  nothing fancy  }
  263.     number := 0;
  264.     Repeat
  265.       number := number + 1;
  266.     Until (number > number_directories) or
  267.       (this_directory = directories[number].directory);
  268.     newdir := (number > number_directories);
  269.     current_directory := this_directory;
  270.   end;
  271. end;
  272.  
  273. procedure find_file( var number : integer; var new : boolean;
  274.                     number_begin, number_end : integer);
  275. {
  276.   Procedure to find the file name.  The directory name has been
  277.   found prior to this time, so the starting point in the search
  278.   has been found.  The search will continue until the first file
  279.    name in the next directory.
  280.  
  281. }
  282. begin
  283.   number := number_begin -1;
  284.   Repeat
  285.     number := number + 1;
  286.   Until (number = number_end) or (filename = fileinfo[number].name);
  287.   new := (filename <> fileinfo[number].name);
  288. end;
  289.  
  290. procedure file_new;
  291. {
  292.   This procedure processes the new files.  new_file is the counter
  293.   for the number of new files.  The file name and information is
  294.   written to the file assigned to newfile.
  295. }
  296.  
  297. begin
  298.   new_file := new_file + 1;
  299.   writeln;
  300.   write ('A new file has been found:                                     ');
  301.   Writeln (this_directory + '\' + filename);
  302.   Writeln ('    Date: ',get_time(TimeOfDay, FileDate));
  303.   if lowsize < 0 then
  304.     filesize := int(highsize)*65536.0 + 32768.0 + int(lowsize and $7FFF)
  305.   else
  306.     filesize := int(highsize)*65536.0 + int(lowsize);
  307.   Writeln ('           Attribute = ',attribute:3,
  308.            ', Size = ',filesize:10:0,', CRC = ', CRC_value);
  309. end;
  310.  
  311. procedure file_deleted;
  312. {
  313.   This procedure processes the updated files.  Update_file is the counter
  314.   for the number of updated files.
  315. }
  316. begin
  317. for file_number := 1 to old_file do
  318.   begin
  319.   if not fileinfo[file_number].found then
  320.     begin
  321.     writeln;
  322.     Write ('A file is no longer in the display list.  File:                ');
  323.     Writeln (fileinfo[file_number].name);
  324.     With fileinfo[file_number] do
  325.       Begin
  326.       Writeln ('    Date: ',get_time(time_of_day,date));
  327.       if lowsize < 0 then
  328.         filesize := int(highsize)*65536.0 + 32768.0 + int(lowsize and $7FFF)
  329.         else
  330.         filesize := int(highsize)*65536.0 + int(lowsize);
  331.       write ('         ');
  332.       write_old_file(file_number);
  333.       End;
  334.     end;
  335.   end;
  336. end;
  337.  
  338. procedure file_updated;
  339. {
  340.   This procedure processes the updated files.  Update_file is the counter
  341.   for the number of updated files.
  342. }
  343. begin
  344.   Update_file := Update_file + 1;
  345.   writeln;
  346.   Write ('A file has been updated.  File:                                ');
  347.   Writeln (this_directory + '\' + filename);
  348.   With fileinfo[file_number] do
  349.   Begin
  350.     Writeln ('Old Date: ',get_time(time_of_day,date));
  351.     Writeln ('New Date: ',get_time(TimeOfDay, FileDate));
  352.     if lowsize < 0 then
  353.       filesize := int(highsize)*65536.0 + 32768.0 + int(lowsize and $7FFF)
  354.     else
  355.       filesize := int(highsize)*65536.0 + int(lowsize);
  356.     write ('Old File:');
  357.     write_old_file(file_number);
  358.   End;
  359.   if lowsize < 0 then
  360.     filesize := int(highsize)*65536.0 + 32768.0 + int(lowsize and $7FFF)
  361.   else
  362.     filesize := int(highsize)*65536.0 + int(lowsize);
  363.   write ('New File:');
  364.   write_new_file;
  365. end;
  366.  
  367. procedure file_OK;
  368. {
  369.   This procedure processes the files that have not been changed, modified
  370.   or deleted.  OK_file is the counter for the number of such files.
  371. }
  372.  
  373. begin
  374.   OK_file := OK_file + 1;
  375. end;
  376.  
  377. procedure bad_CRC;
  378. {
  379.   This procedure processes the files that have been modified without
  380.   changing the directory entry date or time.  Mod_file is the counter for
  381.   the number of such files.  In normal operations, this should not happen,
  382.   so for such files, the name and date information is shown on the console
  383.   and sent to the file assigned to modfile.
  384. }
  385.  
  386. begin
  387.   Mod_file := Mod_file + 1;
  388.   writeln;
  389.   for i := 1 to 79 do write ('-'); writeln;
  390.   Write ('CRC''s do not match!  File:                                     ');
  391.   writeln (this_directory+filename);
  392.   Writeln ('Date: ',get_time(TimeOfDay, FileDate));
  393.   Write ('Old file:');
  394.   write_old_file(file_number);
  395.   Write ('New file:');
  396.   write_new_file;
  397.   writeln ('This may well be SERIOUS.  Investigate, if you did not do this yourself.');
  398.   for i := 1 to 79 do write ('-'); writeln;
  399. end;
  400.  
  401. procedure read_new_file;
  402. {
  403.   Procedure to read the list of new files, and compare them to the
  404.   old files.  The various comparison types are processed according to
  405.   the preceeding routines.
  406. }
  407.  
  408. begin
  409.   current_directory := '';
  410.   new_dir := FALSE;
  411.  
  412.   Assign (infile, new_filename);
  413.   {$I-}
  414.   Reset (infile);  {  See if the file already exists  }
  415.   {$I+}
  416.   if IOresult =0 then found_file2 := true;
  417.  
  418.   if found_file1 and found_file2 then
  419.     begin
  420.     While not eof(infile) do
  421.       begin
  422.       this_directory := get_string;  {  First is the directory name  }
  423.       filename := get_string;  {  Next is the file name  }
  424.       Readln(infile, attribute, TimeOfDay, FileDate, lowsize,
  425.            highsize, crc_value);  {  Then the file parameters  }
  426.       {  Find the entry in the list of old files with the same name  }
  427.       find_directory(directory_number,new_dir);
  428.       if not new_dir then
  429.         find_file(file_number,new,
  430.                 directories[directory_number].FileNum,
  431.                 directories[directory_number + 1].FileNum-1);
  432.       if (new_dir or new) then  {  New directory means new file  }
  433.         file_new
  434.       else  {  Existing file, compare the two  }
  435.         begin
  436.         fileinfo[file_number].found := true;
  437.         if (fileinfo[file_number].Time_of_day <> TimeOfDay)
  438.           or (fileinfo[file_number].date <> FileDate) then
  439.           file_updated
  440.         else
  441.           if (fileinfo[file_number].crc <> CRC_value) then bad_CRC
  442.           else
  443.             file_OK;
  444.         end;
  445.       end;
  446.     end
  447.     else
  448.       begin
  449.       if not found_file1 then writeln ('Input file ',old_filename,' not found');
  450.       if not found_file2 then writeln ('Input file ',new_filename,' not found');
  451.       end;
  452.     Close (infile);
  453.     end;
  454.  
  455.  
  456. BEGIN  {  Compare  }
  457. {
  458.   Writeln('CRC file integrity comparison program');
  459.   Writeln('Version ',version:5:2,', ',version_date);
  460.   Write('Written by Ted H. Emigh -- ');
  461.   Writeln('emigh@ncsugn.uucp or NEMIGH@TUCC.BITNET');
  462.   Writeln('Updated by L. P. Levine -- University of Wisconsin - Milwaukee');
  463.   writeln;
  464.  }
  465.   number_directories := 1;
  466.   current_directory := '';
  467.   directories[1].directory := current_directory;
  468.   directories[1].FileNum := 1;
  469.  
  470.   {  Reset the counters for the various comparisons  }
  471.  
  472.   New_file := 0;
  473.   OK_file := 0;
  474.   Update_file := 0;
  475.   Mod_file := 0;
  476.   found_file1 := false;
  477.   found_file2 := false;
  478.  
  479.   {  Set up the input and output files  }
  480.  
  481.   Case ParamCount of
  482.     0 : begin  {  No command line parameters, use default names  }
  483.           old_filename := 'FILETEST.OLD';
  484.           new_filename := 'FILETEST.NEW';
  485.         end;
  486.     1 : begin  {  File name with listing of new files has been given  }
  487.           old_filename := 'FILETEST.OLD';
  488.           new_filename := ParamStr(1);
  489.         end;
  490.     else
  491.         begin  {  Both file names have been given  }
  492.           old_filename := ParamStr(2);
  493.           new_filename := ParamStr(1);
  494.         end;
  495.   end;
  496.  
  497.   {  Set up the various input and output files  }
  498.  
  499.   Assign (infile,old_filename);
  500.  
  501.   if diagnostics then
  502.   Writeln ('Reading old CRC list.');
  503.  
  504.   read_old_file;
  505.  
  506.   if diagnostics then
  507.   Writeln ('Reading new CRC list and checking.');
  508.  
  509.   read_new_file;
  510.  
  511.   if found_file1 and found_file2 and ((old_file <> OK_file) or
  512.      (new_file <> 0)) then
  513.     begin
  514.  
  515.     file_deleted;
  516.  
  517.   {  Print the summary numbers for this check  }
  518.     writeln;
  519.     Writeln ('Number of Files in the last CRC check:           ',old_file);
  520.     Writeln ('Number of Files that are the same as last time:  ',OK_file);
  521.     Writeln ('Number of New Files:                             ',new_file);
  522.     Writeln ('Number of Removed Files:                         ',
  523.             old_file - update_file - OK_file - Mod_file);
  524.     Writeln ('Number of Updated Files:                         ',update_file);
  525.     Writeln ('Number of Invalidly Modified Files:              ',Mod_file);
  526.     Writeln;
  527.     Writeln;
  528.     write ('Should I update ',old_filename, ' to agree with ',new_filename);
  529.     write (' (YN)? ');
  530.     yesno := 'X';
  531.     while not (yesno in ['Y','y','N','n']) do read (kbd,yesno);
  532.     if (yesno = 'y') or (yesno = 'Y') then
  533.       begin
  534.       writeln ('Yes');
  535.       assign (infile,old_filename);
  536.       erase (infile);
  537.       Assign (infile, new_filename);
  538.       rename (infile,old_filename);
  539.       end
  540.       else
  541.       writeln ('No');
  542.     end;
  543. end.
  544.