feisty meow concerns codebase  2.140
checker.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : checker *
4 * Author : Chris Koeritz *
5 * *
6 * Purpose: *
7 * *
8 * Generates checksums for a set of files. *
9 * *
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 \*****************************************************************************/
18 
20 #include <basis/functions.h>
21 #include <basis/astring.h>
23 #include <structures/checksums.h>
25 #include <timely/time_stamp.h>
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 
31 using namespace application;
32 using namespace basis;
33 using namespace loggers;
34 using namespace structures;
35 using namespace timely;
36 
37 const int buffer_size = 4096;
38 
39 //#define DEBUG_CHECKER
40  // uncomment for noisy version.
41 
42 #undef LOG
43 #define LOG(to_print) program_wide_logger::get().log(to_print, ALWAYS_PRINT)
44 
45 int print_instructions(bool good, const astring &program_name)
46 {
47  printf("\n\
48 Usage:\n\t%s [-q] [-t|-b] filename [filename]\n\n\
49 This program generates a checksum for each file that is entered on the\n\
50 command line. The checksum is (hopefully) an architecture independent\n\
51 number that is a very compressed representation of the file gestalt.\n\
52 If one compares two copies of a file, then the checksums should be identical.\n\
53 This is a useful test of whether a file copy or a program download is\n\
54 successful in making an identical version of the file. In particular, if the\n\
55 file is made slightly bigger or smaller, or if an item in the file is changed,\n\
56 then the checksums of the two versions should be different numbers.\n\n\
57 The -q flag specifies a quieter print-out, without any headers.\n\
58 The -b flag is used if the files are to be compared as binary files, and this\n\
59 is also the default. The -t flag is used if the files are to be compared as\n\
60 text files.\n",
61  program_name.s());
62  return !good; // zero is successful exit.
63 }
64 
65 #define HIGHEST_CHECK 32714
66 
67 // do_checksum: takes the specified file name and generates a checksum for it.
68 // if the file is inaccessible or, at any point, reading it returns an
69 // error message, then a negative value is returned.
70 int do_checksum(const astring &file_name, int open_as_a_text_file)
71 {
72  char file_open_mode[10];
73  if (open_as_a_text_file) strcpy(file_open_mode, "rt");
74  else strcpy(file_open_mode, "rb");
75  FILE *opened_file = fopen(file_name.s(), file_open_mode);
76 #ifdef DEBUG_CHECKER
77  LOG(astring("opened ") + file_name);
78 #endif
79  if (!opened_file) return common::NOT_FOUND;
80  int characters_read = 0;
81  int current_checksum_value = 0;
82  char buffer_chunk[buffer_size];
83  while (!feof(opened_file)) {
84  characters_read = int(fread(buffer_chunk, sizeof(char), buffer_size,
85  opened_file));
86  // if result is 0 or negative, stop messing with the file.
87 #ifdef DEBUG_CHECKER
88  LOG(a_sprintf("char read = %d", characters_read));
89 #endif
90  if (characters_read <= 0) {
91  if (characters_read < 0) current_checksum_value = -1;
92  else if (current_checksum_value == 0) current_checksum_value = -1;
93  break;
94  }
95  current_checksum_value = (current_checksum_value
96  + checksums::bizarre_checksum((abyte *)buffer_chunk, characters_read))
97  % HIGHEST_CHECK;
98 #ifdef DEBUG_CHECKER
99  LOG(a_sprintf("current checksum=%d", current_checksum_value));
100 #endif
101  }
102  fclose(opened_file);
103  return int(current_checksum_value);
104 }
105 
106 // do_fletcher_checksum: takes the specified file name and generates a fletcher
107 // checksum for it. if the file is inaccessible or, at any point,
108 // reading it returns an error message, then a negative value is returned.
109 int do_fletcher_checksum(const astring &file_name, int open_as_a_text_file)
110 {
111  char file_open_mode[10];
112  if (open_as_a_text_file) strcpy(file_open_mode, "rt");
113  else strcpy(file_open_mode, "rb");
114  FILE *opened_file = fopen(file_name.s(), file_open_mode);
115 #ifdef DEBUG_CHECKER
116  LOG(astring("opened ") + file_name);
117 #endif
118  if (!opened_file) return common::NOT_FOUND;
119  int characters_read = 0;
120  int current_checksum_value = 0;
121  char buffer_chunk[buffer_size];
122  while (!feof(opened_file)) {
123  characters_read = int(fread(buffer_chunk, sizeof(char), buffer_size,
124  opened_file));
125  // if result is 0 or negative, stop messing with the file.
126 #ifdef DEBUG_CHECKER
127  LOG(a_sprintf("char read = %d", characters_read));
128 #endif
129  if (characters_read <= 0) {
130  if (characters_read < 0) current_checksum_value = -1;
131  else if (current_checksum_value == 0) current_checksum_value = -1;
132  break;
133  }
134  current_checksum_value = checksums::rolling_fletcher_checksum
135  ((uint16)current_checksum_value, (abyte *)buffer_chunk,
136  characters_read);
137 #ifdef DEBUG_CHECKER
138  LOG(a_sprintf("current checksum=%d", current_checksum_value));
139 #endif
140  }
141  fclose(opened_file);
142  return current_checksum_value;
143 }
144 
145 int main(int argc, char *argv[])
146 {
147  // if the file is to be read as a text file, then this is true.
148  bool open_file_as_text = false;
149  // if we are to show our normal header info, this will be true.
150  bool show_header = true;
151 
152  if (argc <= 1) return print_instructions(false, argv[0]);
153 
154  command_line cmds(argc, argv);
155  int index = 0;
156  if (cmds.find('b', index)) open_file_as_text = false;
157  index = 0;
158  if (cmds.find('t', index)) open_file_as_text = true;
159  index = 0;
160  if (cmds.find('q', index)) show_header = false;
161  index = 0;
162  if (cmds.find('?', index)) return print_instructions(true, argv[0]);
163  index = 0;
164  if (cmds.find("help", index)) return print_instructions(true, argv[0]);
165  bool printed_header = false;
166 
167  for (int entry = 0; entry < cmds.entries(); entry++) {
168  command_parameter c = cmds.get(entry);
169  if (c.type() != command_parameter::VALUE) continue;
170  if (!printed_header) {
171  printed_header = true;
172  if (show_header) {
173  printf("%s\n", (astring("[ checker running at ") + time_stamp::notarize(true) + "]").s());
174  printf("bizarro fletcher filename\n");
175  printf("======= ======== ========\n");
176  }
177  }
178  astring name = c.text();
179  int checksum_of_file = do_checksum(name, open_file_as_text);
180  int fletcher_chksum = do_fletcher_checksum(name, open_file_as_text);
181  if (checksum_of_file >= 0) {
182  printf("%s", a_sprintf(" %05d 0x%04x %s\n", checksum_of_file,
183  fletcher_chksum, name.s()).s());
184  } else {
185  printf("%s", a_sprintf("%s is inaccessible.\n", name.s()).s());
186  }
187  }
188  return 0;
189 }
190 
int main(int argc, char *argv[])
Definition: checker.cpp:145
int do_checksum(const astring &file_name, int open_as_a_text_file)
Definition: checker.cpp:70
const int buffer_size
Definition: checker.cpp:37
#define HIGHEST_CHECK
Definition: checker.cpp:65
#define LOG(to_print)
Definition: checker.cpp:43
int do_fletcher_checksum(const astring &file_name, int open_as_a_text_file)
Definition: checker.cpp:109
int print_instructions(bool good, const astring &program_name)
Definition: checker.cpp:45
int entries() const
Returns the number of fields found on the command line.
bool find(char option_character, int &index, bool case_sense=true) const
Returns true if the "option_character" is found in the parameters.
const command_parameter & get(int field) const
Returns the parameter at the "field" specified.
const basis::astring & text() const
observes the string contents.
parameter_types type() const
observes the type of the parameter.
Definition: command_line.h:69
a_sprintf is a specialization of astring that provides printf style support.
Definition: astring.h:440
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
Definition: astring.h:113
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
unsigned short uint16
Definition: definitions.h:111
unsigned char abyte
A fairly important unit which is seldom defined...
Definition: definitions.h:51
A logger that sends to the console screen using the standard output device.
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37