diff options
Diffstat (limited to 'lib/zlib_inflate/inflate.c')
| -rw-r--r-- | lib/zlib_inflate/inflate.c | 248 | 
1 files changed, 248 insertions, 0 deletions
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c new file mode 100644 index 00000000000..3d94cb90c1d --- /dev/null +++ b/lib/zlib_inflate/inflate.c @@ -0,0 +1,248 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h  + */ + +#include <linux/module.h> +#include <linux/zutil.h> +#include "infblock.h" +#include "infutil.h" + +int zlib_inflate_workspacesize(void) +{ +  return sizeof(struct inflate_workspace); +} + + +int zlib_inflateReset( +	z_streamp z +) +{ +  if (z == NULL || z->state == NULL || z->workspace == NULL) +    return Z_STREAM_ERROR; +  z->total_in = z->total_out = 0; +  z->msg = NULL; +  z->state->mode = z->state->nowrap ? BLOCKS : METHOD; +  zlib_inflate_blocks_reset(z->state->blocks, z, NULL); +  return Z_OK; +} + + +int zlib_inflateEnd( +	z_streamp z +) +{ +  if (z == NULL || z->state == NULL || z->workspace == NULL) +    return Z_STREAM_ERROR; +  if (z->state->blocks != NULL) +    zlib_inflate_blocks_free(z->state->blocks, z); +  z->state = NULL; +  return Z_OK; +} + + +int zlib_inflateInit2_( +	z_streamp z, +	int w, +	const char *version, +	int stream_size +) +{ +  if (version == NULL || version[0] != ZLIB_VERSION[0] || +      stream_size != sizeof(z_stream) || z->workspace == NULL) +      return Z_VERSION_ERROR; + +  /* initialize state */ +  z->msg = NULL; +  z->state = &WS(z)->internal_state; +  z->state->blocks = NULL; + +  /* handle undocumented nowrap option (no zlib header or check) */ +  z->state->nowrap = 0; +  if (w < 0) +  { +    w = - w; +    z->state->nowrap = 1; +  } + +  /* set window size */ +  if (w < 8 || w > 15) +  { +    zlib_inflateEnd(z); +    return Z_STREAM_ERROR; +  } +  z->state->wbits = (uInt)w; + +  /* create inflate_blocks state */ +  if ((z->state->blocks = +      zlib_inflate_blocks_new(z, z->state->nowrap ? NULL : zlib_adler32, (uInt)1 << w)) +      == NULL) +  { +    zlib_inflateEnd(z); +    return Z_MEM_ERROR; +  } + +  /* reset state */ +  zlib_inflateReset(z); +  return Z_OK; +} + + +/* + * At the end of a Deflate-compressed PPP packet, we expect to have seen + * a `stored' block type value but not the (zero) length bytes. + */ +static int zlib_inflate_packet_flush(inflate_blocks_statef *s) +{ +    if (s->mode != LENS) +	return Z_DATA_ERROR; +    s->mode = TYPE; +    return Z_OK; +} + + +int zlib_inflateInit_( +	z_streamp z, +	const char *version, +	int stream_size +) +{ +  return zlib_inflateInit2_(z, DEF_WBITS, version, stream_size); +} + +#undef NEEDBYTE +#undef NEXTBYTE +#define NEEDBYTE {if(z->avail_in==0)goto empty;r=trv;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int zlib_inflate( +	z_streamp z, +	int f +) +{ +  int r, trv; +  uInt b; + +  if (z == NULL || z->state == NULL || z->next_in == NULL) +    return Z_STREAM_ERROR; +  trv = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; +  r = Z_BUF_ERROR; +  while (1) switch (z->state->mode) +  { +    case METHOD: +      NEEDBYTE +      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) +      { +        z->state->mode = I_BAD; +        z->msg = (char*)"unknown compression method"; +        z->state->sub.marker = 5;       /* can't try inflateSync */ +        break; +      } +      if ((z->state->sub.method >> 4) + 8 > z->state->wbits) +      { +        z->state->mode = I_BAD; +        z->msg = (char*)"invalid window size"; +        z->state->sub.marker = 5;       /* can't try inflateSync */ +        break; +      } +      z->state->mode = FLAG; +    case FLAG: +      NEEDBYTE +      b = NEXTBYTE; +      if (((z->state->sub.method << 8) + b) % 31) +      { +        z->state->mode = I_BAD; +        z->msg = (char*)"incorrect header check"; +        z->state->sub.marker = 5;       /* can't try inflateSync */ +        break; +      } +      if (!(b & PRESET_DICT)) +      { +        z->state->mode = BLOCKS; +        break; +      } +      z->state->mode = DICT4; +    case DICT4: +      NEEDBYTE +      z->state->sub.check.need = (uLong)NEXTBYTE << 24; +      z->state->mode = DICT3; +    case DICT3: +      NEEDBYTE +      z->state->sub.check.need += (uLong)NEXTBYTE << 16; +      z->state->mode = DICT2; +    case DICT2: +      NEEDBYTE +      z->state->sub.check.need += (uLong)NEXTBYTE << 8; +      z->state->mode = DICT1; +    case DICT1: +      NEEDBYTE +      z->state->sub.check.need += (uLong)NEXTBYTE; +      z->adler = z->state->sub.check.need; +      z->state->mode = DICT0; +      return Z_NEED_DICT; +    case DICT0: +      z->state->mode = I_BAD; +      z->msg = (char*)"need dictionary"; +      z->state->sub.marker = 0;       /* can try inflateSync */ +      return Z_STREAM_ERROR; +    case BLOCKS: +      r = zlib_inflate_blocks(z->state->blocks, z, r); +      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) +	  r = zlib_inflate_packet_flush(z->state->blocks); +      if (r == Z_DATA_ERROR) +      { +        z->state->mode = I_BAD; +        z->state->sub.marker = 0;       /* can try inflateSync */ +        break; +      } +      if (r == Z_OK) +        r = trv; +      if (r != Z_STREAM_END) +        return r; +      r = trv; +      zlib_inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); +      if (z->state->nowrap) +      { +        z->state->mode = I_DONE; +        break; +      } +      z->state->mode = CHECK4; +    case CHECK4: +      NEEDBYTE +      z->state->sub.check.need = (uLong)NEXTBYTE << 24; +      z->state->mode = CHECK3; +    case CHECK3: +      NEEDBYTE +      z->state->sub.check.need += (uLong)NEXTBYTE << 16; +      z->state->mode = CHECK2; +    case CHECK2: +      NEEDBYTE +      z->state->sub.check.need += (uLong)NEXTBYTE << 8; +      z->state->mode = CHECK1; +    case CHECK1: +      NEEDBYTE +      z->state->sub.check.need += (uLong)NEXTBYTE; + +      if (z->state->sub.check.was != z->state->sub.check.need) +      { +        z->state->mode = I_BAD; +        z->msg = (char*)"incorrect data check"; +        z->state->sub.marker = 5;       /* can't try inflateSync */ +        break; +      } +      z->state->mode = I_DONE; +    case I_DONE: +      return Z_STREAM_END; +    case I_BAD: +      return Z_DATA_ERROR; +    default: +      return Z_STREAM_ERROR; +  } + empty: +  if (f != Z_PACKET_FLUSH) +    return r; +  z->state->mode = I_BAD; +  z->msg = (char *)"need more for packet flush"; +  z->state->sub.marker = 0;       /* can try inflateSync */ +  return Z_DATA_ERROR; +}  |