1 /* cksum.c - produce crc32 checksum value for each input
2  *
3  * Copyright 2008 Rob Landley <rob@landley.net>
4  *
5  * See http://opengroup.org/onlinepubs/9699919799/utilities/cksum.html
6 
7 USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
8 USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
9 
10 config CKSUM
11   bool "cksum"
12   default y
13   help
14     usage: cksum [-IPLN] [file...]
15 
16     For each file, output crc32 checksum value, length and name of file.
17     If no files listed, copy from stdin.  Filename "-" is a synonym for stdin.
18 
19     -H	Hexadecimal checksum (defaults to decimal)
20     -L	Little endian (defaults to big endian)
21     -P	Pre-inversion
22     -I	Skip post-inversion
23     -N	Do not include length in CRC calculation (or output)
24 
25 config CRC32
26   bool "crc32"
27   default y
28   help
29     usage: crc32 [file...]
30 
31     Output crc32 checksum for each file.
32 */
33 
34 #define FOR_cksum
35 #define FORCE_FLAGS
36 #include "toys.h"
37 
GLOBALS(unsigned crc_table[256];)38 GLOBALS(
39   unsigned crc_table[256];
40 )
41 
42 static unsigned cksum_be(unsigned crc, unsigned char c)
43 {
44   return (crc<<8)^TT.crc_table[(crc>>24)^c];
45 }
46 
cksum_le(unsigned crc,unsigned char c)47 static unsigned cksum_le(unsigned crc, unsigned char c)
48 {
49   return TT.crc_table[(crc^c)&0xff] ^ (crc>>8);
50 }
51 
do_cksum(int fd,char * name)52 static void do_cksum(int fd, char *name)
53 {
54   unsigned crc = (toys.optflags & FLAG_P) ? 0xffffffff : 0;
55   uint64_t llen = 0, llen2;
56   unsigned (*cksum)(unsigned crc, unsigned char c);
57   int len, i;
58 
59   cksum = (toys.optflags & FLAG_L) ? cksum_le : cksum_be;
60   // CRC the data
61 
62   for (;;) {
63     len = read(fd, toybuf, sizeof(toybuf));
64     if (len<0) perror_msg_raw(name);
65     if (len<1) break;
66 
67     llen += len;
68     for (i=0; i<len; i++) crc=cksum(crc, toybuf[i]);
69   }
70 
71   // CRC the length
72 
73   llen2 = llen;
74   if (!(toys.optflags & FLAG_N)) {
75     while (llen) {
76       crc = cksum(crc, llen);
77       llen >>= 8;
78     }
79   }
80 
81   printf((toys.optflags & FLAG_H) ? "%08x" : "%u",
82     (toys.optflags & FLAG_I) ? crc : ~crc);
83   if (!(toys.optflags&FLAG_N)) printf(" %"PRIu64, llen2);
84   if (toys.optc) printf(" %s", name);
85   xputc('\n');
86 }
87 
cksum_main(void)88 void cksum_main(void)
89 {
90   crc_init(TT.crc_table, toys.optflags & FLAG_L);
91   loopfiles(toys.optargs, do_cksum);
92 }
93 
crc32_main(void)94 void crc32_main(void)
95 {
96   toys.optflags |= FLAG_H|FLAG_N|FLAG_P|FLAG_L;
97   if (toys.optc) toys.optc--;
98   cksum_main();
99 }
100