1 /* inflate.c -- zlib interface to inflate modules
2 * Copyright (C) 1995 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
9 struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
11 /* inflate private state */
12 struct internal_state {
16 METHOD, /* waiting for method byte */
17 FLAG, /* waiting for flag byte */
18 START, /* make new blocks state */
19 BLOCKS, /* decompressing blocks */
20 CHECK4, /* four check bytes to go */
21 CHECK3, /* three check bytes to go */
22 CHECK2, /* two check bytes to go */
23 CHECK1, /* one check byte to go */
24 DONE, /* finished check, done */
25 ERROR} /* got an error--stay here */
26 mode; /* current inflate mode */
28 /* mode dependent information */
30 uInt method; /* if FLAGS, method byte */
31 struct inflate_blocks_state
32 *blocks; /* if BLOCKS, current state */
34 uLong was; /* computed check value */
35 uLong need; /* stream check value */
36 } check; /* if CHECK, check values to compare */
39 /* mode independent information */
40 int nowrap; /* flag for no wrapper */
41 uInt wbits; /* log2(window size) (8..15, defaults to 15) */
49 return inflateInit2(z, WBITS);
53 int inflateInit2(z, w)
57 /* initialize state */
59 return Z_STREAM_ERROR;
60 if (z->zalloc == Z_NULL) z->zalloc = zcalloc;
61 if (z->zfree == Z_NULL) z->zfree = zcfree;
62 z->total_in = z->total_out = 0;
64 if ((z->state = (struct internal_state *)
65 ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
67 z->state->mode = METHOD;
69 /* handle undocumented nowrap option (no zlib header or check) */
75 z->state->mode = START;
82 return Z_STREAM_ERROR;
89 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
99 if (z == Z_NULL || z->next_in == Z_NULL)
100 return Z_STREAM_ERROR;
102 while (1) switch (z->state->mode)
105 if (z->avail_in == 0) return r; r = Z_OK;
106 if (((z->state->sub.method = NEXTBYTE) & 0xf != DEFLATED))
108 z->state->mode = ERROR;
109 z->msg = "unknown compression method";
112 if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
114 z->state->mode = ERROR;
115 z->msg = "invalid window size";
118 z->state->mode = FLAG;
120 if (z->avail_in == 0) return r; r = Z_OK;
121 if ((b = NEXTBYTE) & 0x20)
123 z->state->mode = ERROR;
124 z->msg = "invalid reserved bit";
127 if (((z->state->sub.method << 8) + b) % 31)
129 z->state->mode = ERROR;
130 z->msg = "incorrect header check";
133 z->state->mode = START;
135 if ((z->state->sub.blocks = inflate_blocks_new(z,
136 z->state->nowrap ? Z_NULL : adler32,
137 1<< z->state->wbits)) == Z_NULL)
139 z->state->mode = BLOCKS;
141 if ((r = inflate_blocks(z->state->sub.blocks, z, r)) != Z_STREAM_END)
143 inflate_blocks_free(z->state->sub.blocks, z, &c, &r);
144 if (z->state->nowrap)
147 z->msg = "inflate bug--took one too many bytes";
148 z->state->mode = r == -1 ? DONE : ERROR;
151 z->state->sub.check.was = c;
154 z->state->sub.check.need = (uLong)r << 24;
155 z->state->mode = CHECK3;
160 z->state->mode = CHECK4;
162 if (z->avail_in == 0) return r; r = Z_OK;
163 z->state->sub.check.need = (uLong)NEXTBYTE << 24;
164 z->state->mode = CHECK3;
166 if (z->avail_in == 0) return r; r = Z_OK;
167 z->state->sub.check.need += (uLong)NEXTBYTE << 16;
168 z->state->mode = CHECK2;
170 if (z->avail_in == 0) return r; r = Z_OK;
171 z->state->sub.check.need += (uLong)NEXTBYTE << 8;
172 z->state->mode = CHECK1;
174 if (z->avail_in == 0) return r; r = Z_OK;
175 z->state->sub.check.need += (uLong)NEXTBYTE;
176 if (z->state->sub.check.was != z->state->sub.check.need)
178 z->state->mode = ERROR;
179 z->msg = "incorrect data check";
182 z->state->mode = DONE;
188 return Z_STREAM_ERROR;
199 if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
200 return Z_STREAM_ERROR;
201 if (z->state->mode == BLOCKS)
202 inflate_blocks_free(z->state->sub.blocks, z, &c, &e);
209 /* inflateSync not implemented yet--this just consumes input */
213 if (z == Z_NULL) return Z_STREAM_ERROR;
214 if (z->avail_in == 0) return Z_BUF_ERROR;
217 } while (--z->avail_in);
222 /* inflateReset not fully implemented yet--this frees and reallocates */
228 if ((r = inflateEnd(z)) != Z_OK)
230 return inflateInit(z);