File: /usr/src/linux/fs/cramfs/inflate/inflate.c

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