1 /*****************************************************************************\
4 * Author : Chris Koeritz *
8 * Generates checksums for a set of files. *
10 *******************************************************************************
11 * Copyright (c) 1990-$now By Author. This program is free software; you can *
12 * redistribute it and/or modify it under the terms of the GNU General Public *
13 * License as published by the Free Software Foundation; either version 2 of *
14 * the License or (at your option) any later version. This is online at: *
15 * http://www.fsf.org/copyleft/gpl.html *
16 * Please send any updates to: fred@gruntose.com *
17 \*****************************************************************************/
19 #include <basis/functions.h>
20 #include <basis/astring.h>
21 #include <structures/checksums.h>
22 #include <structures/static_memory_gremlin.h>
23 #include <timely/time_stamp.h>
29 using namespace basis;
30 using namespace structures;
31 using namespace timely;
33 const int buffer_size = 4096;
35 //HOOPLE_STARTUP_CODE;
37 //#define DEBUG_CHECKER
38 // uncomment for noisy version.
40 void print_instructions_and_exit(char *program_name)
43 Usage:\n\t%s [-t] filename [filename]\n\n\
44 This program generates a checksum for each file that is entered on the\n\
45 command line. The checksum is (hopefully) an architecture independent\n\
46 number that is a very compressed representation of the file gestalt.\n\
47 If one compares two copies of a file, then the checksums should be identical.\n\
48 This is a useful test of whether a file copy or a program download is\n\
49 successful in making an identical version of the file. In particular, if the\n\
50 file is made slightly bigger or smaller, or if an item in the file is changed,\n\
51 then the checksums of the two versions should be different numbers.\n\n\
52 The -b flag is used if the files are to be compared as binary files, and this\n\
53 is also the default. The -t flag is used if the files are to be compared as\n\
59 #define HIGHEST_CHECK 32714
61 // do_checksum: takes the specified file name and generates a checksum for it.
62 // if the file is inaccessible or, at any point, reading it returns an
63 // error message, then a negative value is returned.
64 int do_checksum(char *file_name, int open_as_a_text_file)
66 char file_open_mode[10];
67 if (open_as_a_text_file) strcpy(file_open_mode, "rt");
68 else strcpy(file_open_mode, "rb");
69 FILE *opened_file = fopen(file_name, file_open_mode);
71 LOG(astring("opened ") + file_name);
73 if (!opened_file) return common::NOT_FOUND;
74 int characters_read = 0;
75 int current_checksum_value = 0;
76 char buffer_chunk[buffer_size];
77 while (!feof(opened_file)) {
78 characters_read = int(fread(buffer_chunk, sizeof(char), buffer_size,
80 // if result is 0 or negative, stop messing with the file.
82 LOG(a_sprintf("char read = %d", characters_read));
84 if (characters_read <= 0) {
85 if (characters_read < 0) current_checksum_value = -1;
86 else if (current_checksum_value == 0) current_checksum_value = -1;
89 current_checksum_value = (current_checksum_value
90 + checksums::bizarre_checksum((abyte *)buffer_chunk, characters_read))
93 LOG(a_sprintf("current checksum=%d", current_checksum_value));
97 return int(current_checksum_value);
100 // do_fletcher_checksum: takes the specified file name and generates a fletcher
101 // checksum for it. if the file is inaccessible or, at any point,
102 // reading it returns an error message, then a negative value is returned.
103 int do_fletcher_checksum(char *file_name, int open_as_a_text_file)
105 char file_open_mode[10];
106 if (open_as_a_text_file) strcpy(file_open_mode, "rt");
107 else strcpy(file_open_mode, "rb");
108 FILE *opened_file = fopen(file_name, file_open_mode);
110 LOG(astring("opened ") + file_name);
112 if (!opened_file) return common::NOT_FOUND;
113 int characters_read = 0;
114 int current_checksum_value = 0;
115 char buffer_chunk[buffer_size];
116 while (!feof(opened_file)) {
117 characters_read = int(fread(buffer_chunk, sizeof(char), buffer_size,
119 // if result is 0 or negative, stop messing with the file.
121 LOG(a_sprintf("char read = %d", characters_read));
123 if (characters_read <= 0) {
124 if (characters_read < 0) current_checksum_value = -1;
125 else if (current_checksum_value == 0) current_checksum_value = -1;
128 current_checksum_value = checksums::rolling_fletcher_checksum
129 ((uint16)current_checksum_value, (abyte *)buffer_chunk,
132 LOG(a_sprintf("current checksum=%d", current_checksum_value));
136 return current_checksum_value;
139 int main(int argc, char *argv[])
143 // if the file is to be read as a text file, then this is true.
144 int open_file_as_text = false;
146 if (argc <= 1) print_instructions_and_exit(argv[0]);
148 int current_parameter = 0;
149 if (argv[1][0] == '-') {
150 if (argv[1][1] == 't') {
152 open_file_as_text = true;
153 } else if (argv[1][1] == 'b') {
155 open_file_as_text = false;
156 } else print_instructions_and_exit(argv[0]);
158 bool printed_header = false;
159 while (++current_parameter < argc) {
160 if (!printed_header) {
161 printed_header = true;
162 printf("%s\n", (astring("[ checker running at ") + time_stamp::notarize(true) + "]").s());
163 printf("bizarro fletcher filename\n");
164 printf("======= ======== ========\n");
166 strcpy(name, argv[current_parameter]);
167 int checksum_of_file = do_checksum(name, open_file_as_text);
168 int fletcher_chksum = do_fletcher_checksum(name, open_file_as_text);
169 if (checksum_of_file >= 0) {
170 printf("%s", a_sprintf(" %05d 0x%04x %s\n", checksum_of_file,
171 fletcher_chksum, name).s());
173 printf("%s", a_sprintf("%s is inaccessible.\n", name).s());