tar: handle tarfiles with (broken) checksums a-la Sun.
[oweals/busybox.git] / archival / libunarchive / decompress_bunzip2.c
index 34afd6f99c6c77768e3e223a47a4cecc5b699bdd..ff7d64d83d8fe41476590c0fb6f90a6bc4210e9b 100644 (file)
@@ -1,13 +1,12 @@
 /* vi: set sw=4 ts=4: */
-/*     Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
+/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
 
-       Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
-       which also acknowledges contributions by Mike Burrows, David Wheeler,
-       Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
-       Robert Sedgewick, and Jon L. Bentley.
+   Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
+   which also acknowledges contributions by Mike Burrows, David Wheeler,
+   Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
+   Robert Sedgewick, and Jon L. Bentley.
 
-       This code is licensed under the LGPLv2:
-               LGPL http://www.gnu.org/copyleft/lgpl.html
+   Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
 */
 
 /*
        I would ask that anyone benefiting from this work, especially those
        using it in commercial products, consider making a donation to my local
        non-profit hospice organization (www.hospiceacadiana.com) in the name of
-       the woman I loved, Toni W. Hagan, who passed away Feb. 12, 2003.
+       the woman I loved, Toni W. Hagan, who passed away Feb. 12, 2003.
 
        Manuel
  */
 
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <limits.h>
-
 #include "libbb.h"
+#include "unarchive.h"
 
 /* Constants for Huffman coding */
-#define MAX_GROUPS                     6
-#define GROUP_SIZE                     50              /* 64 would have been more efficient */
-#define MAX_HUFCODE_BITS       20              /* Longest Huffman code allowed */
-#define MAX_SYMBOLS                    258             /* 256 literals + RUNA + RUNB */
-#define SYMBOL_RUNA                    0
-#define SYMBOL_RUNB                    1
+#define MAX_GROUPS          6
+#define GROUP_SIZE          50      /* 64 would have been more efficient */
+#define MAX_HUFCODE_BITS    20      /* Longest Huffman code allowed */
+#define MAX_SYMBOLS         258     /* 256 literals + RUNA + RUNB */
+#define SYMBOL_RUNA         0
+#define SYMBOL_RUNB         1
 
 /* Status return values */
-#define RETVAL_OK                                              0
-#define RETVAL_LAST_BLOCK                              (-1)
-#define RETVAL_NOT_BZIP_DATA                   (-2)
-#define RETVAL_UNEXPECTED_INPUT_EOF            (-3)
-#define RETVAL_UNEXPECTED_OUTPUT_EOF   (-4)
-#define RETVAL_DATA_ERROR                              (-5)
-#define RETVAL_OUT_OF_MEMORY                   (-6)
-#define RETVAL_OBSOLETE_INPUT                  (-7)
+#define RETVAL_OK                       0
+#define RETVAL_LAST_BLOCK               (-1)
+#define RETVAL_NOT_BZIP_DATA            (-2)
+#define RETVAL_UNEXPECTED_INPUT_EOF     (-3)
+#define RETVAL_UNEXPECTED_OUTPUT_EOF    (-4)
+#define RETVAL_DATA_ERROR               (-5)
+#define RETVAL_OUT_OF_MEMORY            (-6)
+#define RETVAL_OBSOLETE_INPUT           (-7)
 
 /* Other housekeeping constants */
