1 /* cksum -- calculate and print POSIX checksums and sizes of files
2 Copyright (C) 1992, 1995-2006, 2008-2011 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>
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];
73 for (i
= 1; i
< 8; i
++)
74 r
[i
] = (r
[i
- 1] << 1) ^ ((r
[i
- 1] & SBIT
) ? GEN
: 0);
80 uint_fast32_t rem
= 0;
83 for (i
= 0; i
< 8; i
++)
87 return rem
& 0xFFFFFFFF; /* Make it run on 64-bit machine. */
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));
111 # include "long-options.h"
114 /* Number of bytes to read at once. */
115 # define BUFLEN (1 << 16)
117 static uint_fast32_t const crctab
[256] =
120 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
121 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
122 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
123 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
124 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
125 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
126 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
127 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
128 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
129 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
130 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
131 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
132 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
133 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
134 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
135 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
136 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
137 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
138 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
139 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
140 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
141 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
142 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
143 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
144 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
145 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
146 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
147 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
148 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
149 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
150 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
151 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
152 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
153 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
154 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
155 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
156 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
157 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
158 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
159 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
160 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
161 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
162 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
163 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
164 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
165 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
166 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
167 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
168 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
169 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
170 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
173 /* Nonzero if any of the files read were the standard input. */
174 static bool have_read_stdin
;
176 /* Calculate and print the checksum and length in bytes
177 of file FILE, or of the standard input if FILE is "-".
178 If PRINT_NAME is true, print FILE next to the checksum and size.
179 Return true if successful. */
182 cksum (const char *file
, bool print_name
)
184 unsigned char buf
[BUFLEN
];
185 uint_fast32_t crc
= 0;
186 uintmax_t length
= 0;
189 char length_buf
[INT_BUFSIZE_BOUND (uintmax_t)];
192 if (STREQ (file
, "-"))
195 have_read_stdin
= true;
196 if (O_BINARY
&& ! isatty (STDIN_FILENO
))
197 xfreopen (NULL
, "rb", stdin
);
201 fp
= fopen (file
, (O_BINARY
? "rb" : "r"));
204 error (0, errno
, "%s", file
);
209 fadvise (fp
, FADVISE_SEQUENTIAL
);
211 while ((bytes_read
= fread (buf
, 1, BUFLEN
, fp
)) > 0)
213 unsigned char *cp
= buf
;
215 if (length
+ bytes_read
< length
)
216 error (EXIT_FAILURE
, 0, _("%s: file too long"), file
);
217 length
+= bytes_read
;
219 crc
= (crc
<< 8) ^ crctab
[((crc
>> 24) ^ *cp
++) & 0xFF];
226 error (0, errno
, "%s", file
);
227 if (!STREQ (file
, "-"))
232 if (!STREQ (file
, "-") && fclose (fp
) == EOF
)
234 error (0, errno
, "%s", file
);
238 hp
= umaxtostr (length
, length_buf
);
240 for (; length
; length
>>= 8)
241 crc
= (crc
<< 8) ^ crctab
[((crc
>> 24) ^ length
) & 0xFF];
243 crc
= ~crc
& 0xFFFFFFFF;
246 printf ("%u %s %s\n", (unsigned int) crc
, hp
, file
);
248 printf ("%u %s\n", (unsigned int) crc
, hp
);
251 error (EXIT_FAILURE
, errno
, "-: %s", _("write error"));
259 if (status
!= EXIT_SUCCESS
)
260 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
265 Usage: %s [FILE]...\n\
268 program_name
, program_name
);
270 Print CRC checksum and byte counts of each FILE.\n\
273 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
274 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
275 emit_ancillary_info ();
281 main (int argc
, char **argv
)
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 parse_long_options (argc
, argv
, PROGRAM_NAME
, PACKAGE
, Version
,
295 usage
, AUTHORS
, (char const *) NULL
);
296 if (getopt_long (argc
, argv
, "", NULL
, NULL
) != -1)
297 usage (EXIT_FAILURE
);
299 have_read_stdin
= false;
302 ok
= cksum ("-", false);
306 for (i
= optind
; i
< argc
; i
++)
307 ok
&= cksum (argv
[i
], true);
310 if (have_read_stdin
&& fclose (stdin
) == EOF
)
311 error (EXIT_FAILURE
, errno
, "-");
312 exit (ok
? EXIT_SUCCESS
: EXIT_FAILURE
);