*** empty log message ***
[coreutils.git] / src / cksum.c
blob0dce68ccadf8fc07c41e080701d077e3e878e2ba
1 /* cksum -- calculate and print POSIX checksums and sizes of files
2 Copyright (C) 92, 1995-2005 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)
7 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, 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
29 crctab > crctab.h
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. */
36 #include <config.h>
38 /* The official name of this program (e.g., no `g' prefix). */
39 #define PROGRAM_NAME "cksum"
41 #define AUTHORS "Q. Frank Xia"
43 #include <stdio.h>
44 #include <sys/types.h>
45 #include "system.h"
47 #if !defined UINT_FAST32_MAX && !defined uint_fast32_t
48 # define uint_fast32_t unsigned int
49 #endif
51 #ifdef CRCTAB
53 # define BIT(x) ((uint_fast32_t) 1 << (x))
54 # define SBIT BIT (31)
56 /* The generating polynomial is
58 32 26 23 22 16 12 11 10 8 7 5 4 2 1
59 G(X)=X + X + X + X + X + X + X + X + X + X + X + X + X + X + 1
61 The i bit in GEN is set if X^i is a summand of G(X) except X^32. */
63 # define GEN (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \
64 | BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \
65 | BIT (4) | BIT (2) | BIT (1) | BIT (0))
67 static uint_fast32_t r[8];
69 static void
70 fill_r (void)
72 int i;
74 r[0] = GEN;
75 for (i = 1; i < 8; i++)
76 r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
79 static uint_fast32_t
80 crc_remainder (int m)
82 uint_fast32_t rem = 0;
83 int i;
85 for (i = 0; i < 8; i++)
86 if (BIT (i) & m)
87 rem ^= r[i];
89 return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
92 int
93 main (void)
95 int i;
97 fill_r ();
98 printf ("static uint_fast32_t const crctab[256] =\n{\n 0x00000000");
99 for (i = 0; i < 51; i++)
101 printf (",\n 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x",
102 crc_remainder (i * 5 + 1), crc_remainder (i * 5 + 2),
103 crc_remainder (i * 5 + 3), crc_remainder (i * 5 + 4),
104 crc_remainder (i * 5 + 5));
106 printf ("\n};\n");
107 exit (EXIT_SUCCESS);
110 #else /* !CRCTAB */
112 # include <getopt.h>
113 # include "long-options.h"
114 # include "error.h"
115 # include "inttostr.h"
117 /* Number of bytes to read at once. */
118 # define BUFLEN (1 << 16)
120 /* The name this program was run with. */
121 char *program_name;
123 static uint_fast32_t const crctab[256] =
125 0x00000000,
126 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
127 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
128 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
129 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
130 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
131 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
132 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
133 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
134 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
135 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
136 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
137 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
138 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
139 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
140 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
141 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
142 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
143 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
144 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
145 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
146 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
147 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
148 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
149 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
150 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
151 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
152 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
153 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
154 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
155 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
156 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
157 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
158 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
159 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
160 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
161 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
162 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
163 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
164 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
165 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
166 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
167 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
168 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
169 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
170 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
171 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
172 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
173 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
174 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
175 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
176 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
179 /* Nonzero if any of the files read were the standard input. */
180 static bool have_read_stdin;
182 /* Calculate and print the checksum and length in bytes
183 of file FILE, or of the standard input if FILE is "-".
184 If PRINT_NAME is true, print FILE next to the checksum and size.
185 Return true if successful. */
187 static bool
188 cksum (const char *file, bool print_name)
190 unsigned char buf[BUFLEN];
191 uint_fast32_t crc = 0;
192 uintmax_t length = 0;
193 size_t bytes_read;
194 FILE *fp;
195 char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
196 char const *hp;
198 if (STREQ (file, "-"))
200 fp = stdin;
201 have_read_stdin = true;
202 if (O_BINARY && ! isatty (STDIN_FILENO))
203 freopen (NULL, "rb", stdin);
205 else
207 fp = fopen (file, (O_BINARY ? "rb" : "r"));
208 if (fp == NULL)
210 error (0, errno, "%s", file);
211 return false;
215 while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
217 unsigned char *cp = buf;
219 if (length + bytes_read < length)
220 error (EXIT_FAILURE, 0, _("%s: file too long"), file);
221 length += bytes_read;
222 while (bytes_read--)
223 crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
224 if (feof (fp))
225 break;
228 if (ferror (fp))
230 error (0, errno, "%s", file);
231 if (!STREQ (file, "-"))
232 fclose (fp);
233 return false;
236 if (!STREQ (file, "-") && fclose (fp) == EOF)
238 error (0, errno, "%s", file);
239 return false;
242 hp = umaxtostr (length, length_buf);
244 for (; length; length >>= 8)
245 crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
247 crc = ~crc & 0xFFFFFFFF;
249 if (print_name)
250 printf ("%u %s %s\n", (unsigned int) crc, hp, file);
251 else
252 printf ("%u %s\n", (unsigned int) crc, hp);
254 if (ferror (stdout))
255 error (EXIT_FAILURE, errno, "-: %s", _("write error"));
257 return true;
260 void
261 usage (int status)
263 if (status != EXIT_SUCCESS)
264 fprintf (stderr, _("Try `%s --help' for more information.\n"),
265 program_name);
266 else
268 printf (_("\
269 Usage: %s [FILE]...\n\
270 or: %s [OPTION]\n\
272 program_name, program_name);
273 fputs (_("\
274 Print CRC checksum and byte counts of each FILE.\n\
276 "), stdout);
277 fputs (HELP_OPTION_DESCRIPTION, stdout);
278 fputs (VERSION_OPTION_DESCRIPTION, stdout);
279 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
281 exit (status);
285 main (int argc, char **argv)
287 int i;
288 bool ok;
290 initialize_main (&argc, &argv);
291 program_name = argv[0];
292 setlocale (LC_ALL, "");
293 bindtextdomain (PACKAGE, LOCALEDIR);
294 textdomain (PACKAGE);
296 atexit (close_stdout);
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 error (EXIT_FAILURE, errno, "-");
316 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
319 #endif /* !CRCTAB */