1*1c60b9acSAndroid Build Coastguard Worker /* infback.c -- inflate using a call-back interface
2*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 1995-2009 Mark Adler
3*1c60b9acSAndroid Build Coastguard Worker * For conditions of distribution and use, see copyright notice in zlib.h
4*1c60b9acSAndroid Build Coastguard Worker */
5*1c60b9acSAndroid Build Coastguard Worker
6*1c60b9acSAndroid Build Coastguard Worker /*
7*1c60b9acSAndroid Build Coastguard Worker This code is largely copied from inflate.c. Normally either infback.o or
8*1c60b9acSAndroid Build Coastguard Worker inflate.o would be linked into an application--not both. The interface
9*1c60b9acSAndroid Build Coastguard Worker with inffast.c is retained so that optimized assembler-coded versions of
10*1c60b9acSAndroid Build Coastguard Worker inflate_fast() can be used with either inflate.c or infback.c.
11*1c60b9acSAndroid Build Coastguard Worker */
12*1c60b9acSAndroid Build Coastguard Worker
13*1c60b9acSAndroid Build Coastguard Worker #include "zutil.h"
14*1c60b9acSAndroid Build Coastguard Worker #include "inftrees.h"
15*1c60b9acSAndroid Build Coastguard Worker #include "inflate.h"
16*1c60b9acSAndroid Build Coastguard Worker #include "inffast.h"
17*1c60b9acSAndroid Build Coastguard Worker
18*1c60b9acSAndroid Build Coastguard Worker /* function prototypes */
19*1c60b9acSAndroid Build Coastguard Worker local void fixedtables OF((struct inflate_state FAR *state));
20*1c60b9acSAndroid Build Coastguard Worker
21*1c60b9acSAndroid Build Coastguard Worker /*
22*1c60b9acSAndroid Build Coastguard Worker strm provides memory allocation functions in zalloc and zfree, or
23*1c60b9acSAndroid Build Coastguard Worker Z_NULL to use the library memory allocation functions.
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker windowBits is in the range 8..15, and window is a user-supplied
26*1c60b9acSAndroid Build Coastguard Worker window and output buffer that is 2**windowBits bytes.
27*1c60b9acSAndroid Build Coastguard Worker */
inflateBackInit_(strm,windowBits,window,version,stream_size)28*1c60b9acSAndroid Build Coastguard Worker int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
29*1c60b9acSAndroid Build Coastguard Worker z_streamp strm;
30*1c60b9acSAndroid Build Coastguard Worker int windowBits;
31*1c60b9acSAndroid Build Coastguard Worker unsigned char FAR *window;
32*1c60b9acSAndroid Build Coastguard Worker const char *version;
33*1c60b9acSAndroid Build Coastguard Worker int stream_size;
34*1c60b9acSAndroid Build Coastguard Worker {
35*1c60b9acSAndroid Build Coastguard Worker struct inflate_state FAR *state;
36*1c60b9acSAndroid Build Coastguard Worker
37*1c60b9acSAndroid Build Coastguard Worker if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
38*1c60b9acSAndroid Build Coastguard Worker stream_size != (int)(sizeof(z_stream)))
39*1c60b9acSAndroid Build Coastguard Worker return Z_VERSION_ERROR;
40*1c60b9acSAndroid Build Coastguard Worker if (strm == Z_NULL || window == Z_NULL ||
41*1c60b9acSAndroid Build Coastguard Worker windowBits < 8 || windowBits > 15)
42*1c60b9acSAndroid Build Coastguard Worker return Z_STREAM_ERROR;
43*1c60b9acSAndroid Build Coastguard Worker strm->msg = Z_NULL; /* in case we return an error */
44*1c60b9acSAndroid Build Coastguard Worker if (strm->zalloc == (alloc_func)0) {
45*1c60b9acSAndroid Build Coastguard Worker strm->zalloc = zcalloc;
46*1c60b9acSAndroid Build Coastguard Worker strm->opaque = (voidpf)0;
47*1c60b9acSAndroid Build Coastguard Worker }
48*1c60b9acSAndroid Build Coastguard Worker if (strm->zfree == (free_func)0) strm->zfree = zcfree;
49*1c60b9acSAndroid Build Coastguard Worker state = (struct inflate_state FAR *)ZALLOC(strm, 1,
50*1c60b9acSAndroid Build Coastguard Worker sizeof(struct inflate_state));
51*1c60b9acSAndroid Build Coastguard Worker if (state == Z_NULL) return Z_MEM_ERROR;
52*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: allocated\n"));
53*1c60b9acSAndroid Build Coastguard Worker strm->state = (struct internal_state FAR *)state;
54*1c60b9acSAndroid Build Coastguard Worker state->dmax = 32768U;
55*1c60b9acSAndroid Build Coastguard Worker state->wbits = windowBits;
56*1c60b9acSAndroid Build Coastguard Worker state->wsize = 1U << windowBits;
57*1c60b9acSAndroid Build Coastguard Worker state->window = window;
58*1c60b9acSAndroid Build Coastguard Worker state->wnext = 0;
59*1c60b9acSAndroid Build Coastguard Worker state->whave = 0;
60*1c60b9acSAndroid Build Coastguard Worker return Z_OK;
61*1c60b9acSAndroid Build Coastguard Worker }
62*1c60b9acSAndroid Build Coastguard Worker
63*1c60b9acSAndroid Build Coastguard Worker /*
64*1c60b9acSAndroid Build Coastguard Worker Return state with length and distance decoding tables and index sizes set to
65*1c60b9acSAndroid Build Coastguard Worker fixed code decoding. Normally this returns fixed tables from inffixed.h.
66*1c60b9acSAndroid Build Coastguard Worker If BUILDFIXED is defined, then instead this routine builds the tables the
67*1c60b9acSAndroid Build Coastguard Worker first time it's called, and returns those tables the first time and
68*1c60b9acSAndroid Build Coastguard Worker thereafter. This reduces the size of the code by about 2K bytes, in
69*1c60b9acSAndroid Build Coastguard Worker exchange for a little execution time. However, BUILDFIXED should not be
70*1c60b9acSAndroid Build Coastguard Worker used for threaded applications, since the rewriting of the tables and virgin
71*1c60b9acSAndroid Build Coastguard Worker may not be thread-safe.
72*1c60b9acSAndroid Build Coastguard Worker */
fixedtables(state)73*1c60b9acSAndroid Build Coastguard Worker local void fixedtables(state)
74*1c60b9acSAndroid Build Coastguard Worker struct inflate_state FAR *state;
75*1c60b9acSAndroid Build Coastguard Worker {
76*1c60b9acSAndroid Build Coastguard Worker #ifdef BUILDFIXED
77*1c60b9acSAndroid Build Coastguard Worker static int virgin = 1;
78*1c60b9acSAndroid Build Coastguard Worker static code *lenfix, *distfix;
79*1c60b9acSAndroid Build Coastguard Worker static code fixed[544];
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker /* build fixed huffman tables if first call (may not be thread safe) */
82*1c60b9acSAndroid Build Coastguard Worker if (virgin) {
83*1c60b9acSAndroid Build Coastguard Worker unsigned sym, bits;
84*1c60b9acSAndroid Build Coastguard Worker static code *next;
85*1c60b9acSAndroid Build Coastguard Worker
86*1c60b9acSAndroid Build Coastguard Worker /* literal/length table */
87*1c60b9acSAndroid Build Coastguard Worker sym = 0;
88*1c60b9acSAndroid Build Coastguard Worker while (sym < 144) state->lens[sym++] = 8;
89*1c60b9acSAndroid Build Coastguard Worker while (sym < 256) state->lens[sym++] = 9;
90*1c60b9acSAndroid Build Coastguard Worker while (sym < 280) state->lens[sym++] = 7;
91*1c60b9acSAndroid Build Coastguard Worker while (sym < 288) state->lens[sym++] = 8;
92*1c60b9acSAndroid Build Coastguard Worker next = fixed;
93*1c60b9acSAndroid Build Coastguard Worker lenfix = next;
94*1c60b9acSAndroid Build Coastguard Worker bits = 9;
95*1c60b9acSAndroid Build Coastguard Worker inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
96*1c60b9acSAndroid Build Coastguard Worker
97*1c60b9acSAndroid Build Coastguard Worker /* distance table */
98*1c60b9acSAndroid Build Coastguard Worker sym = 0;
99*1c60b9acSAndroid Build Coastguard Worker while (sym < 32) state->lens[sym++] = 5;
100*1c60b9acSAndroid Build Coastguard Worker distfix = next;
101*1c60b9acSAndroid Build Coastguard Worker bits = 5;
102*1c60b9acSAndroid Build Coastguard Worker inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
103*1c60b9acSAndroid Build Coastguard Worker
104*1c60b9acSAndroid Build Coastguard Worker /* do this just once */
105*1c60b9acSAndroid Build Coastguard Worker virgin = 0;
106*1c60b9acSAndroid Build Coastguard Worker }
107*1c60b9acSAndroid Build Coastguard Worker #else /* !BUILDFIXED */
108*1c60b9acSAndroid Build Coastguard Worker # include "inffixed.h"
109*1c60b9acSAndroid Build Coastguard Worker #endif /* BUILDFIXED */
110*1c60b9acSAndroid Build Coastguard Worker state->lencode = lenfix;
111*1c60b9acSAndroid Build Coastguard Worker state->lenbits = 9;
112*1c60b9acSAndroid Build Coastguard Worker state->distcode = distfix;
113*1c60b9acSAndroid Build Coastguard Worker state->distbits = 5;
114*1c60b9acSAndroid Build Coastguard Worker }
115*1c60b9acSAndroid Build Coastguard Worker
116*1c60b9acSAndroid Build Coastguard Worker /* Macros for inflateBack(): */
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker /* Load returned state from inflate_fast() */
119*1c60b9acSAndroid Build Coastguard Worker #define LOAD() \
120*1c60b9acSAndroid Build Coastguard Worker do { \
121*1c60b9acSAndroid Build Coastguard Worker put = strm->next_out; \
122*1c60b9acSAndroid Build Coastguard Worker left = strm->avail_out; \
123*1c60b9acSAndroid Build Coastguard Worker next = strm->next_in; \
124*1c60b9acSAndroid Build Coastguard Worker have = strm->avail_in; \
125*1c60b9acSAndroid Build Coastguard Worker hold = state->hold; \
126*1c60b9acSAndroid Build Coastguard Worker bits = state->bits; \
127*1c60b9acSAndroid Build Coastguard Worker } while (0)
128*1c60b9acSAndroid Build Coastguard Worker
129*1c60b9acSAndroid Build Coastguard Worker /* Set state from registers for inflate_fast() */
130*1c60b9acSAndroid Build Coastguard Worker #define RESTORE() \
131*1c60b9acSAndroid Build Coastguard Worker do { \
132*1c60b9acSAndroid Build Coastguard Worker strm->next_out = put; \
133*1c60b9acSAndroid Build Coastguard Worker strm->avail_out = left; \
134*1c60b9acSAndroid Build Coastguard Worker strm->next_in = next; \
135*1c60b9acSAndroid Build Coastguard Worker strm->avail_in = have; \
136*1c60b9acSAndroid Build Coastguard Worker state->hold = hold; \
137*1c60b9acSAndroid Build Coastguard Worker state->bits = bits; \
138*1c60b9acSAndroid Build Coastguard Worker } while (0)
139*1c60b9acSAndroid Build Coastguard Worker
140*1c60b9acSAndroid Build Coastguard Worker /* Clear the input bit accumulator */
141*1c60b9acSAndroid Build Coastguard Worker #define INITBITS() \
142*1c60b9acSAndroid Build Coastguard Worker do { \
143*1c60b9acSAndroid Build Coastguard Worker hold = 0; \
144*1c60b9acSAndroid Build Coastguard Worker bits = 0; \
145*1c60b9acSAndroid Build Coastguard Worker } while (0)
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker /* Assure that some input is available. If input is requested, but denied,
148*1c60b9acSAndroid Build Coastguard Worker then return a Z_BUF_ERROR from inflateBack(). */
149*1c60b9acSAndroid Build Coastguard Worker #define PULL() \
150*1c60b9acSAndroid Build Coastguard Worker do { \
151*1c60b9acSAndroid Build Coastguard Worker if (have == 0) { \
152*1c60b9acSAndroid Build Coastguard Worker have = in(in_desc, &next); \
153*1c60b9acSAndroid Build Coastguard Worker if (have == 0) { \
154*1c60b9acSAndroid Build Coastguard Worker next = Z_NULL; \
155*1c60b9acSAndroid Build Coastguard Worker ret = Z_BUF_ERROR; \
156*1c60b9acSAndroid Build Coastguard Worker goto inf_leave; \
157*1c60b9acSAndroid Build Coastguard Worker } \
158*1c60b9acSAndroid Build Coastguard Worker } \
159*1c60b9acSAndroid Build Coastguard Worker } while (0)
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker /* Get a byte of input into the bit accumulator, or return from inflateBack()
162*1c60b9acSAndroid Build Coastguard Worker with an error if there is no input available. */
163*1c60b9acSAndroid Build Coastguard Worker #define PULLBYTE() \
164*1c60b9acSAndroid Build Coastguard Worker do { \
165*1c60b9acSAndroid Build Coastguard Worker PULL(); \
166*1c60b9acSAndroid Build Coastguard Worker have--; \
167*1c60b9acSAndroid Build Coastguard Worker hold += (unsigned long)(*next++) << bits; \
168*1c60b9acSAndroid Build Coastguard Worker bits += 8; \
169*1c60b9acSAndroid Build Coastguard Worker } while (0)
170*1c60b9acSAndroid Build Coastguard Worker
171*1c60b9acSAndroid Build Coastguard Worker /* Assure that there are at least n bits in the bit accumulator. If there is
172*1c60b9acSAndroid Build Coastguard Worker not enough available input to do that, then return from inflateBack() with
173*1c60b9acSAndroid Build Coastguard Worker an error. */
174*1c60b9acSAndroid Build Coastguard Worker #define NEEDBITS(n) \
175*1c60b9acSAndroid Build Coastguard Worker do { \
176*1c60b9acSAndroid Build Coastguard Worker while (bits < (unsigned)(n)) \
177*1c60b9acSAndroid Build Coastguard Worker PULLBYTE(); \
178*1c60b9acSAndroid Build Coastguard Worker } while (0)
179*1c60b9acSAndroid Build Coastguard Worker
180*1c60b9acSAndroid Build Coastguard Worker /* Return the low n bits of the bit accumulator (n < 16) */
181*1c60b9acSAndroid Build Coastguard Worker #define BITS(n) \
182*1c60b9acSAndroid Build Coastguard Worker ((unsigned)hold & ((1U << (n)) - 1))
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker /* Remove n bits from the bit accumulator */
185*1c60b9acSAndroid Build Coastguard Worker #define DROPBITS(n) \
186*1c60b9acSAndroid Build Coastguard Worker do { \
187*1c60b9acSAndroid Build Coastguard Worker hold >>= (n); \
188*1c60b9acSAndroid Build Coastguard Worker bits -= (unsigned)(n); \
189*1c60b9acSAndroid Build Coastguard Worker } while (0)
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker /* Remove zero to seven bits as needed to go to a byte boundary */
192*1c60b9acSAndroid Build Coastguard Worker #define BYTEBITS() \
193*1c60b9acSAndroid Build Coastguard Worker do { \
194*1c60b9acSAndroid Build Coastguard Worker hold >>= bits & 7; \
195*1c60b9acSAndroid Build Coastguard Worker bits -= bits & 7; \
196*1c60b9acSAndroid Build Coastguard Worker } while (0)
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker /* Assure that some output space is available, by writing out the window
199*1c60b9acSAndroid Build Coastguard Worker if it's full. If the write fails, return from inflateBack() with a
200*1c60b9acSAndroid Build Coastguard Worker Z_BUF_ERROR. */
201*1c60b9acSAndroid Build Coastguard Worker #define ROOM() \
202*1c60b9acSAndroid Build Coastguard Worker do { \
203*1c60b9acSAndroid Build Coastguard Worker if (left == 0) { \
204*1c60b9acSAndroid Build Coastguard Worker put = state->window; \
205*1c60b9acSAndroid Build Coastguard Worker left = state->wsize; \
206*1c60b9acSAndroid Build Coastguard Worker state->whave = left; \
207*1c60b9acSAndroid Build Coastguard Worker if (out(out_desc, put, left)) { \
208*1c60b9acSAndroid Build Coastguard Worker ret = Z_BUF_ERROR; \
209*1c60b9acSAndroid Build Coastguard Worker goto inf_leave; \
210*1c60b9acSAndroid Build Coastguard Worker } \
211*1c60b9acSAndroid Build Coastguard Worker } \
212*1c60b9acSAndroid Build Coastguard Worker } while (0)
213*1c60b9acSAndroid Build Coastguard Worker
214*1c60b9acSAndroid Build Coastguard Worker /*
215*1c60b9acSAndroid Build Coastguard Worker strm provides the memory allocation functions and window buffer on input,
216*1c60b9acSAndroid Build Coastguard Worker and provides information on the unused input on return. For Z_DATA_ERROR
217*1c60b9acSAndroid Build Coastguard Worker returns, strm will also provide an error message.
218*1c60b9acSAndroid Build Coastguard Worker
219*1c60b9acSAndroid Build Coastguard Worker in() and out() are the call-back input and output functions. When
220*1c60b9acSAndroid Build Coastguard Worker inflateBack() needs more input, it calls in(). When inflateBack() has
221*1c60b9acSAndroid Build Coastguard Worker filled the window with output, or when it completes with data in the
222*1c60b9acSAndroid Build Coastguard Worker window, it calls out() to write out the data. The application must not
223*1c60b9acSAndroid Build Coastguard Worker change the provided input until in() is called again or inflateBack()
224*1c60b9acSAndroid Build Coastguard Worker returns. The application must not change the window/output buffer until
225*1c60b9acSAndroid Build Coastguard Worker inflateBack() returns.
226*1c60b9acSAndroid Build Coastguard Worker
227*1c60b9acSAndroid Build Coastguard Worker in() and out() are called with a descriptor parameter provided in the
228*1c60b9acSAndroid Build Coastguard Worker inflateBack() call. This parameter can be a structure that provides the
229*1c60b9acSAndroid Build Coastguard Worker information required to do the read or write, as well as accumulated
230*1c60b9acSAndroid Build Coastguard Worker information on the input and output such as totals and check values.
231*1c60b9acSAndroid Build Coastguard Worker
232*1c60b9acSAndroid Build Coastguard Worker in() should return zero on failure. out() should return non-zero on
233*1c60b9acSAndroid Build Coastguard Worker failure. If either in() or out() fails, than inflateBack() returns a
234*1c60b9acSAndroid Build Coastguard Worker Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
235*1c60b9acSAndroid Build Coastguard Worker was in() or out() that caused in the error. Otherwise, inflateBack()
236*1c60b9acSAndroid Build Coastguard Worker returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
237*1c60b9acSAndroid Build Coastguard Worker error, or Z_MEM_ERROR if it could not allocate memory for the state.
238*1c60b9acSAndroid Build Coastguard Worker inflateBack() can also return Z_STREAM_ERROR if the input parameters
239*1c60b9acSAndroid Build Coastguard Worker are not correct, i.e. strm is Z_NULL or the state was not initialized.
240*1c60b9acSAndroid Build Coastguard Worker */
inflateBack(strm,in,in_desc,out,out_desc)241*1c60b9acSAndroid Build Coastguard Worker int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
242*1c60b9acSAndroid Build Coastguard Worker z_streamp strm;
243*1c60b9acSAndroid Build Coastguard Worker in_func in;
244*1c60b9acSAndroid Build Coastguard Worker void FAR *in_desc;
245*1c60b9acSAndroid Build Coastguard Worker out_func out;
246*1c60b9acSAndroid Build Coastguard Worker void FAR *out_desc;
247*1c60b9acSAndroid Build Coastguard Worker {
248*1c60b9acSAndroid Build Coastguard Worker struct inflate_state FAR *state;
249*1c60b9acSAndroid Build Coastguard Worker unsigned char FAR *next; /* next input */
250*1c60b9acSAndroid Build Coastguard Worker unsigned char FAR *put; /* next output */
251*1c60b9acSAndroid Build Coastguard Worker unsigned have, left; /* available input and output */
252*1c60b9acSAndroid Build Coastguard Worker unsigned long hold; /* bit buffer */
253*1c60b9acSAndroid Build Coastguard Worker unsigned bits; /* bits in bit buffer */
254*1c60b9acSAndroid Build Coastguard Worker unsigned copy; /* number of stored or match bytes to copy */
255*1c60b9acSAndroid Build Coastguard Worker unsigned char FAR *from; /* where to copy match bytes from */
256*1c60b9acSAndroid Build Coastguard Worker code here; /* current decoding table entry */
257*1c60b9acSAndroid Build Coastguard Worker code last; /* parent table entry */
258*1c60b9acSAndroid Build Coastguard Worker unsigned len; /* length to copy for repeats, bits to drop */
259*1c60b9acSAndroid Build Coastguard Worker int ret; /* return code */
260*1c60b9acSAndroid Build Coastguard Worker static const unsigned short order[19] = /* permutation of code lengths */
261*1c60b9acSAndroid Build Coastguard Worker {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
262*1c60b9acSAndroid Build Coastguard Worker
263*1c60b9acSAndroid Build Coastguard Worker /* Check that the strm exists and that the state was initialized */
264*1c60b9acSAndroid Build Coastguard Worker if (strm == Z_NULL || strm->state == Z_NULL)
265*1c60b9acSAndroid Build Coastguard Worker return Z_STREAM_ERROR;
266*1c60b9acSAndroid Build Coastguard Worker state = (struct inflate_state FAR *)strm->state;
267*1c60b9acSAndroid Build Coastguard Worker
268*1c60b9acSAndroid Build Coastguard Worker /* Reset the state */
269*1c60b9acSAndroid Build Coastguard Worker strm->msg = Z_NULL;
270*1c60b9acSAndroid Build Coastguard Worker state->mode = TYPE;
271*1c60b9acSAndroid Build Coastguard Worker state->last = 0;
272*1c60b9acSAndroid Build Coastguard Worker state->whave = 0;
273*1c60b9acSAndroid Build Coastguard Worker next = strm->next_in;
274*1c60b9acSAndroid Build Coastguard Worker have = next != Z_NULL ? strm->avail_in : 0;
275*1c60b9acSAndroid Build Coastguard Worker hold = 0;
276*1c60b9acSAndroid Build Coastguard Worker bits = 0;
277*1c60b9acSAndroid Build Coastguard Worker put = state->window;
278*1c60b9acSAndroid Build Coastguard Worker left = state->wsize;
279*1c60b9acSAndroid Build Coastguard Worker
280*1c60b9acSAndroid Build Coastguard Worker /* Inflate until end of block marked as last */
281*1c60b9acSAndroid Build Coastguard Worker for (;;)
282*1c60b9acSAndroid Build Coastguard Worker switch (state->mode) {
283*1c60b9acSAndroid Build Coastguard Worker case TYPE:
284*1c60b9acSAndroid Build Coastguard Worker /* determine and dispatch block type */
285*1c60b9acSAndroid Build Coastguard Worker if (state->last) {
286*1c60b9acSAndroid Build Coastguard Worker BYTEBITS();
287*1c60b9acSAndroid Build Coastguard Worker state->mode = DONE;
288*1c60b9acSAndroid Build Coastguard Worker break;
289*1c60b9acSAndroid Build Coastguard Worker }
290*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(3);
291*1c60b9acSAndroid Build Coastguard Worker state->last = BITS(1);
292*1c60b9acSAndroid Build Coastguard Worker DROPBITS(1);
293*1c60b9acSAndroid Build Coastguard Worker switch (BITS(2)) {
294*1c60b9acSAndroid Build Coastguard Worker case 0: /* stored block */
295*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: stored block%s\n",
296*1c60b9acSAndroid Build Coastguard Worker state->last ? " (last)" : ""));
297*1c60b9acSAndroid Build Coastguard Worker state->mode = STORED;
298*1c60b9acSAndroid Build Coastguard Worker break;
299*1c60b9acSAndroid Build Coastguard Worker case 1: /* fixed block */
300*1c60b9acSAndroid Build Coastguard Worker fixedtables(state);
301*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: fixed codes block%s\n",
302*1c60b9acSAndroid Build Coastguard Worker state->last ? " (last)" : ""));
303*1c60b9acSAndroid Build Coastguard Worker state->mode = LEN; /* decode codes */
304*1c60b9acSAndroid Build Coastguard Worker break;
305*1c60b9acSAndroid Build Coastguard Worker case 2: /* dynamic block */
306*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: dynamic codes block%s\n",
307*1c60b9acSAndroid Build Coastguard Worker state->last ? " (last)" : ""));
308*1c60b9acSAndroid Build Coastguard Worker state->mode = TABLE;
309*1c60b9acSAndroid Build Coastguard Worker break;
310*1c60b9acSAndroid Build Coastguard Worker case 3:
311*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid block type";
312*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
313*1c60b9acSAndroid Build Coastguard Worker }
314*1c60b9acSAndroid Build Coastguard Worker DROPBITS(2);
315*1c60b9acSAndroid Build Coastguard Worker break;
316*1c60b9acSAndroid Build Coastguard Worker
317*1c60b9acSAndroid Build Coastguard Worker case STORED:
318*1c60b9acSAndroid Build Coastguard Worker /* get and verify stored block length */
319*1c60b9acSAndroid Build Coastguard Worker BYTEBITS(); /* go to byte boundary */
320*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(32);
321*1c60b9acSAndroid Build Coastguard Worker if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
322*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid stored block lengths";
323*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
324*1c60b9acSAndroid Build Coastguard Worker break;
325*1c60b9acSAndroid Build Coastguard Worker }
326*1c60b9acSAndroid Build Coastguard Worker state->length = (unsigned)hold & 0xffff;
327*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: stored length %u\n",
328*1c60b9acSAndroid Build Coastguard Worker state->length));
329*1c60b9acSAndroid Build Coastguard Worker INITBITS();
330*1c60b9acSAndroid Build Coastguard Worker
331*1c60b9acSAndroid Build Coastguard Worker /* copy stored block from input to output */
332*1c60b9acSAndroid Build Coastguard Worker while (state->length != 0) {
333*1c60b9acSAndroid Build Coastguard Worker copy = state->length;
334*1c60b9acSAndroid Build Coastguard Worker PULL();
335*1c60b9acSAndroid Build Coastguard Worker ROOM();
336*1c60b9acSAndroid Build Coastguard Worker if (copy > have) copy = have;
337*1c60b9acSAndroid Build Coastguard Worker if (copy > left) copy = left;
338*1c60b9acSAndroid Build Coastguard Worker zmemcpy(put, next, copy);
339*1c60b9acSAndroid Build Coastguard Worker have -= copy;
340*1c60b9acSAndroid Build Coastguard Worker next += copy;
341*1c60b9acSAndroid Build Coastguard Worker left -= copy;
342*1c60b9acSAndroid Build Coastguard Worker put += copy;
343*1c60b9acSAndroid Build Coastguard Worker state->length -= copy;
344*1c60b9acSAndroid Build Coastguard Worker }
345*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: stored end\n"));
346*1c60b9acSAndroid Build Coastguard Worker state->mode = TYPE;
347*1c60b9acSAndroid Build Coastguard Worker break;
348*1c60b9acSAndroid Build Coastguard Worker
349*1c60b9acSAndroid Build Coastguard Worker case TABLE:
350*1c60b9acSAndroid Build Coastguard Worker /* get dynamic table entries descriptor */
351*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(14);
352*1c60b9acSAndroid Build Coastguard Worker state->nlen = BITS(5) + 257;
353*1c60b9acSAndroid Build Coastguard Worker DROPBITS(5);
354*1c60b9acSAndroid Build Coastguard Worker state->ndist = BITS(5) + 1;
355*1c60b9acSAndroid Build Coastguard Worker DROPBITS(5);
356*1c60b9acSAndroid Build Coastguard Worker state->ncode = BITS(4) + 4;
357*1c60b9acSAndroid Build Coastguard Worker DROPBITS(4);
358*1c60b9acSAndroid Build Coastguard Worker #ifndef PKZIP_BUG_WORKAROUND
359*1c60b9acSAndroid Build Coastguard Worker if (state->nlen > 286 || state->ndist > 30) {
360*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"too many length or distance symbols";
361*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
362*1c60b9acSAndroid Build Coastguard Worker break;
363*1c60b9acSAndroid Build Coastguard Worker }
364*1c60b9acSAndroid Build Coastguard Worker #endif
365*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: table sizes ok\n"));
366*1c60b9acSAndroid Build Coastguard Worker
367*1c60b9acSAndroid Build Coastguard Worker /* get code length code lengths (not a typo) */
368*1c60b9acSAndroid Build Coastguard Worker state->have = 0;
369*1c60b9acSAndroid Build Coastguard Worker while (state->have < state->ncode) {
370*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(3);
371*1c60b9acSAndroid Build Coastguard Worker state->lens[order[state->have++]] = (unsigned short)BITS(3);
372*1c60b9acSAndroid Build Coastguard Worker DROPBITS(3);
373*1c60b9acSAndroid Build Coastguard Worker }
374*1c60b9acSAndroid Build Coastguard Worker while (state->have < 19)
375*1c60b9acSAndroid Build Coastguard Worker state->lens[order[state->have++]] = 0;
376*1c60b9acSAndroid Build Coastguard Worker state->next = state->codes;
377*1c60b9acSAndroid Build Coastguard Worker state->lencode = (code const FAR *)(state->next);
378*1c60b9acSAndroid Build Coastguard Worker state->lenbits = 7;
379*1c60b9acSAndroid Build Coastguard Worker ret = inflate_table(CODES, state->lens, 19, &(state->next),
380*1c60b9acSAndroid Build Coastguard Worker &(state->lenbits), state->work);
381*1c60b9acSAndroid Build Coastguard Worker if (ret) {
382*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid code lengths set";
383*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
384*1c60b9acSAndroid Build Coastguard Worker break;
385*1c60b9acSAndroid Build Coastguard Worker }
386*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: code lengths ok\n"));
387*1c60b9acSAndroid Build Coastguard Worker
388*1c60b9acSAndroid Build Coastguard Worker /* get length and distance code code lengths */
389*1c60b9acSAndroid Build Coastguard Worker state->have = 0;
390*1c60b9acSAndroid Build Coastguard Worker while (state->have < state->nlen + state->ndist) {
391*1c60b9acSAndroid Build Coastguard Worker for (;;) {
392*1c60b9acSAndroid Build Coastguard Worker here = state->lencode[BITS(state->lenbits)];
393*1c60b9acSAndroid Build Coastguard Worker if ((unsigned)(here.bits) <= bits) break;
394*1c60b9acSAndroid Build Coastguard Worker PULLBYTE();
395*1c60b9acSAndroid Build Coastguard Worker }
396*1c60b9acSAndroid Build Coastguard Worker if (here.val < 16) {
397*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(here.bits);
398*1c60b9acSAndroid Build Coastguard Worker DROPBITS(here.bits);
399*1c60b9acSAndroid Build Coastguard Worker state->lens[state->have++] = here.val;
400*1c60b9acSAndroid Build Coastguard Worker }
401*1c60b9acSAndroid Build Coastguard Worker else {
402*1c60b9acSAndroid Build Coastguard Worker if (here.val == 16) {
403*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(here.bits + 2);
404*1c60b9acSAndroid Build Coastguard Worker DROPBITS(here.bits);
405*1c60b9acSAndroid Build Coastguard Worker if (state->have == 0) {
406*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid bit length repeat";
407*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
408*1c60b9acSAndroid Build Coastguard Worker break;
409*1c60b9acSAndroid Build Coastguard Worker }
410*1c60b9acSAndroid Build Coastguard Worker len = (unsigned)(state->lens[state->have - 1]);
411*1c60b9acSAndroid Build Coastguard Worker copy = 3 + BITS(2);
412*1c60b9acSAndroid Build Coastguard Worker DROPBITS(2);
413*1c60b9acSAndroid Build Coastguard Worker }
414*1c60b9acSAndroid Build Coastguard Worker else if (here.val == 17) {
415*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(here.bits + 3);
416*1c60b9acSAndroid Build Coastguard Worker DROPBITS(here.bits);
417*1c60b9acSAndroid Build Coastguard Worker len = 0;
418*1c60b9acSAndroid Build Coastguard Worker copy = 3 + BITS(3);
419*1c60b9acSAndroid Build Coastguard Worker DROPBITS(3);
420*1c60b9acSAndroid Build Coastguard Worker }
421*1c60b9acSAndroid Build Coastguard Worker else {
422*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(here.bits + 7);
423*1c60b9acSAndroid Build Coastguard Worker DROPBITS(here.bits);
424*1c60b9acSAndroid Build Coastguard Worker len = 0;
425*1c60b9acSAndroid Build Coastguard Worker copy = 11 + BITS(7);
426*1c60b9acSAndroid Build Coastguard Worker DROPBITS(7);
427*1c60b9acSAndroid Build Coastguard Worker }
428*1c60b9acSAndroid Build Coastguard Worker if (state->have + copy > state->nlen + state->ndist) {
429*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid bit length repeat";
430*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
431*1c60b9acSAndroid Build Coastguard Worker break;
432*1c60b9acSAndroid Build Coastguard Worker }
433*1c60b9acSAndroid Build Coastguard Worker while (copy--)
434*1c60b9acSAndroid Build Coastguard Worker state->lens[state->have++] = (unsigned short)len;
435*1c60b9acSAndroid Build Coastguard Worker }
436*1c60b9acSAndroid Build Coastguard Worker }
437*1c60b9acSAndroid Build Coastguard Worker
438*1c60b9acSAndroid Build Coastguard Worker /* handle error breaks in while */
439*1c60b9acSAndroid Build Coastguard Worker if (state->mode == BAD) break;
440*1c60b9acSAndroid Build Coastguard Worker
441*1c60b9acSAndroid Build Coastguard Worker /* check for end-of-block code (better have one) */
442*1c60b9acSAndroid Build Coastguard Worker if (state->lens[256] == 0) {
443*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid code -- missing end-of-block";
444*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
445*1c60b9acSAndroid Build Coastguard Worker break;
446*1c60b9acSAndroid Build Coastguard Worker }
447*1c60b9acSAndroid Build Coastguard Worker
448*1c60b9acSAndroid Build Coastguard Worker /* build code tables -- note: do not change the lenbits or distbits
449*1c60b9acSAndroid Build Coastguard Worker values here (9 and 6) without reading the comments in inftrees.h
450*1c60b9acSAndroid Build Coastguard Worker concerning the ENOUGH constants, which depend on those values */
451*1c60b9acSAndroid Build Coastguard Worker state->next = state->codes;
452*1c60b9acSAndroid Build Coastguard Worker state->lencode = (code const FAR *)(state->next);
453*1c60b9acSAndroid Build Coastguard Worker state->lenbits = 9;
454*1c60b9acSAndroid Build Coastguard Worker ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
455*1c60b9acSAndroid Build Coastguard Worker &(state->lenbits), state->work);
456*1c60b9acSAndroid Build Coastguard Worker if (ret) {
457*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid literal/lengths set";
458*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
459*1c60b9acSAndroid Build Coastguard Worker break;
460*1c60b9acSAndroid Build Coastguard Worker }
461*1c60b9acSAndroid Build Coastguard Worker state->distcode = (code const FAR *)(state->next);
462*1c60b9acSAndroid Build Coastguard Worker state->distbits = 6;
463*1c60b9acSAndroid Build Coastguard Worker ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
464*1c60b9acSAndroid Build Coastguard Worker &(state->next), &(state->distbits), state->work);
465*1c60b9acSAndroid Build Coastguard Worker if (ret) {
466*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid distances set";
467*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
468*1c60b9acSAndroid Build Coastguard Worker break;
469*1c60b9acSAndroid Build Coastguard Worker }
470*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: codes ok\n"));
471*1c60b9acSAndroid Build Coastguard Worker state->mode = LEN;
472*1c60b9acSAndroid Build Coastguard Worker
473*1c60b9acSAndroid Build Coastguard Worker case LEN:
474*1c60b9acSAndroid Build Coastguard Worker /* use inflate_fast() if we have enough input and output */
475*1c60b9acSAndroid Build Coastguard Worker if (have >= 6 && left >= 258) {
476*1c60b9acSAndroid Build Coastguard Worker RESTORE();
477*1c60b9acSAndroid Build Coastguard Worker if (state->whave < state->wsize)
478*1c60b9acSAndroid Build Coastguard Worker state->whave = state->wsize - left;
479*1c60b9acSAndroid Build Coastguard Worker inflate_fast(strm, state->wsize);
480*1c60b9acSAndroid Build Coastguard Worker LOAD();
481*1c60b9acSAndroid Build Coastguard Worker break;
482*1c60b9acSAndroid Build Coastguard Worker }
483*1c60b9acSAndroid Build Coastguard Worker
484*1c60b9acSAndroid Build Coastguard Worker /* get a literal, length, or end-of-block code */
485*1c60b9acSAndroid Build Coastguard Worker for (;;) {
486*1c60b9acSAndroid Build Coastguard Worker here = state->lencode[BITS(state->lenbits)];
487*1c60b9acSAndroid Build Coastguard Worker if ((unsigned)(here.bits) <= bits) break;
488*1c60b9acSAndroid Build Coastguard Worker PULLBYTE();
489*1c60b9acSAndroid Build Coastguard Worker }
490*1c60b9acSAndroid Build Coastguard Worker if (here.op && (here.op & 0xf0) == 0) {
491*1c60b9acSAndroid Build Coastguard Worker last = here;
492*1c60b9acSAndroid Build Coastguard Worker for (;;) {
493*1c60b9acSAndroid Build Coastguard Worker here = state->lencode[last.val +
494*1c60b9acSAndroid Build Coastguard Worker (BITS(last.bits + last.op) >> last.bits)];
495*1c60b9acSAndroid Build Coastguard Worker if ((unsigned)(last.bits + here.bits) <= bits) break;
496*1c60b9acSAndroid Build Coastguard Worker PULLBYTE();
497*1c60b9acSAndroid Build Coastguard Worker }
498*1c60b9acSAndroid Build Coastguard Worker DROPBITS(last.bits);
499*1c60b9acSAndroid Build Coastguard Worker }
500*1c60b9acSAndroid Build Coastguard Worker DROPBITS(here.bits);
501*1c60b9acSAndroid Build Coastguard Worker state->length = (unsigned)here.val;
502*1c60b9acSAndroid Build Coastguard Worker
503*1c60b9acSAndroid Build Coastguard Worker /* process literal */
504*1c60b9acSAndroid Build Coastguard Worker if (here.op == 0) {
505*1c60b9acSAndroid Build Coastguard Worker Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
506*1c60b9acSAndroid Build Coastguard Worker "inflate: literal '%c'\n" :
507*1c60b9acSAndroid Build Coastguard Worker "inflate: literal 0x%02x\n", here.val));
508*1c60b9acSAndroid Build Coastguard Worker ROOM();
509*1c60b9acSAndroid Build Coastguard Worker *put++ = (unsigned char)(state->length);
510*1c60b9acSAndroid Build Coastguard Worker left--;
511*1c60b9acSAndroid Build Coastguard Worker state->mode = LEN;
512*1c60b9acSAndroid Build Coastguard Worker break;
513*1c60b9acSAndroid Build Coastguard Worker }
514*1c60b9acSAndroid Build Coastguard Worker
515*1c60b9acSAndroid Build Coastguard Worker /* process end of block */
516*1c60b9acSAndroid Build Coastguard Worker if (here.op & 32) {
517*1c60b9acSAndroid Build Coastguard Worker Tracevv((stderr, "inflate: end of block\n"));
518*1c60b9acSAndroid Build Coastguard Worker state->mode = TYPE;
519*1c60b9acSAndroid Build Coastguard Worker break;
520*1c60b9acSAndroid Build Coastguard Worker }
521*1c60b9acSAndroid Build Coastguard Worker
522*1c60b9acSAndroid Build Coastguard Worker /* invalid code */
523*1c60b9acSAndroid Build Coastguard Worker if (here.op & 64) {
524*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid literal/length code";
525*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
526*1c60b9acSAndroid Build Coastguard Worker break;
527*1c60b9acSAndroid Build Coastguard Worker }
528*1c60b9acSAndroid Build Coastguard Worker
529*1c60b9acSAndroid Build Coastguard Worker /* length code -- get extra bits, if any */
530*1c60b9acSAndroid Build Coastguard Worker state->extra = (unsigned)(here.op) & 15;
531*1c60b9acSAndroid Build Coastguard Worker if (state->extra != 0) {
532*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(state->extra);
533*1c60b9acSAndroid Build Coastguard Worker state->length += BITS(state->extra);
534*1c60b9acSAndroid Build Coastguard Worker DROPBITS(state->extra);
535*1c60b9acSAndroid Build Coastguard Worker }
536*1c60b9acSAndroid Build Coastguard Worker Tracevv((stderr, "inflate: length %u\n", state->length));
537*1c60b9acSAndroid Build Coastguard Worker
538*1c60b9acSAndroid Build Coastguard Worker /* get distance code */
539*1c60b9acSAndroid Build Coastguard Worker for (;;) {
540*1c60b9acSAndroid Build Coastguard Worker here = state->distcode[BITS(state->distbits)];
541*1c60b9acSAndroid Build Coastguard Worker if ((unsigned)(here.bits) <= bits) break;
542*1c60b9acSAndroid Build Coastguard Worker PULLBYTE();
543*1c60b9acSAndroid Build Coastguard Worker }
544*1c60b9acSAndroid Build Coastguard Worker if ((here.op & 0xf0) == 0) {
545*1c60b9acSAndroid Build Coastguard Worker last = here;
546*1c60b9acSAndroid Build Coastguard Worker for (;;) {
547*1c60b9acSAndroid Build Coastguard Worker here = state->distcode[last.val +
548*1c60b9acSAndroid Build Coastguard Worker (BITS(last.bits + last.op) >> last.bits)];
549*1c60b9acSAndroid Build Coastguard Worker if ((unsigned)(last.bits + here.bits) <= bits) break;
550*1c60b9acSAndroid Build Coastguard Worker PULLBYTE();
551*1c60b9acSAndroid Build Coastguard Worker }
552*1c60b9acSAndroid Build Coastguard Worker DROPBITS(last.bits);
553*1c60b9acSAndroid Build Coastguard Worker }
554*1c60b9acSAndroid Build Coastguard Worker DROPBITS(here.bits);
555*1c60b9acSAndroid Build Coastguard Worker if (here.op & 64) {
556*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid distance code";
557*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
558*1c60b9acSAndroid Build Coastguard Worker break;
559*1c60b9acSAndroid Build Coastguard Worker }
560*1c60b9acSAndroid Build Coastguard Worker state->offset = (unsigned)here.val;
561*1c60b9acSAndroid Build Coastguard Worker
562*1c60b9acSAndroid Build Coastguard Worker /* get distance extra bits, if any */
563*1c60b9acSAndroid Build Coastguard Worker state->extra = (unsigned)(here.op) & 15;
564*1c60b9acSAndroid Build Coastguard Worker if (state->extra != 0) {
565*1c60b9acSAndroid Build Coastguard Worker NEEDBITS(state->extra);
566*1c60b9acSAndroid Build Coastguard Worker state->offset += BITS(state->extra);
567*1c60b9acSAndroid Build Coastguard Worker DROPBITS(state->extra);
568*1c60b9acSAndroid Build Coastguard Worker }
569*1c60b9acSAndroid Build Coastguard Worker if (state->offset > state->wsize - (state->whave < state->wsize ?
570*1c60b9acSAndroid Build Coastguard Worker left : 0)) {
571*1c60b9acSAndroid Build Coastguard Worker strm->msg = (char *)"invalid distance too far back";
572*1c60b9acSAndroid Build Coastguard Worker state->mode = BAD;
573*1c60b9acSAndroid Build Coastguard Worker break;
574*1c60b9acSAndroid Build Coastguard Worker }
575*1c60b9acSAndroid Build Coastguard Worker Tracevv((stderr, "inflate: distance %u\n", state->offset));
576*1c60b9acSAndroid Build Coastguard Worker
577*1c60b9acSAndroid Build Coastguard Worker /* copy match from window to output */
578*1c60b9acSAndroid Build Coastguard Worker do {
579*1c60b9acSAndroid Build Coastguard Worker ROOM();
580*1c60b9acSAndroid Build Coastguard Worker copy = state->wsize - state->offset;
581*1c60b9acSAndroid Build Coastguard Worker if (copy < left) {
582*1c60b9acSAndroid Build Coastguard Worker from = put + copy;
583*1c60b9acSAndroid Build Coastguard Worker copy = left - copy;
584*1c60b9acSAndroid Build Coastguard Worker }
585*1c60b9acSAndroid Build Coastguard Worker else {
586*1c60b9acSAndroid Build Coastguard Worker from = put - state->offset;
587*1c60b9acSAndroid Build Coastguard Worker copy = left;
588*1c60b9acSAndroid Build Coastguard Worker }
589*1c60b9acSAndroid Build Coastguard Worker if (copy > state->length) copy = state->length;
590*1c60b9acSAndroid Build Coastguard Worker state->length -= copy;
591*1c60b9acSAndroid Build Coastguard Worker left -= copy;
592*1c60b9acSAndroid Build Coastguard Worker do {
593*1c60b9acSAndroid Build Coastguard Worker *put++ = *from++;
594*1c60b9acSAndroid Build Coastguard Worker } while (--copy);
595*1c60b9acSAndroid Build Coastguard Worker } while (state->length != 0);
596*1c60b9acSAndroid Build Coastguard Worker break;
597*1c60b9acSAndroid Build Coastguard Worker
598*1c60b9acSAndroid Build Coastguard Worker case DONE:
599*1c60b9acSAndroid Build Coastguard Worker /* inflate stream terminated properly -- write leftover output */
600*1c60b9acSAndroid Build Coastguard Worker ret = Z_STREAM_END;
601*1c60b9acSAndroid Build Coastguard Worker if (left < state->wsize) {
602*1c60b9acSAndroid Build Coastguard Worker if (out(out_desc, state->window, state->wsize - left))
603*1c60b9acSAndroid Build Coastguard Worker ret = Z_BUF_ERROR;
604*1c60b9acSAndroid Build Coastguard Worker }
605*1c60b9acSAndroid Build Coastguard Worker goto inf_leave;
606*1c60b9acSAndroid Build Coastguard Worker
607*1c60b9acSAndroid Build Coastguard Worker case BAD:
608*1c60b9acSAndroid Build Coastguard Worker ret = Z_DATA_ERROR;
609*1c60b9acSAndroid Build Coastguard Worker goto inf_leave;
610*1c60b9acSAndroid Build Coastguard Worker
611*1c60b9acSAndroid Build Coastguard Worker default: /* can't happen, but makes compilers happy */
612*1c60b9acSAndroid Build Coastguard Worker ret = Z_STREAM_ERROR;
613*1c60b9acSAndroid Build Coastguard Worker goto inf_leave;
614*1c60b9acSAndroid Build Coastguard Worker }
615*1c60b9acSAndroid Build Coastguard Worker
616*1c60b9acSAndroid Build Coastguard Worker /* Return unused input */
617*1c60b9acSAndroid Build Coastguard Worker inf_leave:
618*1c60b9acSAndroid Build Coastguard Worker strm->next_in = next;
619*1c60b9acSAndroid Build Coastguard Worker strm->avail_in = have;
620*1c60b9acSAndroid Build Coastguard Worker return ret;
621*1c60b9acSAndroid Build Coastguard Worker }
622*1c60b9acSAndroid Build Coastguard Worker
inflateBackEnd(strm)623*1c60b9acSAndroid Build Coastguard Worker int ZEXPORT inflateBackEnd(strm)
624*1c60b9acSAndroid Build Coastguard Worker z_streamp strm;
625*1c60b9acSAndroid Build Coastguard Worker {
626*1c60b9acSAndroid Build Coastguard Worker if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
627*1c60b9acSAndroid Build Coastguard Worker return Z_STREAM_ERROR;
628*1c60b9acSAndroid Build Coastguard Worker ZFREE(strm, strm->state);
629*1c60b9acSAndroid Build Coastguard Worker strm->state = Z_NULL;
630*1c60b9acSAndroid Build Coastguard Worker Tracev((stderr, "inflate: end\n"));
631*1c60b9acSAndroid Build Coastguard Worker return Z_OK;
632*1c60b9acSAndroid Build Coastguard Worker }
633