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>
25#include <timely/time_stamp.h>
26
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30
31using namespace application;
32using namespace basis;
33using namespace loggers;
34using namespace structures;
35using namespace timely;
36
37const 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
45int print_instructions(bool good, const astring &program_name)
46{
47 printf("\n\
48Usage:\n\t%s [-q] [-t|-b] filename [filename]\n\n\
49This program generates a checksum for each file that is entered on the\n\
50command line. The checksum is (hopefully) an architecture independent\n\
51number that is a very compressed representation of the file gestalt.\n\
52If one compares two copies of a file, then the checksums should be identical.\n\
53This is a useful test of whether a file copy or a program download is\n\
54successful in making an identical version of the file. In particular, if the\n\
55file is made slightly bigger or smaller, or if an item in the file is changed,\n\
56then the checksums of the two versions should be different numbers.\n\n\
57The -q flag specifies a quieter print-out, without any headers.\n\
58The -b flag is used if the files are to be compared as binary files, and this\n\
59is also the default. The -t flag is used if the files are to be compared as\n\
60text 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.
70int 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))
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.
109int 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
145int 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.
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
static basis::un_short rolling_fletcher_checksum(basis::un_short previous, const basis::abyte *data, int len)
Fletcher checksums applied to streaming data.
Definition checksums.cpp:56
static unsigned int bizarre_checksum(const basis::abyte *data, int length)
A different type of checksum with somewhat unknown properties.
Definition checksums.cpp:25
static basis::astring notarize(bool add_space=true)
a useful method for getting a textual version of the time "right now".
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
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>