-#include <stdlib.h>
-#include <time.h>
-#include <dirent.h>
-#include "busybox.h"
-#define BB_DECLARE_EXTERN
-#define bb_need_memory_exhausted
-#define bb_need_name_too_long
-#include "messages.c"
-
-static const int RECORD_IO = 0;
-
-/* Return codes from gzip */
-static const int OK = 0;
-static const int ERROR = 1;
-static const int WARNING = 2;
-
-static const int DEFLATED = 8;
-static const int INBUFSIZ = 0x2000; /* input buffer size */
-static const int INBUF_EXTRA = 64; /* required by unlzw() */
-static const int OUTBUFSIZ = 8192; /* output buffer size */
-static const int OUTBUF_EXTRA = 2048; /* required by unlzw() */
-static const int DIST_BUFSIZE = 0x2000; /* buffer for distances, see trees.c */
-
-#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
-
-/* gzip flag byte */
-static const int EXTRA_FIELD = 0x04; /* bit 2 set: extra field present */
-static const int ORIG_NAME = 0x08; /* bit 3 set: original file name present */
-static const int COMMENT = 0x10; /* bit 4 set: file comment present */
-static const int WSIZE = 0x8000; /* window size--must be a power of two, and */
- /* at least 32K for zip's deflate method */
-
-/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
-static const int BMAX = 16; /* maximum bit length of any code (16 for explode) */
-static const int N_MAX = 288; /* maximum number of codes in any set */
-
-/* PKZIP header definitions */
-static const int LOCSIG = 0x04034b50L; /* four-byte lead-in (lsb first) */
-static const int LOCCRC = 14; /* offset of crc */
-static const int LOCLEN = 22; /* offset of uncompressed length */
-static const int EXTHDR = 16; /* size of extended local header, inc sig */
-
-static const int BITS = 16;
-
-/* Diagnostic functions */
-#ifdef DEBUG
-# define Assert(cond,msg) {if(!(cond)) error_msg(msg);}
-# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-# define Assert(cond,msg)
-# define Trace(x)
-# define Tracev(x)
-# define Tracevv(x)
-# define Tracec(c,x)
-# define Tracecv(c,x)
-#endif
-
-#ifndef MAX_PATH_LEN /* max pathname length */
-# ifdef BUFSIZ
-# define MAX_PATH_LEN BUFSIZ
-# else
-static const int MAX_PATH_LEN = 1024;
-# endif
-#endif
-
-#define NEXTBYTE() (uch)get_byte()
-#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
-#define DUMPBITS(n) {b>>=(n);k-=(n);}
-
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
-
-/* Macros for getting two-byte and four-byte header values */
-#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
-#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
-
- /* in gzip.c */
-void abort_gzip (void);
-typedef void (*sig_type) (int);
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-typedef int file_t; /* Do not use stdio */
-
-static uch *inbuf;
-static uch *outbuf;
-static ush *d_buf;
-static uch *window;
-static ush *tab_prefix0;
-static ush *tab_prefix1;
-
-/* local variables */
-static int test_mode = 0; /* check file integrity option */
-static int foreground; /* set if program run in foreground */
-static int method; /* compression method */
-static int exit_code; /* program exit code */
-static int last_member; /* set for .zip and .Z files */
-static int part_nb; /* number of parts in .gz file */
-static long ifile_size; /* input file size, -1 for devices (debug only) */
-static long bytes_in; /* number of input bytes */
-static long bytes_out; /* number of output bytes */
-static int ifd; /* input file descriptor */
-static int ofd; /* output file descriptor */
-static unsigned insize; /* valid bytes in inbuf */
-static unsigned inptr; /* index of next byte to be processed in inbuf */
-static unsigned outcnt; /* bytes in output buffer */
-
-unsigned hufts; /* track memory usage */
-ulg bb; /* bit buffer */
-unsigned bk; /* bits in bit buffer */
-int crc_table_empty = 1;
-
-struct huft {
- uch e; /* number of extra bits or operation */
- uch b; /* number of bits in this code or subcode */
- union {
- ush n; /* literal, length base, or distance base */
- struct huft *t; /* pointer to next level of table */
- } v;
-};
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-static unsigned border[] = { /* Order of the bit length code lengths */
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-};
-static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
-};
-
-/* note: see note #13 above about the 258 in this list. */
-static ush cplext[] = { /* Extra bits for literal codes 257..285 */
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
-}; /* 99==invalid */
-
-static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577
-};
-
-static ush cpdext[] = { /* Extra bits for distance codes */
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13
-};
-
-ush mask_bits[] = {
- 0x0000,
- 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-/* ========================================================================
- * Error handlers.
- */
-void read_error_msg()
-{
- fprintf(stderr, "\n");
- if (errno != 0) {
- perror("");
- } else {
- fprintf(stderr, "unexpected end of file\n");
- }
- abort_gzip();
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty.
- */
-int fill_inbuf(eof_ok)
-int eof_ok; /* set if EOF acceptable as a result */
-{
- int len;
-
- /* Read as much as possible */
- insize = 0;
- errno = 0;
- do {
- len = read(ifd, (char *) inbuf + insize, INBUFSIZ - insize);
- if (len == 0 || len == EOF)
- break;
- insize += len;
- } while (insize < INBUFSIZ);
-
- if (insize == 0) {
- if (eof_ok)
- return EOF;
- read_error_msg();
- }
- bytes_in += (ulg) insize;
- inptr = 1;
- return inbuf[0];
-}
-
-
-/* ========================================================================
- * Check the magic number of the input file and update ofname if an
- * original name was given and tostdout is not set.
- * Return the compression method, -1 for error, -2 for warning.
- * Set inptr to the offset of the next byte to be processed.
- * Updates time_stamp if there is one and --no-time is not used.
- * This function may be called repeatedly for an input file consisting
- * of several contiguous gzip'ed members.
- * IN assertions: there is at least one remaining compressed member.
- * If the member is a zip file, it must be the only one.
- */
-static int get_method(in)
-int in; /* input file descriptor */
-{
- uch flags; /* compression flags */
- char magic[2]; /* magic header */
- long header_bytes = 0; /* number of bytes in gzip header */
-
- magic[0] = (char) get_byte();
- magic[1] = (char) get_byte();
- method = -1; /* unknown yet */
- part_nb++; /* number of parts in gzip file */
- last_member = RECORD_IO;
- /* assume multiple members in gzip file except for record oriented I/O */
-
- if (memcmp(magic, GZIP_MAGIC, 2) == 0) {
-
- method = (int) get_byte();
- if (method != DEFLATED) {
- error_msg("unknown method %d -- get newer version of gzip", method);
- exit_code = ERROR;
- return -1;
- }
- flags = (uch) get_byte();
-
- (ulg) get_byte(); /* Ignore time stamp */
- (ulg) get_byte();
- (ulg) get_byte();
- (ulg) get_byte();
-
- (void) get_byte(); /* Ignore extra flags for the moment */
- (void) get_byte(); /* Ignore OS type for the moment */
-
- if ((flags & EXTRA_FIELD) != 0) {
- unsigned len = (unsigned) get_byte();
- len |= ((unsigned) get_byte()) << 8;
- while (len--)
- (void) get_byte();
- }
-
- /* Discard original name if any */
- if ((flags & ORIG_NAME) != 0) {
- while (get_byte() != 0); /* null */
- }
-
- /* Discard file comment if any */
- if ((flags & COMMENT) != 0) {
- while (get_byte() != 0) /* null */
- ;
- }
- if (part_nb == 1) {
- header_bytes = inptr + 2 * sizeof(long); /* include crc and size */
- }
-
- }
-
- if (method >= 0)
- return method;
-
- if (part_nb == 1) {
- fprintf(stderr, "\nnot in gzip format\n");
- exit_code = ERROR;
- return -1;
- } else {
- fprintf(stderr, "\ndecompression OK, trailing garbage ignored\n");
- if (exit_code == OK)
- exit_code = WARNING;
- return -2;
- }
-}
-
-/* ========================================================================
- * Signal and error handler.
- */
-void abort_gzip()
-{
- exit(ERROR);
-}
-
-/* ===========================================================================
- * Run a set of bytes through the crc shift register. If s is a NULL
- * pointer, then initialize the crc shift register contents instead.
- * Return the current crc in either case.
- */
-ulg updcrc(s, n)
-uch *s; /* pointer to bytes to pump through */
-unsigned n; /* number of bytes in s[] */
-{
- static ulg crc = (ulg) 0xffffffffL; /* shift register contents */
- register ulg c; /* temporary variable */
- static unsigned long crc_32_tab[256];
- if (crc_table_empty) {
- unsigned long csr; /* crc shift register */
- unsigned long e; /* polynomial exclusive-or pattern */
- int i; /* counter for all possible eight bit values */
- int k; /* byte being shifted into crc apparatus */
-
- /* terms of polynomial defining this crc (except x^32): */
- static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
- /* Make exclusive-or pattern from polynomial (0xedb88320) */
- e = 0;
- for (i = 0; i < sizeof(p)/sizeof(int); i++)
- e |= 1L << (31 - p[i]);
-
- /* Compute and print table of CRC's, five per line */
- crc_32_tab[0] = 0x00000000L;
- for (i = 1; i < 256; i++) {
- csr = i;
- /* The idea to initialize the register with the byte instead of
- * zero was stolen from Haruhiko Okumura's ar002
- */
- for (k = 8; k; k--)
- csr = csr & 1 ? (csr >> 1) ^ e : csr >> 1;
- crc_32_tab[i]=csr;
- }
- }
-
- if (s == NULL) {
- c = 0xffffffffL;
- } else {
- c = crc;
- if (n)
- do {
- c = crc_32_tab[((int) c ^ (*s++)) & 0xff] ^ (c >> 8);
- } while (--n);
- }
- crc = c;
- return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
-}
-
-void write_error_msg()
-{
- fprintf(stderr, "\n");
- perror("");
- abort_gzip();
-}
-
-/* ===========================================================================
- * Does the same as write(), but also handles partial pipe writes and checks
- * for error return.
- */
-void write_buf(fd, buf, cnt)
-int fd;
-void * buf;
-unsigned cnt;
-{
- unsigned n;
-
- while ((n = write(fd, buf, cnt)) != cnt) {
- if (n == (unsigned) (-1)) {
- write_error_msg();
- }
- cnt -= n;
- buf = (void *) ((char *) buf + n);
- }
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-void flush_window()
-{
- if (outcnt == 0)
- return;
- updcrc(window, outcnt);
-
- if (!test_mode)
- write_buf(ofd, (char *) window, outcnt);
- bytes_out += (ulg) outcnt;
- outcnt = 0;
-}
-
-int inflate_stored()
-/* "decompress" an inflated type 0 (stored) block. */
-{
- unsigned n; /* number of bytes in block */
- unsigned w; /* current window position */
- register ulg b; /* bit buffer */
- register unsigned k; /* number of bits in bit buffer */
-
- /* make local copies of globals */
- b = bb; /* initialize bit buffer */
- k = bk;
- w = outcnt; /* initialize window position */
-
- /* go to byte boundary */
- n = k & 7;
- DUMPBITS(n);
-
- /* get the length and its complement */
- NEEDBITS(16)
- n = ((unsigned) b & 0xffff);
- DUMPBITS(16)
- NEEDBITS(16)
- if (n != (unsigned) ((~b) & 0xffff))
- return 1; /* error in compressed data */
- DUMPBITS(16)
-
- /* read and output the compressed data */
- while (n--) {
- NEEDBITS(8)
- window[w++] = (uch) b;
- if (w == WSIZE) {
-// flush_output(w);
- outcnt=(w),
- flush_window();
- w = 0;
- }
- DUMPBITS(8)
- }
-
- /* restore the globals from the locals */
- outcnt = w; /* restore global window pointer */
- bb = b; /* restore global bit buffer */
- bk = k;
- return 0;
-}
-
-int huft_free(t)
-struct huft *t; /* table to free */
-
-/* Free the malloc'ed tables built by huft_build(), which makes a linked
- list of the tables it made, with the links in a dummy first entry of
- each table. */
-{
- register struct huft *p, *q;
-
- /* Go through linked list, freeing from the malloced (t[-1]) address. */
- p = t;
- while (p != (struct huft *) NULL) {
- q = (--p)->v.t;
- free((char *) p);
- p = q;
- }
- return 0;
-}