changeset 1206:1b36fd8dd5cf

Add crc code: zcat now works.
author Rob Landley <rob@landley.net>
date Sat, 22 Feb 2014 08:01:11 -0600
parents bd745ae2b115
children 22739b6d5a0e
files toys/pending/compress.c
diffstat 1 files changed, 32 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/toys/pending/compress.c	Fri Feb 21 22:24:02 2014 -0600
+++ b/toys/pending/compress.c	Sat Feb 22 08:01:11 2014 -0600
@@ -49,8 +49,8 @@
   unsigned short lenbase[29], distbase[30];
   void *fixdisthuff, *fixlithuff;
 
-  unsigned (*crcfunc)(char *data, int len);
-  unsigned crc;
+  void (*crcfunc)(char *data, int len);
+  unsigned crc, len;
 
   char *outbuf;
   unsigned outlen;
@@ -102,7 +102,7 @@
 }
 
 // Fetch the next X bits from the bitbuf, little endian
-int bitbuf_get(struct bitbuf *bb, int bits)
+unsigned bitbuf_get(struct bitbuf *bb, int bits)
 {
   int result = 0, offset = 0;
 
@@ -131,7 +131,7 @@
 
   if (!(TT.outlen & 32767)) {
     xwrite(TT.outfd, TT.outbuf, 32768);
-    TT.crcfunc(0, 32768);
+    if (TT.crcfunc) TT.crcfunc(0, 32768);
   }
 }
 
@@ -262,8 +262,8 @@
         }
         if (i > litlen+distlen) error_exit("bad tree");
 
-        len2huff(lithuff = ((struct huff *)toybuf)+2, bits, litlen);
-        len2huff(disthuff = ((struct huff *)toybuf)+3, bits+litlen, distlen);
+        len2huff(lithuff = h2, bits, litlen);
+        len2huff(disthuff = ((struct huff *)toybuf)+2, bits+litlen, distlen);
 
       // Static huffman codes
       } else {
@@ -298,7 +298,11 @@
     // Was that the last block?
     if (final) break;
   }
-  if (TT.outlen & 32767) xwrite(TT.outfd, TT.outbuf, TT.outlen & 32767);
+
+  if (TT.outlen & 32767) {
+    xwrite(TT.outfd, TT.outbuf, TT.outlen & 32767);
+    if (TT.crcfunc) TT.crcfunc(0, TT.outlen & 32767);
+  }
 }
 
 static void init_deflate(void)
@@ -331,9 +335,9 @@
 
   // Init fixed huffman tables
   for (i=0; i<288; i++) toybuf[i] = 8 + (i>143) - ((i>255)<<1) + (i>279);
-  len2huff(TT.fixlithuff = ((struct huff *)toybuf)+4, toybuf, 288);
+  len2huff(TT.fixlithuff = ((struct huff *)toybuf)+3, toybuf, 288);
   memset(toybuf, 5, 30);
-  len2huff(TT.fixdisthuff = ((struct huff *)toybuf)+5, toybuf, 30);
+  len2huff(TT.fixdisthuff = ((struct huff *)toybuf)+4, toybuf, 30);
 }
 
 // Return true/false whether we consumed a gzip header.
@@ -355,16 +359,35 @@
   return 1;
 }
 
+void gzip_crc(char *data, int len)
+{
+  int i;
+  unsigned crc, *crc_table = (unsigned *)(toybuf+sizeof(toybuf)-1024);
+
+  crc = TT.crc;
+  for (i=0; i<len; i++) crc = crc_table[(crc^TT.outbuf[i])&0xff] ^ (crc>>8);
+  TT.crc = crc;
+  TT.len += len;
+}
+
 static void do_zcat(int fd, char *name)
 {
   struct bitbuf *bb = bitbuf_init(fd, sizeof(toybuf));
 
   if (!is_gzip(bb)) error_exit("not gzip");
   TT.outfd = 1;
+
+  // Use last 1k of toybuf for little endian crc table
+  crc_init((unsigned *)(toybuf+sizeof(toybuf)-1024), 1);
+  TT.crcfunc = gzip_crc;
+
   inflate(bb);
 
   // tail: crc32, len32
 
+  bitbuf_skip(bb, (8-bb->bitpos)&7);
+  if (~TT.crc != bitbuf_get(bb, 32) || TT.len != bitbuf_get(bb, 32))
+    error_exit("bad crc");
   free(bb);
 }