1
/* cksum -- calculate and print POSIX checksums and sizes of files
2
Copyright (C) 92, 1995-2006, 2008 Free Software Foundation, Inc.
4
This program is free software: you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation, either version 3 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
/* Written by Q. Frank Xia, qx@math.columbia.edu.
18
Cosmetic changes and reorganization by David MacKenzie, djm@gnu.ai.mit.edu.
20
Usage: cksum [file...]
22
The code segment between "#ifdef CRCTAB" and "#else" is the code
23
which calculates the "crctab". It is included for those who want
24
verify the correctness of the "crctab". To recreate the "crctab",
25
do something like the following:
27
cc -DCRCTAB -o crctab cksum.c
30
This software is compatible with neither the System V nor the BSD
31
`sum' program. It is supposed to conform to POSIX, except perhaps
32
for foreign language support. Any inconsistency with the standard
33
(other than foreign language support) is a bug. */
37
/* The official name of this program (e.g., no `g' prefix). */
38
#define PROGRAM_NAME "cksum"
40
#define AUTHORS proper_name ("Q. Frank Xia")
43
#include <sys/types.h>
50
# define BIT(x) ((uint_fast32_t) 1 << (x))
51
# define SBIT BIT (31)
53
/* The generating polynomial is
55
32 26 23 22 16 12 11 10 8 7 5 4 2 1
56
G(X)=X + X + X + X + X + X + X + X + X + X + X + X + X + X + 1
58
The i bit in GEN is set if X^i is a summand of G(X) except X^32. */
60
# define GEN (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \
61
| BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \
62
| BIT (4) | BIT (2) | BIT (1) | BIT (0))
64
static uint_fast32_t r[8];
72
for (i = 1; i < 8; i++)
73
r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
79
uint_fast32_t rem = 0;
82
for (i = 0; i < 8; i++)
86
return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
95
printf ("static uint_fast32_t const crctab[256] =\n{\n 0x00000000");
96
for (i = 0; i < 51; i++)
98
printf (",\n 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x",
99
crc_remainder (i * 5 + 1), crc_remainder (i * 5 + 2),
100
crc_remainder (i * 5 + 3), crc_remainder (i * 5 + 4),
101
crc_remainder (i * 5 + 5));
110
# include "long-options.h"
113
/* Number of bytes to read at once. */
114
# define BUFLEN (1 << 16)
116
static uint_fast32_t const crctab[256] =
119
0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
120
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
121
0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
122
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
123
0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
124
0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
125
0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
126
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
127
0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
128
0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
129
0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
130
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
131
0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
132
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
133
0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
134
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
135
0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
136
0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
137
0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
138
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
139
0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
140
0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
141
0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
142
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
143
0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
144
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
145
0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
146
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
147
0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
148
0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
149
0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
150
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
151
0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
152
0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
153
0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
154
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
155
0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
156
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
157
0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
158
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
159
0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
160
0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
161
0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
162
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
163
0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
164
0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
165
0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
166
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
167
0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
168
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
169
0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
172
/* Nonzero if any of the files read were the standard input. */
173
static bool have_read_stdin;
175
/* Calculate and print the checksum and length in bytes
176
of file FILE, or of the standard input if FILE is "-".
177
If PRINT_NAME is true, print FILE next to the checksum and size.
178
Return true if successful. */
181
cksum (const char *file, bool print_name)
183
unsigned char buf[BUFLEN];
184
uint_fast32_t crc = 0;
185
uintmax_t length = 0;
188
char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
191
if (STREQ (file, "-"))
194
have_read_stdin = true;
195
if (O_BINARY && ! isatty (STDIN_FILENO))
196
xfreopen (NULL, "rb", stdin);
200
fp = fopen (file, (O_BINARY ? "rb" : "r"));
203
error (0, errno, "%s", file);
208
while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
210
unsigned char *cp = buf;
212
if (length + bytes_read < length)
213
error (EXIT_FAILURE, 0, _("%s: file too long"), file);
214
length += bytes_read;
216
crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
223
error (0, errno, "%s", file);
224
if (!STREQ (file, "-"))
229
if (!STREQ (file, "-") && fclose (fp) == EOF)
231
error (0, errno, "%s", file);
235
hp = umaxtostr (length, length_buf);
237
for (; length; length >>= 8)
238
crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
240
crc = ~crc & 0xFFFFFFFF;
243
printf ("%u %s %s\n", (unsigned int) crc, hp, file);
245
printf ("%u %s\n", (unsigned int) crc, hp);
248
error (EXIT_FAILURE, errno, "-: %s", _("write error"));
256
if (status != EXIT_SUCCESS)
257
fprintf (stderr, _("Try `%s --help' for more information.\n"),
262
Usage: %s [FILE]...\n\
265
program_name, program_name);
267
Print CRC checksum and byte counts of each FILE.\n\
270
fputs (HELP_OPTION_DESCRIPTION, stdout);
271
fputs (VERSION_OPTION_DESCRIPTION, stdout);
272
emit_bug_reporting_address ();
278
main (int argc, char **argv)
283
initialize_main (&argc, &argv);
284
set_program_name (argv[0]);
285
setlocale (LC_ALL, "");
286
bindtextdomain (PACKAGE, LOCALEDIR);
287
textdomain (PACKAGE);
289
atexit (close_stdout);
291
parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version,
292
usage, AUTHORS, (char const *) NULL);
293
if (getopt_long (argc, argv, "", NULL, NULL) != -1)
294
usage (EXIT_FAILURE);
296
have_read_stdin = false;
299
ok = cksum ("-", false);
303
for (i = optind; i < argc; i++)
304
ok &= cksum (argv[i], true);
307
if (have_read_stdin && fclose (stdin) == EOF)
308
error (EXIT_FAILURE, errno, "-");
309
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);