diff options
Diffstat (limited to 'archival/libunarchive')
-rw-r--r-- | archival/libunarchive/decompress_unzip.c | 265 |
1 files changed, 146 insertions, 119 deletions
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index af74e6598..9e8fd7e03 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c @@ -45,22 +45,25 @@ typedef struct huft_s { } v; } huft_t; +enum { + /* gunzip_window size--must be a power of two, and + * at least 32K for zip's deflate method */ + GUNZIP_WSIZE = 0x8000, + /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ + BMAX = 16, /* maximum bit length of any code (16 for explode) */ + N_MAX = 288, /* maximum number of codes in any set */ +}; + static off_t gunzip_bytes_out; /* number of output bytes */ static uint32_t gunzip_crc; static int gunzip_src_fd; static unsigned gunzip_outbuf_count; /* bytes in output buffer */ -/* gunzip_window size--must be a power of two, and - * at least 32K for zip's deflate method */ -enum { gunzip_wsize = 0x8000 }; static unsigned char *gunzip_window; static uint32_t *gunzip_crc_table; -/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ -#define BMAX 16 /* maximum bit length of any code (16 for explode) */ -#define N_MAX 288 /* maximum number of codes in any set */ /* bitbuffer */ static unsigned gunzip_bb; /* bit buffer */ @@ -135,19 +138,16 @@ static unsigned fill_bitbuffer(unsigned bitbuffer, unsigned *current, const unsi * each table. * t: table to free */ -static int huft_free(huft_t * t) +static void huft_free(huft_t * p) { - huft_t *p; huft_t *q; /* Go through linked list, freeing from the malloced (t[-1]) address. */ - p = t; - while (p != (huft_t *) NULL) { + while (p) { q = (--p)->v.t; - free((char *) p); + free(p); p = q; } - return 0; } /* Given a list of code lengths and a maximum table size, make a set of @@ -339,6 +339,7 @@ static int huft_build(unsigned *b, const unsigned n, return y != 0 && g != 1; } + /* * inflate (decompress) the codes in a deflated (compressed) block. * Return an error code or zero if it all goes ok. @@ -346,106 +347,116 @@ static int huft_build(unsigned *b, const unsigned n, * tl, td: literal/length and distance decoder tables * bl, bd: number of bits decoded by tl[] and td[] */ -/* called with setup==1 once from inflate_block */ -/* called once with setup==0 from inflate_get_next_window */ -static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, const unsigned my_bd, int setup) +/* called once from inflate_block */ +#define ml inflate_codes_ml +#define md inflate_codes_md +#define bb inflate_codes_bb +#define k inflate_codes_k +#define w inflate_codes_w +#define tl inflate_codes_tl +#define td inflate_codes_td +#define bl inflate_codes_bl +#define bd inflate_codes_bd +static unsigned ml, md; /* masks for bl and bd bits */ +static unsigned bb; /* bit buffer */ +static unsigned k; /* number of bits in bit buffer */ +static unsigned w; /* current gunzip_window position */ +static huft_t *tl, *td; +static unsigned bl, bd; +static int resumeCopy; /* = 0; */ +static void inflate_codes_setup(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, const unsigned my_bd) { - static unsigned e; /* table entry flag/number of extra bits */ - static unsigned n, d; /* length and index for copy */ - static unsigned w; /* current gunzip_window position */ - static huft_t *t; /* pointer to table entry */ - static unsigned ml, md; /* masks for bl and bd bits */ - static unsigned b; /* bit buffer */ - static unsigned k; /* number of bits in bit buffer */ - static huft_t *tl, *td; - static unsigned bl, bd; - static int resumeCopy = 0; - - if (setup) { // 1st time we are called, copy in variables - tl = my_tl; - td = my_td; - bl = my_bl; - bd = my_bd; - /* make local copies of globals */ - b = gunzip_bb; /* initialize bit buffer */ - k = gunzip_bk; - w = gunzip_outbuf_count; /* initialize gunzip_window position */ - - /* inflate the coded data */ - ml = mask_bits[bl]; /* precompute masks for speed */ - md = mask_bits[bd]; - return 0; // Don't actually do anything the first time - } + tl = my_tl; + td = my_td; + bl = my_bl; + bd = my_bd; + /* make local copies of globals */ + bb = gunzip_bb; /* initialize bit buffer */ + k = gunzip_bk; + w = gunzip_outbuf_count; /* initialize gunzip_window position */ + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; +} +/* called once from inflate_get_next_window */ +static int inflate_codes(void) +{ + unsigned e; /* table entry flag/number of extra bits */ + huft_t *t; /* pointer to table entry */ if (resumeCopy) goto do_copy; while (1) { /* do until end of block */ - b = fill_bitbuffer(b, &k, bl); - t = tl + ((unsigned) b & ml); + bb = fill_bitbuffer(bb, &k, bl); + t = tl + ((unsigned) bb & ml); e = t->e; if (e > 16) do { if (e == 99) { bb_error_msg_and_die("inflate_codes error 1"); } - b >>= t->b; + bb >>= t->b; k -= t->b; e -= 16; - b = fill_bitbuffer(b, &k, e); - t = t->v.t + ((unsigned) b & mask_bits[e]); + bb = fill_bitbuffer(bb, &k, e); + t = t->v.t + ((unsigned) bb & mask_bits[e]); e = t->e; } while (e > 16); - b >>= t->b; + bb >>= t->b; k -= t->b; if (e == 16) { /* then it's a literal */ gunzip_window[w++] = (unsigned char) t->v.n; - if (w == gunzip_wsize) { - gunzip_outbuf_count = (w); + if (w == GUNZIP_WSIZE) { + gunzip_outbuf_count = w; //flush_gunzip_window(); w = 0; return 1; // We have a block to read } } else { /* it's an EOB or a length */ + /* length and index for copy */ + unsigned n = n; /* for gcc */ + unsigned d = d; /* for gcc */ + /* exit if end of block */ if (e == 15) { break; } /* get length of block to copy */ - b = fill_bitbuffer(b, &k, e); - n = t->v.n + ((unsigned) b & mask_bits[e]); - b >>= e; + bb = fill_bitbuffer(bb, &k, e); + n = t->v.n + ((unsigned) bb & mask_bits[e]); + bb >>= e; k -= e; /* decode distance of block to copy */ - b = fill_bitbuffer(b, &k, bd); - t = td + ((unsigned) b & md); + bb = fill_bitbuffer(bb, &k, bd); + t = td + ((unsigned) bb & md); e = t->e; if (e > 16) do { if (e == 99) bb_error_msg_and_die("inflate_codes error 2"); - b >>= t->b; + bb >>= t->b; k -= t->b; e -= 16; - b = fill_bitbuffer(b, &k, e); - t = t->v.t + ((unsigned) b & mask_bits[e]); + bb = fill_bitbuffer(bb, &k, e); + t = t->v.t + ((unsigned) bb & mask_bits[e]); e = t->e; } while (e > 16); - b >>= t->b; + bb >>= t->b; k -= t->b; - b = fill_bitbuffer(b, &k, e); - d = w - t->v.n - ((unsigned) b & mask_bits[e]); - b >>= e; + bb = fill_bitbuffer(bb, &k, e); + d = w - t->v.n - ((unsigned) bb & mask_bits[e]); + bb >>= e; k -= e; /* do the copy */ do_copy: do { - /* Was: n -= (e = (e = gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e); */ + /* Was: n -= (e = (e = GUNZIP_WSIZE - ((d &= GUNZIP_WSIZE - 1) > w ? d : w)) > n ? n : e); */ /* Who wrote THAT?? rewritten as: */ - d &= gunzip_wsize - 1; - e = gunzip_wsize - (d > w ? d : w); + d &= GUNZIP_WSIZE - 1; + e = GUNZIP_WSIZE - (d > w ? d : w); if (e > n) e = n; n -= e; @@ -461,8 +472,8 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, c gunzip_window[w++] = gunzip_window[d++]; } while (--e); } - if (w == gunzip_wsize) { - gunzip_outbuf_count = (w); + if (w == GUNZIP_WSIZE) { + gunzip_outbuf_count = w; resumeCopy = (n != 0); //flush_gunzip_window(); w = 0; @@ -474,8 +485,8 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, c } /* restore the globals from the locals */ - gunzip_outbuf_count = w; /* restore global gunzip_window pointer */ - gunzip_bb = b; /* restore global bit buffer */ + gunzip_outbuf_count = w; /* restore global gunzip_window pointer */ + gunzip_bb = bb; /* restore global bit buffer */ gunzip_bk = k; /* normally just after call to inflate_codes, but save code by putting it here */ @@ -486,44 +497,54 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, c /* done */ return 0; } - -/* called once (setup==1) from inflate_block */ -/* and once (setup==0) from inflate_get_next_window */ -static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) +#undef ml +#undef md +#undef bb +#undef k +#undef w +#undef tl +#undef td +#undef bl +#undef bd + + +static unsigned inflate_stored_n, inflate_stored_b, inflate_stored_k, inflate_stored_w; +/* called once from inflate_block */ +static void inflate_stored_setup(int my_n, int my_b, int my_k) +{ + inflate_stored_n = my_n; + inflate_stored_b = my_b; + inflate_stored_k = my_k; + /* initialize gunzip_window position */ + inflate_stored_w = gunzip_outbuf_count; +} +/* called once from inflate_get_next_window */ +static int inflate_stored(void) { - static unsigned n, b_stored, k_stored, w; - - if (setup) { - n = my_n; - b_stored = my_b_stored; - k_stored = my_k_stored; - w = gunzip_outbuf_count; /* initialize gunzip_window position */ - return 0; // Don't do anything first time - } - /* read and output the compressed data */ - while (n--) { - b_stored = fill_bitbuffer(b_stored, &k_stored, 8); - gunzip_window[w++] = (unsigned char) b_stored; - if (w == gunzip_wsize) { - gunzip_outbuf_count = (w); + while (inflate_stored_n--) { + inflate_stored_b = fill_bitbuffer(inflate_stored_b, &inflate_stored_k, 8); + gunzip_window[inflate_stored_w++] = (unsigned char) inflate_stored_b; + if (inflate_stored_w == GUNZIP_WSIZE) { + gunzip_outbuf_count = inflate_stored_w; //flush_gunzip_window(); - w = 0; - b_stored >>= 8; - k_stored -= 8; + inflate_stored_w = 0; + inflate_stored_b >>= 8; + inflate_stored_k -= 8; return 1; // We have a block } - b_stored >>= 8; - k_stored -= 8; + inflate_stored_b >>= 8; + inflate_stored_k -= 8; } /* restore the globals from the locals */ - gunzip_outbuf_count = w; /* restore global gunzip_window pointer */ - gunzip_bb = b_stored; /* restore global bit buffer */ - gunzip_bk = k_stored; + gunzip_outbuf_count = inflate_stored_w; /* restore global gunzip_window pointer */ + gunzip_bb = inflate_stored_b; /* restore global bit buffer */ + gunzip_bk = inflate_stored_k; return 0; // Finished } + /* * decompress an inflated block * e: last block flag @@ -589,7 +610,8 @@ static int inflate_block(int *e) b_stored >>= 16; k_stored -= 16; - inflate_stored(n, b_stored, k_stored, 1); // Setup inflate_stored + inflate_stored_setup(n, b_stored, k_stored); // Setup inflate_stored + return -1; } case 1: @@ -636,7 +658,7 @@ static int inflate_block(int *e) } /* decompress until an end-of-block code */ - inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes + inflate_codes_setup(tl, td, bl, bd); // Setup inflate_codes /* huft_free code moved into inflate_codes */ @@ -790,7 +812,7 @@ static int inflate_block(int *e) } /* decompress until an end-of-block code */ - inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes + inflate_codes_setup(tl, td, bl, bd); // Setup inflate_codes /* huft_free code moved into inflate_codes */ @@ -812,7 +834,7 @@ static void calculate_gunzip_crc(void) gunzip_bytes_out += gunzip_outbuf_count; } -/* One callsite in inflate_unzip */ +/* One callsite in inflate_unzip_internal */ static int inflate_get_next_window(void) { static int method = -1; // Method == -1 for stored, -2 for codes @@ -825,7 +847,7 @@ static int inflate_get_next_window(void) int ret; if (needAnotherBlock) { - if(e) { + if (e) { calculate_gunzip_crc(); e = 0; needAnotherBlock = 1; @@ -836,32 +858,36 @@ static int inflate_get_next_window(void) } switch (method) { - case -1: ret = inflate_stored(0,0,0,0); - break; - case -2: ret = inflate_codes(0,0,0,0,0); - break; - default: bb_error_msg_and_die("inflate error %d", method); + case -1: + ret = inflate_stored(); + break; + case -2: + ret = inflate_codes(); + break; + default: + bb_error_msg_and_die("inflate error %d", method); } if (ret == 1) { calculate_gunzip_crc(); return 1; // More data left - } else needAnotherBlock = 1; // End of that block + } else + needAnotherBlock = 1; // End of that block } /* Doesnt get here */ } -/* Called from inflate_gunzip() and archival/unzip.c */ +/* Called from inflate_gunzip() and inflate_unzip() */ +/* NB: bytebuffer is allocated here but freeing it is left to the caller! */ static USE_DESKTOP(long long) int inflate_unzip_internal(int in, int out) { - USE_DESKTOP(long long total = 0;) + USE_DESKTOP(long long) int n = 0; ssize_t nwrote; - typedef void (*sig_type) (int); /* Allocate all global buffers (for DYN_ALLOC option) */ - gunzip_window = xmalloc(gunzip_wsize); + gunzip_window = xmalloc(GUNZIP_WSIZE); gunzip_outbuf_count = 0; gunzip_bytes_out = 0; gunzip_src_fd = in; @@ -878,20 +904,17 @@ inflate_unzip_internal(int in, int out) bytebuffer = xmalloc(bytebuffer_max); while (1) { - int ret = inflate_get_next_window(); + int r = inflate_get_next_window(); nwrote = full_write(out, gunzip_window, gunzip_outbuf_count); if (nwrote != gunzip_outbuf_count) { bb_perror_msg("write"); - return -1; + n = -1; + goto ret; } - USE_DESKTOP(total += nwrote;) - if (ret == 0) break; + USE_DESKTOP(n += nwrote;) + if (r == 0) break; } - /* Cleanup */ - free(gunzip_window); - free(gunzip_crc_table); - /* Store unused bytes in a global buffer so calling applets can access it */ if (gunzip_bk >= 8) { /* Undo too much lookahead. The next read will be byte aligned @@ -901,7 +924,11 @@ inflate_unzip_internal(int in, int out) gunzip_bb >>= 8; gunzip_bk -= 8; } - return USE_DESKTOP(total) + 0; + ret: + /* Cleanup */ + free(gunzip_window); + free(gunzip_crc_table); + return n; } |