bootstrap: resynchronize from gnulib
[coreutils.git] / src / cksum.c
blobd240eb38623af1776c2007979aad294e43413e45
1 /* cksum -- calculate and print POSIX checksums and sizes of files
2 Copyright (C) 1992, 1995-2006, 2008-2010 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 "xfreopen.h"
48 #ifdef CRCTAB
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];
66 static void
67 fill_r (void)
69 int i;
71 r[0] = GEN;
72 for (i = 1; i < 8; i++)
73 r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
76 static uint_fast32_t
77 crc_remainder (int m)
79 uint_fast32_t rem = 0;
80 int i;
82 for (i = 0; i < 8; i++)
83 if (BIT (i) & m)
84 rem ^= r[i];
86 return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
89 int
90 main (void)
92 int i;
94 fill_r ();
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));
103 printf ("\n};\n");
104 exit (EXIT_SUCCESS);
107 #else /* !CRCTAB */
109 # include <getopt.h>
110 # include "long-options.h"
111 # include "error.h"
113 /* Number of bytes to read at once. */
114 # define BUFLEN (1 << 16)
116 static uint_fast32_t const crctab[256] =
118 0x00000000,
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. */
180 static bool
181 cksum (const char *file, bool print_name)
183 unsigned char buf[BUFLEN];
184 uint_fast32_t crc = 0;
185 uintmax_t length = 0;
186 size_t bytes_read;
187 FILE *fp;
188 char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
189 char const *hp;
191 if (STREQ (file, "-"))
193 fp = stdin;
194 have_read_stdin = true;
195 if (O_BINARY && ! isatty (STDIN_FILENO))
196 xfreopen (NULL, "rb", stdin);
198 else
200 fp = fopen (file, (O_BINARY ? "rb" : "r"));
201 if (fp == NULL)
203 error (0, errno, "%s", file);
204 return false;
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;
215 while (bytes_read--)
216 crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
217 if (feof (fp))
218 break;
221 if (ferror (fp))
223 error (0, errno, "%s", file);
224 if (!STREQ (file, "-"))
225 fclose (fp);
226 return false;
229 if (!STREQ (file, "-") && fclose (fp) == EOF)
231 error (0, errno, "%s", file);
232 return false;
235 hp = umaxtostr (length, length_buf);
237 for (; length; length >>= 8)
238 crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
240 crc = ~crc & 0xFFFFFFFF;
242 if (print_name)
243 printf ("%u %s %s\n", (unsigned int) crc, hp, file);
244 else
245 printf ("%u %s\n", (unsigned int) crc, hp);
247 if (ferror (stdout))
248 error (EXIT_FAILURE, errno, "-: %s", _("write error"));
250 return true;
253 void
254 usage (int status)
256 if (status != EXIT_SUCCESS)
257 fprintf (stderr, _("Try `%s --help' for more information.\n"),
258 program_name);
259 else
261 printf (_("\
262 Usage: %s [FILE]...\n\
263 or: %s [OPTION]\n\
265 program_name, program_name);
266 fputs (_("\
267 Print CRC checksum and byte counts of each FILE.\n\
269 "), stdout);
270 fputs (HELP_OPTION_DESCRIPTION, stdout);
271 fputs (VERSION_OPTION_DESCRIPTION, stdout);
272 emit_ancillary_info ();
274 exit (status);
278 main (int argc, char **argv)
280 int i;
281 bool ok;
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;
298 if (optind == argc)
299 ok = cksum ("-", false);
300 else
302 ok = true;
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);
312 #endif /* !CRCTAB */