📄 gunzip.c
字号:
} guz->outbuf = outbuf; guz->outptr = outptr; return 0;}static int inflate_stored(gunzip_t *guz){ ulong n; /* number of bytes in block */ /* go to byte boundary */ n = guz->bufbits & 7; get_bits(guz, n); /* get the length and its complement */ n = get_bits(guz, 16); if (n != (~get_bits(guz, 16) & 0xffff)) return 1; /* error in compressed data */ /* read and output the compressed data */ while (n--) output_char(guz, (uchar)get_bits(guz, 8)); return 0;}static int inflate_fixed(gunzip_t *guz){ huft_bits ll[288], ld[32]; huft_code tl[288], td[32]; int i; /* set up literal table */ for (i = 0; i < 144; i++) ll[i] = 8; for (; i < 256; i++) ll[i] = 9; for (; i < 280; i++) ll[i] = 7; for (; i < 288; i++) /* make a complete, but wrong code set */ ll[i] = 8; huft_build_table(ll, 288, tl); for (i = 0; i < 30; i++) ld[i] = 5; huft_build_table(ld, 30, td); return inflate_codes(guz, ll, tl, ld, td, 288, 30);}static int build_bits_table(gunzip_t *guz, huft_bits *lb, huft_code *tb, int nb, huft_bits *ll, int nl ){ huft_bits bits; huft_code code; int value, i, n; i = 0; while (i < nl) { code = peek_bits(guz, 16); value = huft_get_value(lb, tb, 19, code, &bits); if (value == -1) return 1; /* error in compressed data */ skip_bits(guz, bits); if (value < 16) { ll[i++] = value; } else if (value == 16) { code = get_bits(guz, 2); for (n = 0; n < code + 3; n++) { ll[i++] = ll[i - 1]; } } else if (value == 17) { code = get_bits(guz, 3); for (n = 0; n < code + 3; n++) ll[i++] = 0; } else if (value == 18) { code = get_bits(guz, 7); for (n = 0; n < code + 11; n++) ll[i++] = 0; } } return 0;}static int inflate_dynamic(gunzip_t *guz){ huft_bits lb[19], ll[288], ld[32]; huft_code tb[19], tl[288], td[32]; int nb; /* number of bit length codes */ int nl; /* number of literal/length codes */ int nd; /* number of distance codes */ int i; /* read in table lengths */ nl = 257 + get_bits(guz, 5); /* number of literal/length codes */ nd = 1 + get_bits(guz, 5); /* number of distance codes */ nb = 4 + get_bits(guz, 4); /* number of bit length codes */ if (nl > 286 || nd > 30) return 1; /* bad lengths */ /* read in bit-length-code lengths */ for (i = 0; i < nb; i++) lb[border[i]] = get_bits(guz, 3); for (; i < 19; i++) lb[border[i]] = 0; huft_build_table(lb, 19, tb); build_bits_table(guz, lb, tb, 19, ll, nl); huft_build_table(ll, nl, tl); build_bits_table(guz, lb, tb, 19, ld, nd); huft_build_table(ld, nd, td); return inflate_codes(guz, ll, tl, ld, td, nl, nd);}static int inflate_block(gunzip_t *guz, ulong *e){ ulong t; /* block type */ /* read in last block bit */ *e = get_bits(guz, 1); /* read in block type */ t = get_bits(guz, 2); /* inflate that block type */ if (t == 0) return inflate_stored(guz); if (t == 1) return inflate_fixed(guz); if (t == 2) return inflate_dynamic(guz); /* bad block type */ return 2;}static int inflate(gunzip_t *guz){ ulong e; /* last block flag */ int r; /* result code */ /* unsigned h; maximum struct huft's malloc'ed */ /* decompress until the last block */ do { if ((r = inflate_block(guz, &e)) != 0) { return r; } } while (!e); /* Undo too much lookahead. The next read will be byte aligned so we * can discard unused bits in the last meaningful byte. */ while (guz->bufbits >= 8) { guz->bufbits -= 8; guz->inptr--; } /* return success */ return 0;}static void init_gunzip_struct(gunzip_t *guz, uchar *inbuf, ulong insize, uchar *outbuf, ulong outsize){ guz->inbuf = inbuf; guz->insize = insize; guz->inptr = 0; guz->outbuf = outbuf; guz->outsize = outsize; guz->outptr = 0; guz->bitbuf = 0; guz->bufbits = 0;}ulong get_crc(uchar *buf, int len){ ulong crc; uchar ch; int i; crc = 0xffffffffL; for (i = 0; i < len; i++) { ch = buf[i]; crc = crc_32_tab[((int)crc ^ ch) & 0xff] ^ (crc >> 8); } crc = (crc ^ 0xffffffffL); return crc;}int gunzip(uchar *inbuf, ulong *insize, uchar *outbuf, ulong *outsize){ gunzip_t guz_struct; gunzip_t *guz; uchar magic[2]; /* magic header */ uchar method; uchar flags; ulong orig_crc = 0; /* original crc */ ulong orig_len = 0; /* original uncompressed length */ int res; guz = &guz_struct; init_gunzip_struct(guz, inbuf, *insize, outbuf, *outsize); magic[0] = get_uchar(guz); magic[1] = get_uchar(guz); method = get_uchar(guz); if (magic[0] != 0x1f || magic[1] != 0x8b) return ERR_BADMAGIC; /* We only support method #8, DEFLATED */ if (method != 8) return ERR_BADMETHOD; flags = get_uchar(guz); if (flags & ENCRYPTED) return ERR_ENCRYPTED; if (flags & CONTINUATION) return ERR_MULTIPART; if (flags & RESERVED) return ERR_INVALIDFLAGS; get_ulong(guz); /* Get timestamp */ get_uchar(guz); /* Ignore extra flags for the moment */ get_uchar(guz); /* Ignore OS type for the moment */ if (flags & EXTRA_FIELD) { ushort len; len = get_ushort(guz); while (len--) get_uchar(guz); } /* Get original file name if it was truncated */ if (flags & ORIG_NAME) { /* Discard the old name */ while (get_uchar(guz) != 0); } /* Discard file comment if any */ if (flags & COMMENT) { while (get_uchar(guz) != 0); } /* Decompress */ if ((res = inflate(guz)) != 0) { switch (res) { case 1: /* invalid compressed format (err=1) */ res = ERR_BADFORMAT1; break; case 2: /* invalid compressed format (err=2) */ res = ERR_BADFORMAT2; break; case 3: /* out of memory */ res = ERR_MEM; break; default: /* invalid compressed format (other) */ res = ERR_BADFORMAT; } return res; } /* Get the crc and original length */ /* crc32 (see algorithm.doc) * uncompressed input size modulo 2^32 */ orig_crc = get_ulong(guz); orig_len = get_ulong(guz); /* Validate decompression */// if (orig_crc != get_crc(guz->outbuf, guz->outptr))// return ERR_CRC; if (orig_len != guz->outptr) return ERR_LENGTH; *insize = guz->inptr; *outsize = guz->outptr; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -