*** empty log message ***
[coreutils.git] / src / cksum.c
blobdb4db25dabc189822cc89dd77f751f0a24e7682c
1 /* cksum -- calculate and print POSIX.2 checksums and sizes of files
2 Copyright (C) 92, 1995-1999 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 #ifdef CRCTAB
52 # include <stdio.h>
54 # define BIT(x) ( (unsigned long)1 << (x) )
55 # define SBIT BIT(31)
57 /* The generating polynomial is
59 32 26 23 22 16 12 11 10 8 7 5 4 2 1
60 G(X)=X + X + X + X + X + X + X + X + X + X + X + X + X + X + 1
62 The i bit in GEN is set if X^i is a summand of G(X) except X^32. */
64 # define GEN (BIT(26)|BIT(23)|BIT(22)|BIT(16)|BIT(12)|BIT(11)|BIT(10)\
65 |BIT(8) |BIT(7) |BIT(5) |BIT(4) |BIT(2) |BIT(1) |BIT(0));
67 static unsigned long r[8];
69 static void
70 fill_r ()
72 int i;
74 r[0] = GEN;
75 for (i = 1; i < 8; i++)
76 r[i] = (r[i - 1] & SBIT) ? (r[i - 1] << 1) ^ r[0] : r[i - 1] << 1;
79 static unsigned long
80 remainder (m)
81 int m;
83 unsigned long rem = 0;
84 int i;
86 for (i = 0; i < 8; i++)
87 if (BIT (i) & m)
88 rem = rem ^ r[i];
90 return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
93 int
94 main ()
96 int i;
98 fill_r ();
99 printf ("unsigned long crctab[256] = {\n 0x0");
100 for (i = 0; i < 51; i++)
102 printf (",\n 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X",
103 remainder (i * 5 + 1), remainder (i * 5 + 2), remainder (i * 5 + 3),
104 remainder (i * 5 + 4), remainder (i * 5 + 5));
106 printf ("\n};\n");
107 exit (EXIT_SUCCESS);
110 #else /* !CRCTAB */
112 # include <stdio.h>
113 # include <getopt.h>
114 # include <sys/types.h>
115 # include "system.h"
116 # include "long-options.h"
117 # include "error.h"
119 /* Number of bytes to read at once. */
120 # define BUFLEN (1 << 16)
122 /* The name this program was run with. */
123 char *program_name;
125 static struct option const long_options[] =
127 {0, 0, 0, 0}
130 static unsigned long const crctab[256] =
132 0x0,
133 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
134 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
135 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
136 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
137 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
138 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
139 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
140 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
141 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
142 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
143 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
144 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
145 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
146 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
147 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
148 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
149 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
150 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
151 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
152 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
153 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
154 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
155 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
156 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
157 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
158 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
159 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
160 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
161 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
162 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
163 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
164 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
165 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
166 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
167 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
168 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
169 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
170 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
171 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
172 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
173 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
174 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
175 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
176 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
177 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
178 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
179 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
180 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
181 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
182 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
183 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
186 /* Nonzero if any of the files read were the standard input. */
187 static int have_read_stdin;
189 /* Calculate and print the checksum and length in bytes
190 of file FILE, or of the standard input if FILE is "-".
191 If PRINT_NAME is nonzero, print FILE next to the checksum and size.
192 Return 0 if successful, -1 if an error occurs. */
194 static int
195 cksum (const char *file, int print_name)
197 unsigned char buf[BUFLEN];
198 unsigned long crc = 0;
199 long length = 0;
200 long bytes_read;
201 register FILE *fp;
203 if (STREQ (file, "-"))
205 fp = stdin;
206 have_read_stdin = 1;
208 else
210 fp = fopen (file, "r");
211 if (fp == NULL)
213 error (0, errno, "%s", file);
214 return -1;
218 /* Read input in BINARY mode, unless it is a console device. */
219 SET_BINARY (fileno (fp));
221 while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
223 unsigned char *cp = buf;
225 length += bytes_read;
226 while (bytes_read--)
227 crc = (crc << 8) ^ crctab[((crc >> 24) ^ *(cp++)) & 0xFF];
230 if (ferror (fp))
232 error (0, errno, "%s", file);
233 if (!STREQ (file, "-"))
234 fclose (fp);
235 return -1;
238 if (!STREQ (file, "-") && fclose (fp) == EOF)
240 error (0, errno, "%s", file);
241 return -1;
244 bytes_read = length;
245 while (bytes_read > 0)
247 crc = (crc << 8) ^ crctab[((crc >> 24) ^ bytes_read) & 0xFF];
248 bytes_read >>= 8;
251 crc = ~crc & 0xFFFFFFFF;
253 printf ("%lu %ld", crc, length);
254 if (print_name)
255 printf (" %s", file);
256 putchar ('\n');
258 return 0;
261 void
262 usage (int status)
264 if (status != 0)
265 fprintf (stderr, _("Try `%s --help' for more information.\n"),
266 program_name);
267 else
269 printf (_("\
270 Usage: %s [OPTION]... [FILE]...\n\
272 program_name);
273 printf (_("\
274 Print CRC checksum and byte counts of each FILE.\n\
276 --help display this help and exit\n\
277 --version output version information and exit\n\
278 "));
279 puts (_("\nReport bugs to <bug-textutils@gnu.org>."));
281 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
285 main (int argc, char **argv)
287 int i, c;
288 int errors = 0;
290 program_name = argv[0];
291 setlocale (LC_ALL, "");
292 bindtextdomain (PACKAGE, LOCALEDIR);
293 textdomain (PACKAGE);
295 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
296 AUTHORS, usage);
298 have_read_stdin = 0;
300 while ((c = getopt_long (argc, argv, "", long_options, NULL)) != -1)
302 switch (c)
304 case 0:
305 break;
307 default:
308 usage (1);
312 if (optind >= argc)
314 if (cksum ("-", 0) < 0)
315 errors = 1;
317 else
319 for (i = optind; i < argc; i++)
320 if (cksum (argv[i], 1) < 0)
321 errors = 1;
324 if (have_read_stdin && fclose (stdin) == EOF)
325 error (EXIT_FAILURE, errno, "-");
326 exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
329 #endif /* !CRCTAB */