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