]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* inflate.c -- zlib interface to inflate modules |
2 | * Copyright (C) 1995-1998 Mark Adler | |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | |
4 | */ | |
5 | ||
1da177e4 LT |
6 | #include <linux/zutil.h> |
7 | #include "infblock.h" | |
8 | #include "infutil.h" | |
9 | ||
10 | int zlib_inflate_workspacesize(void) | |
11 | { | |
12 | return sizeof(struct inflate_workspace); | |
13 | } | |
14 | ||
15 | ||
16 | int zlib_inflateReset( | |
17 | z_streamp z | |
18 | ) | |
19 | { | |
20 | if (z == NULL || z->state == NULL || z->workspace == NULL) | |
21 | return Z_STREAM_ERROR; | |
22 | z->total_in = z->total_out = 0; | |
23 | z->msg = NULL; | |
24 | z->state->mode = z->state->nowrap ? BLOCKS : METHOD; | |
25 | zlib_inflate_blocks_reset(z->state->blocks, z, NULL); | |
26 | return Z_OK; | |
27 | } | |
28 | ||
29 | ||
30 | int zlib_inflateEnd( | |
31 | z_streamp z | |
32 | ) | |
33 | { | |
34 | if (z == NULL || z->state == NULL || z->workspace == NULL) | |
35 | return Z_STREAM_ERROR; | |
36 | if (z->state->blocks != NULL) | |
37 | zlib_inflate_blocks_free(z->state->blocks, z); | |
38 | z->state = NULL; | |
39 | return Z_OK; | |
40 | } | |
41 | ||
42 | ||
43 | int zlib_inflateInit2_( | |
44 | z_streamp z, | |
45 | int w, | |
46 | const char *version, | |
47 | int stream_size | |
48 | ) | |
49 | { | |
50 | if (version == NULL || version[0] != ZLIB_VERSION[0] || | |
51 | stream_size != sizeof(z_stream) || z->workspace == NULL) | |
52 | return Z_VERSION_ERROR; | |
53 | ||
54 | /* initialize state */ | |
55 | z->msg = NULL; | |
56 | z->state = &WS(z)->internal_state; | |
57 | z->state->blocks = NULL; | |
58 | ||
59 | /* handle undocumented nowrap option (no zlib header or check) */ | |
60 | z->state->nowrap = 0; | |
61 | if (w < 0) | |
62 | { | |
63 | w = - w; | |
64 | z->state->nowrap = 1; | |
65 | } | |
66 | ||
67 | /* set window size */ | |
68 | if (w < 8 || w > 15) | |
69 | { | |
70 | zlib_inflateEnd(z); | |
71 | return Z_STREAM_ERROR; | |
72 | } | |
73 | z->state->wbits = (uInt)w; | |
74 | ||
75 | /* create inflate_blocks state */ | |
76 | if ((z->state->blocks = | |
77 | zlib_inflate_blocks_new(z, z->state->nowrap ? NULL : zlib_adler32, (uInt)1 << w)) | |
78 | == NULL) | |
79 | { | |
80 | zlib_inflateEnd(z); | |
81 | return Z_MEM_ERROR; | |
82 | } | |
83 | ||
84 | /* reset state */ | |
85 | zlib_inflateReset(z); | |
86 | return Z_OK; | |
87 | } | |
88 | ||
89 | ||
90 | /* | |
91 | * At the end of a Deflate-compressed PPP packet, we expect to have seen | |
92 | * a `stored' block type value but not the (zero) length bytes. | |
93 | */ | |
94 | static int zlib_inflate_packet_flush(inflate_blocks_statef *s) | |
95 | { | |
96 | if (s->mode != LENS) | |
97 | return Z_DATA_ERROR; | |
98 | s->mode = TYPE; | |
99 | return Z_OK; | |
100 | } | |
101 | ||
102 | ||
103 | int zlib_inflateInit_( | |
104 | z_streamp z, | |
105 | const char *version, | |
106 | int stream_size | |
107 | ) | |
108 | { | |
109 | return zlib_inflateInit2_(z, DEF_WBITS, version, stream_size); | |
110 | } | |
111 | ||
112 | #undef NEEDBYTE | |
113 | #undef NEXTBYTE | |
114 | #define NEEDBYTE {if(z->avail_in==0)goto empty;r=trv;} | |
115 | #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) | |
116 | ||
117 | int zlib_inflate( | |
118 | z_streamp z, | |
119 | int f | |
120 | ) | |
121 | { | |
122 | int r, trv; | |
123 | uInt b; | |
124 | ||
125 | if (z == NULL || z->state == NULL || z->next_in == NULL) | |
126 | return Z_STREAM_ERROR; | |
127 | trv = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; | |
128 | r = Z_BUF_ERROR; | |
129 | while (1) switch (z->state->mode) | |
130 | { | |
131 | case METHOD: | |
132 | NEEDBYTE | |
133 | if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) | |
134 | { | |
135 | z->state->mode = I_BAD; | |
136 | z->msg = (char*)"unknown compression method"; | |
137 | z->state->sub.marker = 5; /* can't try inflateSync */ | |
138 | break; | |
139 | } | |
140 | if ((z->state->sub.method >> 4) + 8 > z->state->wbits) | |
141 | { | |
142 | z->state->mode = I_BAD; | |
143 | z->msg = (char*)"invalid window size"; | |
144 | z->state->sub.marker = 5; /* can't try inflateSync */ | |
145 | break; | |
146 | } | |
147 | z->state->mode = FLAG; | |
148 | case FLAG: | |
149 | NEEDBYTE | |
150 | b = NEXTBYTE; | |
151 | if (((z->state->sub.method << 8) + b) % 31) | |
152 | { | |
153 | z->state->mode = I_BAD; | |
154 | z->msg = (char*)"incorrect header check"; | |
155 | z->state->sub.marker = 5; /* can't try inflateSync */ | |
156 | break; | |
157 | } | |
158 | if (!(b & PRESET_DICT)) | |
159 | { | |
160 | z->state->mode = BLOCKS; | |
161 | break; | |
162 | } | |
163 | z->state->mode = DICT4; | |
164 | case DICT4: | |
165 | NEEDBYTE | |
166 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; | |
167 | z->state->mode = DICT3; | |
168 | case DICT3: | |
169 | NEEDBYTE | |
170 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; | |
171 | z->state->mode = DICT2; | |
172 | case DICT2: | |
173 | NEEDBYTE | |
174 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; | |
175 | z->state->mode = DICT1; | |
176 | case DICT1: | |
177 | NEEDBYTE | |
178 | z->state->sub.check.need += (uLong)NEXTBYTE; | |
179 | z->adler = z->state->sub.check.need; | |
180 | z->state->mode = DICT0; | |
181 | return Z_NEED_DICT; | |
182 | case DICT0: | |
183 | z->state->mode = I_BAD; | |
184 | z->msg = (char*)"need dictionary"; | |
185 | z->state->sub.marker = 0; /* can try inflateSync */ | |
186 | return Z_STREAM_ERROR; | |
187 | case BLOCKS: | |
188 | r = zlib_inflate_blocks(z->state->blocks, z, r); | |
189 | if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) | |
190 | r = zlib_inflate_packet_flush(z->state->blocks); | |
191 | if (r == Z_DATA_ERROR) | |
192 | { | |
193 | z->state->mode = I_BAD; | |
194 | z->state->sub.marker = 0; /* can try inflateSync */ | |
195 | break; | |
196 | } | |
197 | if (r == Z_OK) | |
198 | r = trv; | |
199 | if (r != Z_STREAM_END) | |
200 | return r; | |
201 | r = trv; | |
202 | zlib_inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); | |
203 | if (z->state->nowrap) | |
204 | { | |
205 | z->state->mode = I_DONE; | |
206 | break; | |
207 | } | |
208 | z->state->mode = CHECK4; | |
209 | case CHECK4: | |
210 | NEEDBYTE | |
211 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; | |
212 | z->state->mode = CHECK3; | |
213 | case CHECK3: | |
214 | NEEDBYTE | |
215 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; | |
216 | z->state->mode = CHECK2; | |
217 | case CHECK2: | |
218 | NEEDBYTE | |
219 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; | |
220 | z->state->mode = CHECK1; | |
221 | case CHECK1: | |
222 | NEEDBYTE | |
223 | z->state->sub.check.need += (uLong)NEXTBYTE; | |
224 | ||
225 | if (z->state->sub.check.was != z->state->sub.check.need) | |
226 | { | |
227 | z->state->mode = I_BAD; | |
228 | z->msg = (char*)"incorrect data check"; | |
229 | z->state->sub.marker = 5; /* can't try inflateSync */ | |
230 | break; | |
231 | } | |
232 | z->state->mode = I_DONE; | |
233 | case I_DONE: | |
234 | return Z_STREAM_END; | |
235 | case I_BAD: | |
236 | return Z_DATA_ERROR; | |
237 | default: | |
238 | return Z_STREAM_ERROR; | |
239 | } | |
240 | empty: | |
241 | if (f != Z_PACKET_FLUSH) | |
242 | return r; | |
243 | z->state->mode = I_BAD; | |
244 | z->msg = (char *)"need more for packet flush"; | |
245 | z->state->sub.marker = 0; /* can try inflateSync */ | |
246 | return Z_DATA_ERROR; | |
247 | } |