Tizen 2.0 Release
[external/tizen-coreutils.git] / src / cksum.c
1 /* cksum -- calculate and print POSIX checksums and sizes of files
2    Copyright (C) 92, 1995-2006 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 Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 something like the following:
27
28       cc -DCRCTAB -o crctab cksum.c
29       crctab > crctab.h
30
31   This software is compatible with neither the System V nor the BSD
32   `sum' program.  It is supposed to conform to POSIX, except perhaps
33   for foreign language support.  Any inconsistency with the standard
34   (other than foreign language support) is a bug.  */
35
36 #include <config.h>
37
38 /* The official name of this program (e.g., no `g' prefix).  */
39 #define PROGRAM_NAME "cksum"
40
41 #define AUTHORS "Q. Frank Xia"
42
43 #include <stdio.h>
44 #include <sys/types.h>
45 #include <stdint.h>
46 #include "system.h"
47
48 #ifdef CRCTAB
49
50 # define BIT(x) ((uint_fast32_t) 1 << (x))
51 # define SBIT   BIT (31)
52
53 /* The generating polynomial is
54
55           32   26   23   22   16   12   11   10   8   7   5   4   2   1
56     G(X)=X  + X  + X  + X  + X  + X  + X  + X  + X + X + X + X + X + X + 1
57
58   The i bit in GEN is set if X^i is a summand of G(X) except X^32.  */
59
60 # define GEN    (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \
61                  | BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \
62                  | BIT (4) | BIT (2) | BIT (1) | BIT (0))
63
64 static uint_fast32_t r[8];
65
66 static void
67 fill_r (void)
68 {
69   int i;
70
71   r[0] = GEN;
72   for (i = 1; i < 8; i++)
73     r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
74 }
75
76 static uint_fast32_t
77 crc_remainder (int m)
78 {
79   uint_fast32_t rem = 0;
80   int i;
81
82   for (i = 0; i < 8; i++)
83     if (BIT (i) & m)
84       rem ^= r[i];
85
86   return rem & 0xFFFFFFFF;      /* Make it run on 64-bit machine.  */
87 }
88
89 int
90 main (void)
91 {
92   int i;
93
94   fill_r ();
95   printf ("static uint_fast32_t const crctab[256] =\n{\n  0x00000000");
96   for (i = 0; i < 51; i++)
97     {
98       printf (",\n  0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x",
99               crc_remainder (i * 5 + 1), crc_remainder (i * 5 + 2),
100               crc_remainder (i * 5 + 3), crc_remainder (i * 5 + 4),
101               crc_remainder (i * 5 + 5));
102     }
103   printf ("\n};\n");
104   exit (EXIT_SUCCESS);
105 }
106
107 #else /* !CRCTAB */
108
109 # include <getopt.h>
110 # include "long-options.h"
111 # include "error.h"
112 # include "inttostr.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 static uint_fast32_t const crctab[256] =
121 {
122   0x00000000,
123   0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
124   0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
125   0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
126   0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
127   0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
128   0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
129   0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
130   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
131   0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
132   0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
133   0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
134   0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
135   0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
136   0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
137   0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
138   0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
139   0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
140   0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
141   0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
142   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
143   0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
144   0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
145   0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
146   0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
147   0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
148   0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
149   0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
150   0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
151   0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
152   0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
153   0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
154   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
155   0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
156   0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
157   0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
158   0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
159   0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
160   0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
161   0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
162   0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
163   0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
164   0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
165   0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
166   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
167   0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
168   0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
169   0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
170   0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
171   0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
172   0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
173   0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
174 };
175
176 /* Nonzero if any of the files read were the standard input. */
177 static bool have_read_stdin;
178
179 /* Calculate and print the checksum and length in bytes
180    of file FILE, or of the standard input if FILE is "-".
181    If PRINT_NAME is true, print FILE next to the checksum and size.
182    Return true if successful.  */
183
184 static bool
185 cksum (const char *file, bool print_name)
186 {
187   unsigned char buf[BUFLEN];
188   uint_fast32_t crc = 0;
189   uintmax_t length = 0;
190   size_t bytes_read;
191   FILE *fp;
192   char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
193   char const *hp;
194
195   if (STREQ (file, "-"))
196     {
197       fp = stdin;
198       have_read_stdin = true;
199       if (O_BINARY && ! isatty (STDIN_FILENO))
200         freopen (NULL, "rb", stdin);
201     }
202   else
203     {
204       fp = fopen (file, (O_BINARY ? "rb" : "r"));
205       if (fp == NULL)
206         {
207           error (0, errno, "%s", file);
208           return false;
209         }
210     }
211
212   while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
213     {
214       unsigned char *cp = buf;
215
216       if (length + bytes_read < length)
217         error (EXIT_FAILURE, 0, _("%s: file too long"), file);
218       length += bytes_read;
219       while (bytes_read--)
220         crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
221       if (feof (fp))
222         break;
223     }
224
225   if (ferror (fp))
226     {
227       error (0, errno, "%s", file);
228       if (!STREQ (file, "-"))
229         fclose (fp);
230       return false;
231     }
232
233   if (!STREQ (file, "-") && fclose (fp) == EOF)
234     {
235       error (0, errno, "%s", file);
236       return false;
237     }
238
239   hp = umaxtostr (length, length_buf);
240
241   for (; length; length >>= 8)
242     crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
243
244   crc = ~crc & 0xFFFFFFFF;
245
246   if (print_name)
247     printf ("%u %s %s\n", (unsigned int) crc, hp, file);
248   else
249     printf ("%u %s\n", (unsigned int) crc, hp);
250
251   if (ferror (stdout))
252     error (EXIT_FAILURE, errno, "-: %s", _("write error"));
253
254   return true;
255 }
256
257 void
258 usage (int status)
259 {
260   if (status != EXIT_SUCCESS)
261     fprintf (stderr, _("Try `%s --help' for more information.\n"),
262              program_name);
263   else
264     {
265       printf (_("\
266 Usage: %s [FILE]...\n\
267   or:  %s [OPTION]\n\
268 "),
269               program_name, program_name);
270       fputs (_("\
271 Print CRC checksum and byte counts of each FILE.\n\
272 \n\
273 "), stdout);
274       fputs (HELP_OPTION_DESCRIPTION, stdout);
275       fputs (VERSION_OPTION_DESCRIPTION, stdout);
276       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
277     }
278   exit (status);
279 }
280
281 int
282 main (int argc, char **argv)
283 {
284   int i;
285   bool ok;
286
287   initialize_main (&argc, &argv);
288   program_name = argv[0];
289   setlocale (LC_ALL, "");
290   bindtextdomain (PACKAGE, LOCALEDIR);
291   textdomain (PACKAGE);
292
293   atexit (close_stdout);
294
295   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, VERSION,
296                       usage, AUTHORS, (char const *) NULL);
297   if (getopt_long (argc, argv, "", NULL, NULL) != -1)
298     usage (EXIT_FAILURE);
299
300   have_read_stdin = false;
301
302   if (optind == argc)
303     ok = cksum ("-", false);
304   else
305     {
306       ok = true;
307       for (i = optind; i < argc; i++)
308         ok &= cksum (argv[i], true);
309     }
310
311   if (have_read_stdin && fclose (stdin) == EOF)
312     error (EXIT_FAILURE, errno, "-");
313   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
314 }
315
316 #endif /* !CRCTAB */