Back to index

plt-scheme  4.2.1
inflate.c
Go to the documentation of this file.
00001 /* inflate.c -- zlib interface to inflate modules
00002  * Copyright (C) 1995-2002 Mark Adler
00003  * For conditions of distribution and use, see copyright notice in zlib.h 
00004  */
00005 
00006 #include "zutil.h"
00007 #include "infblock.h"
00008 
00009 struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
00010 
00011 typedef enum {
00012       METHOD,   /* waiting for method byte */
00013       FLAG,     /* waiting for flag byte */
00014       DICT4,    /* four dictionary check bytes to go */
00015       DICT3,    /* three dictionary check bytes to go */
00016       DICT2,    /* two dictionary check bytes to go */
00017       DICT1,    /* one dictionary check byte to go */
00018       DICT0,    /* waiting for inflateSetDictionary */
00019       BLOCKS,   /* decompressing blocks */
00020       CHECK4,   /* four check bytes to go */
00021       CHECK3,   /* three check bytes to go */
00022       CHECK2,   /* two check bytes to go */
00023       CHECK1,   /* one check byte to go */
00024       DONE,     /* finished check, done */
00025       BAD}      /* got an error--stay here */
00026 inflate_mode;
00027 
00028 /* inflate private state */
00029 struct internal_state {
00030 
00031   /* mode */
00032   inflate_mode  mode;   /* current inflate mode */
00033 
00034   /* mode dependent information */
00035   union {
00036     uInt method;        /* if FLAGS, method byte */
00037     struct {
00038       uLong was;                /* computed check value */
00039       uLong need;               /* stream check value */
00040     } check;            /* if CHECK, check values to compare */
00041     uInt marker;        /* if BAD, inflateSync's marker bytes count */
00042   } sub;        /* submode */
00043 
00044   /* mode independent information */
00045   int  nowrap;          /* flag for no wrapper */
00046   uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
00047   inflate_blocks_statef 
00048     *blocks;            /* current inflate_blocks state */
00049 
00050 };
00051 
00052 
00053 int ZEXPORT inflateReset(z)
00054 z_streamp z;
00055 {
00056   if (z == Z_NULL || z->state == Z_NULL)
00057     return Z_STREAM_ERROR;
00058   z->total_in = z->total_out = 0;
00059   z->msg = Z_NULL;
00060   z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
00061   inflate_blocks_reset(z->state->blocks, z, Z_NULL);
00062   Tracev((stderr, "inflate: reset\n"));
00063   return Z_OK;
00064 }
00065 
00066 
00067 int ZEXPORT inflateEnd(z)
00068 z_streamp z;
00069 {
00070   if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
00071     return Z_STREAM_ERROR;
00072   if (z->state->blocks != Z_NULL)
00073     inflate_blocks_free(z->state->blocks, z);
00074   ZFREE(z, z->state);
00075   z->state = Z_NULL;
00076   Tracev((stderr, "inflate: end\n"));
00077   return Z_OK;
00078 }
00079 
00080 
00081 int ZEXPORT inflateInit2_(z, w, version, stream_size)
00082 z_streamp z;
00083 int w;
00084 const char *version;
00085 int stream_size;
00086 {
00087   if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
00088       stream_size != sizeof(z_stream))
00089       return Z_VERSION_ERROR;
00090 
00091   /* initialize state */
00092   if (z == Z_NULL)
00093     return Z_STREAM_ERROR;
00094   z->msg = Z_NULL;
00095   if (z->zalloc == Z_NULL)
00096   {
00097     z->zalloc = zcalloc;
00098     z->opaque = (voidpf)0;
00099   }
00100   if (z->zfree == Z_NULL) z->zfree = zcfree;
00101   if ((z->state = (struct internal_state FAR *)
00102        ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
00103     return Z_MEM_ERROR;
00104   z->state->blocks = Z_NULL;
00105 
00106   /* handle undocumented nowrap option (no zlib header or check) */
00107   z->state->nowrap = 0;
00108   if (w < 0)
00109   {
00110     w = - w;
00111     z->state->nowrap = 1;
00112   }
00113 
00114   /* set window size */
00115   if (w < 8 || w > 15)
00116   {
00117     inflateEnd(z);
00118     return Z_STREAM_ERROR;
00119   }
00120   z->state->wbits = (uInt)w;
00121 
00122   /* create inflate_blocks state */
00123   if ((z->state->blocks =
00124       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
00125       == Z_NULL)
00126   {
00127     inflateEnd(z);
00128     return Z_MEM_ERROR;
00129   }
00130   Tracev((stderr, "inflate: allocated\n"));
00131 
00132   /* reset state */
00133   inflateReset(z);
00134   return Z_OK;
00135 }
00136 
00137 
00138 int ZEXPORT inflateInit_(z, version, stream_size)
00139 z_streamp z;
00140 const char *version;
00141 int stream_size;
00142 {
00143   return inflateInit2_(z, DEF_WBITS, version, stream_size);
00144 }
00145 
00146 
00147 #define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
00148 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
00149 
00150 int ZEXPORT inflate(z, f)
00151 z_streamp z;
00152 int f;
00153 {
00154   int r;
00155   uInt b;
00156 
00157   if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
00158     return Z_STREAM_ERROR;
00159   f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
00160   r = Z_BUF_ERROR;
00161   while (1) switch (z->state->mode)
00162   {
00163     case METHOD:
00164       NEEDBYTE
00165       if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
00166       {
00167         z->state->mode = BAD;
00168         z->msg = (char*)"unknown compression method";
00169         z->state->sub.marker = 5;       /* can't try inflateSync */
00170         break;
00171       }
00172       if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
00173       {
00174         z->state->mode = BAD;
00175         z->msg = (char*)"invalid window size";
00176         z->state->sub.marker = 5;       /* can't try inflateSync */
00177         break;
00178       }
00179       z->state->mode = FLAG;
00180     case FLAG:
00181       NEEDBYTE
00182       b = NEXTBYTE;
00183       if (((z->state->sub.method << 8) + b) % 31)
00184       {
00185         z->state->mode = BAD;
00186         z->msg = (char*)"incorrect header check";
00187         z->state->sub.marker = 5;       /* can't try inflateSync */
00188         break;
00189       }
00190       Tracev((stderr, "inflate: zlib header ok\n"));
00191       if (!(b & PRESET_DICT))
00192       {
00193         z->state->mode = BLOCKS;
00194         break;
00195       }
00196       z->state->mode = DICT4;
00197     case DICT4:
00198       NEEDBYTE
00199       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
00200       z->state->mode = DICT3;
00201     case DICT3:
00202       NEEDBYTE
00203       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
00204       z->state->mode = DICT2;
00205     case DICT2:
00206       NEEDBYTE
00207       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
00208       z->state->mode = DICT1;
00209     case DICT1:
00210       NEEDBYTE
00211       z->state->sub.check.need += (uLong)NEXTBYTE;
00212       z->adler = z->state->sub.check.need;
00213       z->state->mode = DICT0;
00214       return Z_NEED_DICT;
00215     case DICT0:
00216       z->state->mode = BAD;
00217       z->msg = (char*)"need dictionary";
00218       z->state->sub.marker = 0;       /* can try inflateSync */
00219       return Z_STREAM_ERROR;
00220     case BLOCKS:
00221       r = inflate_blocks(z->state->blocks, z, r);
00222       if (r == Z_DATA_ERROR)
00223       {
00224         z->state->mode = BAD;
00225         z->state->sub.marker = 0;       /* can try inflateSync */
00226         break;
00227       }
00228       if (r == Z_OK)
00229         r = f;
00230       if (r != Z_STREAM_END)
00231         return r;
00232       r = f;
00233       inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
00234       if (z->state->nowrap)
00235       {
00236         z->state->mode = DONE;
00237         break;
00238       }
00239       z->state->mode = CHECK4;
00240     case CHECK4:
00241       NEEDBYTE
00242       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
00243       z->state->mode = CHECK3;
00244     case CHECK3:
00245       NEEDBYTE
00246       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
00247       z->state->mode = CHECK2;
00248     case CHECK2:
00249       NEEDBYTE
00250       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
00251       z->state->mode = CHECK1;
00252     case CHECK1:
00253       NEEDBYTE
00254       z->state->sub.check.need += (uLong)NEXTBYTE;
00255 
00256       if (z->state->sub.check.was != z->state->sub.check.need)
00257       {
00258         z->state->mode = BAD;
00259         z->msg = (char*)"incorrect data check";
00260         z->state->sub.marker = 5;       /* can't try inflateSync */
00261         break;
00262       }
00263       Tracev((stderr, "inflate: zlib check ok\n"));
00264       z->state->mode = DONE;
00265     case DONE:
00266       return Z_STREAM_END;
00267     case BAD:
00268       return Z_DATA_ERROR;
00269     default:
00270       return Z_STREAM_ERROR;
00271   }
00272 #ifdef NEED_DUMMY_RETURN
00273   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
00274 #endif
00275 }
00276 
00277 
00278 int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
00279 z_streamp z;
00280 const Bytef *dictionary;
00281 uInt  dictLength;
00282 {
00283   uInt length = dictLength;
00284 
00285   if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
00286     return Z_STREAM_ERROR;
00287 
00288   if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
00289   z->adler = 1L;
00290 
00291   if (length >= ((uInt)1<<z->state->wbits))
00292   {
00293     length = (1<<z->state->wbits)-1;
00294     dictionary += dictLength - length;
00295   }
00296   inflate_set_dictionary(z->state->blocks, dictionary, length);
00297   z->state->mode = BLOCKS;
00298   return Z_OK;
00299 }
00300 
00301 
00302 int ZEXPORT inflateSync(z)
00303 z_streamp z;
00304 {
00305   uInt n;       /* number of bytes to look at */
00306   Bytef *p;     /* pointer to bytes */
00307   uInt m;       /* number of marker bytes found in a row */
00308   uLong r, w;   /* temporaries to save total_in and total_out */
00309 
00310   /* set up */
00311   if (z == Z_NULL || z->state == Z_NULL)
00312     return Z_STREAM_ERROR;
00313   if (z->state->mode != BAD)
00314   {
00315     z->state->mode = BAD;
00316     z->state->sub.marker = 0;
00317   }
00318   if ((n = z->avail_in) == 0)
00319     return Z_BUF_ERROR;
00320   p = z->next_in;
00321   m = z->state->sub.marker;
00322 
00323   /* search */
00324   while (n && m < 4)
00325   {
00326     static const Byte mark[4] = {0, 0, 0xff, 0xff};
00327     if (*p == mark[m])
00328       m++;
00329     else if (*p)
00330       m = 0;
00331     else
00332       m = 4 - m;
00333     p++, n--;
00334   }
00335 
00336   /* restore */
00337   z->total_in += p - z->next_in;
00338   z->next_in = p;
00339   z->avail_in = n;
00340   z->state->sub.marker = m;
00341 
00342   /* return no joy or set up to restart on a new block */
00343   if (m != 4)
00344     return Z_DATA_ERROR;
00345   r = z->total_in;  w = z->total_out;
00346   inflateReset(z);
00347   z->total_in = r;  z->total_out = w;
00348   z->state->mode = BLOCKS;
00349   return Z_OK;
00350 }
00351 
00352 
00353 /* Returns true if inflate is currently at the end of a block generated
00354  * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
00355  * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
00356  * but removes the length bytes of the resulting empty stored block. When
00357  * decompressing, PPP checks that at the end of input packet, inflate is
00358  * waiting for these length bytes.
00359  */
00360 int ZEXPORT inflateSyncPoint(z)
00361 z_streamp z;
00362 {
00363   if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
00364     return Z_STREAM_ERROR;
00365   return inflate_blocks_sync_point(z->state->blocks);
00366 }