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