-#define IOBUF_SIZE                     4096
+#define IOBUF_SIZE          4096
 
 /* This is what we know about each Huffman coding group */
 struct group_data {
@@ -82,8 +75,8 @@ typedef struct {
 
        /* The CRC values stored in the block header and calculated from the data */
 
-       unsigned int crc32Table[256],headerCRC, totalCRC, writeCRC;
-
+       uint32_t headerCRC, totalCRC, writeCRC;
+       uint32_t *crc32Table;
        /* Intermediate buffer and its size (in bytes) */
 
        unsigned int *dbuf, dbufSize;
@@ -158,7 +151,7 @@ static int get_next_block(bunzip_data *bd)
        /* Reset longjmp I/O error handling */
 
        i=setjmp(bd->jmpbuf);
-       if(i) return i;
+       if (i) return i;
 
        /* Read in header signature and CRC, then validate signature.
           (last block signature means CRC is for whole file, return now) */
@@ -173,8 +166,8 @@ static int get_next_block(bunzip_data *bd)
           some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
           it didn't actually work. */
 
-       if(get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT;
-       if((origPtr=get_bits(bd,24)) > dbufSize) return RETVAL_DATA_ERROR;
+       if (get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT;
+       if ((origPtr=get_bits(bd,24)) > dbufSize) return RETVAL_DATA_ERROR;
 
        /* mapping table: if some byte values are never used (encoding things
           like ascii text), the compression code removes the gaps to have fewer
@@ -187,7 +180,7 @@ static int get_next_block(bunzip_data *bd)
        for (i=0;i<16;i++) {
                if(t&(1<<(15-i))) {
                        k=get_bits(bd,16);
-                       for(j=0;j<16;j++)
+                       for (j=0;j<16;j++)
                                if(k&(1<<(15-j))) symToByte[symTotal++]=(16*i)+j;
                }
        }
@@ -203,17 +196,17 @@ static int get_next_block(bunzip_data *bd)
           start of the list.) */
 
        if(!(nSelectors=get_bits(bd, 15))) return RETVAL_DATA_ERROR;
-       for(i=0; i<groupCount; i++) mtfSymbol[i] = i;
-       for(i=0; i<nSelectors; i++) {
+       for (i=0; i<groupCount; i++) mtfSymbol[i] = i;
+       for (i=0; i<nSelectors; i++) {
 
                /* Get next value */
 
-               for(j=0;get_bits(bd,1);j++) if (j>=groupCount) return RETVAL_DATA_ERROR;
+               for (j=0;get_bits(bd,1);j++) if (j>=groupCount) return RETVAL_DATA_ERROR;
 
                /* Decode MTF to get the next selector */
 
                uc = mtfSymbol[j];
-               for(;j;j--) mtfSymbol[j] = mtfSymbol[j-1];
+               for (;j;j--) mtfSymbol[j] = mtfSymbol[j-1];
                mtfSymbol[0]=selectors[i]=uc;
        }
 
@@ -234,7 +227,7 @@ static int get_next_block(bunzip_data *bd)
 
                t=get_bits(bd, 5)-1;
                for (i = 0; i < symCount; i++) {
-                       for(;;) {
+                       for (;;) {
                                if (((unsigned)t) > (MAX_HUFCODE_BITS-1))
                                        return RETVAL_DATA_ERROR;
 
@@ -261,7 +254,7 @@ static int get_next_block(bunzip_data *bd)
                /* Find largest and smallest lengths in this group */
 
                minLen=maxLen=length[0];
-               for(i = 1; i < symCount; i++) {
+               for (i = 1; i < symCount; i++) {
                        if(length[i] > maxLen) maxLen = length[i];
                        else if(length[i] < minLen) minLen = length[i];
                }
@@ -291,9 +284,9 @@ static int get_next_block(bunzip_data *bd)
                /* Calculate permute[].  Concurently, initialize temp[] and limit[]. */
 
                pp=0;
-               for(i=minLen;i<=maxLen;i++) {
+               for (i=minLen;i<=maxLen;i++) {
                        temp[i]=limit[i]=0;
-                       for(t=0;t<symCount;t++)
+                       for (t=0;t<symCount;t++)
                                if(length[t]==i) hufGroup->permute[pp++] = t;
                }
 
@@ -332,7 +325,7 @@ static int get_next_block(bunzip_data *bd)
 
        /* Initialize symbol occurrence counters and symbol Move To Front table */
 
-       for(i=0;i<256;i++) {
+       for (i=0;i<256;i++) {
                byteCount[i] = 0;
                mtfSymbol[i]=(unsigned char)i;
        }
@@ -340,7 +333,7 @@ static int get_next_block(bunzip_data *bd)
        /* Loop through compressed symbols. */
 
        runPos=dbufCount=selector=0;
-       for(;;) {
+       for (;;) {
 
                /* fetch next Huffman coding group from list. */
 
@@ -379,7 +372,7 @@ got_huff_bits:
                /* Figure how how many bits are in next symbol and unget extras */
 
                i=hufGroup->minLen;
-               while(j>limit[i]) ++i;
+               while (j>limit[i]) ++i;
                bd->inbufBitCount += (hufGroup->maxLen - i);
 
                /* Huffman decode value to get nextSym (with bounds checking) */
@@ -413,7 +406,7 @@ got_huff_bits:
                           context).  Thus space is saved. */
 
                        t += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */
-                       runPos <<= 1;
+                       if(runPos < dbufSize) runPos <<= 1;
                        goto end_of_huffman_loop;
                }
 
@@ -428,7 +421,7 @@ got_huff_bits:
 
                        uc = symToByte[mtfSymbol[0]];
                        byteCount[uc] += t;
-                       while(t--) dbuf[dbufCount++]=uc;
+                       while (t--) dbuf[dbufCount++]=uc;
                }
 
                /* Is this the terminating symbol? */
@@ -480,7 +473,7 @@ end_of_huffman_loop:
        /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
 
        j=0;
-       for(i=0;i<256;i++) {
+       for (i=0;i<256;i++) {
                k=j+byteCount[i];
                byteCount[i] = j;
                j=k;
@@ -542,7 +535,7 @@ static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
 
                /* Loop outputting bytes */
 
-               for(;;) {
+               for (;;) {
 
                        /* If the output buffer is full, snapshot state and return */
 
@@ -618,7 +611,7 @@ decode_next_byte:
                bd->writeCount=previous;
                return (previous!=RETVAL_LAST_BLOCK) ? previous : gotcount;
        }
-       bd->writeCRC=0xffffffffUL;
+       bd->writeCRC=~0;
        pos=bd->writePos;
        current=bd->writeCurrent;
        goto decode_next_byte;
@@ -632,7 +625,7 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
                                                int len)
 {
        bunzip_data *bd;
-       unsigned int i,j,c;
+       unsigned int i;
        const unsigned int BZh0=(((unsigned int)'B')<<24)+(((unsigned int)'Z')<<16)
                                                        +(((unsigned int)'h')<<8)+(unsigned int)'0';
 
@@ -643,8 +636,7 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
 
        /* Allocate bunzip_data.  Most fields initialize to zero. */
 
-       bd=*bdp=xmalloc(i);
-       memset(bd,0,sizeof(bunzip_data));
+       bd=*bdp=xzalloc(i);
 
        /* Setup input buffer */
 
@@ -655,12 +647,7 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
 
        /* Init the CRC32 table (big endian) */
 
-       for(i=0;i<256;i++) {
-               c=i<<24;
-               for(j=8;j;j--)
-                       c=c&0x80000000 ? (c<<1)^0x04c11db7 : (c<<1);
-               bd->crc32Table[i]=c;
-       }
+       bd->crc32Table = crc32_filltable(1);
 
        /* Setup for I/O error handling via longjmp */
 
@@ -684,20 +671,24 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
 /* Example usage: decompress src_fd to dst_fd.  (Stops at end of bzip data,
    not end of file.) */
 
-extern int uncompressStream(int src_fd, int dst_fd)
+USE_DESKTOP(long long) int
+uncompressStream(int src_fd, int dst_fd)
 {
+       USE_DESKTOP(long long total_written = 0;)
        char *outbuf;
        bunzip_data *bd;
        int i;
 
        outbuf=xmalloc(IOBUF_SIZE);
-       if(!(i=start_bunzip(&bd,src_fd,0,0))) {
-               for(;;) {
+       i=start_bunzip(&bd,src_fd,0,0);
+       if(!i) {
+               for (;;) {
                        if((i=read_bunzip(bd,outbuf,IOBUF_SIZE)) <= 0) break;
                        if(i!=write(dst_fd,outbuf,i)) {
                                i=RETVAL_UNEXPECTED_OUTPUT_EOF;
                                break;
                        }
+                       USE_DESKTOP(total_written += i;)
                }
        }
 
@@ -705,27 +696,27 @@ extern int uncompressStream(int src_fd, int dst_fd)
 
        if(i==RETVAL_LAST_BLOCK) {
                if (bd->headerCRC!=bd->totalCRC) {
-                       bb_error_msg("Data integrity error when decompressing.");
+                       bb_error_msg("data integrity error when decompressing");
                } else {
                        i=RETVAL_OK;
                }
        } else if (i==RETVAL_UNEXPECTED_OUTPUT_EOF) {
-               bb_error_msg("Compressed file ends unexpectedly");
+               bb_error_msg("compressed file ends unexpectedly");
        } else {
-               bb_error_msg("Decompression failed");
+               bb_error_msg("decompression failed");
        }
-       if(bd->dbuf) free(bd->dbuf);
+       free(bd->dbuf);
        free(bd);
        free(outbuf);
 
-       return i;
+       return i ? i : USE_DESKTOP(total_written) + 0;
 }
 
 #ifdef TESTING
 
 static char * const bunzip_errors[]={NULL,"Bad file checksum","Not bzip data",
                "Unexpected input EOF","Unexpected output EOF","Data error",
-                "Out of memory","Obsolete (pre 0.9.5) bzip format not supported."};
+               "Out of memory","Obsolete (pre 0.9.5) bzip format not supported."};
 
 /* Dumb little test thing, decompress stdin to stdout */
 int main(int argc, char *argv[])
@@ -733,8 +724,8 @@ int main(int argc, char *argv[])
        int i=uncompressStream(0,1);
        char c;
 
-       if(i) fprintf(stderr,"%s\n", bunzip_errors[-i]);
-    else if(read(0,&c,1)) fprintf(stderr,"Trailing garbage ignored\n");
+       if(i<0) fprintf(stderr,"%s\n", bunzip_errors[-i]);
+       else if(read(0,&c,1)) fprintf(stderr,"Trailing garbage ignored\n");
        return -i;
 }
 #endif