*** empty log message ***
[coreutils.git] / src / cksum.c
blob7d0fdc75da048b73fa1e79982e6eb190bd3e50fd
1 /* cksum -- calculate and print POSIX checksums and sizes of files
2 Copyright (C) 92, 1995-2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 following:
28 cc -DCRCTAB -o crctab cksum.c
29 crctab > crctab.h
31 As Bruce Evans pointed out to me, the crctab in the sample C code
32 in 4.9.10 Rationale of P1003.2/D11.2 is represented in reversed order.
33 Namely, 0x01 is represented as 0x80, 0x02 is represented as 0x40, etc.
34 The generating polynomial is crctab[0x80]=0xedb88320 instead of
35 crctab[1]=0x04C11DB7. But the code works only for a non-reverse order
36 crctab. Therefore, the sample implementation is wrong.
38 This software is compatible with neither the System V nor the BSD
39 `sum' program. It is supposed to conform to P1003.2/D11.2,
40 except foreign language interface (4.9.5.3 of P1003.2/D11.2) support.
41 Any inconsistency with the standard except 4.9.5.3 is a bug. */
43 #include <config.h>
45 /* The official name of this program (e.g., no `g' prefix). */
46 #define PROGRAM_NAME "cksum"
48 #define AUTHORS "Q. Frank Xia"
50 #include <stdio.h>
51 #include <sys/types.h>
52 #include "system.h"
54 #if !defined UINT_FAST32_MAX && !defined uint_fast32_t
55 # define uint_fast32_t unsigned int
56 #endif
58 #ifdef CRCTAB
60 # define BIT(x) ((uint_fast32_t) 1 << (x))
61 # define SBIT BIT (31)
63 /* The generating polynomial is
65 32 26 23 22 16 12 11 10 8 7 5 4 2 1
66 G(X)=X + X + X + X + X + X + X + X + X + X + X + X + X + X + 1
68 The i bit in GEN is set if X^i is a summand of G(X) except X^32. */
70 # define GEN (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \
71 | BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \
72 | BIT (4) | BIT (2) | BIT (1) | BIT (0))
74 static uint_fast32_t r[8];
76 static void
77 fill_r (void)
79 int i;
81 r[0] = GEN;
82 for (i = 1; i < 8; i++)
83 r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
86 static uint_fast32_t
87 remainder (int m)
89 uint_fast32_t rem = 0;
90 int i;
92 for (i = 0; i < 8; i++)
93 if (BIT (i) & m)
94 rem ^= r[i];
96 return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
99 int
100 main (void)
102 int i;
104 fill_r ();
105 printf ("static uint_fast32_t crctab[256] =\n{\n 0x0");
106 for (i = 0; i < 51; i++)
108 printf (",\n 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X",
109 remainder (i * 5 + 1), remainder (i * 5 + 2),
110 remainder (i * 5 + 3), remainder (i * 5 + 4),
111 remainder (i * 5 + 5));
113 printf ("\n};\n");
114 exit (EXIT_SUCCESS);
117 #else /* !CRCTAB */
119 # include <getopt.h>
120 # include "closeout.h"
121 # include "long-options.h"
122 # include "error.h"
123 # include "human.h"
125 /* Number of bytes to read at once. */
126 # define BUFLEN (1 << 16)
128 /* The name this program was run with. */
129 char *program_name;
131 static struct option const long_options[] =
133 {0, 0, 0, 0}
136 static uint_fast32_t crctab[256] =
138 0x0,
139 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
140 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
141 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
142 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
143 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
144 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
145 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
146 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
147 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
148 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
149 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
150 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
151 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
152 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
153 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
154 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
155 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
156 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
157 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
158 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
159 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
160 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
161 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
162 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
163 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
164 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
165 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
166 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
167 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
168 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
169 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
170 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
171 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
172 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
173 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
174 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
175 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
176 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
177 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
178 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
179 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
180 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
181 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
182 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
183 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
184 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
185 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
186 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
187 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
188 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
189 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
192 /* Nonzero if any of the files read were the standard input. */
193 static int have_read_stdin;
195 /* Calculate and print the checksum and length in bytes
196 of file FILE, or of the standard input if FILE is "-".
197 If PRINT_NAME is nonzero, print FILE next to the checksum and size.
198 Return 0 if successful, -1 if an error occurs. */
200 static int
201 cksum (const char *file, int print_name)
203 unsigned char buf[BUFLEN];
204 uint_fast32_t crc = 0;
205 uintmax_t length = 0;
206 size_t bytes_read;
207 register FILE *fp;
208 char hbuf[LONGEST_HUMAN_READABLE + 1];
209 char *hp;
211 if (STREQ (file, "-"))
213 fp = stdin;
214 have_read_stdin = 1;
216 else
218 fp = fopen (file, "r");
219 if (fp == NULL)
221 error (0, errno, "%s", file);
222 return -1;
226 /* Read input in BINARY mode, unless it is a console device. */
227 SET_BINARY (fileno (fp));
229 while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
231 unsigned char *cp = buf;
233 if (length + bytes_read < length)
234 error (EXIT_FAILURE, 0, _("%s: file too long"), file);
235 length += bytes_read;
236 while (bytes_read--)
237 crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
240 if (ferror (fp))
242 error (0, errno, "%s", file);
243 if (!STREQ (file, "-"))
244 fclose (fp);
245 return -1;
248 if (!STREQ (file, "-") && fclose (fp) == EOF)
250 error (0, errno, "%s", file);
251 return -1;
254 hp = human_readable (length, hbuf, 1, 1);
256 for (; length; length >>= 8)
257 crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
259 crc = ~crc & 0xFFFFFFFF;
261 if (print_name)
262 printf ("%u %s %s\n", (unsigned) crc, hp, file);
263 else
264 printf ("%u %s\n", (unsigned) crc, hp);
266 if (ferror (stdout))
267 error (EXIT_FAILURE, errno, "-: %s", _("write error"));
269 return 0;
272 void
273 usage (int status)
275 if (status != 0)
276 fprintf (stderr, _("Try `%s --help' for more information.\n"),
277 program_name);
278 else
280 printf (_("\
281 Usage: %s [FILE]...\n\
282 or: %s [OPTION]\n\
284 program_name, program_name);
285 fputs (_("\
286 Print CRC checksum and byte counts of each FILE.\n\
288 "), stdout);
289 fputs (HELP_OPTION_DESCRIPTION, stdout);
290 fputs (VERSION_OPTION_DESCRIPTION, stdout);
291 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
293 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
297 main (int argc, char **argv)
299 int i, c;
300 int errors = 0;
302 program_name = argv[0];
303 setlocale (LC_ALL, "");
304 bindtextdomain (PACKAGE, LOCALEDIR);
305 textdomain (PACKAGE);
307 atexit (close_stdout);
309 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, VERSION,
310 AUTHORS, usage);
312 have_read_stdin = 0;
314 while ((c = getopt_long (argc, argv, "", long_options, NULL)) != -1)
316 switch (c)
318 case 0:
319 break;
321 default:
322 usage (1);
326 if (optind == argc)
327 errors |= cksum ("-", 0);
328 else
330 for (i = optind; i < argc; i++)
331 errors |= cksum (argv[i], 1);
334 if (have_read_stdin && fclose (stdin) == EOF)
335 error (EXIT_FAILURE, errno, "-");
336 exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
339 #endif /* !CRCTAB */