maint: update all copyright year number ranges
[coreutils.git] / src / cksum.c
blob0785e727d4eaaa9d310c8eb7eadbd15705fa63c0
1 /* cksum -- calculate and print POSIX checksums and sizes of files
2 Copyright (C) 1992-2017 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
28 crctab > crctab.h
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. */
35 #include <config.h>
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")
42 #include <stdio.h>
43 #include <sys/types.h>
44 #include <stdint.h>
45 #include "system.h"
46 #include "fadvise.h"
47 #include "xfreopen.h"
49 #ifdef CRCTAB
51 # define BIT(x) ((uint_fast32_t) 1 << (x))
52 # define SBIT BIT (31)
54 /* The generating polynomial is
56 32 26 23 22 16 12 11 10 8 7 5 4 2 1
57 G(X)=X + X + X + X + X + X + X + X + X + X + X + X + X + X + 1
59 The i bit in GEN is set if X^i is a summand of G(X) except X^32. */
61 # define GEN (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \
62 | BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \
63 | BIT (4) | BIT (2) | BIT (1) | BIT (0))
65 static uint_fast32_t r[8];
67 static void
68 fill_r (void)
70 int i;
72 r[0] = GEN;
73 for (i = 1; i < 8; i++)
74 r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
77 static uint_fast32_t
78 crc_remainder (int m)
80 uint_fast32_t rem = 0;
81 int i;
83 for (i = 0; i < 8; i++)
84 if (BIT (i) & m)
85 rem ^= r[i];
87 return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
90 int
91 main (void)
93 int i;
95 fill_r ();
96 printf ("static uint_fast32_t const crctab[256] =\n{\n 0x00000000");
97 for (i = 0; i < 51; i++)
99 printf (",\n 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x",
100 crc_remainder (i * 5 + 1), crc_remainder (i * 5 + 2),
101 crc_remainder (i * 5 + 3), crc_remainder (i * 5 + 4),
102 crc_remainder (i * 5 + 5));
104 printf ("\n};\n");
105 return EXIT_SUCCESS;
108 #else /* !CRCTAB */
110 # include <getopt.h>
111 # include "long-options.h"
112 # include "die.h"
113 # include "error.h"
115 /* Number of bytes to read at once. */
116 # define BUFLEN (1 << 16)
118 static uint_fast32_t const crctab[256] =
120 0x00000000,
121 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
122 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
123 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
124 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
125 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
126 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
127 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
128 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
129 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
130 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
131 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
132 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
133 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
134 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
135 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
136 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
137 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
138 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
139 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
140 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
141 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
142 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
143 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
144 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
145 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
146 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
147 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
148 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
149 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
150 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
151 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
152 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
153 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
154 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
155 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
156 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
157 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
158 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
159 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
160 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
161 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
162 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
163 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
164 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
165 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
166 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
167 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
168 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
169 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
170 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
171 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
174 /* Nonzero if any of the files read were the standard input. */
175 static bool have_read_stdin;
177 /* Calculate and print the checksum and length in bytes
178 of file FILE, or of the standard input if FILE is "-".
179 If PRINT_NAME is true, print FILE next to the checksum and size.
180 Return true if successful. */
182 static bool
183 cksum (const char *file, bool print_name)
185 unsigned char buf[BUFLEN];
186 uint_fast32_t crc = 0;
187 uintmax_t length = 0;
188 size_t bytes_read;
189 FILE *fp;
190 char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
191 char const *hp;
193 if (STREQ (file, "-"))
195 fp = stdin;
196 have_read_stdin = true;
197 if (O_BINARY && ! isatty (STDIN_FILENO))
198 xfreopen (NULL, "rb", stdin);
200 else
202 fp = fopen (file, (O_BINARY ? "rb" : "r"));
203 if (fp == NULL)
205 error (0, errno, "%s", quotef (file));
206 return false;
210 fadvise (fp, FADVISE_SEQUENTIAL);
212 while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
214 unsigned char *cp = buf;
216 if (length + bytes_read < length)
217 die (EXIT_FAILURE, 0, _("%s: file too long"), quotef (file));
218 length += bytes_read;
219 while (bytes_read--)
220 crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
221 if (feof (fp))
222 break;
225 if (ferror (fp))
227 error (0, errno, "%s", quotef (file));
228 if (!STREQ (file, "-"))
229 fclose (fp);
230 return false;
233 if (!STREQ (file, "-") && fclose (fp) == EOF)
235 error (0, errno, "%s", quotef (file));
236 return false;
239 hp = umaxtostr (length, length_buf);
241 for (; length; length >>= 8)
242 crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
244 crc = ~crc & 0xFFFFFFFF;
246 if (print_name)
247 printf ("%u %s %s\n", (unsigned int) crc, hp, file);
248 else
249 printf ("%u %s\n", (unsigned int) crc, hp);
251 if (ferror (stdout))
252 die (EXIT_FAILURE, errno, "-: %s", _("write error"));
254 return true;
257 void
258 usage (int status)
260 if (status != EXIT_SUCCESS)
261 emit_try_help ();
262 else
264 printf (_("\
265 Usage: %s [FILE]...\n\
266 or: %s [OPTION]\n\
268 program_name, program_name);
269 fputs (_("\
270 Print CRC checksum and byte counts of each FILE.\n\
272 "), stdout);
273 fputs (HELP_OPTION_DESCRIPTION, stdout);
274 fputs (VERSION_OPTION_DESCRIPTION, stdout);
275 emit_ancillary_info (PROGRAM_NAME);
277 exit (status);
281 main (int argc, char **argv)
283 int i;
284 bool ok;
286 initialize_main (&argc, &argv);
287 set_program_name (argv[0]);
288 setlocale (LC_ALL, "");
289 bindtextdomain (PACKAGE, LOCALEDIR);
290 textdomain (PACKAGE);
292 atexit (close_stdout);
294 /* Line buffer stdout to ensure lines are written atomically and immediately
295 so that processes running in parallel do not intersperse their output. */
296 setvbuf (stdout, NULL, _IOLBF, 0);
298 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version,
299 usage, AUTHORS, (char const *) NULL);
300 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
301 usage (EXIT_FAILURE);
303 have_read_stdin = false;
305 if (optind == argc)
306 ok = cksum ("-", false);
307 else
309 ok = true;
310 for (i = optind; i < argc; i++)
311 ok &= cksum (argv[i], true);
314 if (have_read_stdin && fclose (stdin) == EOF)
315 die (EXIT_FAILURE, errno, "-");
316 return ok ? EXIT_SUCCESS : EXIT_FAILURE;
319 #endif /* !CRCTAB */