00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdio.h>
00011
00012 #include "zutil.h"
00013
00014 #ifdef NO_DEFLATE
00015 # define NO_GZCOMPRESS
00016 #endif
00017
00018 #ifndef NO_DUMMY_DECL
00019 struct internal_state {int dummy;};
00020 #endif
00021
00022 #ifndef Z_BUFSIZE
00023 # ifdef MAXSEG_64K
00024 # define Z_BUFSIZE 4096
00025 # else
00026 # define Z_BUFSIZE 16384
00027 # endif
00028 #endif
00029 #ifndef Z_PRINTF_BUFSIZE
00030 # define Z_PRINTF_BUFSIZE 4096
00031 #endif
00032
00033 #ifdef __MVS__
00034 # pragma map (fdopen , "\174\174FDOPEN")
00035 FILE *fdopen(int, const char *);
00036 #endif
00037
00038 #ifndef STDC
00039 extern voidp malloc OF((uInt size));
00040 extern void free OF((voidpf ptr));
00041 #endif
00042
00043 #define ALLOC(size) malloc(size)
00044 #define TRYFREE(p) {if (p) free(p);}
00045
00046 static int const gz_magic[2] = {0x1f, 0x8b};
00047
00048
00049 #define ASCII_FLAG 0x01
00050 #define HEAD_CRC 0x02
00051 #define EXTRA_FIELD 0x04
00052 #define ORIG_NAME 0x08
00053 #define COMMENT 0x10
00054 #define RESERVED 0xE0
00055
00056 typedef struct gz_stream {
00057 z_stream stream;
00058 int z_err;
00059 int z_eof;
00060 FILE *file;
00061 Byte *inbuf;
00062 Byte *outbuf;
00063 uLong crc;
00064 char *msg;
00065 char *path;
00066 int transparent;
00067 char mode;
00068 z_off_t start;
00069 z_off_t in;
00070 z_off_t out;
00071 int back;
00072 int last;
00073 } gz_stream;
00074
00075
00076 local gzFile gz_open OF((const char *path, const char *mode, int fd));
00077 local int do_flush OF((gzFile file, int flush));
00078 local int get_byte OF((gz_stream *s));
00079 local void check_header OF((gz_stream *s));
00080 local int destroy OF((gz_stream *s));
00081 local void putLong OF((FILE *file, uLong x));
00082 local uLong getLong OF((gz_stream *s));
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 local gzFile gz_open (path, mode, fd)
00094 const char *path;
00095 const char *mode;
00096 int fd;
00097 {
00098 int err;
00099 int level = Z_DEFAULT_COMPRESSION;
00100 int strategy = Z_DEFAULT_STRATEGY;
00101 char *p = (char*)mode;
00102 gz_stream *s;
00103 char fmode[80];
00104 char *m = fmode;
00105
00106 if (!path || !mode) return Z_NULL;
00107
00108 s = (gz_stream *)ALLOC(sizeof(gz_stream));
00109 if (!s) return Z_NULL;
00110
00111 s->stream.zalloc = (alloc_func)0;
00112 s->stream.zfree = (free_func)0;
00113 s->stream.opaque = (voidpf)0;
00114 s->stream.next_in = s->inbuf = Z_NULL;
00115 s->stream.next_out = s->outbuf = Z_NULL;
00116 s->stream.avail_in = s->stream.avail_out = 0;
00117 s->file = NULL;
00118 s->z_err = Z_OK;
00119 s->z_eof = 0;
00120 s->in = 0;
00121 s->out = 0;
00122 s->back = EOF;
00123 s->crc = crc32(0L, Z_NULL, 0);
00124 s->msg = NULL;
00125 s->transparent = 0;
00126
00127 s->path = (char*)ALLOC(strlen(path)+1);
00128 if (s->path == NULL) {
00129 return destroy(s), (gzFile)Z_NULL;
00130 }
00131 strcpy(s->path, path);
00132
00133 s->mode = '\0';
00134 do {
00135 if (*p == 'r') s->mode = 'r';
00136 if (*p == 'w' || *p == 'a') s->mode = 'w';
00137 if (*p >= '0' && *p <= '9') {
00138 level = *p - '0';
00139 } else if (*p == 'f') {
00140 strategy = Z_FILTERED;
00141 } else if (*p == 'h') {
00142 strategy = Z_HUFFMAN_ONLY;
00143 } else if (*p == 'R') {
00144 strategy = Z_RLE;
00145 } else {
00146 *m++ = *p;
00147 }
00148 } while (*p++ && m != fmode + sizeof(fmode));
00149 if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
00150
00151 if (s->mode == 'w') {
00152 #ifdef NO_GZCOMPRESS
00153 err = Z_STREAM_ERROR;
00154 #else
00155 err = deflateInit2(&(s->stream), level,
00156 Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
00157
00158
00159 s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
00160 #endif
00161 if (err != Z_OK || s->outbuf == Z_NULL) {
00162 return destroy(s), (gzFile)Z_NULL;
00163 }
00164 } else {
00165 s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
00166
00167 err = inflateInit2(&(s->stream), -MAX_WBITS);
00168
00169
00170
00171
00172
00173
00174 if (err != Z_OK || s->inbuf == Z_NULL) {
00175 return destroy(s), (gzFile)Z_NULL;
00176 }
00177 }
00178 s->stream.avail_out = Z_BUFSIZE;
00179
00180 errno = 0;
00181 s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
00182
00183 if (s->file == NULL) {
00184 return destroy(s), (gzFile)Z_NULL;
00185 }
00186 if (s->mode == 'w') {
00187
00188
00189 fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
00190 Z_DEFLATED, 0 , 0,0,0,0 , 0 , OS_CODE);
00191 s->start = 10L;
00192
00193
00194
00195
00196
00197 } else {
00198 check_header(s);
00199 s->start = ftell(s->file) - s->stream.avail_in;
00200 }
00201
00202 return (gzFile)s;
00203 }
00204
00205
00206
00207
00208 gzFile ZEXPORT gzopen (path, mode)
00209 const char *path;
00210 const char *mode;
00211 {
00212 return gz_open (path, mode, -1);
00213 }
00214
00215
00216
00217
00218
00219 gzFile ZEXPORT gzdopen (fd, mode)
00220 int fd;
00221 const char *mode;
00222 {
00223 char name[46];
00224
00225 if (fd < 0) return (gzFile)Z_NULL;
00226 sprintf(name, "<fd:%d>", fd);
00227
00228 return gz_open (name, mode, fd);
00229 }
00230
00231
00232
00233
00234 int ZEXPORT gzsetparams (file, level, strategy)
00235 gzFile file;
00236 int level;
00237 int strategy;
00238 {
00239 gz_stream *s = (gz_stream*)file;
00240
00241 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
00242
00243
00244 if (s->stream.avail_out == 0) {
00245
00246 s->stream.next_out = s->outbuf;
00247 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
00248 s->z_err = Z_ERRNO;
00249 }
00250 s->stream.avail_out = Z_BUFSIZE;
00251 }
00252
00253 return deflateParams (&(s->stream), level, strategy);
00254 }
00255
00256
00257
00258
00259
00260
00261 local int get_byte(s)
00262 gz_stream *s;
00263 {
00264 if (s->z_eof) return EOF;
00265 if (s->stream.avail_in == 0) {
00266 errno = 0;
00267 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
00268 if (s->stream.avail_in == 0) {
00269 s->z_eof = 1;
00270 if (ferror(s->file)) s->z_err = Z_ERRNO;
00271 return EOF;
00272 }
00273 s->stream.next_in = s->inbuf;
00274 }
00275 s->stream.avail_in--;
00276 return *(s->stream.next_in)++;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 local void check_header(s)
00289 gz_stream *s;
00290 {
00291 int method;
00292 int flags;
00293 uInt len;
00294 int c;
00295
00296
00297
00298
00299 len = s->stream.avail_in;
00300 if (len < 2) {
00301 if (len) s->inbuf[0] = s->stream.next_in[0];
00302 errno = 0;
00303 len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
00304 if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
00305 s->stream.avail_in += len;
00306 s->stream.next_in = s->inbuf;
00307 if (s->stream.avail_in < 2) {
00308 s->transparent = s->stream.avail_in;
00309 return;
00310 }
00311 }
00312
00313
00314 if (s->stream.next_in[0] != gz_magic[0] ||
00315 s->stream.next_in[1] != gz_magic[1]) {
00316 s->transparent = 1;
00317 return;
00318 }
00319 s->stream.avail_in -= 2;
00320 s->stream.next_in += 2;
00321
00322
00323 method = get_byte(s);
00324 flags = get_byte(s);
00325 if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
00326 s->z_err = Z_DATA_ERROR;
00327 return;
00328 }
00329
00330
00331 for (len = 0; len < 6; len++) (void)get_byte(s);
00332
00333 if ((flags & EXTRA_FIELD) != 0) {
00334 len = (uInt)get_byte(s);
00335 len += ((uInt)get_byte(s))<<8;
00336
00337 while (len-- != 0 && get_byte(s) != EOF) ;
00338 }
00339 if ((flags & ORIG_NAME) != 0) {
00340 while ((c = get_byte(s)) != 0 && c != EOF) ;
00341 }
00342 if ((flags & COMMENT) != 0) {
00343 while ((c = get_byte(s)) != 0 && c != EOF) ;
00344 }
00345 if ((flags & HEAD_CRC) != 0) {
00346 for (len = 0; len < 2; len++) (void)get_byte(s);
00347 }
00348 s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
00349 }
00350
00351
00352
00353
00354
00355 local int destroy (s)
00356 gz_stream *s;
00357 {
00358 int err = Z_OK;
00359
00360 if (!s) return Z_STREAM_ERROR;
00361
00362 TRYFREE(s->msg);
00363
00364 if (s->stream.state != NULL) {
00365 if (s->mode == 'w') {
00366 #ifdef NO_GZCOMPRESS
00367 err = Z_STREAM_ERROR;
00368 #else
00369 err = deflateEnd(&(s->stream));
00370 #endif
00371 } else if (s->mode == 'r') {
00372 err = inflateEnd(&(s->stream));
00373 }
00374 }
00375 if (s->file != NULL && fclose(s->file)) {
00376 #ifdef ESPIPE
00377 if (errno != ESPIPE)
00378 #endif
00379 err = Z_ERRNO;
00380 }
00381 if (s->z_err < 0) err = s->z_err;
00382
00383 TRYFREE(s->inbuf);
00384 TRYFREE(s->outbuf);
00385 TRYFREE(s->path);
00386 TRYFREE(s);
00387 return err;
00388 }
00389
00390
00391
00392
00393
00394 int ZEXPORT gzread (file, buf, len)
00395 gzFile file;
00396 voidp buf;
00397 unsigned len;
00398 {
00399 gz_stream *s = (gz_stream*)file;
00400 Bytef *start = (Bytef*)buf;
00401 Byte *next_out;
00402
00403 if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
00404
00405 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
00406 if (s->z_err == Z_STREAM_END) return 0;
00407
00408 next_out = (Byte*)buf;
00409 s->stream.next_out = (Bytef*)buf;
00410 s->stream.avail_out = len;
00411
00412 if (s->stream.avail_out && s->back != EOF) {
00413 *next_out++ = s->back;
00414 s->stream.next_out++;
00415 s->stream.avail_out--;
00416 s->back = EOF;
00417 s->out++;
00418 start++;
00419 if (s->last) {
00420 s->z_err = Z_STREAM_END;
00421 return 1;
00422 }
00423 }
00424
00425 while (s->stream.avail_out != 0) {
00426
00427 if (s->transparent) {
00428
00429 uInt n = s->stream.avail_in;
00430 if (n > s->stream.avail_out) n = s->stream.avail_out;
00431 if (n > 0) {
00432 zmemcpy(s->stream.next_out, s->stream.next_in, n);
00433 next_out += n;
00434 s->stream.next_out = next_out;
00435 s->stream.next_in += n;
00436 s->stream.avail_out -= n;
00437 s->stream.avail_in -= n;
00438 }
00439 if (s->stream.avail_out > 0) {
00440 s->stream.avail_out -=
00441 (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
00442 }
00443 len -= s->stream.avail_out;
00444 s->in += len;
00445 s->out += len;
00446 if (len == 0) s->z_eof = 1;
00447 return (int)len;
00448 }
00449 if (s->stream.avail_in == 0 && !s->z_eof) {
00450
00451 errno = 0;
00452 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
00453 if (s->stream.avail_in == 0) {
00454 s->z_eof = 1;
00455 if (ferror(s->file)) {
00456 s->z_err = Z_ERRNO;
00457 break;
00458 }
00459 }
00460 s->stream.next_in = s->inbuf;
00461 }
00462 s->in += s->stream.avail_in;
00463 s->out += s->stream.avail_out;
00464 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
00465 s->in -= s->stream.avail_in;
00466 s->out -= s->stream.avail_out;
00467
00468 if (s->z_err == Z_STREAM_END) {
00469
00470 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
00471 start = s->stream.next_out;
00472
00473 if (getLong(s) != s->crc) {
00474 s->z_err = Z_DATA_ERROR;
00475 } else {
00476 (void)getLong(s);
00477
00478
00479
00480
00481 check_header(s);
00482 if (s->z_err == Z_OK) {
00483 inflateReset(&(s->stream));
00484 s->crc = crc32(0L, Z_NULL, 0);
00485 }
00486 }
00487 }
00488 if (s->z_err != Z_OK || s->z_eof) break;
00489 }
00490 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
00491
00492 if (len == s->stream.avail_out &&
00493 (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
00494 return -1;
00495 return (int)(len - s->stream.avail_out);
00496 }
00497
00498
00499
00500
00501
00502
00503 int ZEXPORT gzgetc(file)
00504 gzFile file;
00505 {
00506 unsigned char c;
00507
00508 return gzread(file, &c, 1) == 1 ? c : -1;
00509 }
00510
00511
00512
00513
00514
00515 int ZEXPORT gzungetc(c, file)
00516 int c;
00517 gzFile file;
00518 {
00519 gz_stream *s = (gz_stream*)file;
00520
00521 if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
00522 s->back = c;
00523 s->out--;
00524 s->last = (s->z_err == Z_STREAM_END);
00525 if (s->last) s->z_err = Z_OK;
00526 s->z_eof = 0;
00527 return c;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 char * ZEXPORT gzgets(file, buf, len)
00541 gzFile file;
00542 char *buf;
00543 int len;
00544 {
00545 char *b = buf;
00546 if (buf == Z_NULL || len <= 0) return Z_NULL;
00547
00548 while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
00549 *buf = '\0';
00550 return b == buf && len > 0 ? Z_NULL : b;
00551 }
00552
00553
00554 #ifndef NO_GZCOMPRESS
00555
00556
00557
00558
00559 int ZEXPORT gzwrite (file, buf, len)
00560 gzFile file;
00561 voidpc buf;
00562 unsigned len;
00563 {
00564 gz_stream *s = (gz_stream*)file;
00565
00566 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
00567
00568 s->stream.next_in = (Bytef*)buf;
00569 s->stream.avail_in = len;
00570
00571 while (s->stream.avail_in != 0) {
00572
00573 if (s->stream.avail_out == 0) {
00574
00575 s->stream.next_out = s->outbuf;
00576 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
00577 s->z_err = Z_ERRNO;
00578 break;
00579 }
00580 s->stream.avail_out = Z_BUFSIZE;
00581 }
00582 s->in += s->stream.avail_in;
00583 s->out += s->stream.avail_out;
00584 s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
00585 s->in -= s->stream.avail_in;
00586 s->out -= s->stream.avail_out;
00587 if (s->z_err != Z_OK) break;
00588 }
00589 s->crc = crc32(s->crc, (const Bytef *)buf, len);
00590
00591 return (int)(len - s->stream.avail_in);
00592 }
00593
00594
00595
00596
00597
00598
00599
00600 #ifdef STDC
00601 #include <stdarg.h>
00602
00603 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
00604 {
00605 char buf[Z_PRINTF_BUFSIZE];
00606 va_list va;
00607 int len;
00608
00609 buf[sizeof(buf) - 1] = 0;
00610 va_start(va, format);
00611 #ifdef NO_vsnprintf
00612 # ifdef HAS_vsprintf_void
00613 (void)vsprintf(buf, format, va);
00614 va_end(va);
00615 for (len = 0; len < sizeof(buf); len++)
00616 if (buf[len] == 0) break;
00617 # else
00618 len = vsprintf(buf, format, va);
00619 va_end(va);
00620 # endif
00621 #else
00622 # ifdef HAS_vsnprintf_void
00623 (void)vsnprintf(buf, sizeof(buf), format, va);
00624 va_end(va);
00625 len = strlen(buf);
00626 # else
00627 len = vsnprintf(buf, sizeof(buf), format, va);
00628 va_end(va);
00629 # endif
00630 #endif
00631 if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
00632 return 0;
00633 return gzwrite(file, buf, (unsigned)len);
00634 }
00635 #else
00636
00637 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
00638 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
00639 gzFile file;
00640 const char *format;
00641 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
00642 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
00643 {
00644 char buf[Z_PRINTF_BUFSIZE];
00645 int len;
00646
00647 buf[sizeof(buf) - 1] = 0;
00648 #ifdef NO_snprintf
00649 # ifdef HAS_sprintf_void
00650 sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
00651 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00652 for (len = 0; len < sizeof(buf); len++)
00653 if (buf[len] == 0) break;
00654 # else
00655 len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
00656 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00657 # endif
00658 #else
00659 # ifdef HAS_snprintf_void
00660 snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
00661 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00662 len = strlen(buf);
00663 # else
00664 len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
00665 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00666 # endif
00667 #endif
00668 if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
00669 return 0;
00670 return gzwrite(file, buf, len);
00671 }
00672 #endif
00673
00674
00675
00676
00677
00678 int ZEXPORT gzputc(file, c)
00679 gzFile file;
00680 int c;
00681 {
00682 unsigned char cc = (unsigned char) c;
00683
00684 return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693 int ZEXPORT gzputs(file, s)
00694 gzFile file;
00695 const char *s;
00696 {
00697 return gzwrite(file, (char*)s, (unsigned)strlen(s));
00698 }
00699
00700
00701
00702
00703
00704
00705 local int do_flush (file, flush)
00706 gzFile file;
00707 int flush;
00708 {
00709 uInt len;
00710 int done = 0;
00711 gz_stream *s = (gz_stream*)file;
00712
00713 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
00714
00715 s->stream.avail_in = 0;
00716
00717 for (;;) {
00718 len = Z_BUFSIZE - s->stream.avail_out;
00719
00720 if (len != 0) {
00721 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
00722 s->z_err = Z_ERRNO;
00723 return Z_ERRNO;
00724 }
00725 s->stream.next_out = s->outbuf;
00726 s->stream.avail_out = Z_BUFSIZE;
00727 }
00728 if (done) break;
00729 s->out += s->stream.avail_out;
00730 s->z_err = deflate(&(s->stream), flush);
00731 s->out -= s->stream.avail_out;
00732
00733
00734 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
00735
00736
00737
00738
00739 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
00740
00741 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
00742 }
00743 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
00744 }
00745
00746 int ZEXPORT gzflush (file, flush)
00747 gzFile file;
00748 int flush;
00749 {
00750 gz_stream *s = (gz_stream*)file;
00751 int err = do_flush (file, flush);
00752
00753 if (err) return err;
00754 fflush(s->file);
00755 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
00756 }
00757 #endif
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 z_off_t ZEXPORT gzseek (file, offset, whence)
00768 gzFile file;
00769 z_off_t offset;
00770 int whence;
00771 {
00772 gz_stream *s = (gz_stream*)file;
00773
00774 if (s == NULL || whence == SEEK_END ||
00775 s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
00776 return -1L;
00777 }
00778
00779 if (s->mode == 'w') {
00780 #ifdef NO_GZCOMPRESS
00781 return -1L;
00782 #else
00783 if (whence == SEEK_SET) {
00784 offset -= s->in;
00785 }
00786 if (offset < 0) return -1L;
00787
00788
00789 if (s->inbuf == Z_NULL) {
00790 s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
00791 if (s->inbuf == Z_NULL) return -1L;
00792 zmemzero(s->inbuf, Z_BUFSIZE);
00793 }
00794 while (offset > 0) {
00795 uInt size = Z_BUFSIZE;
00796 if (offset < Z_BUFSIZE) size = (uInt)offset;
00797
00798 size = gzwrite(file, s->inbuf, size);
00799 if (size == 0) return -1L;
00800
00801 offset -= size;
00802 }
00803 return s->in;
00804 #endif
00805 }
00806
00807
00808
00809 if (whence == SEEK_CUR) {
00810 offset += s->out;
00811 }
00812 if (offset < 0) return -1L;
00813
00814 if (s->transparent) {
00815
00816 s->back = EOF;
00817 s->stream.avail_in = 0;
00818 s->stream.next_in = s->inbuf;
00819 if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
00820
00821 s->in = s->out = offset;
00822 return offset;
00823 }
00824
00825
00826 if (offset >= s->out) {
00827 offset -= s->out;
00828 } else if (gzrewind(file) < 0) {
00829 return -1L;
00830 }
00831
00832
00833 if (offset != 0 && s->outbuf == Z_NULL) {
00834 s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
00835 if (s->outbuf == Z_NULL) return -1L;
00836 }
00837 if (offset && s->back != EOF) {
00838 s->back = EOF;
00839 s->out++;
00840 offset--;
00841 if (s->last) s->z_err = Z_STREAM_END;
00842 }
00843 while (offset > 0) {
00844 int size = Z_BUFSIZE;
00845 if (offset < Z_BUFSIZE) size = (int)offset;
00846
00847 size = gzread(file, s->outbuf, (uInt)size);
00848 if (size <= 0) return -1L;
00849 offset -= size;
00850 }
00851 return s->out;
00852 }
00853
00854
00855
00856
00857 int ZEXPORT gzrewind (file)
00858 gzFile file;
00859 {
00860 gz_stream *s = (gz_stream*)file;
00861
00862 if (s == NULL || s->mode != 'r') return -1;
00863
00864 s->z_err = Z_OK;
00865 s->z_eof = 0;
00866 s->back = EOF;
00867 s->stream.avail_in = 0;
00868 s->stream.next_in = s->inbuf;
00869 s->crc = crc32(0L, Z_NULL, 0);
00870 if (!s->transparent) (void)inflateReset(&s->stream);
00871 s->in = 0;
00872 s->out = 0;
00873 return fseek(s->file, s->start, SEEK_SET);
00874 }
00875
00876
00877
00878
00879
00880
00881 z_off_t ZEXPORT gztell (file)
00882 gzFile file;
00883 {
00884 return gzseek(file, 0L, SEEK_CUR);
00885 }
00886
00887
00888
00889
00890
00891 int ZEXPORT gzeof (file)
00892 gzFile file;
00893 {
00894 gz_stream *s = (gz_stream*)file;
00895
00896
00897
00898
00899
00900 if (s == NULL || s->mode != 'r') return 0;
00901 if (s->z_eof) return 1;
00902 return s->z_err == Z_STREAM_END;
00903 }
00904
00905
00906
00907
00908 int ZEXPORT gzdirect (file)
00909 gzFile file;
00910 {
00911 gz_stream *s = (gz_stream*)file;
00912
00913 if (s == NULL || s->mode != 'r') return 0;
00914 return s->transparent;
00915 }
00916
00917
00918
00919
00920 local void putLong (file, x)
00921 FILE *file;
00922 uLong x;
00923 {
00924 int n;
00925 for (n = 0; n < 4; n++) {
00926 fputc((int)(x & 0xff), file);
00927 x >>= 8;
00928 }
00929 }
00930
00931
00932
00933
00934
00935 local uLong getLong (s)
00936 gz_stream *s;
00937 {
00938 uLong x = (uLong)get_byte(s);
00939 int c;
00940
00941 x += ((uLong)get_byte(s))<<8;
00942 x += ((uLong)get_byte(s))<<16;
00943 c = get_byte(s);
00944 if (c == EOF) s->z_err = Z_DATA_ERROR;
00945 x += ((uLong)c)<<24;
00946 return x;
00947 }
00948
00949
00950
00951
00952
00953 int ZEXPORT gzclose (file)
00954 gzFile file;
00955 {
00956 gz_stream *s = (gz_stream*)file;
00957
00958 if (s == NULL) return Z_STREAM_ERROR;
00959
00960 if (s->mode == 'w') {
00961 #ifdef NO_GZCOMPRESS
00962 return Z_STREAM_ERROR;
00963 #else
00964 if (do_flush (file, Z_FINISH) != Z_OK)
00965 return destroy((gz_stream*)file);
00966
00967 putLong (s->file, s->crc);
00968 putLong (s->file, (uLong)(s->in & 0xffffffff));
00969 #endif
00970 }
00971 return destroy((gz_stream*)file);
00972 }
00973
00974 #ifdef STDC
00975 # define zstrerror(errnum) strerror(errnum)
00976 #else
00977 # define zstrerror(errnum) ""
00978 #endif
00979
00980
00981
00982
00983
00984
00985
00986
00987 const char * ZEXPORT gzerror (file, errnum)
00988 gzFile file;
00989 int *errnum;
00990 {
00991 char *m;
00992 gz_stream *s = (gz_stream*)file;
00993
00994 if (s == NULL) {
00995 *errnum = Z_STREAM_ERROR;
00996 return (const char*)ERR_MSG(Z_STREAM_ERROR);
00997 }
00998 *errnum = s->z_err;
00999 if (*errnum == Z_OK) return (const char*)"";
01000
01001 m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
01002
01003 if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
01004
01005 TRYFREE(s->msg);
01006 s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
01007 if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
01008 strcpy(s->msg, s->path);
01009 strcat(s->msg, ": ");
01010 strcat(s->msg, m);
01011 return (const char*)s->msg;
01012 }
01013
01014
01015
01016
01017 void ZEXPORT gzclearerr (file)
01018 gzFile file;
01019 {
01020 gz_stream *s = (gz_stream*)file;
01021
01022 if (s == NULL) return;
01023 if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
01024 s->z_eof = 0;
01025 clearerr(s->file);
01026 }