1 /* cksum -- calculate and print POSIX checksums and sizes of files
2 Copyright (C) 92, 1995-2006 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 2, or (at your option)
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, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Written by Q. Frank Xia, qx@math.columbia.edu.
19 Cosmetic changes and reorganization by David MacKenzie, djm@gnu.ai.mit.edu.
21 Usage: cksum [file...]
23 The code segment between "#ifdef CRCTAB" and "#else" is the code
24 which calculates the "crctab". It is included for those who want
25 verify the correctness of the "crctab". To recreate the "crctab",
26 do something like the following:
28 cc -DCRCTAB -o crctab cksum.c
31 This software is compatible with neither the System V nor the BSD
32 `sum' program. It is supposed to conform to POSIX, except perhaps
33 for foreign language support. Any inconsistency with the standard
34 (other than foreign language support) is a bug. */
38 /* The official name of this program (e.g., no `g' prefix). */
39 #define PROGRAM_NAME "cksum"
41 #define AUTHORS "Q. Frank Xia"
44 #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"
112 # include "inttostr.h"
114 /* Number of bytes to read at once. */
115 # define BUFLEN (1 << 16)
117 /* The name this program was run with. */
120 static uint_fast32_t const crctab[256] =
123 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
124 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
125 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
126 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
127 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
128 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
129 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
130 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
131 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
132 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
133 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
134 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
135 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
136 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
137 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
138 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
139 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
140 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
141 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
142 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
143 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
144 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
145 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
146 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
147 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
148 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
149 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
150 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
151 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
152 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
153 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
154 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
155 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
156 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
157 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
158 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
159 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
160 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
161 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
162 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
163 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
164 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
165 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
166 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
167 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
168 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
169 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
170 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
171 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
172 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
173 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
176 /* Nonzero if any of the files read were the standard input. */
177 static bool have_read_stdin;
179 /* Calculate and print the checksum and length in bytes
180 of file FILE, or of the standard input if FILE is "-".
181 If PRINT_NAME is true, print FILE next to the checksum and size.
182 Return true if successful. */
185 cksum (const char *file, bool print_name)
187 unsigned char buf[BUFLEN];
188 uint_fast32_t crc = 0;
189 uintmax_t length = 0;
192 char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
195 if (STREQ (file, "-"))
198 have_read_stdin = true;
199 if (O_BINARY && ! isatty (STDIN_FILENO))
200 freopen (NULL, "rb", stdin);
204 fp = fopen (file, (O_BINARY ? "rb" : "r"));
207 error (0, errno, "%s", file);
212 while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
214 unsigned char *cp = buf;
216 if (length + bytes_read < length)
217 error (EXIT_FAILURE, 0, _("%s: file too long"), file);
218 length += bytes_read;
220 crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
227 error (0, errno, "%s", file);
228 if (!STREQ (file, "-"))
233 if (!STREQ (file, "-") && fclose (fp) == EOF)
235 error (0, errno, "%s", file);
239 hp = umaxtostr (length, length_buf);
241 for (; length; length >>= 8)
242 crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
244 crc = ~crc & 0xFFFFFFFF;
247 printf ("%u %s %s\n", (unsigned int) crc, hp, file);
249 printf ("%u %s\n", (unsigned int) crc, hp);
252 error (EXIT_FAILURE, errno, "-: %s", _("write error"));
260 if (status != EXIT_SUCCESS)
261 fprintf (stderr, _("Try `%s --help' for more information.\n"),
266 Usage: %s [FILE]...\n\
269 program_name, program_name);
271 Print CRC checksum and byte counts of each FILE.\n\
274 fputs (HELP_OPTION_DESCRIPTION, stdout);
275 fputs (VERSION_OPTION_DESCRIPTION, stdout);
276 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
282 main (int argc, char **argv)
287 initialize_main (&argc, &argv);
288 program_name = argv[0];
289 setlocale (LC_ALL, "");
290 bindtextdomain (PACKAGE, LOCALEDIR);
291 textdomain (PACKAGE);
293 atexit (close_stdout);
295 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, VERSION,
296 usage, AUTHORS, (char const *) NULL);
297 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
298 usage (EXIT_FAILURE);
300 have_read_stdin = false;
303 ok = cksum ("-", false);
307 for (i = optind; i < argc; i++)
308 ok &= cksum (argv[i], true);
311 if (have_read_stdin && fclose (stdin) == EOF)
312 error (EXIT_FAILURE, errno, "-");
313 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);