17aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley/* cksum.c - produce crc32 checksum value for each input
2433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley *
3433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley * Copyright 2008 Rob Landley <rob@landley.net>
4433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley *
5f91b7c89bc852868692b9518185421ebb52d67b3Rob Landley * See http://opengroup.org/onlinepubs/9699919799/utilities/cksum.html
6433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley
72992a66e2c7f1c5225f49c68274a8a323e445a80Rob LandleyUSE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
8433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley
9433c030b1e1921e0253f6b9896a827aac5728cdcRob Landleyconfig CKSUM
107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  bool "cksum"
117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  default y
127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  help
137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    usage: cksum [-IPLN] [file...]
147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
157aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    For each file, output crc32 checksum value, length and name of file.
167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    If no files listed, copy from stdin.  Filename "-" is a synonym for stdin.
177aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
182992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley    -H	Hexadecimal checksum (defaults to decimal)
197aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    -L	Little endian (defaults to big endian)
207aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    -P	Pre-inversion
217aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    -I	Skip post-inversion
227aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    -N	Do not include length in CRC calculation
23433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley*/
24433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley
25c0e56edaf256adb6c60c5a052525a1ffbb927901Rob Landley#define FOR_cksum
26433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley#include "toys.h"
27433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley
28c0e56edaf256adb6c60c5a052525a1ffbb927901Rob LandleyGLOBALS(
297aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  unsigned crc_table[256];
30433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley)
31433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley
32b15b8fa99ae53396145ea540106b74d37797f774Rob Landleystatic unsigned cksum_be(unsigned crc, unsigned char c)
33433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley{
347aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  return (crc<<8)^TT.crc_table[(crc>>24)^c];
35433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley}
36433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley
37b15b8fa99ae53396145ea540106b74d37797f774Rob Landleystatic unsigned cksum_le(unsigned crc, unsigned char c)
38b15b8fa99ae53396145ea540106b74d37797f774Rob Landley{
397aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  return TT.crc_table[(crc^c)&0xff] ^ (crc>>8);
40b15b8fa99ae53396145ea540106b74d37797f774Rob Landley}
41b15b8fa99ae53396145ea540106b74d37797f774Rob Landley
42433c030b1e1921e0253f6b9896a827aac5728cdcRob Landleystatic void do_cksum(int fd, char *name)
43433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley{
442992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley  unsigned crc = (toys.optflags & FLAG_P) ? 0xffffffff : 0;
457aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  uint64_t llen = 0, llen2;
467aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  unsigned (*cksum)(unsigned crc, unsigned char c);
477aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
482992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley  cksum = (toys.optflags & FLAG_L) ? cksum_le : cksum_be;
497aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  // CRC the data
507aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
517aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  for (;;) {
527aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    int len, i;
537aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
547aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    len = read(fd, toybuf, sizeof(toybuf));
55662a267c9b52f256b027d0f176a846b1d973ab99Rob Landley    if (len<0) perror_msg("%s", name);
567aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    if (len<1) break;
577aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
587aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    llen += len;
597aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    for (i=0; i<len; i++) crc=cksum(crc, toybuf[i]);
607aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  }
617aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
627aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  // CRC the length
637aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
647aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  llen2 = llen;
652992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley  if (!(toys.optflags & FLAG_N)) {
667aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    while (llen) {
677aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley      crc = cksum(crc, llen);
687aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley      llen >>= 8;
697aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    }
707aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  }
717aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
722992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley  printf((toys.optflags & FLAG_H) ? "%x" : "%u",
732992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley    (toys.optflags & FLAG_I) ? crc : ~crc);
742992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley  printf(" %"PRIu64, llen2);
757aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  if (strcmp("-", name)) printf(" %s", name);
767aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  xputc('\n');
77433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley}
78433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley
79433c030b1e1921e0253f6b9896a827aac5728cdcRob Landleyvoid cksum_main(void)
80433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley{
812992a66e2c7f1c5225f49c68274a8a323e445a80Rob Landley  crc_init(TT.crc_table, toys.optflags & FLAG_L);
827aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  loopfiles(toys.optargs, do_cksum);
83433c030b1e1921e0253f6b9896a827aac5728cdcRob Landley}
84