~ubuntu-branches/ubuntu/lucid/coreutils/lucid-updates

« back to all changes in this revision

Viewing changes to src/cksum.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Stone
  • Date: 2009-04-07 19:21:42 UTC
  • mfrom: (1.2.1 upstream) (5.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090407192142-eez7bafqc4oqxox5
* new upstream version (Closes: #517558)
* [78] fix kfreebsd build problem (Closes: #520368)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* cksum -- calculate and print POSIX checksums and sizes of files
 
2
   Copyright (C) 92, 1995-2006, 2008 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
 
 
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 "xfreopen.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
 
 
113
/* Number of bytes to read at once.  */
 
114
# define BUFLEN (1 << 16)
 
115
 
 
116
static uint_fast32_t const crctab[256] =
 
117
{
 
118
  0x00000000,
 
119
  0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
 
120
  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
 
121
  0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
 
122
  0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
 
123
  0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
 
124
  0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
 
125
  0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
 
126
  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
 
127
  0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
 
128
  0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
 
129
  0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
 
130
  0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
 
131
  0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
 
132
  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
 
133
  0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
 
134
  0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
 
135
  0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
 
136
  0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
 
137
  0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
 
138
  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
 
139
  0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
 
140
  0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
 
141
  0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
 
142
  0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
 
143
  0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
 
144
  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
 
145
  0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
 
146
  0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
 
147
  0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
 
148
  0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
 
149
  0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
 
150
  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
 
151
  0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
 
152
  0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
 
153
  0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
 
154
  0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
 
155
  0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
 
156
  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
 
157
  0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
 
158
  0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
 
159
  0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
 
160
  0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
 
161
  0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
 
162
  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
 
163
  0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
 
164
  0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
 
165
  0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
 
166
  0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
 
167
  0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
 
168
  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
 
169
  0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
 
170
};
 
171
 
 
172
/* Nonzero if any of the files read were the standard input. */
 
173
static bool have_read_stdin;
 
174
 
 
175
/* Calculate and print the checksum and length in bytes
 
176
   of file FILE, or of the standard input if FILE is "-".
 
177
   If PRINT_NAME is true, print FILE next to the checksum and size.
 
178
   Return true if successful.  */
 
179
 
 
180
static bool
 
181
cksum (const char *file, bool print_name)
 
182
{
 
183
  unsigned char buf[BUFLEN];
 
184
  uint_fast32_t crc = 0;
 
185
  uintmax_t length = 0;
 
186
  size_t bytes_read;
 
187
  FILE *fp;
 
188
  char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
 
189
  char const *hp;
 
190
 
 
191
  if (STREQ (file, "-"))
 
192
    {
 
193
      fp = stdin;
 
194
      have_read_stdin = true;
 
195
      if (O_BINARY && ! isatty (STDIN_FILENO))
 
196
        xfreopen (NULL, "rb", stdin);
 
197
    }
 
198
  else
 
199
    {
 
200
      fp = fopen (file, (O_BINARY ? "rb" : "r"));
 
201
      if (fp == NULL)
 
202
        {
 
203
          error (0, errno, "%s", file);
 
204
          return false;
 
205
        }
 
206
    }
 
207
 
 
208
  while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
 
209
    {
 
210
      unsigned char *cp = buf;
 
211
 
 
212
      if (length + bytes_read < length)
 
213
        error (EXIT_FAILURE, 0, _("%s: file too long"), file);
 
214
      length += bytes_read;
 
215
      while (bytes_read--)
 
216
        crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
 
217
      if (feof (fp))
 
218
        break;
 
219
    }
 
220
 
 
221
  if (ferror (fp))
 
222
    {
 
223
      error (0, errno, "%s", file);
 
224
      if (!STREQ (file, "-"))
 
225
        fclose (fp);
 
226
      return false;
 
227
    }
 
228
 
 
229
  if (!STREQ (file, "-") && fclose (fp) == EOF)
 
230
    {
 
231
      error (0, errno, "%s", file);
 
232
      return false;
 
233
    }
 
234
 
 
235
  hp = umaxtostr (length, length_buf);
 
236
 
 
237
  for (; length; length >>= 8)
 
238
    crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
 
239
 
 
240
  crc = ~crc & 0xFFFFFFFF;
 
241
 
 
242
  if (print_name)
 
243
    printf ("%u %s %s\n", (unsigned int) crc, hp, file);
 
244
  else
 
245
    printf ("%u %s\n", (unsigned int) crc, hp);
 
246
 
 
247
  if (ferror (stdout))
 
248
    error (EXIT_FAILURE, errno, "-: %s", _("write error"));
 
249
 
 
250
  return true;
 
251
}
 
252
 
 
253
void
 
254
usage (int status)
 
255
{
 
256
  if (status != EXIT_SUCCESS)
 
257
    fprintf (stderr, _("Try `%s --help' for more information.\n"),
 
258
             program_name);
 
259
  else
 
260
    {
 
261
      printf (_("\
 
262
Usage: %s [FILE]...\n\
 
263
  or:  %s [OPTION]\n\
 
264
"),
 
265
              program_name, program_name);
 
266
      fputs (_("\
 
267
Print CRC checksum and byte counts of each FILE.\n\
 
268
\n\
 
269
"), stdout);
 
270
      fputs (HELP_OPTION_DESCRIPTION, stdout);
 
271
      fputs (VERSION_OPTION_DESCRIPTION, stdout);
 
272
      emit_bug_reporting_address ();
 
273
    }
 
274
  exit (status);
 
275
}
 
276
 
 
277
int
 
278
main (int argc, char **argv)
 
279
{
 
280
  int i;
 
281
  bool ok;
 
282
 
 
283
  initialize_main (&argc, &argv);
 
284
  set_program_name (argv[0]);
 
285
  setlocale (LC_ALL, "");
 
286
  bindtextdomain (PACKAGE, LOCALEDIR);
 
287
  textdomain (PACKAGE);
 
288
 
 
289
  atexit (close_stdout);
 
290
 
 
291
  parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version,
 
292
                      usage, AUTHORS, (char const *) NULL);
 
293
  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
 
294
    usage (EXIT_FAILURE);
 
295
 
 
296
  have_read_stdin = false;
 
297
 
 
298
  if (optind == argc)
 
299
    ok = cksum ("-", false);
 
300
  else
 
301
    {
 
302
      ok = true;
 
303
      for (i = optind; i < argc; i++)
 
304
        ok &= cksum (argv[i], true);
 
305
    }
 
306
 
 
307
  if (have_read_stdin && fclose (stdin) == EOF)
 
308
    error (EXIT_FAILURE, errno, "-");
 
309
  exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 
310
}
 
311
 
 
312
#endif /* !CRCTAB */