1*cf5a6c84SAndroid Build Coastguard Worker /* deflate.c - deflate/inflate code for gzip and friends
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2014 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * See RFCs 1950 (zlib), 1951 (deflate), and 1952 (gzip)
6*cf5a6c84SAndroid Build Coastguard Worker * LSB 4.1 has gzip, gunzip, and zcat
7*cf5a6c84SAndroid Build Coastguard Worker *
8*cf5a6c84SAndroid Build Coastguard Worker * TODO: zip -d DIR -x LIST -list -quiet -no overwrite -overwrite -p to stdout
9*cf5a6c84SAndroid Build Coastguard Worker */
10*cf5a6c84SAndroid Build Coastguard Worker
11*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
12*cf5a6c84SAndroid Build Coastguard Worker
13*cf5a6c84SAndroid Build Coastguard Worker struct deflate {
14*cf5a6c84SAndroid Build Coastguard Worker // Huffman codes: base offset and extra bits tables (length and distance)
15*cf5a6c84SAndroid Build Coastguard Worker char lenbits[29], distbits[30];
16*cf5a6c84SAndroid Build Coastguard Worker unsigned short lenbase[29], distbase[30];
17*cf5a6c84SAndroid Build Coastguard Worker void *fixdisthuff, *fixlithuff;
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker // CRC
20*cf5a6c84SAndroid Build Coastguard Worker void (*crcfunc)(struct deflate *dd, char *data, unsigned len);
21*cf5a6c84SAndroid Build Coastguard Worker unsigned crctable[256], crc;
22*cf5a6c84SAndroid Build Coastguard Worker
23*cf5a6c84SAndroid Build Coastguard Worker
24*cf5a6c84SAndroid Build Coastguard Worker // Tables only used for deflation
25*cf5a6c84SAndroid Build Coastguard Worker unsigned short *hashhead, *hashchain;
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker // Compressed data buffer (extra space malloced at end)
28*cf5a6c84SAndroid Build Coastguard Worker unsigned pos, len;
29*cf5a6c84SAndroid Build Coastguard Worker int infd, outfd, outbuflen;
30*cf5a6c84SAndroid Build Coastguard Worker char *outbuf, data[];
31*cf5a6c84SAndroid Build Coastguard Worker };
32*cf5a6c84SAndroid Build Coastguard Worker
33*cf5a6c84SAndroid Build Coastguard Worker // little endian bit buffer
34*cf5a6c84SAndroid Build Coastguard Worker struct bitbuf {
35*cf5a6c84SAndroid Build Coastguard Worker int fd, bitpos, len, max;
36*cf5a6c84SAndroid Build Coastguard Worker char *buf, data[];
37*cf5a6c84SAndroid Build Coastguard Worker };
38*cf5a6c84SAndroid Build Coastguard Worker
39*cf5a6c84SAndroid Build Coastguard Worker // malloc a struct bitbuf
bitbuf_init(int fd,int size)40*cf5a6c84SAndroid Build Coastguard Worker static struct bitbuf *bitbuf_init(int fd, int size)
41*cf5a6c84SAndroid Build Coastguard Worker {
42*cf5a6c84SAndroid Build Coastguard Worker struct bitbuf *bb = xzalloc(sizeof(struct bitbuf)+size);
43*cf5a6c84SAndroid Build Coastguard Worker
44*cf5a6c84SAndroid Build Coastguard Worker bb->max = size;
45*cf5a6c84SAndroid Build Coastguard Worker bb->fd = fd;
46*cf5a6c84SAndroid Build Coastguard Worker bb->buf = bb->data;
47*cf5a6c84SAndroid Build Coastguard Worker
48*cf5a6c84SAndroid Build Coastguard Worker return bb;
49*cf5a6c84SAndroid Build Coastguard Worker }
50*cf5a6c84SAndroid Build Coastguard Worker
51*cf5a6c84SAndroid Build Coastguard Worker // Advance bitpos without the overhead of recording bits
52*cf5a6c84SAndroid Build Coastguard Worker // Loads more data when input buffer empty
53*cf5a6c84SAndroid Build Coastguard Worker // call with 0 to just load data, returns 0 at EOF
bitbuf_skip(struct bitbuf * bb,int bits)54*cf5a6c84SAndroid Build Coastguard Worker static int bitbuf_skip(struct bitbuf *bb, int bits)
55*cf5a6c84SAndroid Build Coastguard Worker {
56*cf5a6c84SAndroid Build Coastguard Worker int pos = bb->bitpos + bits + (bits<0), len;
57*cf5a6c84SAndroid Build Coastguard Worker
58*cf5a6c84SAndroid Build Coastguard Worker while (pos >= (len = bb->len<<3)) {
59*cf5a6c84SAndroid Build Coastguard Worker pos -= len;
60*cf5a6c84SAndroid Build Coastguard Worker if (1 > (bb->len = read(bb->fd, bb->buf, bb->max))) {
61*cf5a6c84SAndroid Build Coastguard Worker if (!bits) break;
62*cf5a6c84SAndroid Build Coastguard Worker error_exit("inflate EOF");
63*cf5a6c84SAndroid Build Coastguard Worker }
64*cf5a6c84SAndroid Build Coastguard Worker }
65*cf5a6c84SAndroid Build Coastguard Worker bb->bitpos = pos;
66*cf5a6c84SAndroid Build Coastguard Worker
67*cf5a6c84SAndroid Build Coastguard Worker return pos<len;
68*cf5a6c84SAndroid Build Coastguard Worker }
69*cf5a6c84SAndroid Build Coastguard Worker
70*cf5a6c84SAndroid Build Coastguard Worker // Optimized single bit inlined version
bitbuf_bit(struct bitbuf * bb)71*cf5a6c84SAndroid Build Coastguard Worker static inline int bitbuf_bit(struct bitbuf *bb)
72*cf5a6c84SAndroid Build Coastguard Worker {
73*cf5a6c84SAndroid Build Coastguard Worker int bufpos = bb->bitpos>>3;
74*cf5a6c84SAndroid Build Coastguard Worker
75*cf5a6c84SAndroid Build Coastguard Worker if (bufpos == bb->len) {
76*cf5a6c84SAndroid Build Coastguard Worker bitbuf_skip(bb, -1);
77*cf5a6c84SAndroid Build Coastguard Worker bufpos = 0;
78*cf5a6c84SAndroid Build Coastguard Worker }
79*cf5a6c84SAndroid Build Coastguard Worker
80*cf5a6c84SAndroid Build Coastguard Worker return (bb->buf[bufpos]>>(bb->bitpos++&7))&1;
81*cf5a6c84SAndroid Build Coastguard Worker }
82*cf5a6c84SAndroid Build Coastguard Worker
83*cf5a6c84SAndroid Build Coastguard Worker // Fetch the next X bits from the bitbuf, little endian
bitbuf_get(struct bitbuf * bb,int bits)84*cf5a6c84SAndroid Build Coastguard Worker static unsigned bitbuf_get(struct bitbuf *bb, int bits)
85*cf5a6c84SAndroid Build Coastguard Worker {
86*cf5a6c84SAndroid Build Coastguard Worker int result = 0, offset = 0;
87*cf5a6c84SAndroid Build Coastguard Worker
88*cf5a6c84SAndroid Build Coastguard Worker while (bits) {
89*cf5a6c84SAndroid Build Coastguard Worker int click = bb->bitpos >> 3, blow, blen;
90*cf5a6c84SAndroid Build Coastguard Worker
91*cf5a6c84SAndroid Build Coastguard Worker // Load more data if buffer empty
92*cf5a6c84SAndroid Build Coastguard Worker if (click == bb->len) {
93*cf5a6c84SAndroid Build Coastguard Worker bitbuf_skip(bb, -1);
94*cf5a6c84SAndroid Build Coastguard Worker click = 0;
95*cf5a6c84SAndroid Build Coastguard Worker }
96*cf5a6c84SAndroid Build Coastguard Worker
97*cf5a6c84SAndroid Build Coastguard Worker // grab bits from next byte
98*cf5a6c84SAndroid Build Coastguard Worker blow = bb->bitpos & 7;
99*cf5a6c84SAndroid Build Coastguard Worker blen = 8-blow;
100*cf5a6c84SAndroid Build Coastguard Worker if (blen > bits) blen = bits;
101*cf5a6c84SAndroid Build Coastguard Worker result |= ((bb->buf[click] >> blow) & ((1<<blen)-1)) << offset;
102*cf5a6c84SAndroid Build Coastguard Worker offset += blen;
103*cf5a6c84SAndroid Build Coastguard Worker bits -= blen;
104*cf5a6c84SAndroid Build Coastguard Worker bb->bitpos += blen;
105*cf5a6c84SAndroid Build Coastguard Worker }
106*cf5a6c84SAndroid Build Coastguard Worker
107*cf5a6c84SAndroid Build Coastguard Worker return result;
108*cf5a6c84SAndroid Build Coastguard Worker }
109*cf5a6c84SAndroid Build Coastguard Worker
bitbuf_flush(struct bitbuf * bb)110*cf5a6c84SAndroid Build Coastguard Worker static void bitbuf_flush(struct bitbuf *bb)
111*cf5a6c84SAndroid Build Coastguard Worker {
112*cf5a6c84SAndroid Build Coastguard Worker if (!bb->bitpos) return;
113*cf5a6c84SAndroid Build Coastguard Worker
114*cf5a6c84SAndroid Build Coastguard Worker xwrite(bb->fd, bb->buf, (bb->bitpos+7)>>3);
115*cf5a6c84SAndroid Build Coastguard Worker memset(bb->buf, 0, bb->max);
116*cf5a6c84SAndroid Build Coastguard Worker bb->bitpos = 0;
117*cf5a6c84SAndroid Build Coastguard Worker }
118*cf5a6c84SAndroid Build Coastguard Worker
bitbuf_put(struct bitbuf * bb,int data,int len)119*cf5a6c84SAndroid Build Coastguard Worker static void bitbuf_put(struct bitbuf *bb, int data, int len)
120*cf5a6c84SAndroid Build Coastguard Worker {
121*cf5a6c84SAndroid Build Coastguard Worker while (len) {
122*cf5a6c84SAndroid Build Coastguard Worker int click = bb->bitpos >> 3, blow, blen;
123*cf5a6c84SAndroid Build Coastguard Worker
124*cf5a6c84SAndroid Build Coastguard Worker // Flush buffer if necessary
125*cf5a6c84SAndroid Build Coastguard Worker if (click == bb->max) {
126*cf5a6c84SAndroid Build Coastguard Worker bitbuf_flush(bb);
127*cf5a6c84SAndroid Build Coastguard Worker click = 0;
128*cf5a6c84SAndroid Build Coastguard Worker }
129*cf5a6c84SAndroid Build Coastguard Worker blow = bb->bitpos & 7;
130*cf5a6c84SAndroid Build Coastguard Worker blen = 8-blow;
131*cf5a6c84SAndroid Build Coastguard Worker if (blen > len) blen = len;
132*cf5a6c84SAndroid Build Coastguard Worker bb->buf[click] |= data << blow;
133*cf5a6c84SAndroid Build Coastguard Worker bb->bitpos += blen;
134*cf5a6c84SAndroid Build Coastguard Worker data >>= blen;
135*cf5a6c84SAndroid Build Coastguard Worker len -= blen;
136*cf5a6c84SAndroid Build Coastguard Worker }
137*cf5a6c84SAndroid Build Coastguard Worker }
138*cf5a6c84SAndroid Build Coastguard Worker
139*cf5a6c84SAndroid Build Coastguard Worker // Output inflated data
inflate_out(struct deflate * dd,int len)140*cf5a6c84SAndroid Build Coastguard Worker static void inflate_out(struct deflate *dd, int len)
141*cf5a6c84SAndroid Build Coastguard Worker {
142*cf5a6c84SAndroid Build Coastguard Worker if (!len) return;
143*cf5a6c84SAndroid Build Coastguard Worker if (dd->outfd!=-1) xwrite(dd->outfd, dd->data, len);
144*cf5a6c84SAndroid Build Coastguard Worker else if (len>dd->outbuflen) error_exit("inflate too big");
145*cf5a6c84SAndroid Build Coastguard Worker else {
146*cf5a6c84SAndroid Build Coastguard Worker memcpy(dd->outbuf, dd->data, len);
147*cf5a6c84SAndroid Build Coastguard Worker dd->outbuf += len;
148*cf5a6c84SAndroid Build Coastguard Worker dd->outbuflen -= len;
149*cf5a6c84SAndroid Build Coastguard Worker }
150*cf5a6c84SAndroid Build Coastguard Worker if (dd->crcfunc) dd->crcfunc(dd, dd->data, len);
151*cf5a6c84SAndroid Build Coastguard Worker }
152*cf5a6c84SAndroid Build Coastguard Worker
output_byte(struct deflate * dd,char sym)153*cf5a6c84SAndroid Build Coastguard Worker static void output_byte(struct deflate *dd, char sym)
154*cf5a6c84SAndroid Build Coastguard Worker {
155*cf5a6c84SAndroid Build Coastguard Worker int pos = dd->pos++ & 32767;
156*cf5a6c84SAndroid Build Coastguard Worker
157*cf5a6c84SAndroid Build Coastguard Worker dd->data[pos] = sym;
158*cf5a6c84SAndroid Build Coastguard Worker if (pos == 32767) inflate_out(dd, 32768);
159*cf5a6c84SAndroid Build Coastguard Worker }
160*cf5a6c84SAndroid Build Coastguard Worker
161*cf5a6c84SAndroid Build Coastguard Worker // Huffman coding uses bits to traverse a binary tree to a leaf node,
162*cf5a6c84SAndroid Build Coastguard Worker // By placing frequently occurring symbols at shorter paths, frequently
163*cf5a6c84SAndroid Build Coastguard Worker // used symbols may be represented in fewer bits than uncommon symbols.
164*cf5a6c84SAndroid Build Coastguard Worker // (length[0] isn't used but code's clearer if it's there.)
165*cf5a6c84SAndroid Build Coastguard Worker
166*cf5a6c84SAndroid Build Coastguard Worker struct huff {
167*cf5a6c84SAndroid Build Coastguard Worker unsigned short length[16]; // How many symbols have this bit length?
168*cf5a6c84SAndroid Build Coastguard Worker unsigned short symbol[288]; // sorted by bit length, then ascending order
169*cf5a6c84SAndroid Build Coastguard Worker };
170*cf5a6c84SAndroid Build Coastguard Worker
171*cf5a6c84SAndroid Build Coastguard Worker // Create simple huffman tree from array of bit lengths.
172*cf5a6c84SAndroid Build Coastguard Worker
173*cf5a6c84SAndroid Build Coastguard Worker // The symbols in the huffman trees are sorted (first by bit length
174*cf5a6c84SAndroid Build Coastguard Worker // of the code to reach them, then by symbol number). This means that given
175*cf5a6c84SAndroid Build Coastguard Worker // the bit length of each symbol, we can construct a unique tree.
len2huff(struct huff * huff,char bitlen[],int len)176*cf5a6c84SAndroid Build Coastguard Worker static void len2huff(struct huff *huff, char bitlen[], int len)
177*cf5a6c84SAndroid Build Coastguard Worker {
178*cf5a6c84SAndroid Build Coastguard Worker int offset[16];
179*cf5a6c84SAndroid Build Coastguard Worker int i;
180*cf5a6c84SAndroid Build Coastguard Worker
181*cf5a6c84SAndroid Build Coastguard Worker // Count number of codes at each bit length
182*cf5a6c84SAndroid Build Coastguard Worker memset(huff, 0, sizeof(struct huff));
183*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<len; i++) huff->length[bitlen[i]]++;
184*cf5a6c84SAndroid Build Coastguard Worker
185*cf5a6c84SAndroid Build Coastguard Worker // Sort symbols by bit length, then symbol. Get list of starting positions
186*cf5a6c84SAndroid Build Coastguard Worker // for each group, then write each symbol to next position within its group.
187*cf5a6c84SAndroid Build Coastguard Worker *huff->length = *offset = 0;
188*cf5a6c84SAndroid Build Coastguard Worker for (i = 1; i<16; i++) offset[i] = offset[i-1] + huff->length[i-1];
189*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<len; i++) if (bitlen[i]) huff->symbol[offset[bitlen[i]]++] = i;
190*cf5a6c84SAndroid Build Coastguard Worker }
191*cf5a6c84SAndroid Build Coastguard Worker
192*cf5a6c84SAndroid Build Coastguard Worker // Fetch and decode next huffman coded symbol from bitbuf.
193*cf5a6c84SAndroid Build Coastguard Worker // This takes advantage of the sorting to navigate the tree as an array:
194*cf5a6c84SAndroid Build Coastguard Worker // each time we fetch a bit we have all the codes at that bit level in
195*cf5a6c84SAndroid Build Coastguard Worker // order with no gaps.
huff_and_puff(struct bitbuf * bb,struct huff * huff)196*cf5a6c84SAndroid Build Coastguard Worker static unsigned huff_and_puff(struct bitbuf *bb, struct huff *huff)
197*cf5a6c84SAndroid Build Coastguard Worker {
198*cf5a6c84SAndroid Build Coastguard Worker unsigned short *length = huff->length;
199*cf5a6c84SAndroid Build Coastguard Worker int start = 0, offset = 0;
200*cf5a6c84SAndroid Build Coastguard Worker
201*cf5a6c84SAndroid Build Coastguard Worker // Traverse through the bit lengths until our code is in this range
202*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
203*cf5a6c84SAndroid Build Coastguard Worker offset = (offset << 1) | bitbuf_bit(bb);
204*cf5a6c84SAndroid Build Coastguard Worker start += *++length;
205*cf5a6c84SAndroid Build Coastguard Worker if ((offset -= *length) < 0) break;
206*cf5a6c84SAndroid Build Coastguard Worker if ((length - huff->length) & 16) error_exit("bad symbol");
207*cf5a6c84SAndroid Build Coastguard Worker }
208*cf5a6c84SAndroid Build Coastguard Worker
209*cf5a6c84SAndroid Build Coastguard Worker return huff->symbol[start + offset];
210*cf5a6c84SAndroid Build Coastguard Worker }
211*cf5a6c84SAndroid Build Coastguard Worker
212*cf5a6c84SAndroid Build Coastguard Worker // Decompress deflated data from bitbuf to dd->outfd.
inflate(struct deflate * dd,struct bitbuf * bb)213*cf5a6c84SAndroid Build Coastguard Worker static void inflate(struct deflate *dd, struct bitbuf *bb)
214*cf5a6c84SAndroid Build Coastguard Worker {
215*cf5a6c84SAndroid Build Coastguard Worker dd->crc = ~0;
216*cf5a6c84SAndroid Build Coastguard Worker
217*cf5a6c84SAndroid Build Coastguard Worker // repeat until spanked
218*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
219*cf5a6c84SAndroid Build Coastguard Worker int final, type;
220*cf5a6c84SAndroid Build Coastguard Worker
221*cf5a6c84SAndroid Build Coastguard Worker final = bitbuf_get(bb, 1);
222*cf5a6c84SAndroid Build Coastguard Worker type = bitbuf_get(bb, 2);
223*cf5a6c84SAndroid Build Coastguard Worker
224*cf5a6c84SAndroid Build Coastguard Worker if (type == 3) error_exit("bad type");
225*cf5a6c84SAndroid Build Coastguard Worker
226*cf5a6c84SAndroid Build Coastguard Worker // Uncompressed block?
227*cf5a6c84SAndroid Build Coastguard Worker if (!type) {
228*cf5a6c84SAndroid Build Coastguard Worker int len, nlen;
229*cf5a6c84SAndroid Build Coastguard Worker
230*cf5a6c84SAndroid Build Coastguard Worker // Align to byte, read length
231*cf5a6c84SAndroid Build Coastguard Worker bitbuf_skip(bb, (8-bb->bitpos)&7);
232*cf5a6c84SAndroid Build Coastguard Worker len = bitbuf_get(bb, 16);
233*cf5a6c84SAndroid Build Coastguard Worker nlen = bitbuf_get(bb, 16);
234*cf5a6c84SAndroid Build Coastguard Worker if (len != (0xffff & ~nlen)) error_exit("bad len");
235*cf5a6c84SAndroid Build Coastguard Worker
236*cf5a6c84SAndroid Build Coastguard Worker // Dump literal output data
237*cf5a6c84SAndroid Build Coastguard Worker while (len) {
238*cf5a6c84SAndroid Build Coastguard Worker int pos = bb->bitpos >> 3, bblen = bb->len - pos;
239*cf5a6c84SAndroid Build Coastguard Worker char *p = bb->buf+pos;
240*cf5a6c84SAndroid Build Coastguard Worker
241*cf5a6c84SAndroid Build Coastguard Worker // dump bytes until done or end of current bitbuf contents
242*cf5a6c84SAndroid Build Coastguard Worker if (bblen > len) bblen = len;
243*cf5a6c84SAndroid Build Coastguard Worker pos = bblen;
244*cf5a6c84SAndroid Build Coastguard Worker while (pos--) output_byte(dd, *(p++));
245*cf5a6c84SAndroid Build Coastguard Worker bitbuf_skip(bb, bblen << 3);
246*cf5a6c84SAndroid Build Coastguard Worker len -= bblen;
247*cf5a6c84SAndroid Build Coastguard Worker }
248*cf5a6c84SAndroid Build Coastguard Worker
249*cf5a6c84SAndroid Build Coastguard Worker // Compressed block
250*cf5a6c84SAndroid Build Coastguard Worker } else {
251*cf5a6c84SAndroid Build Coastguard Worker struct huff *disthuff, *lithuff;
252*cf5a6c84SAndroid Build Coastguard Worker
253*cf5a6c84SAndroid Build Coastguard Worker // Dynamic huffman codes?
254*cf5a6c84SAndroid Build Coastguard Worker if (type == 2) {
255*cf5a6c84SAndroid Build Coastguard Worker struct huff *h2 = ((struct huff *)libbuf)+1;
256*cf5a6c84SAndroid Build Coastguard Worker int i, litlen, distlen, hufflen;
257*cf5a6c84SAndroid Build Coastguard Worker char *hufflen_order = "\x10\x11\x12\0\x08\x07\x09\x06\x0a\x05\x0b"
258*cf5a6c84SAndroid Build Coastguard Worker "\x04\x0c\x03\x0d\x02\x0e\x01\x0f", *bits;
259*cf5a6c84SAndroid Build Coastguard Worker
260*cf5a6c84SAndroid Build Coastguard Worker // The huffman trees are stored as a series of bit lengths
261*cf5a6c84SAndroid Build Coastguard Worker litlen = bitbuf_get(bb, 5)+257; // max 288
262*cf5a6c84SAndroid Build Coastguard Worker distlen = bitbuf_get(bb, 5)+1; // max 32
263*cf5a6c84SAndroid Build Coastguard Worker hufflen = bitbuf_get(bb, 4)+4; // max 19
264*cf5a6c84SAndroid Build Coastguard Worker
265*cf5a6c84SAndroid Build Coastguard Worker // The literal and distance codes are themselves compressed, in
266*cf5a6c84SAndroid Build Coastguard Worker // a complicated way: an array of bit lengths (hufflen many
267*cf5a6c84SAndroid Build Coastguard Worker // entries, each 3 bits) is used to fill out an array of 19 entries
268*cf5a6c84SAndroid Build Coastguard Worker // in a magic order, leaving the rest 0. Then make a tree out of it:
269*cf5a6c84SAndroid Build Coastguard Worker memset(bits = libbuf+1, 0, 19);
270*cf5a6c84SAndroid Build Coastguard Worker for (i=0; i<hufflen; i++) bits[hufflen_order[i]] = bitbuf_get(bb, 3);
271*cf5a6c84SAndroid Build Coastguard Worker len2huff(h2, bits, 19);
272*cf5a6c84SAndroid Build Coastguard Worker
273*cf5a6c84SAndroid Build Coastguard Worker // Use that tree to read in the literal and distance bit lengths
274*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < litlen + distlen;) {
275*cf5a6c84SAndroid Build Coastguard Worker int sym = huff_and_puff(bb, h2);
276*cf5a6c84SAndroid Build Coastguard Worker
277*cf5a6c84SAndroid Build Coastguard Worker // 0-15 are literals, 16 = repeat previous code 3-6 times,
278*cf5a6c84SAndroid Build Coastguard Worker // 17 = 3-10 zeroes (3 bit), 18 = 11-138 zeroes (7 bit)
279*cf5a6c84SAndroid Build Coastguard Worker if (sym < 16) bits[i++] = sym;
280*cf5a6c84SAndroid Build Coastguard Worker else {
281*cf5a6c84SAndroid Build Coastguard Worker int len = sym & 2;
282*cf5a6c84SAndroid Build Coastguard Worker
283*cf5a6c84SAndroid Build Coastguard Worker len = bitbuf_get(bb, sym-14+len+(len>>1)) + 3 + (len<<2);
284*cf5a6c84SAndroid Build Coastguard Worker memset(bits+i, bits[i-1] * !(sym&3), len);
285*cf5a6c84SAndroid Build Coastguard Worker i += len;
286*cf5a6c84SAndroid Build Coastguard Worker }
287*cf5a6c84SAndroid Build Coastguard Worker }
288*cf5a6c84SAndroid Build Coastguard Worker if (i > litlen+distlen) error_exit("bad tree");
289*cf5a6c84SAndroid Build Coastguard Worker
290*cf5a6c84SAndroid Build Coastguard Worker len2huff(lithuff = h2, bits, litlen);
291*cf5a6c84SAndroid Build Coastguard Worker len2huff(disthuff = ((struct huff *)libbuf)+2, bits+litlen, distlen);
292*cf5a6c84SAndroid Build Coastguard Worker
293*cf5a6c84SAndroid Build Coastguard Worker // Static huffman codes
294*cf5a6c84SAndroid Build Coastguard Worker } else {
295*cf5a6c84SAndroid Build Coastguard Worker lithuff = dd->fixlithuff;
296*cf5a6c84SAndroid Build Coastguard Worker disthuff = dd->fixdisthuff;
297*cf5a6c84SAndroid Build Coastguard Worker }
298*cf5a6c84SAndroid Build Coastguard Worker
299*cf5a6c84SAndroid Build Coastguard Worker // Use huffman tables to decode block of compressed symbols
300*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
301*cf5a6c84SAndroid Build Coastguard Worker int sym = huff_and_puff(bb, lithuff);
302*cf5a6c84SAndroid Build Coastguard Worker
303*cf5a6c84SAndroid Build Coastguard Worker // Literal?
304*cf5a6c84SAndroid Build Coastguard Worker if (sym < 256) output_byte(dd, sym);
305*cf5a6c84SAndroid Build Coastguard Worker
306*cf5a6c84SAndroid Build Coastguard Worker // Copy range?
307*cf5a6c84SAndroid Build Coastguard Worker else if (sym > 256) {
308*cf5a6c84SAndroid Build Coastguard Worker int len, dist;
309*cf5a6c84SAndroid Build Coastguard Worker
310*cf5a6c84SAndroid Build Coastguard Worker sym -= 257;
311*cf5a6c84SAndroid Build Coastguard Worker len = dd->lenbase[sym] + bitbuf_get(bb, dd->lenbits[sym]);
312*cf5a6c84SAndroid Build Coastguard Worker sym = huff_and_puff(bb, disthuff);
313*cf5a6c84SAndroid Build Coastguard Worker dist = dd->distbase[sym] + bitbuf_get(bb, dd->distbits[sym]);
314*cf5a6c84SAndroid Build Coastguard Worker sym = dd->pos & 32767;
315*cf5a6c84SAndroid Build Coastguard Worker
316*cf5a6c84SAndroid Build Coastguard Worker while (len--) output_byte(dd, dd->data[(dd->pos-dist) & 32767]);
317*cf5a6c84SAndroid Build Coastguard Worker
318*cf5a6c84SAndroid Build Coastguard Worker // End of block
319*cf5a6c84SAndroid Build Coastguard Worker } else break;
320*cf5a6c84SAndroid Build Coastguard Worker }
321*cf5a6c84SAndroid Build Coastguard Worker }
322*cf5a6c84SAndroid Build Coastguard Worker
323*cf5a6c84SAndroid Build Coastguard Worker // Was that the last block?
324*cf5a6c84SAndroid Build Coastguard Worker if (final) break;
325*cf5a6c84SAndroid Build Coastguard Worker }
326*cf5a6c84SAndroid Build Coastguard Worker
327*cf5a6c84SAndroid Build Coastguard Worker if (dd->pos & 32767) inflate_out(dd, dd->pos&32767);
328*cf5a6c84SAndroid Build Coastguard Worker }
329*cf5a6c84SAndroid Build Coastguard Worker
330*cf5a6c84SAndroid Build Coastguard Worker // Deflate from dd->infd to bitbuf
331*cf5a6c84SAndroid Build Coastguard Worker // For deflate, dd->len = input read, dd->pos = input consumed
deflate(struct deflate * dd,struct bitbuf * bb)332*cf5a6c84SAndroid Build Coastguard Worker static void deflate(struct deflate *dd, struct bitbuf *bb)
333*cf5a6c84SAndroid Build Coastguard Worker {
334*cf5a6c84SAndroid Build Coastguard Worker char *data = dd->data;
335*cf5a6c84SAndroid Build Coastguard Worker int len, final = 0;
336*cf5a6c84SAndroid Build Coastguard Worker
337*cf5a6c84SAndroid Build Coastguard Worker dd->crc = ~0;
338*cf5a6c84SAndroid Build Coastguard Worker
339*cf5a6c84SAndroid Build Coastguard Worker while (!final) {
340*cf5a6c84SAndroid Build Coastguard Worker // Read next half-window of data if we haven't hit EOF yet.
341*cf5a6c84SAndroid Build Coastguard Worker len = readall(dd->infd, data+(dd->len&32768), 32768);
342*cf5a6c84SAndroid Build Coastguard Worker if (len < 0) perror_exit("read"); // TODO: add filename
343*cf5a6c84SAndroid Build Coastguard Worker if (len != 32768) final++;
344*cf5a6c84SAndroid Build Coastguard Worker if (dd->crcfunc) dd->crcfunc(dd, data+(dd->len&32768), len);
345*cf5a6c84SAndroid Build Coastguard Worker // dd->len += len; crcfunc advances len TODO
346*cf5a6c84SAndroid Build Coastguard Worker
347*cf5a6c84SAndroid Build Coastguard Worker // store block as literal
348*cf5a6c84SAndroid Build Coastguard Worker // TODO: actually compress!
349*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, final, 1);
350*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, 0, 1);
351*cf5a6c84SAndroid Build Coastguard Worker
352*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, 0, (8-bb->bitpos)&7);
353*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, len, 16);
354*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, 0xffff & ~len, 16);
355*cf5a6c84SAndroid Build Coastguard Worker
356*cf5a6c84SAndroid Build Coastguard Worker // repeat until spanked
357*cf5a6c84SAndroid Build Coastguard Worker while (dd->pos != dd->len) {
358*cf5a6c84SAndroid Build Coastguard Worker unsigned pos = dd->pos&65535;
359*cf5a6c84SAndroid Build Coastguard Worker
360*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, data[pos], 8);
361*cf5a6c84SAndroid Build Coastguard Worker
362*cf5a6c84SAndroid Build Coastguard Worker // need to refill buffer?
363*cf5a6c84SAndroid Build Coastguard Worker if (!(32767 & ++dd->pos) && !final) break;
364*cf5a6c84SAndroid Build Coastguard Worker }
365*cf5a6c84SAndroid Build Coastguard Worker }
366*cf5a6c84SAndroid Build Coastguard Worker bitbuf_flush(bb);
367*cf5a6c84SAndroid Build Coastguard Worker }
368*cf5a6c84SAndroid Build Coastguard Worker
369*cf5a6c84SAndroid Build Coastguard Worker // Allocate memory for deflate/inflate.
init_deflate(int compress)370*cf5a6c84SAndroid Build Coastguard Worker static struct deflate *init_deflate(int compress)
371*cf5a6c84SAndroid Build Coastguard Worker {
372*cf5a6c84SAndroid Build Coastguard Worker int i, n = 1;
373*cf5a6c84SAndroid Build Coastguard Worker struct deflate *dd = xmalloc(sizeof(struct deflate)+32768*(compress ? 4 : 1));
374*cf5a6c84SAndroid Build Coastguard Worker
375*cf5a6c84SAndroid Build Coastguard Worker memset(dd, 0, sizeof(struct deflate));
376*cf5a6c84SAndroid Build Coastguard Worker // decompress needs 32k history, compress adds 64k hashhead and 32k hashchain
377*cf5a6c84SAndroid Build Coastguard Worker if (compress) {
378*cf5a6c84SAndroid Build Coastguard Worker dd->hashhead = (unsigned short *)(dd->data+65536);
379*cf5a6c84SAndroid Build Coastguard Worker dd->hashchain = (unsigned short *)(dd->data+65536+32768);
380*cf5a6c84SAndroid Build Coastguard Worker }
381*cf5a6c84SAndroid Build Coastguard Worker
382*cf5a6c84SAndroid Build Coastguard Worker // Calculate lenbits, lenbase, distbits, distbase
383*cf5a6c84SAndroid Build Coastguard Worker *dd->lenbase = 3;
384*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<sizeof(dd->lenbits)-1; i++) {
385*cf5a6c84SAndroid Build Coastguard Worker if (i>4) {
386*cf5a6c84SAndroid Build Coastguard Worker if (!(i&3)) {
387*cf5a6c84SAndroid Build Coastguard Worker dd->lenbits[i]++;
388*cf5a6c84SAndroid Build Coastguard Worker n <<= 1;
389*cf5a6c84SAndroid Build Coastguard Worker }
390*cf5a6c84SAndroid Build Coastguard Worker if (i == 27) n--;
391*cf5a6c84SAndroid Build Coastguard Worker else dd->lenbits[i+1] = dd->lenbits[i];
392*cf5a6c84SAndroid Build Coastguard Worker }
393*cf5a6c84SAndroid Build Coastguard Worker dd->lenbase[i+1] = n + dd->lenbase[i];
394*cf5a6c84SAndroid Build Coastguard Worker }
395*cf5a6c84SAndroid Build Coastguard Worker n = 0;
396*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<sizeof(dd->distbits); i++) {
397*cf5a6c84SAndroid Build Coastguard Worker dd->distbase[i] = 1<<n;
398*cf5a6c84SAndroid Build Coastguard Worker if (i) dd->distbase[i] += dd->distbase[i-1];
399*cf5a6c84SAndroid Build Coastguard Worker if (i>3 && !(i&1)) n++;
400*cf5a6c84SAndroid Build Coastguard Worker dd->distbits[i] = n;
401*cf5a6c84SAndroid Build Coastguard Worker }
402*cf5a6c84SAndroid Build Coastguard Worker
403*cf5a6c84SAndroid Build Coastguard Worker // TODO layout and lifetime of this?
404*cf5a6c84SAndroid Build Coastguard Worker // Init fixed huffman tables
405*cf5a6c84SAndroid Build Coastguard Worker for (i=0; i<288; i++) libbuf[i] = 8 + (i>143) - ((i>255)<<1) + (i>279);
406*cf5a6c84SAndroid Build Coastguard Worker len2huff(dd->fixlithuff = ((struct huff *)libbuf)+3, libbuf, 288);
407*cf5a6c84SAndroid Build Coastguard Worker memset(libbuf, 5, 30);
408*cf5a6c84SAndroid Build Coastguard Worker len2huff(dd->fixdisthuff = ((struct huff *)libbuf)+4, libbuf, 30);
409*cf5a6c84SAndroid Build Coastguard Worker
410*cf5a6c84SAndroid Build Coastguard Worker return dd;
411*cf5a6c84SAndroid Build Coastguard Worker }
412*cf5a6c84SAndroid Build Coastguard Worker
413*cf5a6c84SAndroid Build Coastguard Worker // Return true/false whether we consumed a gzip header.
is_gzip(struct bitbuf * bb)414*cf5a6c84SAndroid Build Coastguard Worker static int is_gzip(struct bitbuf *bb)
415*cf5a6c84SAndroid Build Coastguard Worker {
416*cf5a6c84SAndroid Build Coastguard Worker int flags;
417*cf5a6c84SAndroid Build Coastguard Worker
418*cf5a6c84SAndroid Build Coastguard Worker // Confirm signature
419*cf5a6c84SAndroid Build Coastguard Worker if (bitbuf_get(bb, 24) != 0x088b1f || (flags = bitbuf_get(bb, 8)) > 31)
420*cf5a6c84SAndroid Build Coastguard Worker return 0;
421*cf5a6c84SAndroid Build Coastguard Worker bitbuf_skip(bb, 6*8);
422*cf5a6c84SAndroid Build Coastguard Worker
423*cf5a6c84SAndroid Build Coastguard Worker // Skip extra, name, comment, header CRC fields
424*cf5a6c84SAndroid Build Coastguard Worker if (flags & 4) bitbuf_skip(bb, bitbuf_get(bb, 16) * 8);
425*cf5a6c84SAndroid Build Coastguard Worker if (flags & 8) while (bitbuf_get(bb, 8));
426*cf5a6c84SAndroid Build Coastguard Worker if (flags & 16) while (bitbuf_get(bb, 8));
427*cf5a6c84SAndroid Build Coastguard Worker if (flags & 2) bitbuf_skip(bb, 16);
428*cf5a6c84SAndroid Build Coastguard Worker
429*cf5a6c84SAndroid Build Coastguard Worker return 1;
430*cf5a6c84SAndroid Build Coastguard Worker }
431*cf5a6c84SAndroid Build Coastguard Worker
gzip_crc(struct deflate * dd,char * data,unsigned len)432*cf5a6c84SAndroid Build Coastguard Worker static void gzip_crc(struct deflate *dd, char *data, unsigned len)
433*cf5a6c84SAndroid Build Coastguard Worker {
434*cf5a6c84SAndroid Build Coastguard Worker int i;
435*cf5a6c84SAndroid Build Coastguard Worker unsigned crc, *crc_table = dd->crctable;
436*cf5a6c84SAndroid Build Coastguard Worker
437*cf5a6c84SAndroid Build Coastguard Worker crc = dd->crc;
438*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<len; i++) crc = crc_table[(crc^data[i])&0xff] ^ (crc>>8);
439*cf5a6c84SAndroid Build Coastguard Worker dd->crc = crc;
440*cf5a6c84SAndroid Build Coastguard Worker dd->len += len;
441*cf5a6c84SAndroid Build Coastguard Worker }
442*cf5a6c84SAndroid Build Coastguard Worker
443*cf5a6c84SAndroid Build Coastguard Worker /*
444*cf5a6c84SAndroid Build Coastguard Worker // Start with crc = 1, or pass in last crc to append more data
445*cf5a6c84SAndroid Build Coastguard Worker // Deferred modulus good for paged size inputs (can't overflow for ~5500 bytes)
446*cf5a6c84SAndroid Build Coastguard Worker unsigned adler32(char *buf, unsigned len, unsigned crc)
447*cf5a6c84SAndroid Build Coastguard Worker {
448*cf5a6c84SAndroid Build Coastguard Worker unsigned aa = crc&((1<<16)-1), bb = crc>>16;
449*cf5a6c84SAndroid Build Coastguard Worker
450*cf5a6c84SAndroid Build Coastguard Worker while (len--) {
451*cf5a6c84SAndroid Build Coastguard Worker aa += *buf++;
452*cf5a6c84SAndroid Build Coastguard Worker bb += aa;
453*cf5a6c84SAndroid Build Coastguard Worker }
454*cf5a6c84SAndroid Build Coastguard Worker
455*cf5a6c84SAndroid Build Coastguard Worker return ((bb%65521)<<16)+aa%65521;
456*cf5a6c84SAndroid Build Coastguard Worker }
457*cf5a6c84SAndroid Build Coastguard Worker */
458*cf5a6c84SAndroid Build Coastguard Worker
gzip_fd(int infd,int outfd)459*cf5a6c84SAndroid Build Coastguard Worker long long gzip_fd(int infd, int outfd)
460*cf5a6c84SAndroid Build Coastguard Worker {
461*cf5a6c84SAndroid Build Coastguard Worker struct bitbuf *bb = bitbuf_init(outfd, 4096);
462*cf5a6c84SAndroid Build Coastguard Worker struct deflate *dd = init_deflate(1);
463*cf5a6c84SAndroid Build Coastguard Worker long long rc;
464*cf5a6c84SAndroid Build Coastguard Worker
465*cf5a6c84SAndroid Build Coastguard Worker // Header from RFC 1952 section 2.2:
466*cf5a6c84SAndroid Build Coastguard Worker // 2 ID bytes (1F, 8b), gzip method byte (8=deflate), FLAG byte (none),
467*cf5a6c84SAndroid Build Coastguard Worker // 4 byte MTIME (zeroed), Extra Flags (2=maximum compression),
468*cf5a6c84SAndroid Build Coastguard Worker // Operating System (FF=unknown)
469*cf5a6c84SAndroid Build Coastguard Worker
470*cf5a6c84SAndroid Build Coastguard Worker dd->infd = infd;
471*cf5a6c84SAndroid Build Coastguard Worker xwrite(bb->fd, "\x1f\x8b\x08\0\0\0\0\0\x02\xff", 10);
472*cf5a6c84SAndroid Build Coastguard Worker
473*cf5a6c84SAndroid Build Coastguard Worker // Little endian crc table
474*cf5a6c84SAndroid Build Coastguard Worker crc_init(dd->crctable, 1);
475*cf5a6c84SAndroid Build Coastguard Worker dd->crcfunc = gzip_crc;
476*cf5a6c84SAndroid Build Coastguard Worker
477*cf5a6c84SAndroid Build Coastguard Worker deflate(dd, bb);
478*cf5a6c84SAndroid Build Coastguard Worker
479*cf5a6c84SAndroid Build Coastguard Worker // tail: crc32, len32
480*cf5a6c84SAndroid Build Coastguard Worker
481*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, 0, (8-bb->bitpos)&7);
482*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, ~dd->crc, 32);
483*cf5a6c84SAndroid Build Coastguard Worker bitbuf_put(bb, dd->len, 32);
484*cf5a6c84SAndroid Build Coastguard Worker rc = dd->len;
485*cf5a6c84SAndroid Build Coastguard Worker
486*cf5a6c84SAndroid Build Coastguard Worker bitbuf_flush(bb);
487*cf5a6c84SAndroid Build Coastguard Worker free(bb);
488*cf5a6c84SAndroid Build Coastguard Worker free(dd);
489*cf5a6c84SAndroid Build Coastguard Worker
490*cf5a6c84SAndroid Build Coastguard Worker return rc;
491*cf5a6c84SAndroid Build Coastguard Worker }
492*cf5a6c84SAndroid Build Coastguard Worker
gunzip_common(struct bitbuf * bb,struct deflate * dd)493*cf5a6c84SAndroid Build Coastguard Worker long long gunzip_common(struct bitbuf *bb, struct deflate *dd)
494*cf5a6c84SAndroid Build Coastguard Worker {
495*cf5a6c84SAndroid Build Coastguard Worker long long rc = 0;
496*cf5a6c84SAndroid Build Coastguard Worker
497*cf5a6c84SAndroid Build Coastguard Worker // Little endian crc table
498*cf5a6c84SAndroid Build Coastguard Worker crc_init(dd->crctable, 1);
499*cf5a6c84SAndroid Build Coastguard Worker dd->crcfunc = gzip_crc;
500*cf5a6c84SAndroid Build Coastguard Worker
501*cf5a6c84SAndroid Build Coastguard Worker do {
502*cf5a6c84SAndroid Build Coastguard Worker if (!is_gzip(bb)) error_exit("not gzip");
503*cf5a6c84SAndroid Build Coastguard Worker
504*cf5a6c84SAndroid Build Coastguard Worker inflate(dd, bb);
505*cf5a6c84SAndroid Build Coastguard Worker // tail: crc32, len32
506*cf5a6c84SAndroid Build Coastguard Worker bitbuf_skip(bb, (8-bb->bitpos)&7);
507*cf5a6c84SAndroid Build Coastguard Worker if (~dd->crc != bitbuf_get(bb, 32) || dd->len != bitbuf_get(bb, 32))
508*cf5a6c84SAndroid Build Coastguard Worker error_exit("bad crc");
509*cf5a6c84SAndroid Build Coastguard Worker rc += dd->len;
510*cf5a6c84SAndroid Build Coastguard Worker bitbuf_skip(bb, (8-bb->bitpos)&7);
511*cf5a6c84SAndroid Build Coastguard Worker dd->pos = dd->len = 0;
512*cf5a6c84SAndroid Build Coastguard Worker } while (bitbuf_skip(bb, 0));
513*cf5a6c84SAndroid Build Coastguard Worker free(bb);
514*cf5a6c84SAndroid Build Coastguard Worker free(dd);
515*cf5a6c84SAndroid Build Coastguard Worker
516*cf5a6c84SAndroid Build Coastguard Worker return rc;
517*cf5a6c84SAndroid Build Coastguard Worker }
518*cf5a6c84SAndroid Build Coastguard Worker
gunzip_mem(char * inbuf,int inlen,char * outbuf,int outlen)519*cf5a6c84SAndroid Build Coastguard Worker long long gunzip_mem(char *inbuf, int inlen, char *outbuf, int outlen)
520*cf5a6c84SAndroid Build Coastguard Worker {
521*cf5a6c84SAndroid Build Coastguard Worker struct bitbuf *bb = bitbuf_init(-1, 0);
522*cf5a6c84SAndroid Build Coastguard Worker struct deflate *dd = init_deflate(0);
523*cf5a6c84SAndroid Build Coastguard Worker
524*cf5a6c84SAndroid Build Coastguard Worker bb->buf = inbuf;
525*cf5a6c84SAndroid Build Coastguard Worker bb->max = bb->len = inlen;
526*cf5a6c84SAndroid Build Coastguard Worker dd->outfd = -1;
527*cf5a6c84SAndroid Build Coastguard Worker dd->outbuf = outbuf;
528*cf5a6c84SAndroid Build Coastguard Worker dd->outbuflen = outlen;
529*cf5a6c84SAndroid Build Coastguard Worker
530*cf5a6c84SAndroid Build Coastguard Worker return gunzip_common(bb, dd);
531*cf5a6c84SAndroid Build Coastguard Worker }
532*cf5a6c84SAndroid Build Coastguard Worker
gunzip_fd(int infd,int outfd)533*cf5a6c84SAndroid Build Coastguard Worker long long gunzip_fd(int infd, int outfd)
534*cf5a6c84SAndroid Build Coastguard Worker {
535*cf5a6c84SAndroid Build Coastguard Worker struct bitbuf *bb = bitbuf_init(infd, 4096);
536*cf5a6c84SAndroid Build Coastguard Worker struct deflate *dd = init_deflate(0);
537*cf5a6c84SAndroid Build Coastguard Worker
538*cf5a6c84SAndroid Build Coastguard Worker dd->outfd = outfd;
539*cf5a6c84SAndroid Build Coastguard Worker return gunzip_common(bb, dd);
540*cf5a6c84SAndroid Build Coastguard Worker }
541