00001
00002
00003
00004
00005
00006 #include "gzguts.h"
00007
00008
00009 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
00010 local int gz_avail OF((gz_statep));
00011 local int gz_next4 OF((gz_statep, unsigned long *));
00012 local int gz_head OF((gz_statep));
00013 local int gz_decomp OF((gz_statep));
00014 local int gz_make OF((gz_statep));
00015 local int gz_skip OF((gz_statep, z_off64_t));
00016
00017
00018
00019
00020
00021 local int gz_load(state, buf, len, have)
00022 gz_statep state;
00023 unsigned char *buf;
00024 unsigned len;
00025 unsigned *have;
00026 {
00027 int ret;
00028
00029 *have = 0;
00030 do {
00031 ret = read(state->fd, buf + *have, len - *have);
00032 if (ret <= 0)
00033 break;
00034 *have += ret;
00035 } while (*have < len);
00036 if (ret < 0) {
00037 gz_error(state, Z_ERRNO, zstrerror());
00038 return -1;
00039 }
00040 if (ret == 0)
00041 state->eof = 1;
00042 return 0;
00043 }
00044
00045
00046
00047
00048
00049
00050 local int gz_avail(state)
00051 gz_statep state;
00052 {
00053 z_streamp strm = &(state->strm);
00054
00055 if (state->err != Z_OK)
00056 return -1;
00057 if (state->eof == 0) {
00058 if (gz_load(state, state->in, state->size,
00059 (unsigned *)&(strm->avail_in)) == -1)
00060 return -1;
00061 strm->next_in = state->in;
00062 }
00063 return 0;
00064 }
00065
00066
00067 #define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
00068 (strm->avail_in == 0 ? -1 : \
00069 (strm->avail_in--, *(strm->next_in)++)))
00070
00071
00072
00073 local int gz_next4(state, ret)
00074 gz_statep state;
00075 unsigned long *ret;
00076 {
00077 int ch;
00078 unsigned long val;
00079 z_streamp strm = &(state->strm);
00080
00081 val = NEXT();
00082 val += (unsigned)NEXT() << 8;
00083 val += (unsigned long)NEXT() << 16;
00084 ch = NEXT();
00085 if (ch == -1)
00086 return -1;
00087 val += (unsigned long)ch << 24;
00088 *ret = val;
00089 return 0;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 local int gz_head(state)
00105 gz_statep state;
00106 {
00107 z_streamp strm = &(state->strm);
00108 int flags;
00109 unsigned len;
00110
00111
00112 if (state->size == 0) {
00113
00114 state->in = malloc(state->want);
00115 state->out = malloc(state->want << 1);
00116 if (state->in == NULL || state->out == NULL) {
00117 if (state->out != NULL)
00118 free(state->out);
00119 if (state->in != NULL)
00120 free(state->in);
00121 gz_error(state, Z_MEM_ERROR, "out of memory");
00122 return -1;
00123 }
00124 state->size = state->want;
00125
00126
00127 state->strm.zalloc = Z_NULL;
00128 state->strm.zfree = Z_NULL;
00129 state->strm.opaque = Z_NULL;
00130 state->strm.avail_in = 0;
00131 state->strm.next_in = Z_NULL;
00132 if (inflateInit2(&(state->strm), -15) != Z_OK) {
00133 free(state->out);
00134 free(state->in);
00135 state->size = 0;
00136 gz_error(state, Z_MEM_ERROR, "out of memory");
00137 return -1;
00138 }
00139 }
00140
00141
00142 if (strm->avail_in == 0) {
00143 if (gz_avail(state) == -1)
00144 return -1;
00145 if (strm->avail_in == 0)
00146 return 0;
00147 }
00148
00149
00150 if (strm->next_in[0] == 31) {
00151 strm->avail_in--;
00152 strm->next_in++;
00153 if (strm->avail_in == 0 && gz_avail(state) == -1)
00154 return -1;
00155 if (strm->avail_in && strm->next_in[0] == 139) {
00156
00157 strm->avail_in--;
00158 strm->next_in++;
00159
00160
00161 if (NEXT() != 8) {
00162 gz_error(state, Z_DATA_ERROR, "unknown compression method");
00163 return -1;
00164 }
00165 flags = NEXT();
00166 if (flags & 0xe0) {
00167 gz_error(state, Z_DATA_ERROR, "unknown header flags set");
00168 return -1;
00169 }
00170 NEXT();
00171 NEXT();
00172 NEXT();
00173 NEXT();
00174 NEXT();
00175 NEXT();
00176 if (flags & 4) {
00177 len = (unsigned)NEXT();
00178 len += (unsigned)NEXT() << 8;
00179 while (len--)
00180 if (NEXT() < 0)
00181 break;
00182 }
00183 if (flags & 8)
00184 while (NEXT() > 0)
00185 ;
00186 if (flags & 16)
00187 while (NEXT() > 0)
00188 ;
00189 if (flags & 2) {
00190 NEXT();
00191 NEXT();
00192 }
00193
00194
00195
00196
00197 inflateReset(strm);
00198 strm->adler = crc32(0L, Z_NULL, 0);
00199 state->how = GZIP;
00200 state->direct = 0;
00201 return 0;
00202 }
00203 else {
00204
00205 state->out[0] = 31;
00206 state->have = 1;
00207 }
00208 }
00209
00210
00211
00212
00213 state->raw = state->pos;
00214 state->next = state->out;
00215 if (strm->avail_in) {
00216 memcpy(state->next + state->have, strm->next_in, strm->avail_in);
00217 state->have += strm->avail_in;
00218 strm->avail_in = 0;
00219 }
00220 state->how = COPY;
00221 state->direct = 1;
00222 return 0;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 local int gz_decomp(state)
00234 gz_statep state;
00235 {
00236 int ret;
00237 unsigned had;
00238 unsigned long crc, len;
00239 z_streamp strm = &(state->strm);
00240
00241
00242 had = strm->avail_out;
00243 do {
00244
00245 if (strm->avail_in == 0 && gz_avail(state) == -1)
00246 return -1;
00247 if (strm->avail_in == 0) {
00248 gz_error(state, Z_DATA_ERROR, "unexpected end of file");
00249 return -1;
00250 }
00251
00252
00253 ret = inflate(strm, Z_NO_FLUSH);
00254 if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
00255 gz_error(state, Z_STREAM_ERROR,
00256 "internal error: inflate stream corrupt");
00257 return -1;
00258 }
00259 if (ret == Z_MEM_ERROR) {
00260 gz_error(state, Z_MEM_ERROR, "out of memory");
00261 return -1;
00262 }
00263 if (ret == Z_DATA_ERROR) {
00264 gz_error(state, Z_DATA_ERROR,
00265 strm->msg == NULL ? "compressed data error" : strm->msg);
00266 return -1;
00267 }
00268 } while (strm->avail_out && ret != Z_STREAM_END);
00269
00270
00271 state->have = had - strm->avail_out;
00272 state->next = strm->next_out - state->have;
00273 strm->adler = crc32(strm->adler, state->next, state->have);
00274
00275
00276 if (ret == Z_STREAM_END) {
00277 if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
00278 gz_error(state, Z_DATA_ERROR, "unexpected end of file");
00279 return -1;
00280 }
00281 if (crc != strm->adler) {
00282 gz_error(state, Z_DATA_ERROR, "incorrect data check");
00283 return -1;
00284 }
00285 if (len != (strm->total_out & 0xffffffffL)) {
00286 gz_error(state, Z_DATA_ERROR, "incorrect length check");
00287 return -1;
00288 }
00289 state->how = LOOK;
00290
00291 }
00292
00293
00294 return 0;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 local int gz_make(state)
00305 gz_statep state;
00306 {
00307 z_streamp strm = &(state->strm);
00308
00309 if (state->how == LOOK) {
00310 if (gz_head(state) == -1)
00311 return -1;
00312 if (state->have)
00313 return 0;
00314 }
00315 if (state->how == COPY) {
00316 if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
00317 return -1;
00318 state->next = state->out;
00319 }
00320 else if (state->how == GZIP) {
00321 strm->avail_out = state->size << 1;
00322 strm->next_out = state->out;
00323 if (gz_decomp(state) == -1)
00324 return -1;
00325 }
00326 return 0;
00327 }
00328
00329
00330 local int gz_skip(state, len)
00331 gz_statep state;
00332 z_off64_t len;
00333 {
00334 unsigned n;
00335
00336
00337 while (len)
00338
00339 if (state->have) {
00340 n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
00341 (unsigned)len : state->have;
00342 state->have -= n;
00343 state->next += n;
00344 state->pos += n;
00345 len -= n;
00346 }
00347
00348
00349 else if (state->eof && state->strm.avail_in == 0)
00350 break;
00351
00352
00353 else {
00354
00355 if (gz_make(state) == -1)
00356 return -1;
00357 }
00358 return 0;
00359 }
00360
00361
00362 int ZEXPORT gzread(file, buf, len)
00363 gzFile file;
00364 voidp buf;
00365 unsigned len;
00366 {
00367 unsigned got, n;
00368 gz_statep state;
00369 z_streamp strm;
00370
00371
00372 if (file == NULL)
00373 return -1;
00374 state = (gz_statep)file;
00375 strm = &(state->strm);
00376
00377
00378 if (state->mode != GZ_READ || state->err != Z_OK)
00379 return -1;
00380
00381
00382
00383 if ((int)len < 0) {
00384 gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
00385 return -1;
00386 }
00387
00388
00389 if (len == 0)
00390 return 0;
00391
00392
00393 if (state->seek) {
00394 state->seek = 0;
00395 if (gz_skip(state, state->skip) == -1)
00396 return -1;
00397 }
00398
00399
00400 got = 0;
00401 do {
00402
00403 if (state->have) {
00404 n = state->have > len ? len : state->have;
00405 memcpy(buf, state->next, n);
00406 state->next += n;
00407 state->have -= n;
00408 }
00409
00410
00411 else if (state->eof && strm->avail_in == 0)
00412 break;
00413
00414
00415
00416 else if (state->how == LOOK || len < (state->size << 1)) {
00417
00418 if (gz_make(state) == -1)
00419 return -1;
00420 continue;
00421
00422
00423 }
00424
00425
00426 else if (state->how == COPY) {
00427 if (gz_load(state, buf, len, &n) == -1)
00428 return -1;
00429 }
00430
00431
00432 else {
00433 strm->avail_out = len;
00434 strm->next_out = buf;
00435 if (gz_decomp(state) == -1)
00436 return -1;
00437 n = state->have;
00438 state->have = 0;
00439 }
00440
00441
00442 len -= n;
00443 buf = (char *)buf + n;
00444 got += n;
00445 state->pos += n;
00446 } while (len);
00447
00448
00449 return (int)got;
00450 }
00451
00452
00453 int ZEXPORT gzgetc(file)
00454 gzFile file;
00455 {
00456 int ret;
00457 unsigned char buf[1];
00458 gz_statep state;
00459
00460
00461 if (file == NULL)
00462 return -1;
00463 state = (gz_statep)file;
00464
00465
00466 if (state->mode != GZ_READ || state->err != Z_OK)
00467 return -1;
00468
00469
00470 if (state->have) {
00471 state->have--;
00472 state->pos++;
00473 return *(state->next)++;
00474 }
00475
00476
00477 ret = gzread(file, buf, 1);
00478 return ret < 1 ? -1 : buf[0];
00479 }
00480
00481
00482 int ZEXPORT gzungetc(c, file)
00483 int c;
00484 gzFile file;
00485 {
00486 gz_statep state;
00487
00488
00489 if (file == NULL)
00490 return -1;
00491 state = (gz_statep)file;
00492
00493
00494 if (state->mode != GZ_READ || state->err != Z_OK)
00495 return -1;
00496
00497
00498 if (state->seek) {
00499 state->seek = 0;
00500 if (gz_skip(state, state->skip) == -1)
00501 return -1;
00502 }
00503
00504
00505 if (c < 0)
00506 return -1;
00507
00508
00509 if (state->have == 0) {
00510 state->have = 1;
00511 state->next = state->out + (state->size << 1) - 1;
00512 state->next[0] = c;
00513 state->pos--;
00514 return c;
00515 }
00516
00517
00518 if (state->have == (state->size << 1)) {
00519 gz_error(state, Z_BUF_ERROR, "out of room to push characters");
00520 return -1;
00521 }
00522
00523
00524 if (state->next == state->out) {
00525 unsigned char *src = state->out + state->have;
00526 unsigned char *dest = state->out + (state->size << 1);
00527 while (src > state->out)
00528 *--dest = *--src;
00529 state->next = dest;
00530 }
00531 state->have++;
00532 state->next--;
00533 state->next[0] = c;
00534 state->pos--;
00535 return c;
00536 }
00537
00538
00539 char * ZEXPORT gzgets(file, buf, len)
00540 gzFile file;
00541 char *buf;
00542 int len;
00543 {
00544 unsigned left, n;
00545 char *str;
00546 unsigned char *eol;
00547 gz_statep state;
00548
00549
00550 if (file == NULL || buf == NULL || len < 1)
00551 return NULL;
00552 state = (gz_statep)file;
00553
00554
00555 if (state->mode != GZ_READ || state->err != Z_OK)
00556 return NULL;
00557
00558
00559 if (state->seek) {
00560 state->seek = 0;
00561 if (gz_skip(state, state->skip) == -1)
00562 return NULL;
00563 }
00564
00565
00566
00567
00568 str = buf;
00569 left = (unsigned)len - 1;
00570 if (left) do {
00571
00572 if (state->have == 0) {
00573 if (gz_make(state) == -1)
00574 return NULL;
00575 if (state->have == 0) {
00576 if (buf == str)
00577 return NULL;
00578 break;
00579 }
00580 }
00581
00582
00583 n = state->have > left ? left : state->have;
00584 eol = memchr(state->next, '\n', n);
00585 if (eol != NULL)
00586 n = (unsigned)(eol - state->next) + 1;
00587
00588
00589 memcpy(buf, state->next, n);
00590 state->have -= n;
00591 state->next += n;
00592 state->pos += n;
00593 left -= n;
00594 buf += n;
00595 } while (left && eol == NULL);
00596
00597
00598 buf[0] = 0;
00599 return str;
00600 }
00601
00602
00603 int ZEXPORT gzdirect(file)
00604 gzFile file;
00605 {
00606 gz_statep state;
00607
00608
00609 if (file == NULL)
00610 return 0;
00611 state = (gz_statep)file;
00612
00613
00614 if (state->mode != GZ_READ)
00615 return 0;
00616
00617
00618
00619 if (state->how == LOOK && state->have == 0)
00620 (void)gz_head(state);
00621
00622
00623 return state->direct;
00624 }
00625
00626
00627 int ZEXPORT gzclose_r(file)
00628 gzFile file;
00629 {
00630 int ret;
00631 gz_statep state;
00632
00633
00634 if (file == NULL)
00635 return Z_STREAM_ERROR;
00636 state = (gz_statep)file;
00637
00638
00639 if (state->mode != GZ_READ)
00640 return Z_STREAM_ERROR;
00641
00642
00643 if (state->size) {
00644 inflateEnd(&(state->strm));
00645 free(state->out);
00646 free(state->in);
00647 }
00648 gz_error(state, Z_OK, NULL);
00649 free(state->path);
00650 ret = close(state->fd);
00651 free(state);
00652 return ret ? Z_ERRNO : Z_OK;
00653 }