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