(add_tabstop): Give correct size when reallocating tab_list buffer.
[platform/upstream/coreutils.git] / src / cksum.c
1 /* cksum -- calculate and print POSIX.2 checksums and sizes of files
2    Copyright (C) 1992, 1995 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 2, or (at your option)
7    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, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17 \f
18 /* Written by Q. Frank Xia, qx@math.columbia.edu.
19    Cosmetic changes and reorganization by David MacKenzie, djm@gnu.ai.mit.edu.
20
21   Usage: cksum [file...]
22
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:
27
28       cc -DCRCTAB -o crctab cksum.c
29       crctab > crctab.h
30
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.
37
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.  */
42
43 #include <config.h>
44
45 #ifdef CRCTAB
46
47 #include <stdio.h>
48
49 #define BIT(x)  ( (unsigned long)1 << (x) )
50 #define SBIT    BIT(31)
51
52 /* The generating polynomial is
53
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
56
57   The i bit in GEN is set if X^i is a summand of G(X) except X^32.  */
58
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));
61
62 static unsigned long r[8];
63
64 static void
65 fill_r ()
66 {
67   int i;
68
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;
72 }
73
74 static unsigned long
75 remainder (m)
76      int m;
77 {
78   unsigned long rem = 0;
79   int i;
80
81   for (i = 0; i < 8; i++)
82     if (BIT (i) & m)
83       rem = rem ^ r[i];
84
85   return rem & 0xFFFFFFFF;      /* Make it run on 64-bit machine.  */
86 }
87
88 void
89 main ()
90 {
91   int i;
92
93   fill_r ();
94   printf ("unsigned long crctab[256] = {\n  0x0");
95   for (i = 0; i < 51; i++)
96     {
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));
100     }
101   printf ("\n};\n");
102   exit (0);
103 }
104
105 #else /* !CRCTAB */
106
107 #include <stdio.h>
108 #include <getopt.h>
109 #include <sys/types.h>
110 #include "system.h"
111 #include "version.h"
112 #include "error.h"
113
114 /* Number of bytes to read at once.  */
115 #define BUFLEN (1 << 16)
116
117 /* The name this program was run with.  */
118 char *program_name;
119
120 /* If non-zero, display usage information and exit.  */
121 static int show_help;
122
123 /* If non-zero, print the version on standard output then exit.  */
124 static int show_version;
125
126 static struct option const long_options[] =
127 {
128   {"help", no_argument, &show_help, 1},
129   {"version", no_argument, &show_version, 1},
130   {0, 0, 0, 0}
131 };
132
133 static unsigned long const crctab[256] =
134 {
135   0x0,
136   0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
137   0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
138   0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
139   0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
140   0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
141   0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
142   0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
143   0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
144   0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
145   0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
146   0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
147   0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
148   0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
149   0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
150   0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
151   0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
152   0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
153   0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
154   0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
155   0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
156   0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
157   0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
158   0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
159   0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
160   0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
161   0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
162   0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
163   0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
164   0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
165   0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
166   0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
167   0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
168   0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
169   0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
170   0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
171   0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
172   0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
173   0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
174   0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
175   0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
176   0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
177   0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
178   0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
179   0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
180   0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
181   0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
182   0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
183   0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
184   0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
185   0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
186   0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
187 };
188
189 /* Nonzero if any of the files read were the standard input. */
190 static int have_read_stdin;
191
192 /* Calculate and print the checksum and length in bytes
193    of file FILE, or of the standard input if FILE is "-".
194    If PRINT_NAME is nonzero, print FILE next to the checksum and size.
195    Return 0 if successful, -1 if an error occurs. */
196
197 static int
198 cksum (file, print_name)
199      char *file;
200      int print_name;
201 {
202   unsigned char buf[BUFLEN];
203   unsigned long crc = 0;
204   long length = 0;
205   long bytes_read;
206   register FILE *fp;
207
208   if (!strcmp (file, "-"))
209     {
210       fp = stdin;
211       have_read_stdin = 1;
212     }
213   else
214     {
215       fp = fopen (file, "r");
216       if (fp == NULL)
217         {
218           error (0, errno, "%s", file);
219           return -1;
220         }
221     }
222
223   while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
224     {
225       unsigned char *cp = buf;
226
227       length += bytes_read;
228       while (bytes_read--)
229         crc = (crc << 8) ^ crctab[((crc >> 24) ^ *(cp++)) & 0xFF];
230     }
231
232   if (ferror (fp))
233     {
234       error (0, errno, "%s", file);
235       if (strcmp (file, "-"))
236         fclose (fp);
237       return -1;
238     }
239
240   if (strcmp (file, "-") && fclose (fp) == EOF)
241     {
242       error (0, errno, "%s", file);
243       return -1;
244     }
245
246   bytes_read = length;
247   while (bytes_read > 0)
248     {
249       crc = (crc << 8) ^ crctab[((crc >> 24) ^ bytes_read) & 0xFF];
250       bytes_read >>= 8;
251     }
252
253   crc = ~crc & 0xFFFFFFFF;
254
255   printf ("%10lu %8ld", crc, length);
256   if (print_name)
257     printf (" %s", file);
258   putchar ('\n');
259
260   return 0;
261 }
262
263 static void
264 usage (status)
265      int status;
266 {
267   if (status != 0)
268     fprintf (stderr, "Try `%s --help' for more information.\n",
269              program_name);
270   else
271     {
272       printf ("\
273 Usage: %s [OPTION]... [FILE]...\n\
274 ",
275               program_name);
276       printf ("\
277 \n\
278   --help      display this help and exit\n\
279   --version   output version information and exit\n\
280 ");
281     }
282   exit (status);
283 }
284
285 void
286 main (argc, argv)
287      int argc;
288      char **argv;
289 {
290   int i, c;
291   int errors = 0;
292
293   program_name = argv[0];
294   have_read_stdin = 0;
295
296   while ((c = getopt_long (argc, argv, "", long_options, (int *) 0)) != EOF)
297     {
298       switch (c)
299         {
300         case 0:
301           break;
302
303         default:
304           usage (1);
305         }
306     }
307
308   if (show_version)
309     {
310       printf ("cksum - %s\n", version_string);
311       exit (0);
312     }
313
314   if (show_help)
315     usage (0);
316
317   if (optind >= argc)
318     {
319       if (cksum ("-", 0) < 0)
320         errors = 1;
321     }
322   else
323     {
324       for (i = optind; i < argc; i++)
325         if (cksum (argv[i], 1) < 0)
326           errors = 1;
327     }
328
329   if (have_read_stdin && fclose (stdin) == EOF)
330     error (1, errno, "-");
331   exit (errors);
332 }
333
334 #endif /* !CRCTAB */