Initial revision
[platform/upstream/coreutils.git] / src / cksum.c
1 /* cksum -- calculate and print POSIX.2 checksums and sizes of files
2    Copyright (C) 1992 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 #ifdef CRCTAB
44
45 #include <stdio.h>
46
47 #define BIT(x)  ( (unsigned long)1 << (x) )
48 #define SBIT    BIT(31)
49
50 /* The generating polynomial is
51
52           32   26   23   22   16   12   11   10   8   7   5   4   2   1
53     G(X)=X  + X  + X  + X  + X  + X  + X  + X  + X + X + X + X + X + X + 1
54
55   The i bit in GEN is set if X^i is a summand of G(X) except X^32.  */
56
57 #define GEN     (BIT(26)|BIT(23)|BIT(22)|BIT(16)|BIT(12)|BIT(11)|BIT(10)\
58                 |BIT(8) |BIT(7) |BIT(5) |BIT(4) |BIT(2) |BIT(1) |BIT(0));
59
60 unsigned long r[8];
61
62 void
63 fill_r ()
64 {
65   int i;
66
67   r[0] = GEN;
68   for (i = 1; i < 8; i++)
69     r[i] = (r[i - 1] & SBIT) ? (r[i - 1] << 1) ^ r[0] : r[i - 1] << 1;
70 }
71
72 unsigned long
73 remainder (m)
74      int m;
75 {
76   unsigned long rem = 0;
77   int i;
78
79   for (i = 0; i < 8; i++)
80     if (BIT (i) & m)
81       rem = rem ^ r[i];
82
83   return rem & 0xFFFFFFFF;      /* Make it run on 64-bit machine.  */
84 }
85
86 void
87 main ()
88 {
89   int i;
90
91   fill_r ();
92   printf ("unsigned long crctab[256] = {\n  0x0");
93   for (i = 0; i < 51; i++)
94     {
95       printf (",\n  0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X",
96         remainder (i * 5 + 1), remainder (i * 5 + 2), remainder (i * 5 + 3),
97               remainder (i * 5 + 4), remainder (i * 5 + 5));
98     }
99   printf ("\n};\n");
100   exit (0);
101 }
102
103 #else /* !CRCTAB */
104
105 #include <stdio.h>
106 #include <sys/types.h>
107 #include "system.h"
108
109 /* Number of bytes to read at once.  */
110 #define BUFLEN (1 << 16)
111
112 unsigned long crctab[256] =
113 {
114   0x0,
115   0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
116   0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
117   0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
118   0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
119   0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
120   0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
121   0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
122   0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
123   0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
124   0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
125   0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
126   0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
127   0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
128   0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
129   0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
130   0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
131   0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
132   0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
133   0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
134   0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
135   0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
136   0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
137   0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
138   0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
139   0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
140   0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
141   0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
142   0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
143   0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
144   0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
145   0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
146   0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
147   0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
148   0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
149   0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
150   0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
151   0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
152   0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
153   0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
154   0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
155   0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
156   0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
157   0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
158   0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
159   0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
160   0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
161   0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
162   0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
163   0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
164   0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
165   0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
166 };
167
168 /* The name this program was run with.  */
169 char *program_name;
170
171 /* Nonzero if any of the files read were the standard input. */
172 int have_read_stdin;
173
174 /* Calculate and print the checksum and length in bytes
175    of file FILE, or of the standard input if FILE is "-".
176    If PRINT_NAME is nonzero, print FILE next to the checksum and size.
177    Return 0 if successful, -1 if an error occurs. */
178
179 int
180 cksum (file, print_name)
181      char *file;
182      int print_name;
183 {
184   unsigned char buf[BUFLEN];
185   unsigned long crc = 0;
186   long length = 0;
187   long bytes_read;
188   register FILE *fp;
189
190   if (!strcmp (file, "-"))
191     {
192       fp = stdin;
193       have_read_stdin = 1;
194     }
195   else
196     {
197       fp = fopen (file, "r");
198       if (fp == NULL)
199         {
200           error (0, errno, "%s", file);
201           return -1;
202         }
203     }
204
205   while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
206     {
207       unsigned char *cp = buf;
208
209       length += bytes_read;
210       while (bytes_read--)
211         crc = (crc << 8) ^ crctab[((crc >> 24) ^ *(cp++)) & 0xFF];
212     }
213
214   if (ferror (fp))
215     {
216       error (0, errno, "%s", file);
217       if (strcmp (file, "-"))
218         fclose (fp);
219       return -1;
220     }
221
222   if (strcmp (file, "-") && fclose (fp) == EOF)
223     {
224       error (0, errno, "%s", file);
225       return -1;
226     }
227
228   bytes_read = length;
229   while (bytes_read > 0)
230     {
231       crc = (crc << 8) ^ crctab[((crc >> 24) ^ bytes_read) & 0xFF];
232       bytes_read >>= 8;
233     }
234
235   crc = ~crc & 0xFFFFFFFF;
236
237   printf ("%10lu %8ld", crc, length);
238   if (print_name)
239     printf (" %s", file);
240   putchar ('\n');
241
242   return 0;
243 }
244
245 void
246 main (argc, argv)
247      int argc;
248      char **argv;
249 {
250   int errors = 0;
251
252   program_name = argv[0];
253   have_read_stdin = 0;
254
255   if (argc == 1)
256     {
257       if (cksum ("-", 0) < 0)
258         errors = 1;
259     }
260   else
261     {
262       int optind;
263
264       for (optind = 1; optind < argc; ++optind)
265         if (cksum (argv[optind], 1) < 0)
266           errors = 1;
267     }
268
269   if (have_read_stdin && fclose (stdin) == EOF)
270     error (1, errno, "-");
271   exit (errors);
272 }
273
274 #endif /* !CRCTAB */