checker.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : checker                                                           *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *  Purpose:                                                                   *
00007 *                                                                             *
00008 *    Generates checksums for a set of files.                                  *
00009 *                                                                             *
00010 *******************************************************************************
00011 * Copyright (c) 1990-$now By Author.  This program is free software; you can  *
00012 * redistribute it and/or modify it under the terms of the GNU General Public  *
00013 * License as published by the Free Software Foundation; either version 2 of   *
00014 * the License or (at your option) any later version.  This is online at:      *
00015 *     http://www.fsf.org/copyleft/gpl.html                                    *
00016 * Please send any updates to: fred@gruntose.com                               *
00017 \*****************************************************************************/
00018 
00019 #include <basis/function.h>
00020 #include <basis/istring.h>
00021 #include <basis/utility.h>
00022 #include <data_struct/static_memory_gremlin.h>
00023 
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <stdlib.h>
00027 
00028 const int buffer_size = 4096;
00029 
00030 HOOPLE_STARTUP_CODE;
00031 
00032 //#define DEBUG_CHECKER
00033   // uncomment for noisy version.
00034 
00035 void print_instructions_and_exit(char *program_name)
00036 {
00037   printf("\n\
00038 Usage:\n\t%s [-t] filename [filename]\n\n\
00039 This program generates a checksum for each file that is entered on the\n\
00040 command line.  The checksum is (hopefully) an architecture independent\n\
00041 number that is a very compressed representation of the file gestalt.\n\
00042 If one compares two copies of a file, then the checksums should be identical.\n\
00043 This is a useful test of whether a file copy or a program download is\n\
00044 successful in making an identical version of the file.  In particular, if the\n\
00045 file is made slightly bigger or smaller, or if an item in the file is changed,\n\
00046 then the checksums of the two versions should be different numbers.\n\n\
00047 The -b flag is used if the files are to be compared as binary files, and this\n\
00048 is also the default.  The -t flag is used if the files are to be compared as\n\
00049 text files.\n",
00050   program_name);
00051   exit(1);
00052 }
00053 
00054 #define HIGHEST_CHECK 32714
00055 
00056 // do_checksum: takes the specified file name and generates a checksum for it.
00057 // if the file is inaccessible or, at any point, reading it returns an
00058 // error message, then a negative value is returned.
00059 int do_checksum(char *file_name, int open_as_a_text_file)
00060 {
00061   char file_open_mode[10];
00062   if (open_as_a_text_file) strcpy(file_open_mode, "rt");
00063   else strcpy(file_open_mode, "rb");
00064   FILE *opened_file = fopen(file_name, file_open_mode);
00065 #ifdef DEBUG_CHECKER
00066   LOG(istring("opened ") + file_name);
00067 #endif
00068   if (!opened_file) return common::NOT_FOUND;
00069   int characters_read = 0;
00070   int current_checksum_value = 0;
00071   char buffer_chunk[buffer_size];
00072   while (!feof(opened_file)) {
00073     characters_read = int(fread(buffer_chunk, sizeof(char), buffer_size,
00074         opened_file));
00075     // if result is 0 or negative, stop messing with the file.
00076 #ifdef DEBUG_CHECKER
00077     LOG(isprintf("char read = %d", characters_read));
00078 #endif
00079     if (characters_read <= 0) {
00080       if (characters_read < 0) current_checksum_value = -1;
00081       else if (current_checksum_value == 0) current_checksum_value = -1;
00082       break;
00083     }
00084     current_checksum_value = (current_checksum_value
00085             + utility::bizarre_checksum((byte *)buffer_chunk, characters_read))
00086         % HIGHEST_CHECK;
00087 #ifdef DEBUG_CHECKER
00088     LOG(isprintf("current checksum=%d", current_checksum_value));
00089 #endif
00090   }
00091   fclose(opened_file);
00092   return int(current_checksum_value);
00093 }
00094 
00095 // do_fletcher_checksum: takes the specified file name and generates a fletcher
00096 // checksum for it.  if the file is inaccessible or, at any point,
00097 // reading it returns an error message, then a negative value is returned.
00098 int do_fletcher_checksum(char *file_name, int open_as_a_text_file)
00099 {
00100   char file_open_mode[10];
00101   if (open_as_a_text_file) strcpy(file_open_mode, "rt");
00102   else strcpy(file_open_mode, "rb");
00103   FILE *opened_file = fopen(file_name, file_open_mode);
00104 #ifdef DEBUG_CHECKER
00105   LOG(istring("opened ") + file_name);
00106 #endif
00107   if (!opened_file) return common::NOT_FOUND;
00108   int characters_read = 0;
00109   int current_checksum_value = 0;
00110   char buffer_chunk[buffer_size];
00111   while (!feof(opened_file)) {
00112     characters_read = int(fread(buffer_chunk, sizeof(char), buffer_size,
00113         opened_file));
00114     // if result is 0 or negative, stop messing with the file.
00115 #ifdef DEBUG_CHECKER
00116     LOG(isprintf("char read = %d", characters_read));
00117 #endif
00118     if (characters_read <= 0) {
00119       if (characters_read < 0) current_checksum_value = -1;
00120       else if (current_checksum_value == 0) current_checksum_value = -1;
00121       break;
00122     }
00123     current_checksum_value = utility::rolling_fletcher_checksum
00124         ((uint16)current_checksum_value, (byte *)buffer_chunk,
00125         characters_read);
00126 #ifdef DEBUG_CHECKER
00127     LOG(isprintf("current checksum=%d", current_checksum_value));
00128 #endif
00129   }
00130   fclose(opened_file);
00131   return current_checksum_value;
00132 }
00133 
00134 int main(int argc, char *argv[])
00135 {
00136   char name[200];
00137 
00138   // if the file is to be read as a text file, then this is true.
00139   int open_file_as_text = false;
00140 
00141   if (argc <= 1) print_instructions_and_exit(argv[0]);
00142   else {
00143     int current_parameter = 0;
00144     if (argv[1][0] == '-') {
00145       if (argv[1][1] == 't') {
00146         current_parameter++;
00147         open_file_as_text = true;
00148       } else if (argv[1][1] == 'b') {
00149         current_parameter++;
00150         open_file_as_text = false;
00151       } else print_instructions_and_exit(argv[0]);
00152     }
00153     bool printed_header = false;
00154     while (++current_parameter < argc) {
00155       if (!printed_header) {
00156         printed_header = true;
00157         printf("bizarro  fletcher  filename\n");
00158         printf("=======  ========  ========\n");
00159       }
00160       strcpy(name, argv[current_parameter]);
00161       int checksum_of_file = do_checksum(name, open_file_as_text);
00162       int fletcher_chksum = do_fletcher_checksum(name, open_file_as_text);
00163       if (checksum_of_file >= 0) {
00164         printf(isprintf(" %05d    0x%04x   %s\n", checksum_of_file,
00165             fletcher_chksum, name).s());
00166       } else {
00167         printf(isprintf("%s is inaccessible.\n", name).s());
00168       }
00169     }
00170   }
00171   return 0;
00172 }
00173 
00174 #ifdef __BUILD_STATIC_APPLICATION__
00175   // static dependencies found by buildor_gen_deps.sh:
00176   #include <basis/array.cpp>
00177   #include <basis/byte_array.cpp>
00178   #include <basis/callstack_tracker.cpp>
00179   #include <basis/chaos.cpp>
00180   #include <basis/convert_utf.cpp>
00181   #include <basis/definitions.cpp>
00182   #include <basis/earth_time.cpp>
00183   #include <basis/guards.cpp>
00184   #include <basis/istring.cpp>
00185   #include <basis/log_base.cpp>
00186   #include <basis/memory_checker.cpp>
00187   #include <basis/mutex.cpp>
00188   #include <basis/object_base.cpp>
00189   #include <basis/outcome.cpp>
00190   #include <basis/packable.cpp>
00191   #include <basis/portable.cpp>
00192   #include <basis/sequence.cpp>
00193   #include <basis/set.cpp>
00194   #include <basis/utility.cpp>
00195   #include <basis/version_record.cpp>
00196   #include <data_struct/amorph.cpp>
00197   #include <data_struct/bit_vector.cpp>
00198   #include <data_struct/byte_hasher.cpp>
00199   #include <data_struct/configurator.cpp>
00200   #include <data_struct/hash_table.cpp>
00201   #include <data_struct/pointer_hash.cpp>
00202   #include <data_struct/stack.cpp>
00203   #include <data_struct/static_memory_gremlin.cpp>
00204   #include <data_struct/string_hash.cpp>
00205   #include <data_struct/string_hasher.cpp>
00206   #include <data_struct/string_table.cpp>
00207   #include <data_struct/symbol_table.cpp>
00208   #include <data_struct/table_configurator.cpp>
00209   #include <loggers/console_logger.cpp>
00210   #include <loggers/file_logger.cpp>
00211   #include <loggers/locked_logger.cpp>
00212   #include <loggers/null_logger.cpp>
00213   #include <loggers/program_wide_logger.cpp>
00214   #include <opsystem/byte_filer.cpp>
00215   #include <opsystem/command_line.cpp>
00216   #include <opsystem/critical_events.cpp>
00217   #include <opsystem/directory.cpp>
00218   #include <opsystem/filename.cpp>
00219   #include <opsystem/ini_config.cpp>
00220   #include <opsystem/ini_parser.cpp>
00221   #include <opsystem/path_configuration.cpp>
00222   #include <opsystem/rendezvous.cpp>
00223   #include <textual/byte_format.cpp>
00224   #include <textual/parser_bits.cpp>
00225   #include <textual/string_manipulation.cpp>
00226   #include <textual/tokenizer.cpp>
00227 #endif // __BUILD_STATIC_APPLICATION__
00228 

Generated on Thu Nov 20 04:28:44 2008 for HOOPLE Libraries by  doxygen 1.5.1