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