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>
49 # define BIT(x) ((uint_fast32_t) 1 << (x))
50 # define SBIT BIT (31)
52 /* The generating polynomial is
54 32 26 23 22 16 12 11 10 8 7 5 4 2 1
55 G(X)=X + X + X + X + X + X + X + X + X + X + X + X + X + X + 1
57 The i bit in GEN is set if X^i is a summand of G(X) except X^32. */
59 # define GEN (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \
60 | BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \
61 | BIT (4) | BIT (2) | BIT (1) | BIT (0))
63 static uint_fast32_t r[8];
71 for (i = 1; i < 8; i++)
72 r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
78 uint_fast32_t rem = 0;
81 for (i = 0; i < 8; i++)
85 return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
94 printf ("static uint_fast32_t const crctab[256] =\n{\n 0x00000000");
95 for (i = 0; i < 51; i++)
97 printf (",\n 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x",
98 crc_remainder (i * 5 + 1), crc_remainder (i * 5 + 2),
99 crc_remainder (i * 5 + 3), crc_remainder (i * 5 + 4),
100 crc_remainder (i * 5 + 5));
109 # include "long-options.h"
112 /* Number of bytes to read at once. */
113 # define BUFLEN (1 << 16)
115 static uint_fast32_t const crctab[256] =
118 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
119 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
120 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
121 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
122 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
123 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
124 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
125 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
126 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
127 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
128 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
129 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
130 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
131 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
132 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
133 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
134 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
135 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
136 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
137 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
138 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
139 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
140 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
141 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
142 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
143 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
144 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
145 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
146 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
147 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
148 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
149 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
150 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
151 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
152 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
153 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
154 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
155 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
156 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
157 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
158 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
159 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
160 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
161 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
162 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
163 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
164 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
165 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
166 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
167 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
168 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
171 /* Nonzero if any of the files read were the standard input. */
172 static bool have_read_stdin;
174 /* Calculate and print the checksum and length in bytes
175 of file FILE, or of the standard input if FILE is "-".
176 If PRINT_NAME is true, print FILE next to the checksum and size.
177 Return true if successful. */
180 cksum (const char *file, bool print_name)
182 unsigned char buf[BUFLEN];
183 uint_fast32_t crc = 0;
184 uintmax_t length = 0;
187 char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
190 if (STREQ (file, "-"))
193 have_read_stdin = true;
194 if (O_BINARY && ! isatty (STDIN_FILENO))
195 freopen (NULL, "rb", stdin);
199 fp = fopen (file, (O_BINARY ? "rb" : "r"));
202 error (0, errno, "%s", file);
207 while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
209 unsigned char *cp = buf;
211 if (length + bytes_read < length)
212 error (EXIT_FAILURE, 0, _("%s: file too long"), file);
213 length += bytes_read;
215 crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
222 error (0, errno, "%s", file);
223 if (!STREQ (file, "-"))
228 if (!STREQ (file, "-") && fclose (fp) == EOF)
230 error (0, errno, "%s", file);
234 hp = umaxtostr (length, length_buf);
236 for (; length; length >>= 8)
237 crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
239 crc = ~crc & 0xFFFFFFFF;
242 printf ("%u %s %s\n", (unsigned int) crc, hp, file);
244 printf ("%u %s\n", (unsigned int) crc, hp);
247 error (EXIT_FAILURE, errno, "-: %s", _("write error"));
255 if (status != EXIT_SUCCESS)
256 fprintf (stderr, _("Try `%s --help' for more information.\n"),
261 Usage: %s [FILE]...\n\
264 program_name, program_name);
266 Print CRC checksum and byte counts of each FILE.\n\
269 fputs (HELP_OPTION_DESCRIPTION, stdout);
270 fputs (VERSION_OPTION_DESCRIPTION, stdout);
271 emit_bug_reporting_address ();
277 main (int argc, char **argv)
282 initialize_main (&argc, &argv);
283 set_program_name (argv[0]);
284 setlocale (LC_ALL, "");
285 bindtextdomain (PACKAGE, LOCALEDIR);
286 textdomain (PACKAGE);
288 atexit (close_stdout);
290 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version,
291 usage, AUTHORS, (char const *) NULL);
292 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
293 usage (EXIT_FAILURE);
295 have_read_stdin = false;
298 ok = cksum ("-", false);
302 for (i = optind; i < argc; i++)
303 ok &= cksum (argv[i], true);
306 if (have_read_stdin && fclose (stdin) == EOF)
307 error (EXIT_FAILURE, errno, "-");
308 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);