build: ensure make-prime-list doesn't access out of bounds memory
[platform/upstream/coreutils.git] / src / cksum.c
1 /* cksum -- calculate and print POSIX checksums and sizes of files
2    Copyright (C) 1992-2013 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>.  */
16 \f
17 /* Written by Q. Frank Xia, qx@math.columbia.edu.
18    Cosmetic changes and reorganization by David MacKenzie, djm@gnu.ai.mit.edu.
19
20   Usage: cksum [file...]
21
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:
26
27       cc -DCRCTAB -o crctab cksum.c
28       crctab > crctab.h
29
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.  */
34
35 #include <config.h>
36
37 /* The official name of this program (e.g., no 'g' prefix).  */
38 #define PROGRAM_NAME "cksum"
39
40 #define AUTHORS proper_name ("Q. Frank Xia")
41
42 #include <stdio.h>
43 #include <sys/types.h>
44 #include <stdint.h>
45 #include "system.h"
46 #include "fadvise.h"
47 #include "xfreopen.h"
48
49 #ifdef CRCTAB
50
51 # define BIT(x) ((uint_fast32_t) 1 << (x))
52 # define SBIT   BIT (31)
53
54 /* The generating polynomial is
55
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
58
59   The i bit in GEN is set if X^i is a summand of G(X) except X^32.  */
60
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))
64
65 static uint_fast32_t r[8];
66
67 static void
68 fill_r (void)
69 {
70   int i;
71
72   r[0] = GEN;
73   for (i = 1; i < 8; i++)
74     r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
75 }
76
77 static uint_fast32_t
78 crc_remainder (int m)
79 {
80   uint_fast32_t rem = 0;
81   int i;
82
83   for (i = 0; i < 8; i++)
84     if (BIT (i) & m)
85       rem ^= r[i];
86
87   return rem & 0xFFFFFFFF;      /* Make it run on 64-bit machine.  */
88 }
89
90 int
91 main (void)
92 {
93   int i;
94
95   fill_r ();
96   printf ("static uint_fast32_t const crctab[256] =\n{\n  0x00000000");
97   for (i = 0; i < 51; i++)
98     {
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));
103     }
104   printf ("\n};\n");
105   exit (EXIT_SUCCESS);
106 }
107
108 #else /* !CRCTAB */
109
110 # include <getopt.h>
111 # include "long-options.h"
112 # include "error.h"
113
114 /* Number of bytes to read at once.  */
115 # define BUFLEN (1 << 16)
116
117 static uint_fast32_t const crctab[256] =
118 {
119   0x00000000,
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
171 };
172
173 /* Nonzero if any of the files read were the standard input. */
174 static bool have_read_stdin;
175
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.  */
180
181 static bool
182 cksum (const char *file, bool print_name)
183 {
184   unsigned char buf[BUFLEN];
185   uint_fast32_t crc = 0;
186   uintmax_t length = 0;
187   size_t bytes_read;
188   FILE *fp;
189   char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
190   char const *hp;
191
192   if (STREQ (file, "-"))
193     {
194       fp = stdin;
195       have_read_stdin = true;
196       if (O_BINARY && ! isatty (STDIN_FILENO))
197         xfreopen (NULL, "rb", stdin);
198     }
199   else
200     {
201       fp = fopen (file, (O_BINARY ? "rb" : "r"));
202       if (fp == NULL)
203         {
204           error (0, errno, "%s", file);
205           return false;
206         }
207     }
208
209   fadvise (fp, FADVISE_SEQUENTIAL);
210
211   while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
212     {
213       unsigned char *cp = buf;
214
215       if (length + bytes_read < length)
216         error (EXIT_FAILURE, 0, _("%s: file too long"), file);
217       length += bytes_read;
218       while (bytes_read--)
219         crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
220       if (feof (fp))
221         break;
222     }
223
224   if (ferror (fp))
225     {
226       error (0, errno, "%s", file);
227       if (!STREQ (file, "-"))
228         fclose (fp);
229       return false;
230     }
231
232   if (!STREQ (file, "-") && fclose (fp) == EOF)
233     {
234       error (0, errno, "%s", file);
235       return false;
236     }
237
238   hp = umaxtostr (length, length_buf);
239
240   for (; length; length >>= 8)
241     crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
242
243   crc = ~crc & 0xFFFFFFFF;
244
245   if (print_name)
246     printf ("%u %s %s\n", (unsigned int) crc, hp, file);
247   else
248     printf ("%u %s\n", (unsigned int) crc, hp);
249
250   if (ferror (stdout))
251     error (EXIT_FAILURE, errno, "-: %s", _("write error"));
252
253   return true;
254 }
255
256 void
257 usage (int status)
258 {
259   if (status != EXIT_SUCCESS)
260     emit_try_help ();
261   else
262     {
263       printf (_("\
264 Usage: %s [FILE]...\n\
265   or:  %s [OPTION]\n\
266 "),
267               program_name, program_name);
268       fputs (_("\
269 Print CRC checksum and byte counts of each FILE.\n\
270 \n\
271 "), stdout);
272       fputs (HELP_OPTION_DESCRIPTION, stdout);
273       fputs (VERSION_OPTION_DESCRIPTION, stdout);
274       emit_ancillary_info ();
275     }
276   exit (status);
277 }
278
279 int
280 main (int argc, char **argv)
281 {
282   int i;
283   bool ok;
284
285   initialize_main (&argc, &argv);
286   set_program_name (argv[0]);
287   setlocale (LC_ALL, "");
288   bindtextdomain (PACKAGE, LOCALEDIR);
289   textdomain (PACKAGE);
290
291   atexit (close_stdout);
292
293   /* Line buffer stdout to ensure lines are written atomically and immediately
294      so that processes running in parallel do not intersperse their output.  */
295   setvbuf (stdout, NULL, _IOLBF, 0);
296
297   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version,
298                       usage, AUTHORS, (char const *) NULL);
299   if (getopt_long (argc, argv, "", NULL, NULL) != -1)
300     usage (EXIT_FAILURE);
301
302   have_read_stdin = false;
303
304   if (optind == argc)
305     ok = cksum ("-", false);
306   else
307     {
308       ok = true;
309       for (i = optind; i < argc; i++)
310         ok &= cksum (argv[i], true);
311     }
312
313   if (have_read_stdin && fclose (stdin) == EOF)
314     error (EXIT_FAILURE, errno, "-");
315   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
316 }
317
318 #endif /* !CRCTAB */