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