1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate /* 9*0Sstevel@tonic-gate * inflate.c -- zlib interface to inflate modules 10*0Sstevel@tonic-gate * Copyright (C) 1995-1998 Mark Adler 11*0Sstevel@tonic-gate * For conditions of distribution and use, see copyright notice in zlib.h 12*0Sstevel@tonic-gate */ 13*0Sstevel@tonic-gate 14*0Sstevel@tonic-gate #include "zutil.h" 15*0Sstevel@tonic-gate #include "infblock.h" 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate typedef enum { 18*0Sstevel@tonic-gate METHOD, /* waiting for method byte */ 19*0Sstevel@tonic-gate FLAG, /* waiting for flag byte */ 20*0Sstevel@tonic-gate DICT4, /* four dictionary check bytes to go */ 21*0Sstevel@tonic-gate DICT3, /* three dictionary check bytes to go */ 22*0Sstevel@tonic-gate DICT2, /* two dictionary check bytes to go */ 23*0Sstevel@tonic-gate DICT1, /* one dictionary check byte to go */ 24*0Sstevel@tonic-gate DICT0, /* waiting for inflateSetDictionary */ 25*0Sstevel@tonic-gate BLOCKS, /* decompressing blocks */ 26*0Sstevel@tonic-gate CHECK4, /* four check bytes to go */ 27*0Sstevel@tonic-gate CHECK3, /* three check bytes to go */ 28*0Sstevel@tonic-gate CHECK2, /* two check bytes to go */ 29*0Sstevel@tonic-gate CHECK1, /* one check byte to go */ 30*0Sstevel@tonic-gate DONE, /* finished check, done */ 31*0Sstevel@tonic-gate BAD} /* got an error--stay here */ 32*0Sstevel@tonic-gate inflate_mode; 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate /* inflate private state */ 35*0Sstevel@tonic-gate struct internal_state { 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* mode */ 38*0Sstevel@tonic-gate inflate_mode mode; /* current inflate mode */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate /* mode dependent information */ 41*0Sstevel@tonic-gate union { 42*0Sstevel@tonic-gate uInt method; /* if FLAGS, method byte */ 43*0Sstevel@tonic-gate struct { 44*0Sstevel@tonic-gate uLong was; /* computed check value */ 45*0Sstevel@tonic-gate uLong need; /* stream check value */ 46*0Sstevel@tonic-gate } check; /* if CHECK, check values to compare */ 47*0Sstevel@tonic-gate uInt marker; /* if BAD, inflateSync's marker bytes count */ 48*0Sstevel@tonic-gate } sub; /* submode */ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* mode independent information */ 51*0Sstevel@tonic-gate int nowrap; /* flag for no wrapper */ 52*0Sstevel@tonic-gate uInt wbits; /* log2(window size) (8..15, defaults to 15) */ 53*0Sstevel@tonic-gate inflate_blocks_statef 54*0Sstevel@tonic-gate *blocks; /* current inflate_blocks state */ 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate }; 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate int ZEXPORT inflateReset(z) 60*0Sstevel@tonic-gate z_streamp z; 61*0Sstevel@tonic-gate { 62*0Sstevel@tonic-gate if (z == Z_NULL || z->state == Z_NULL) 63*0Sstevel@tonic-gate return Z_STREAM_ERROR; 64*0Sstevel@tonic-gate z->total_in = z->total_out = 0; 65*0Sstevel@tonic-gate z->msg = Z_NULL; 66*0Sstevel@tonic-gate z->state->mode = z->state->nowrap ? BLOCKS : METHOD; 67*0Sstevel@tonic-gate inflate_blocks_reset(z->state->blocks, z, Z_NULL); 68*0Sstevel@tonic-gate Tracev((stderr, "inflate: reset\n")); 69*0Sstevel@tonic-gate return Z_OK; 70*0Sstevel@tonic-gate } 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate int ZEXPORT inflateEnd(z) 74*0Sstevel@tonic-gate z_streamp z; 75*0Sstevel@tonic-gate { 76*0Sstevel@tonic-gate if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) 77*0Sstevel@tonic-gate return Z_STREAM_ERROR; 78*0Sstevel@tonic-gate if (z->state->blocks != Z_NULL) 79*0Sstevel@tonic-gate (void) inflate_blocks_free(z->state->blocks, z); 80*0Sstevel@tonic-gate ZFREE(z, z->state); 81*0Sstevel@tonic-gate z->state = Z_NULL; 82*0Sstevel@tonic-gate Tracev((stderr, "inflate: end\n")); 83*0Sstevel@tonic-gate return Z_OK; 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate int ZEXPORT inflateInit2_(z, w, version, stream_size) 88*0Sstevel@tonic-gate z_streamp z; 89*0Sstevel@tonic-gate int w; 90*0Sstevel@tonic-gate const char *version; 91*0Sstevel@tonic-gate int stream_size; 92*0Sstevel@tonic-gate { 93*0Sstevel@tonic-gate if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || 94*0Sstevel@tonic-gate stream_size != sizeof(z_stream)) 95*0Sstevel@tonic-gate return Z_VERSION_ERROR; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* initialize state */ 98*0Sstevel@tonic-gate if (z == Z_NULL) 99*0Sstevel@tonic-gate return Z_STREAM_ERROR; 100*0Sstevel@tonic-gate z->msg = Z_NULL; 101*0Sstevel@tonic-gate if (z->zalloc == Z_NULL) 102*0Sstevel@tonic-gate { 103*0Sstevel@tonic-gate z->zalloc = zcalloc; 104*0Sstevel@tonic-gate z->opaque = (voidpf)0; 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate if (z->zfree == Z_NULL) z->zfree = zcfree; 107*0Sstevel@tonic-gate if ((z->state = (struct internal_state FAR *) 108*0Sstevel@tonic-gate ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) 109*0Sstevel@tonic-gate return Z_MEM_ERROR; 110*0Sstevel@tonic-gate z->state->blocks = Z_NULL; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* handle undocumented nowrap option (no zlib header or check) */ 113*0Sstevel@tonic-gate z->state->nowrap = 0; 114*0Sstevel@tonic-gate if (w < 0) 115*0Sstevel@tonic-gate { 116*0Sstevel@tonic-gate w = - w; 117*0Sstevel@tonic-gate z->state->nowrap = 1; 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* set window size */ 121*0Sstevel@tonic-gate if (w < 8 || w > 15) 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate (void) inflateEnd(z); 124*0Sstevel@tonic-gate return Z_STREAM_ERROR; 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate z->state->wbits = (uInt)w; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate /* create inflate_blocks state */ 129*0Sstevel@tonic-gate if ((z->state->blocks = 130*0Sstevel@tonic-gate inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) 131*0Sstevel@tonic-gate == Z_NULL) 132*0Sstevel@tonic-gate { 133*0Sstevel@tonic-gate (void) inflateEnd(z); 134*0Sstevel@tonic-gate return Z_MEM_ERROR; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate Tracev((stderr, "inflate: allocated\n")); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate /* reset state */ 139*0Sstevel@tonic-gate (void) inflateReset(z); 140*0Sstevel@tonic-gate return Z_OK; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate int ZEXPORT inflateInit_(z, version, stream_size) 145*0Sstevel@tonic-gate z_streamp z; 146*0Sstevel@tonic-gate const char *version; 147*0Sstevel@tonic-gate int stream_size; 148*0Sstevel@tonic-gate { 149*0Sstevel@tonic-gate return inflateInit2_(z, DEF_WBITS, version, stream_size); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate #define NEEDBYTE {if(z->avail_in==0)return r;r=f;} 154*0Sstevel@tonic-gate #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate int ZEXPORT inflate(z, f) 157*0Sstevel@tonic-gate z_streamp z; 158*0Sstevel@tonic-gate int f; 159*0Sstevel@tonic-gate { 160*0Sstevel@tonic-gate int r; 161*0Sstevel@tonic-gate uInt b; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) 164*0Sstevel@tonic-gate return Z_STREAM_ERROR; 165*0Sstevel@tonic-gate f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; 166*0Sstevel@tonic-gate r = Z_BUF_ERROR; 167*0Sstevel@tonic-gate /*CONSTCOND*/ 168*0Sstevel@tonic-gate while (1) switch (z->state->mode) 169*0Sstevel@tonic-gate { 170*0Sstevel@tonic-gate case METHOD: 171*0Sstevel@tonic-gate NEEDBYTE 172*0Sstevel@tonic-gate if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) 173*0Sstevel@tonic-gate { 174*0Sstevel@tonic-gate z->state->mode = BAD; 175*0Sstevel@tonic-gate z->msg = (char*)"unknown compression method"; 176*0Sstevel@tonic-gate z->state->sub.marker = 5; /* can't try inflateSync */ 177*0Sstevel@tonic-gate break; 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate if ((z->state->sub.method >> 4) + 8 > z->state->wbits) 180*0Sstevel@tonic-gate { 181*0Sstevel@tonic-gate z->state->mode = BAD; 182*0Sstevel@tonic-gate z->msg = (char*)"invalid window size"; 183*0Sstevel@tonic-gate z->state->sub.marker = 5; /* can't try inflateSync */ 184*0Sstevel@tonic-gate break; 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate z->state->mode = FLAG; 187*0Sstevel@tonic-gate /*FALLTHRU*/ 188*0Sstevel@tonic-gate case FLAG: 189*0Sstevel@tonic-gate NEEDBYTE 190*0Sstevel@tonic-gate b = NEXTBYTE; 191*0Sstevel@tonic-gate if (((z->state->sub.method << 8) + b) % 31) 192*0Sstevel@tonic-gate { 193*0Sstevel@tonic-gate z->state->mode = BAD; 194*0Sstevel@tonic-gate z->msg = (char*)"incorrect header check"; 195*0Sstevel@tonic-gate z->state->sub.marker = 5; /* can't try inflateSync */ 196*0Sstevel@tonic-gate break; 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate Tracev((stderr, "inflate: zlib header ok\n")); 199*0Sstevel@tonic-gate if (!(b & PRESET_DICT)) 200*0Sstevel@tonic-gate { 201*0Sstevel@tonic-gate z->state->mode = BLOCKS; 202*0Sstevel@tonic-gate break; 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate z->state->mode = DICT4; 205*0Sstevel@tonic-gate /*FALLTHRU*/ 206*0Sstevel@tonic-gate case DICT4: 207*0Sstevel@tonic-gate NEEDBYTE 208*0Sstevel@tonic-gate z->state->sub.check.need = (uLong)NEXTBYTE << 24; 209*0Sstevel@tonic-gate z->state->mode = DICT3; 210*0Sstevel@tonic-gate /*FALLTHRU*/ 211*0Sstevel@tonic-gate case DICT3: 212*0Sstevel@tonic-gate NEEDBYTE 213*0Sstevel@tonic-gate z->state->sub.check.need += (uLong)NEXTBYTE << 16; 214*0Sstevel@tonic-gate z->state->mode = DICT2; 215*0Sstevel@tonic-gate /*FALLTHRU*/ 216*0Sstevel@tonic-gate case DICT2: 217*0Sstevel@tonic-gate NEEDBYTE 218*0Sstevel@tonic-gate z->state->sub.check.need += (uLong)NEXTBYTE << 8; 219*0Sstevel@tonic-gate z->state->mode = DICT1; 220*0Sstevel@tonic-gate /*FALLTHRU*/ 221*0Sstevel@tonic-gate case DICT1: 222*0Sstevel@tonic-gate NEEDBYTE 223*0Sstevel@tonic-gate z->state->sub.check.need += (uLong)NEXTBYTE; 224*0Sstevel@tonic-gate z->adler = z->state->sub.check.need; 225*0Sstevel@tonic-gate z->state->mode = DICT0; 226*0Sstevel@tonic-gate return Z_NEED_DICT; 227*0Sstevel@tonic-gate case DICT0: 228*0Sstevel@tonic-gate z->state->mode = BAD; 229*0Sstevel@tonic-gate z->msg = (char*)"need dictionary"; 230*0Sstevel@tonic-gate z->state->sub.marker = 0; /* can try inflateSync */ 231*0Sstevel@tonic-gate return Z_STREAM_ERROR; 232*0Sstevel@tonic-gate case BLOCKS: 233*0Sstevel@tonic-gate r = inflate_blocks(z->state->blocks, z, r); 234*0Sstevel@tonic-gate if (r == Z_DATA_ERROR) 235*0Sstevel@tonic-gate { 236*0Sstevel@tonic-gate z->state->mode = BAD; 237*0Sstevel@tonic-gate z->state->sub.marker = 0; /* can try inflateSync */ 238*0Sstevel@tonic-gate break; 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate if (r == Z_OK) 241*0Sstevel@tonic-gate r = f; 242*0Sstevel@tonic-gate if (r != Z_STREAM_END) 243*0Sstevel@tonic-gate return r; 244*0Sstevel@tonic-gate r = f; 245*0Sstevel@tonic-gate inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); 246*0Sstevel@tonic-gate if (z->state->nowrap) 247*0Sstevel@tonic-gate { 248*0Sstevel@tonic-gate z->state->mode = DONE; 249*0Sstevel@tonic-gate break; 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate z->state->mode = CHECK4; 252*0Sstevel@tonic-gate /*FALLTHRU*/ 253*0Sstevel@tonic-gate case CHECK4: 254*0Sstevel@tonic-gate NEEDBYTE 255*0Sstevel@tonic-gate z->state->sub.check.need = (uLong)NEXTBYTE << 24; 256*0Sstevel@tonic-gate z->state->mode = CHECK3; 257*0Sstevel@tonic-gate /*FALLTHRU*/ 258*0Sstevel@tonic-gate case CHECK3: 259*0Sstevel@tonic-gate NEEDBYTE 260*0Sstevel@tonic-gate z->state->sub.check.need += (uLong)NEXTBYTE << 16; 261*0Sstevel@tonic-gate z->state->mode = CHECK2; 262*0Sstevel@tonic-gate /*FALLTHRU*/ 263*0Sstevel@tonic-gate case CHECK2: 264*0Sstevel@tonic-gate NEEDBYTE 265*0Sstevel@tonic-gate z->state->sub.check.need += (uLong)NEXTBYTE << 8; 266*0Sstevel@tonic-gate z->state->mode = CHECK1; 267*0Sstevel@tonic-gate /*FALLTHRU*/ 268*0Sstevel@tonic-gate case CHECK1: 269*0Sstevel@tonic-gate NEEDBYTE 270*0Sstevel@tonic-gate z->state->sub.check.need += (uLong)NEXTBYTE; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate if (z->state->sub.check.was != z->state->sub.check.need) 273*0Sstevel@tonic-gate { 274*0Sstevel@tonic-gate z->state->mode = BAD; 275*0Sstevel@tonic-gate z->msg = (char*)"incorrect data check"; 276*0Sstevel@tonic-gate z->state->sub.marker = 5; /* can't try inflateSync */ 277*0Sstevel@tonic-gate break; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate Tracev((stderr, "inflate: zlib check ok\n")); 280*0Sstevel@tonic-gate z->state->mode = DONE; 281*0Sstevel@tonic-gate /*FALLTHRU*/ 282*0Sstevel@tonic-gate case DONE: 283*0Sstevel@tonic-gate return Z_STREAM_END; 284*0Sstevel@tonic-gate case BAD: 285*0Sstevel@tonic-gate return Z_DATA_ERROR; 286*0Sstevel@tonic-gate default: 287*0Sstevel@tonic-gate return Z_STREAM_ERROR; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate /*NOTREACHED*/ 290*0Sstevel@tonic-gate } 291