📄 decompress_unzip.c
字号:
} for (; i < 280; i++) { l[i] = 7; } for (; i < 288; i++) { /* make a complete, but wrong code set */ l[i] = 8; } bl = 7; i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl); if (i != 0) { return i; } /* set up distance table */ for (i = 0; i < 30; i++) { /* make an incomplete code set */ l[i] = 5; } bd = 5; i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd); if (i > 1) { huft_free(tl); return i; } /* decompress until an end-of-block code */ inflate_codes_setup(PASS_STATE tl, td, bl, bd); // Setup inflate_codes /* huft_free code moved into inflate_codes */ return -2; } case 2: /* Inflate dynamic */ { const int dbits = 6; /* bits in base distance lookup table */ const int lbits = 9; /* bits in base literal/length lookup table */ huft_t *tl; /* literal/length code table */ huft_t *td; /* distance code table */ unsigned i; /* temporary variables */ unsigned j; unsigned l; /* last length */ unsigned m; /* mask for bit lengths table */ unsigned n; /* number of lengths to get */ unsigned bl; /* lookup bits for tl */ unsigned bd; /* lookup bits for td */ unsigned nb; /* number of bit length codes */ unsigned nl; /* number of literal/length codes */ unsigned nd; /* number of distance codes */ unsigned ll[286 + 30]; /* literal/length and distance code lengths */ unsigned b_dynamic; /* bit buffer */ unsigned k_dynamic; /* number of bits in bit buffer */ /* make local bit buffer */ b_dynamic = gunzip_bb; k_dynamic = gunzip_bk; /* read in table lengths */ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 5); nl = 257 + ((unsigned) b_dynamic & 0x1f); /* number of literal/length codes */ b_dynamic >>= 5; k_dynamic -= 5; b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 5); nd = 1 + ((unsigned) b_dynamic & 0x1f); /* number of distance codes */ b_dynamic >>= 5; k_dynamic -= 5; b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 4); nb = 4 + ((unsigned) b_dynamic & 0xf); /* number of bit length codes */ b_dynamic >>= 4; k_dynamic -= 4; if (nl > 286 || nd > 30) { return 1; /* bad lengths */ } /* read in bit-length-code lengths */ for (j = 0; j < nb; j++) { b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 3); ll[border[j]] = (unsigned) b_dynamic & 7; b_dynamic >>= 3; k_dynamic -= 3; } for (; j < 19; j++) { ll[border[j]] = 0; } /* build decoding table for trees--single level, 7 bit lookup */ bl = 7; i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl); if (i != 0) { if (i == 1) { huft_free(tl); } return i; /* incomplete code set */ } /* read in literal and distance code lengths */ n = nl + nd; m = mask_bits[bl]; i = l = 0; while ((unsigned) i < n) { b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, (unsigned)bl); j = (td = tl + ((unsigned) b_dynamic & m))->b; b_dynamic >>= j; k_dynamic -= j; j = td->v.n; if (j < 16) { /* length of code in bits (0..15) */ ll[i++] = l = j; /* save last length in l */ } else if (j == 16) { /* repeat last length 3 to 6 times */ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 2); j = 3 + ((unsigned) b_dynamic & 3); b_dynamic >>= 2; k_dynamic -= 2; if ((unsigned) i + j > n) { return 1; } while (j--) { ll[i++] = l; } } else if (j == 17) { /* 3 to 10 zero length codes */ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 3); j = 3 + ((unsigned) b_dynamic & 7); b_dynamic >>= 3; k_dynamic -= 3; if ((unsigned) i + j > n) { return 1; } while (j--) { ll[i++] = 0; } l = 0; } else { /* j == 18: 11 to 138 zero length codes */ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 7); j = 11 + ((unsigned) b_dynamic & 0x7f); b_dynamic >>= 7; k_dynamic -= 7; if ((unsigned) i + j > n) { return 1; } while (j--) { ll[i++] = 0; } l = 0; } } /* free decoding table for trees */ huft_free(tl); /* restore the global bit buffer */ gunzip_bb = b_dynamic; gunzip_bk = k_dynamic; /* build the decoding tables for literal/length and distance codes */ bl = lbits; i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl); if (i != 0) { if (i == 1) {//shouldn't we propagate error? bb_error_msg_and_die("incomplete literal tree"); /* huft_free(tl); */ } return i; /* incomplete code set */ } bd = dbits; i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd); if (i != 0) { if (i == 1) {//shouldn't we propagate error? bb_error_msg_and_die("incomplete distance tree"); /* huft_free(td); */ } huft_free(tl); return i; /* incomplete code set */ } /* decompress until an end-of-block code */ inflate_codes_setup(PASS_STATE tl, td, bl, bd); // Setup inflate_codes /* huft_free code moved into inflate_codes */ return -2; } default: /* bad block type *///shouldn't we propagate error? bb_error_msg_and_die("bad block type %d", t); }}/* Two callsites, both in inflate_get_next_window */static void calculate_gunzip_crc(STATE_PARAM_ONLY){ int n; for (n = 0; n < gunzip_outbuf_count; n++) { gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); } gunzip_bytes_out += gunzip_outbuf_count;}/* One callsite in inflate_unzip_internal */static int inflate_get_next_window(STATE_PARAM_ONLY){ gunzip_outbuf_count = 0; while (1) { int ret; if (need_another_block) { if (end_reached) { calculate_gunzip_crc(PASS_STATE_ONLY); end_reached = 0; need_another_block = 1; return 0; /* Last block */ } method = inflate_block(PASS_STATE &end_reached); need_another_block = 0; } switch (method) { case -1: ret = inflate_stored(PASS_STATE_ONLY); break; case -2: ret = inflate_codes(PASS_STATE_ONLY); break; default://shouldn't we propagate error? bb_error_msg_and_die("inflate error %d", method); } if (ret == 1) { calculate_gunzip_crc(PASS_STATE_ONLY); return 1; // More data left } need_another_block = 1; // End of that block } /* Doesnt get here */}/* 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) intinflate_unzip_internal(STATE_PARAM int in, int out){ USE_DESKTOP(long long) int n = 0; ssize_t nwrote; /* Allocate all global buffers (for DYN_ALLOC option) */ gunzip_window = xmalloc(GUNZIP_WSIZE); gunzip_outbuf_count = 0; gunzip_bytes_out = 0; gunzip_src_fd = in; /* initialize gunzip_window, bit buffer */ gunzip_bk = 0; gunzip_bb = 0; /* Create the crc table */ gunzip_crc_table = crc32_filltable(0); gunzip_crc = ~0; /* Allocate space for buffer */ bytebuffer = xmalloc(bytebuffer_max); while (1) { int r = inflate_get_next_window(PASS_STATE_ONLY); nwrote = full_write(out, gunzip_window, gunzip_outbuf_count); if (nwrote != gunzip_outbuf_count) { bb_perror_msg("write"); n = -1; goto ret; } USE_DESKTOP(n += nwrote;) if (r == 0) break; } /* 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 * so we can discard unused bits in the last meaningful byte. */ bytebuffer_offset--; bytebuffer[bytebuffer_offset] = gunzip_bb & 0xff; gunzip_bb >>= 8; gunzip_bk -= 8; } ret: /* Cleanup */ free(gunzip_window); free(gunzip_crc_table); return n;}USE_DESKTOP(long long) intinflate_unzip(inflate_unzip_result *res, unsigned bufsize, int in, int out){ USE_DESKTOP(long long) int n; DECLARE_STATE; ALLOC_STATE; bytebuffer_max = bufsize + 8; bytebuffer_offset = 4; n = inflate_unzip_internal(PASS_STATE in, out); res->crc = gunzip_crc; res->bytes_out = gunzip_bytes_out; free(bytebuffer); DEALLOC_STATE; return n;}USE_DESKTOP(long long) intinflate_gunzip(int in, int out){ uint32_t stored_crc = 0; unsigned count; USE_DESKTOP(long long) int n; DECLARE_STATE; ALLOC_STATE; bytebuffer_max = 0x8000; n = inflate_unzip_internal(PASS_STATE in, out); if (n < 0) goto ret; /* top up the input buffer with the rest of the trailer */ count = bytebuffer_size - bytebuffer_offset; if (count < 8) { xread(in, &bytebuffer[bytebuffer_size], 8 - count);//shouldn't we propagate error? bytebuffer_size += 8 - count; } for (count = 0; count != 4; count++) { stored_crc |= (bytebuffer[bytebuffer_offset] << (count * 8)); bytebuffer_offset++; } /* Validate decompression - crc */ if (stored_crc != (~gunzip_crc)) { bb_error_msg("crc error"); n = -1; goto ret; } /* Validate decompression - size */ if (gunzip_bytes_out != (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) | (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24)) ) { bb_error_msg("incorrect length"); n = -1; } ret: free(bytebuffer); DEALLOC_STATE; return n;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -