* Use id(1) instead of grep(1) to detect the presence of the smmsp
[dragonfly.git] / lib / libz / inflate.c
1 /* inflate.c -- zlib interface to inflate modules
2  * Copyright (C) 1995-2002 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h 
4  *
5  * $FreeBSD: src/lib/libz/inflate.c,v 1.1.1.2.6.1 2003/02/01 13:33:12 sobomax Exp $
6  * $DragonFly: src/lib/libz/Attic/inflate.c,v 1.2 2003/06/17 04:26:52 dillon Exp $
7  */
8
9 #include "zutil.h"
10 #include "infblock.h"
11
12 struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
13
14 typedef enum {
15       METHOD,   /* waiting for method byte */
16       FLAG,     /* waiting for flag byte */
17       DICT4,    /* four dictionary check bytes to go */
18       DICT3,    /* three dictionary check bytes to go */
19       DICT2,    /* two dictionary check bytes to go */
20       DICT1,    /* one dictionary check byte to go */
21       DICT0,    /* waiting for inflateSetDictionary */
22       BLOCKS,   /* decompressing blocks */
23       CHECK4,   /* four check bytes to go */
24       CHECK3,   /* three check bytes to go */
25       CHECK2,   /* two check bytes to go */
26       CHECK1,   /* one check byte to go */
27       DONE,     /* finished check, done */
28       BAD}      /* got an error--stay here */
29 inflate_mode;
30
31 /* inflate private state */
32 struct internal_state {
33
34   /* mode */
35   inflate_mode  mode;   /* current inflate mode */
36
37   /* mode dependent information */
38   union {
39     uInt method;        /* if FLAGS, method byte */
40     struct {
41       uLong was;                /* computed check value */
42       uLong need;               /* stream check value */
43     } check;            /* if CHECK, check values to compare */
44     uInt marker;        /* if BAD, inflateSync's marker bytes count */
45   } sub;        /* submode */
46
47   /* mode independent information */
48   int  nowrap;          /* flag for no wrapper */
49   uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
50   inflate_blocks_statef 
51     *blocks;            /* current inflate_blocks state */
52
53 };
54
55
56 int ZEXPORT inflateReset(z)
57 z_streamp z;
58 {
59   if (z == Z_NULL || z->state == Z_NULL)
60     return Z_STREAM_ERROR;
61   z->total_in = z->total_out = 0;
62   z->msg = Z_NULL;
63   z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
64   inflate_blocks_reset(z->state->blocks, z, Z_NULL);
65   Tracev((stderr, "inflate: reset\n"));
66   return Z_OK;
67 }
68
69
70 int ZEXPORT inflateEnd(z)
71 z_streamp z;
72 {
73   if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
74     return Z_STREAM_ERROR;
75   if (z->state->blocks != Z_NULL)
76     inflate_blocks_free(z->state->blocks, z);
77   ZFREE(z, z->state);
78   z->state = Z_NULL;
79   Tracev((stderr, "inflate: end\n"));
80   return Z_OK;
81 }
82
83
84 int ZEXPORT inflateInit2_(z, w, version, stream_size)
85 z_streamp z;
86 int w;
87 const char *version;
88 int stream_size;
89 {
90   if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
91       stream_size != sizeof(z_stream))
92       return Z_VERSION_ERROR;
93
94   /* initialize state */
95   if (z == Z_NULL)
96     return Z_STREAM_ERROR;
97   z->msg = Z_NULL;
98   if (z->zalloc == Z_NULL)
99   {
100     z->zalloc = zcalloc;
101     z->opaque = (voidpf)0;
102   }
103   if (z->zfree == Z_NULL) z->zfree = zcfree;
104   if ((z->state = (struct internal_state FAR *)
105        ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
106     return Z_MEM_ERROR;
107   z->state->blocks = Z_NULL;
108
109   /* handle undocumented nowrap option (no zlib header or check) */
110   z->state->nowrap = 0;
111   if (w < 0)
112   {
113     w = - w;
114     z->state->nowrap = 1;
115   }
116
117   /* set window size */
118   if (w < 8 || w > 15)
119   {
120     inflateEnd(z);
121     return Z_STREAM_ERROR;
122   }
123   z->state->wbits = (uInt)w;
124
125   /* create inflate_blocks state */
126   if ((z->state->blocks =
127       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
128       == Z_NULL)
129   {
130     inflateEnd(z);
131     return Z_MEM_ERROR;
132   }
133   Tracev((stderr, "inflate: allocated\n"));
134
135   /* reset state */
136   inflateReset(z);
137   return Z_OK;
138 }
139
140
141 int ZEXPORT inflateInit_(z, version, stream_size)
142 z_streamp z;
143 const char *version;
144 int stream_size;
145 {
146   return inflateInit2_(z, DEF_WBITS, version, stream_size);
147 }
148
149
150 #define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
151 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
152
153 int ZEXPORT inflate(z, f)
154 z_streamp z;
155 int f;
156 {
157   int r;
158   uInt b;
159
160   if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
161     return Z_STREAM_ERROR;
162   f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
163   r = Z_BUF_ERROR;
164   while (1) switch (z->state->mode)
165   {
166     case METHOD:
167       NEEDBYTE
168       if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
169       {
170         z->state->mode = BAD;
171         z->msg = (char*)"unknown compression method";
172         z->state->sub.marker = 5;       /* can't try inflateSync */
173         break;
174       }
175       if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
176       {
177         z->state->mode = BAD;
178         z->msg = (char*)"invalid window size";
179         z->state->sub.marker = 5;       /* can't try inflateSync */
180         break;
181       }
182       z->state->mode = FLAG;
183     case FLAG:
184       NEEDBYTE
185       b = NEXTBYTE;
186       if (((z->state->sub.method << 8) + b) % 31)
187       {
188         z->state->mode = BAD;
189         z->msg = (char*)"incorrect header check";
190         z->state->sub.marker = 5;       /* can't try inflateSync */
191         break;
192       }
193       Tracev((stderr, "inflate: zlib header ok\n"));
194       if (!(b & PRESET_DICT))
195       {
196         z->state->mode = BLOCKS;
197         break;
198       }
199       z->state->mode = DICT4;
200     case DICT4:
201       NEEDBYTE
202       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
203       z->state->mode = DICT3;
204     case DICT3:
205       NEEDBYTE
206       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
207       z->state->mode = DICT2;
208     case DICT2:
209       NEEDBYTE
210       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
211       z->state->mode = DICT1;
212     case DICT1:
213       NEEDBYTE
214       z->state->sub.check.need += (uLong)NEXTBYTE;
215       z->adler = z->state->sub.check.need;
216       z->state->mode = DICT0;
217       return Z_NEED_DICT;
218     case DICT0:
219       z->state->mode = BAD;
220       z->msg = (char*)"need dictionary";
221       z->state->sub.marker = 0;       /* can try inflateSync */
222       return Z_STREAM_ERROR;
223     case BLOCKS:
224       r = inflate_blocks(z->state->blocks, z, r);
225       if (r == Z_DATA_ERROR)
226       {
227         z->state->mode = BAD;
228         z->state->sub.marker = 0;       /* can try inflateSync */
229         break;
230       }
231       if (r == Z_OK)
232         r = f;
233       if (r != Z_STREAM_END)
234         return r;
235       r = f;
236       inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
237       if (z->state->nowrap)
238       {
239         z->state->mode = DONE;
240         break;
241       }
242       z->state->mode = CHECK4;
243     case CHECK4:
244       NEEDBYTE
245       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
246       z->state->mode = CHECK3;
247     case CHECK3:
248       NEEDBYTE
249       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
250       z->state->mode = CHECK2;
251     case CHECK2:
252       NEEDBYTE
253       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
254       z->state->mode = CHECK1;
255     case CHECK1:
256       NEEDBYTE
257       z->state->sub.check.need += (uLong)NEXTBYTE;
258
259       if (z->state->sub.check.was != z->state->sub.check.need)
260       {
261         z->state->mode = BAD;
262         z->msg = (char*)"incorrect data check";
263         z->state->sub.marker = 5;       /* can't try inflateSync */
264         break;
265       }
266       Tracev((stderr, "inflate: zlib check ok\n"));
267       z->state->mode = DONE;
268     case DONE:
269       return Z_STREAM_END;
270     case BAD:
271       return Z_DATA_ERROR;
272     default:
273       return Z_STREAM_ERROR;
274   }
275 #ifdef NEED_DUMMY_RETURN
276   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
277 #endif
278 }
279
280
281 int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
282 z_streamp z;
283 const Bytef *dictionary;
284 uInt  dictLength;
285 {
286   uInt length = dictLength;
287
288   if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
289     return Z_STREAM_ERROR;
290
291   if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
292   z->adler = 1L;
293
294   if (length >= ((uInt)1<<z->state->wbits))
295   {
296     length = (1<<z->state->wbits)-1;
297     dictionary += dictLength - length;
298   }
299   inflate_set_dictionary(z->state->blocks, dictionary, length);
300   z->state->mode = BLOCKS;
301   return Z_OK;
302 }
303
304
305 int ZEXPORT inflateSync(z)
306 z_streamp z;
307 {
308   uInt n;       /* number of bytes to look at */
309   Bytef *p;     /* pointer to bytes */
310   uInt m;       /* number of marker bytes found in a row */
311   uLong r, w;   /* temporaries to save total_in and total_out */
312
313   /* set up */
314   if (z == Z_NULL || z->state == Z_NULL)
315     return Z_STREAM_ERROR;
316   if (z->state->mode != BAD)
317   {
318     z->state->mode = BAD;
319     z->state->sub.marker = 0;
320   }
321   if ((n = z->avail_in) == 0)
322     return Z_BUF_ERROR;
323   p = z->next_in;
324   m = z->state->sub.marker;
325
326   /* search */
327   while (n && m < 4)
328   {
329     static const Byte mark[4] = {0, 0, 0xff, 0xff};
330     if (*p == mark[m])
331       m++;
332     else if (*p)
333       m = 0;
334     else
335       m = 4 - m;
336     p++, n--;
337   }
338
339   /* restore */
340   z->total_in += p - z->next_in;
341   z->next_in = p;
342   z->avail_in = n;
343   z->state->sub.marker = m;
344
345   /* return no joy or set up to restart on a new block */
346   if (m != 4)
347     return Z_DATA_ERROR;
348   r = z->total_in;  w = z->total_out;
349   inflateReset(z);
350   z->total_in = r;  z->total_out = w;
351   z->state->mode = BLOCKS;
352   return Z_OK;
353 }
354
355
356 /* Returns true if inflate is currently at the end of a block generated
357  * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
358  * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
359  * but removes the length bytes of the resulting empty stored block. When
360  * decompressing, PPP checks that at the end of input packet, inflate is
361  * waiting for these length bytes.
362  */
363 int ZEXPORT inflateSyncPoint(z)
364 z_streamp z;
365 {
366   if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
367     return Z_STREAM_ERROR;
368   return inflate_blocks_sync_point(z->state->blocks);
369 }