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 }