     1			/* gzio.c -- IO on .gz files
     2			 * Copyright (C) 1995-2003 Jean-loup Gailly.
     3			 * For conditions of distribution and use, see copyright notice in zlib.h
     4			 *
     5			 * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
     6			 */
     7			
     8			/* @(#) $Id$ */
     9			
    10			#include <stdio.h>
    11			
    12			#include "zutil.h"
    13			
    14			#ifdef NO_DEFLATE       /* for compatiblity with old definition */
    15			#  define NO_GZCOMPRESS
    16			#endif
    17			
    18			#ifndef NO_DUMMY_DECL
    19			struct internal_state {int dummy;}; /* for buggy compilers */
    20			#endif
    21			
    22			#ifndef Z_BUFSIZE
    23			#  ifdef MAXSEG_64K
    24			#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
    25			#  else
    26			#    define Z_BUFSIZE 16384
    27			#  endif
    28			#endif
    29			#ifndef Z_PRINTF_BUFSIZE
    30			#  define Z_PRINTF_BUFSIZE 4096
    31			#endif
    32			
    33			#ifdef __MVS__
    34			#  pragma map (fdopen , "\174\174FDOPEN")
    35			   FILE *fdopen(int, const char *);
    36			#endif
    37			
    38			#ifndef STDC
    39			extern voidp  malloc OF((uInt size));
    40			extern void   free   OF((voidpf ptr));
    41			#endif
    42			
    43			#define ALLOC(size) malloc(size)
    44			#define TRYFREE(p) {if (p) free(p);}
    45			
    46			static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
    47			
    48			/* gzip flag byte */
    49			#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
    50			#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
    51			#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
    52			#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
    53			#define COMMENT      0x10 /* bit 4 set: file comment present */
    54			#define RESERVED     0xE0 /* bits 5..7: reserved */
    55			
    56			typedef struct gz_stream {
    57			    z_stream stream;
    58			    int      z_err;   /* error code for last stream operation */
    59			    int      z_eof;   /* set if end of input file */
    60			    FILE     *file;   /* .gz file */
    61			    Byte     *inbuf;  /* input buffer */
    62			    Byte     *outbuf; /* output buffer */
    63			    uLong    crc;     /* crc32 of uncompressed data */
    64			    char     *msg;    /* error message */
    65			    char     *path;   /* path name for debugging only */
    66			    int      transparent; /* 1 if input file is not a .gz file */
    67			    char     mode;    /* 'w' or 'r' */
    68			    z_off_t  start;   /* start of compressed data in file (header skipped) */
    69			    z_off_t  in;      /* bytes into deflate or inflate */
    70			    z_off_t  out;     /* bytes out of deflate or inflate */
    71			    int      back;    /* one character push-back */
    72			    int      last;    /* true if push-back is last character */
    73			} gz_stream;
    74			
    75			
    76			local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
    77			local int do_flush        OF((gzFile file, int flush));
    78			local int    get_byte     OF((gz_stream *s));
    79			local void   check_header OF((gz_stream *s));
    80			local int    destroy      OF((gz_stream *s));
    81			local void   putLong      OF((FILE *file, uLong x));
    82			local uLong  getLong      OF((gz_stream *s));
    83			
    84			/* ===========================================================================
    85			     Opens a gzip (.gz) file for reading or writing. The mode parameter
    86			   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
    87			   or path name (if fd == -1).
    88			     gz_open returns NULL if the file could not be opened or if there was
    89			   insufficient memory to allocate the (de)compression state; errno
    90			   can be checked to distinguish the two cases (if errno is zero, the
    91			   zlib error is Z_MEM_ERROR).
    92			*/
    93			local gzFile gz_open (path, mode, fd)
    94			    const char *path;
    95			    const char *mode;
    96			    int  fd;
    97	          81    {
    98	          81        int err;
    99	          81        int level = Z_DEFAULT_COMPRESSION; /* compression level */
   100	          81        int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
   101	          81        char *p = (char*)mode;
   102	          81        gz_stream *s;
   103	          81        char fmode[80]; /* copy of mode, without the compression level */
   104	          81        char *m = fmode;
   105			
   106	          81        if (!path || !mode) return Z_NULL;
   107			
   108	          81        s = (gz_stream *)ALLOC(sizeof(gz_stream));
   109	          81        if (!s) return Z_NULL;
   110			
   111	          81        s->stream.zalloc = (alloc_func)0;
   112	          81        s->stream.zfree = (free_func)0;
   113	          81        s->stream.opaque = (voidpf)0;
   114	          81        s->stream.next_in = s->inbuf = Z_NULL;
   115	          81        s->stream.next_out = s->outbuf = Z_NULL;
   116	          81        s->stream.avail_in = s->stream.avail_out = 0;
   117	          81        s->file = NULL;
   118	          81        s->z_err = Z_OK;
   119	          81        s->z_eof = 0;
   120	          81        s->in = 0;
   121	          81        s->out = 0;
   122	          81        s->back = EOF;
   123	          81        s->crc = crc32(0L, Z_NULL, 0);
   124	          81        s->msg = NULL;
   125	          81        s->transparent = 0;
   126			
   127	          81        s->path = (char*)ALLOC(strlen(path)+1);
   128	          81        if (s->path == NULL) {
   129	      ######            return destroy(s), (gzFile)Z_NULL;
   130			    }
   131	          81        strcpy(s->path, path); /* do this early for debugging */
   132			
   133	          81        s->mode = '\0';
   134	         249        do {
   135	         249            if (*p == 'r') s->mode = 'r';
   136	         249            if (*p == 'w' || *p == 'a') s->mode = 'w';
   137	         249            if (*p >= '0' && *p <= '9') {
   138	           6                level = *p - '0';
   139	         243            } else if (*p == 'f') {
   140	      ######              strategy = Z_FILTERED;
   141	         243            } else if (*p == 'h') {
   142	      ######              strategy = Z_HUFFMAN_ONLY;
   143	         243            } else if (*p == 'R') {
   144	      ######              strategy = Z_RLE;
   145			        } else {
   146	         243                *m++ = *p; /* copy the mode */
   147			        }
   148	         249        } while (*p++ && m != fmode + sizeof(fmode));
   149	          81        if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
   150			
   151	          81        if (s->mode == 'w') {
   152			#ifdef NO_GZCOMPRESS
   153			        err = Z_STREAM_ERROR;
   154			#else
   155	          24            err = deflateInit2(&(s->stream), level,
   156			                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
   157			        /* windowBits is passed < 0 to suppress zlib header */
   158			
   159	          24            s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
   160			#endif
   161	          24            if (err != Z_OK || s->outbuf == Z_NULL) {
   162	      ######                return destroy(s), (gzFile)Z_NULL;
   163			        }
   164			    } else {
   165	          57            s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
   166			
   167	          57            err = inflateInit2(&(s->stream), -MAX_WBITS);
   168			        /* windowBits is passed < 0 to tell that there is no zlib header.
   169			         * Note that in this case inflate *requires* an extra "dummy" byte
   170			         * after the compressed stream in order to complete decompression and
   171			         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
   172			         * present after the compressed stream.
   173			         */
   174	          57            if (err != Z_OK || s->inbuf == Z_NULL) {
   175	      ######                return destroy(s), (gzFile)Z_NULL;
   176			        }
   177			    }
   178	          81        s->stream.avail_out = Z_BUFSIZE;
   179			
   180	          81        errno = 0;
   181	          81        s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
   182			
   183	          81        if (s->file == NULL) {
   184	           3            return destroy(s), (gzFile)Z_NULL;
   185			    }
   186	          78        if (s->mode == 'w') {
   187			        /* Write a very simple .gz header:
   188			         */
   189	          24            fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
   190			             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
   191	          24            s->start = 10L;
   192			        /* We use 10L instead of ftell(s->file) to because ftell causes an
   193			         * fflush on some systems. This version of the library doesn't use
   194			         * start anyway in write mode, so this initialization is not
   195			         * necessary.
   196			         */
   197			    } else {
   198	          54            check_header(s); /* skip the .gz header */
   199	          54            s->start = ftell(s->file) - s->stream.avail_in;
   200			    }
   201			
   202	          78        return (gzFile)s;
   203			}
   204			
   205			/* ===========================================================================
   206			     Opens a gzip (.gz) file for reading or writing.
   207			*/
   208			gzFile ZEXPORT gzopen (path, mode)
   209			    const char *path;
   210			    const char *mode;
   211	          76    {
   212	          76        return gz_open (path, mode, -1);
   213			}
   214			
   215			/* ===========================================================================
   216			     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
   217			   to mimic the behavio(u)r of fdopen.
   218			*/
   219			gzFile ZEXPORT gzdopen (fd, mode)
   220			    int fd;
   221			    const char *mode;
   222	           5    {
   223	           5        char name[20];
   224			
   225	           5        if (fd < 0) return (gzFile)Z_NULL;
   226	           5        sprintf(name, "<fd:%d>", fd); /* for debugging */
   227			
   228	           5        return gz_open (name, mode, fd);
   229			}
   230			
   231			/* ===========================================================================
   232			 * Update the compression level and strategy
   233			 */
   234			int ZEXPORT gzsetparams (file, level, strategy)
   235			    gzFile file;
   236			    int level;
   237			    int strategy;
   238	           1    {
   239	           1        gz_stream *s = (gz_stream*)file;
   240			
   241	           1        if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
   242			
   243			    /* Make room to allow flushing */
   244	           1        if (s->stream.avail_out == 0) {
   245			
   246	      ######            s->stream.next_out = s->outbuf;
   247	      ######            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
   248	      ######                s->z_err = Z_ERRNO;
   249			        }
   250	      ######            s->stream.avail_out = Z_BUFSIZE;
   251			    }
   252			
   253	           1        return deflateParams (&(s->stream), level, strategy);
   254			}
   255			
   256			/* ===========================================================================
   257			     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
   258			   for end of file.
   259			   IN assertion: the stream s has been sucessfully opened for reading.
   260			*/
   261			local int get_byte(s)
   262			    gz_stream *s;
   263	         620    {
   264	         620        if (s->z_eof) return EOF;
   265	         620        if (s->stream.avail_in == 0) {
   266	      ######            errno = 0;
   267	      ######            s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
   268	      ######            if (s->stream.avail_in == 0) {
   269	      ######                s->z_eof = 1;
   270	      ######                if (ferror(s->file)) s->z_err = Z_ERRNO;
   271	      ######                return EOF;
   272			        }
   273	      ######            s->stream.next_in = s->inbuf;
   274			    }
   275	         620        s->stream.avail_in--;
   276	         620        return *(s->stream.next_in)++;
   277			}
   278			
   279			/* ===========================================================================
   280			      Check the gzip header of a gz_stream opened for reading. Set the stream
   281			    mode to transparent if the gzip magic header is not present; set s->err
   282			    to Z_DATA_ERROR if the magic header is present but the rest of the header
   283			    is incorrect.
   284			    IN assertion: the stream s has already been created sucessfully;
   285			       s->stream.avail_in is zero for the first time, but may be non-zero
   286			       for concatenated .gz files.
   287			*/
   288			local void check_header(s)
   289			    gz_stream *s;
   290	          91    {
   291	          91        int method; /* method byte */
   292	          91        int flags;  /* flags byte */
   293	          91        uInt len;
   294	          91        int c;
   295			
   296			    /* Assure two bytes in the buffer so we can peek ahead -- handle case
   297			       where first byte of header is at the end of the buffer after the last
   298			       gzip segment */
   299	          91        len = s->stream.avail_in;
   300	          91        if (len < 2) {
   301	          91            if (len) s->inbuf[0] = s->stream.next_in[0];
   302	          91            errno = 0;
   303	          91            len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
   304	          91            if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
   305	          91            s->stream.avail_in += len;
   306	          91            s->stream.next_in = s->inbuf;
   307	          91            if (s->stream.avail_in < 2) {
   308	          37                s->transparent = s->stream.avail_in;
   309	          37                return;
   310			        }
   311			    }
   312			
   313			    /* Peek ahead to check the gzip magic header */
   314	          54        if (s->stream.next_in[0] != gz_magic[0] ||
   315			        s->stream.next_in[1] != gz_magic[1]) {
   316	          17            s->transparent = 1;
   317	          17            return;
   318			    }
   319	          37        s->stream.avail_in -= 2;
   320	          37        s->stream.next_in += 2;
   321			
   322			    /* Check the rest of the gzip header */
   323	          37        method = get_byte(s);
   324	          37        flags = get_byte(s);
   325	          37        if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
   326	      ######            s->z_err = Z_DATA_ERROR;
   327	      ######            return;
   328			    }
   329			
   330			    /* Discard time, xflags and OS code: */
   331	          37        for (len = 0; len < 6; len++) (void)get_byte(s);
   332			
   333	          37        if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
   334	      ######            len  =  (uInt)get_byte(s);
   335	      ######            len += ((uInt)get_byte(s))<<8;
   336			        /* len is garbage if EOF but the loop below will quit anyway */
   337	      ######            while (len-- != 0 && get_byte(s) != EOF) ;
   338			    }
   339	          37        if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
   340	          28            while ((c = get_byte(s)) != 0 && c != EOF) ;
   341			    }
   342	          37        if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
   343	      ######            while ((c = get_byte(s)) != 0 && c != EOF) ;
   344			    }
   345	          37        if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
   346	      ######            for (len = 0; len < 2; len++) (void)get_byte(s);
   347			    }
   348	          37        s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
   349			}
   350			
   351			 /* ===========================================================================
   352			 * Cleanup then free the given gz_stream. Return a zlib error code.
   353			   Try freeing in the reverse order of allocations.
   354			 */
   355			local int destroy (s)
   356			    gz_stream *s;
   357	          81    {
   358	          81        int err = Z_OK;
   359			
   360	          81        if (!s) return Z_STREAM_ERROR;
   361			
   362	          81        TRYFREE(s->msg);
   363			
   364	          81        if (s->stream.state != NULL) {
   365	          81            if (s->mode == 'w') {
   366			#ifdef NO_GZCOMPRESS
   367			            err = Z_STREAM_ERROR;
   368			#else
   369	          24                err = deflateEnd(&(s->stream));
   370			#endif
   371	          57            } else if (s->mode == 'r') {
   372	          57                err = inflateEnd(&(s->stream));
   373			        }
   374			    }
   375	          81        if (s->file != NULL && fclose(s->file)) {
   376			#ifdef ESPIPE
   377	      ######            if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
   378			#endif
   379	      ######                err = Z_ERRNO;
   380			    }
   381	          81        if (s->z_err < 0) err = s->z_err;
   382			
   383	          81        TRYFREE(s->inbuf);
   384	          81        TRYFREE(s->outbuf);
   385	          81        TRYFREE(s->path);
   386	          81        TRYFREE(s);
   387	          81        return err;
   388			}
   389			
   390			/* ===========================================================================
   391			     Reads the given number of uncompressed bytes from the compressed file.
   392			   gzread returns the number of bytes actually read (0 for end of file).
   393			*/
   394			int ZEXPORT gzread (file, buf, len)
   395			    gzFile file;
   396			    voidp buf;
   397			    unsigned len;
   398	         350    {
   399	         350        gz_stream *s = (gz_stream*)file;
   400	         350        Bytef *start = (Bytef*)buf; /* starting point for crc computation */
   401	         350        Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
   402			
   403	         350        if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
   404			
   405	         350        if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
   406	         350        if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
   407			
   408	         330        next_out = (Byte*)buf;
   409	         330        s->stream.next_out = (Bytef*)buf;
   410	         330        s->stream.avail_out = len;
   411			
   412	         330        if (s->stream.avail_out && s->back != EOF) {
   413	      ######            *next_out++ = s->back;
   414	      ######            s->stream.next_out++;
   415	      ######            s->stream.avail_out--;
   416	      ######            s->back = EOF;
   417	      ######            s->out++;
   418	      ######            if (s->last) {
   419	      ######                s->z_err = Z_STREAM_END;
   420	      ######                return 1;
   421			        }
   422			    }
   423			
   424	         418        while (s->stream.avail_out != 0) {
   425			
   426	         330            if (s->transparent) {
   427			            /* Copy first the lookahead bytes: */
   428	         205                uInt n = s->stream.avail_in;
   429	         205                if (n > s->stream.avail_out) n = s->stream.avail_out;
   430	         205                if (n > 0) {
   431	         183                    zmemcpy(s->stream.next_out, s->stream.next_in, n);
   432	         183                    next_out += n;
   433	         183                    s->stream.next_out = next_out;
   434	         183                    s->stream.next_in   += n;
   435	         183                    s->stream.avail_out -= n;
   436	         183                    s->stream.avail_in  -= n;
   437			            }
   438	         205                if (s->stream.avail_out > 0) {
   439	          28                    s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
   440			                                             s->file);
   441			            }
   442	         205                len -= s->stream.avail_out;
   443	         205                s->in  += len;
   444	         205                s->out += len;
   445	         205                if (len == 0) s->z_eof = 1;
   446	         205                return (int)len;
   447			        }
   448	         125            if (s->stream.avail_in == 0 && !s->z_eof) {
   449			
   450	      ######                errno = 0;
   451	      ######                s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
   452	      ######                if (s->stream.avail_in == 0) {
   453	      ######                    s->z_eof = 1;
   454	      ######                    if (ferror(s->file)) {
   455	      ######                        s->z_err = Z_ERRNO;
   456	      ######                        break;
   457			                }
   458	      ######                    if (feof(s->file)) {        /* avoid error for empty file */
   459	      ######                        s->z_err = Z_STREAM_END;
   460	      ######                        break;
   461			                }
   462			            }
   463	      ######                s->stream.next_in = s->inbuf;
   464			        }
   465	         125            s->in += s->stream.avail_in;
   466	         125            s->out += s->stream.avail_out;
   467	         125            s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
   468	         125            s->in -= s->stream.avail_in;
   469	         125            s->out -= s->stream.avail_out;
   470			
   471	         125            if (s->z_err == Z_STREAM_END) {
   472			            /* Check CRC and original size */
   473	          37                s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
   474	          37                start = s->stream.next_out;
   475			
   476	          37                if (getLong(s) != s->crc) {
   477	      ######                    s->z_err = Z_DATA_ERROR;
   478			            } else {
   479	          37                    (void)getLong(s);
   480			                /* The uncompressed length returned by above getlong() may be
   481			                 * different from s->out in case of concatenated .gz files.
   482			                 * Check for such files:
   483			                 */
   484	          37                    check_header(s);
   485	          37                    if (s->z_err == Z_OK) {
   486	      ######                        inflateReset(&(s->stream));
   487	      ######                        s->crc = crc32(0L, Z_NULL, 0);
   488			                }
   489			            }
   490			        }
   491	         125            if (s->z_err != Z_OK || s->z_eof) break;
   492			    }
   493	         125        s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
   494			
   495	         125        return (int)(len - s->stream.avail_out);
   496			}
   497			
   498			
   499			/* ===========================================================================
   500			      Reads one byte from the compressed file. gzgetc returns this byte
   501			   or -1 in case of end of file or error.
   502			*/
   503			int ZEXPORT gzgetc(file)
   504			    gzFile file;
   505	      ######    {
   506	      ######        unsigned char c;
   507			
   508	      ######        return gzread(file, &c, 1) == 1 ? c : -1;
   509			}
   510			
   511			
   512			/* ===========================================================================
   513			      Push one byte back onto the stream.
   514			*/
   515			int ZEXPORT gzungetc(c, file)
   516			    int c;
   517			    gzFile file;
   518	      ######    {
   519	      ######        gz_stream *s = (gz_stream*)file;
   520			
   521	      ######        if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
   522	      ######        s->back = c;
   523	      ######        s->out--;
   524	      ######        s->last = (s->z_err == Z_STREAM_END);
   525	      ######        if (s->last) s->z_err = Z_OK;
   526	      ######        s->z_eof = 0;
   527	      ######        return c;
   528			}
   529			
   530			
   531			/* ===========================================================================
   532			      Reads bytes from the compressed file until len-1 characters are
   533			   read, or a newline character is read and transferred to buf, or an
   534			   end-of-file condition is encountered.  The string is then terminated
   535			   with a null character.
   536			      gzgets returns buf, or Z_NULL in case of error.
   537			
   538			      The current implementation is not optimized at all.
   539			*/
   540			char * ZEXPORT gzgets(file, buf, len)
   541			    gzFile file;
   542			    char *buf;
   543			    int len;
   544	      ######    {
   545	      ######        char *b = buf;
   546	      ######        if (buf == Z_NULL || len <= 0) return Z_NULL;
   547			
   548	      ######        while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
   549	      ######        *buf = '\0';
   550	      ######        return b == buf && len > 0 ? Z_NULL : b;
   551			}
   552			
   553			
   554			#ifndef NO_GZCOMPRESS
   555			/* ===========================================================================
   556			     Writes the given number of uncompressed bytes into the compressed file.
   557			   gzwrite returns the number of bytes actually written (0 in case of error).
   558			*/
   559			int ZEXPORT gzwrite (file, buf, len)
   560			    gzFile file;
   561			    voidpc buf;
   562			    unsigned len;
   563	          77    {
   564	          77        gz_stream *s = (gz_stream*)file;
   565			
   566	          77        if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
   567			
   568	          77        s->stream.next_in = (Bytef*)buf;
   569	          77        s->stream.avail_in = len;
   570			
   571	         154        while (s->stream.avail_in != 0) {
   572			
   573	          77            if (s->stream.avail_out == 0) {
   574			
   575	      ######                s->stream.next_out = s->outbuf;
   576	      ######                if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
   577	      ######                    s->z_err = Z_ERRNO;
   578	      ######                    break;
   579			            }
   580	      ######                s->stream.avail_out = Z_BUFSIZE;
   581			        }
   582	          77            s->in += s->stream.avail_in;
   583	          77            s->out += s->stream.avail_out;
   584	          77            s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
   585	          77            s->in -= s->stream.avail_in;
   586	          77            s->out -= s->stream.avail_out;
   587	          77            if (s->z_err != Z_OK) break;
   588			    }
   589	          77        s->crc = crc32(s->crc, (const Bytef *)buf, len);
   590			
   591	          77        return (int)(len - s->stream.avail_in);
   592			}
   593			
   594			
   595			/* ===========================================================================
   596			     Converts, formats, and writes the args to the compressed file under
   597			   control of the format string, as in fprintf. gzprintf returns the number of
   598			   uncompressed bytes actually written (0 in case of error).
   599			*/
   600			#ifdef STDC
   601			#include <stdarg.h>
   602			
   603			int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
   604	      ######    {
   605	      ######        char buf[Z_PRINTF_BUFSIZE];
   606	      ######        va_list va;
   607	      ######        int len;
   608			
   609	      ######        buf[sizeof(buf) - 1] = 0;
   610	      ######        va_start(va, format);
   611			#ifdef NO_vsnprintf
   612			#  ifdef HAS_vsprintf_void
   613			    (void)vsprintf(buf, format, va);
   614			    va_end(va);
   615			    for (len = 0; len < sizeof(buf); len++)
   616			        if (buf[len] == 0) break;
   617			#  else
   618			    len = vsprintf(buf, format, va);
   619			    va_end(va);
   620			#  endif
   621			#else
   622			#  ifdef HAS_vsnprintf_void
   623			    (void)vsnprintf(buf, sizeof(buf), format, va);
   624			    va_end(va);
   625			    len = strlen(buf);
   626			#  else
   627	      ######        len = vsnprintf(buf, sizeof(buf), format, va);
   628	      ######        va_end(va);
   629			#  endif
   630			#endif
   631	      ######        if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
   632	      ######            return 0;
   633	      ######        return gzwrite(file, buf, (unsigned)len);
   634			}
   635			#else /* not ANSI C */
   636			
   637			int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
   638			                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
   639			    gzFile file;
   640			    const char *format;
   641			    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
   642			        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
   643			{
   644			    char buf[Z_PRINTF_BUFSIZE];
   645			    int len;
   646			
   647			    buf[sizeof(buf) - 1] = 0;
   648			#ifdef NO_snprintf
   649			#  ifdef HAS_sprintf_void
   650			    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
   651			            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
   652			    for (len = 0; len < sizeof(buf); len++)
   653			        if (buf[len] == 0) break;
   654			#  else
   655			    len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
   656			                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
   657			#  endif
   658			#else
   659			#  ifdef HAS_snprintf_void
   660			    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
   661			             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
   662			    len = strlen(buf);
   663			#  else
   664			    len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
   665			                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
   666			#  endif
   667			#endif
   668			    if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
   669			        return 0;
   670			    return gzwrite(file, buf, len);
   671			}
   672			#endif
   673			
   674			/* ===========================================================================
   675			      Writes c, converted to an unsigned char, into the compressed file.
   676			   gzputc returns the value that was written, or -1 in case of error.
   677			*/
   678			int ZEXPORT gzputc(file, c)
   679			    gzFile file;
   680			    int c;
   681	      ######    {
   682	      ######        unsigned char cc = (unsigned char) c; /* required for big endian systems */
   683			
   684	      ######        return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
   685			}
   686			
   687			
   688			/* ===========================================================================
   689			      Writes the given null-terminated string to the compressed file, excluding
   690			   the terminating null character.
   691			      gzputs returns the number of characters written, or -1 in case of error.
   692			*/
   693			int ZEXPORT gzputs(file, s)
   694			    gzFile file;
   695			    const char *s;
   696	      ######    {
   697	      ######        return gzwrite(file, (char*)s, (unsigned)strlen(s));
   698			}
   699			
   700			
   701			/* ===========================================================================
   702			     Flushes all pending output into the compressed file. The parameter
   703			   flush is as in the deflate() function.
   704			*/
   705			local int do_flush (file, flush)
   706			    gzFile file;
   707			    int flush;
   708	          24    {
   709	          24        uInt len;
   710	          24        int done = 0;
   711	          24        gz_stream *s = (gz_stream*)file;
   712			
   713	          24        if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
   714			
   715	          24        s->stream.avail_in = 0; /* should be zero already anyway */
   716			
   717	          72        for (;;) {
   718	          48            len = Z_BUFSIZE - s->stream.avail_out;
   719			
   720	          48            if (len != 0) {
   721	          25                if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
   722	      ######                    s->z_err = Z_ERRNO;
   723	      ######                    return Z_ERRNO;
   724			            }
   725	          25                s->stream.next_out = s->outbuf;
   726	          25                s->stream.avail_out = Z_BUFSIZE;
   727			        }
   728	          48            if (done) break;
   729	          24            s->out += s->stream.avail_out;
   730	          24            s->z_err = deflate(&(s->stream), flush);
   731	          24            s->out -= s->stream.avail_out;
   732			
   733			        /* Ignore the second of two consecutive flushes: */
   734	          24            if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
   735			
   736			        /* deflate has finished flushing only when it hasn't used up
   737			         * all the available space in the output buffer:
   738			         */
   739	          24            done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
   740			
   741	          24            if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
   742			    }
   743	          24        return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
   744			}
   745			
   746			int ZEXPORT gzflush (file, flush)
   747			     gzFile file;
   748			     int flush;
   749	      ######    {
   750	      ######        gz_stream *s = (gz_stream*)file;
   751	      ######        int err = do_flush (file, flush);
   752			
   753	      ######        if (err) return err;
   754	      ######        fflush(s->file);
   755	      ######        return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
   756			}
   757			#endif /* NO_GZCOMPRESS */
   758			
   759			/* ===========================================================================
   760			      Sets the starting position for the next gzread or gzwrite on the given
   761			   compressed file. The offset represents a number of bytes in the
   762			      gzseek returns the resulting offset location as measured in bytes from
   763			   the beginning of the uncompressed stream, or -1 in case of error.
   764			      SEEK_END is not implemented, returns error.
   765			      In this version of the library, gzseek can be extremely slow.
   766			*/
   767			z_off_t ZEXPORT gzseek (file, offset, whence)
   768			    gzFile file;
   769			    z_off_t offset;
   770			    int whence;
   771	      ######    {
   772	      ######        gz_stream *s = (gz_stream*)file;
   773			
   774	      ######        if (s == NULL || whence == SEEK_END ||
   775			        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
   776	      ######            return -1L;
   777			    }
   778			
   779	      ######        if (s->mode == 'w') {
   780			#ifdef NO_GZCOMPRESS
   781			        return -1L;
   782			#else
   783	      ######            if (whence == SEEK_SET) {
   784	      ######                offset -= s->in;
   785			        }
   786	      ######            if (offset < 0) return -1L;
   787			
   788			        /* At this point, offset is the number of zero bytes to write. */
   789	      ######            if (s->inbuf == Z_NULL) {
   790	      ######                s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
   791	      ######                if (s->inbuf == Z_NULL) return -1L;
   792	      ######                zmemzero(s->inbuf, Z_BUFSIZE);
   793			        }
   794	      ######            while (offset > 0)  {
   795	      ######                uInt size = Z_BUFSIZE;
   796	      ######                if (offset < Z_BUFSIZE) size = (uInt)offset;
   797			
   798	      ######                size = gzwrite(file, s->inbuf, size);
   799	      ######                if (size == 0) return -1L;
   800			
   801	      ######                offset -= size;
   802			        }
   803	      ######            return s->in;
   804			#endif
   805			    }
   806			    /* Rest of function is for reading only */
   807			
   808			    /* compute absolute position */
   809	      ######        if (whence == SEEK_CUR) {
   810	      ######            offset += s->out;
   811			    }
   812	      ######        if (offset < 0) return -1L;
   813			
   814	      ######        if (s->transparent) {
   815			        /* map to fseek */
   816	      ######            s->back = EOF;
   817	      ######            s->stream.avail_in = 0;
   818	      ######            s->stream.next_in = s->inbuf;
   819	      ######            if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
   820			
   821	      ######            s->in = s->out = offset;
   822	      ######            return offset;
   823			    }
   824			
   825			    /* For a negative seek, rewind and use positive seek */
   826	      ######        if (offset >= s->out) {
   827	      ######            offset -= s->out;
   828	      ######        } else if (gzrewind(file) < 0) {
   829	      ######            return -1L;
   830			    }
   831			    /* offset is now the number of bytes to skip. */
   832			
   833	      ######        if (offset != 0 && s->outbuf == Z_NULL) {
   834	      ######            s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
   835	      ######            if (s->outbuf == Z_NULL) return -1L;
   836			    }
   837	      ######        if (offset && s->back != EOF) {
   838	      ######            s->back = EOF;
   839	      ######            s->out++;
   840	      ######            offset--;
   841	      ######            if (s->last) s->z_err = Z_STREAM_END;
   842			    }
   843	      ######        while (offset > 0)  {
   844	      ######            int size = Z_BUFSIZE;
   845	      ######            if (offset < Z_BUFSIZE) size = (int)offset;
   846			
   847	      ######            size = gzread(file, s->outbuf, (uInt)size);
   848	      ######            if (size <= 0) return -1L;
   849	      ######            offset -= size;
   850			    }
   851	      ######        return s->out;
   852			}
   853			
   854			/* ===========================================================================
   855			     Rewinds input file.
   856			*/
   857			int ZEXPORT gzrewind (file)
   858			    gzFile file;
   859	      ######    {
   860	      ######        gz_stream *s = (gz_stream*)file;
   861			
   862	      ######        if (s == NULL || s->mode != 'r') return -1;
   863			
   864	      ######        s->z_err = Z_OK;
   865	      ######        s->z_eof = 0;
   866	      ######        s->back = EOF;
   867	      ######        s->stream.avail_in = 0;
   868	      ######        s->stream.next_in = s->inbuf;
   869	      ######        s->crc = crc32(0L, Z_NULL, 0);
   870	      ######        if (!s->transparent) (void)inflateReset(&s->stream);
   871	      ######        s->in = 0;
   872	      ######        s->out = 0;
   873	      ######        return fseek(s->file, s->start, SEEK_SET);
   874			}
   875			
   876			/* ===========================================================================
   877			     Returns the starting position for the next gzread or gzwrite on the
   878			   given compressed file. This position represents a number of bytes in the
   879			   uncompressed data stream.
   880			*/
   881			z_off_t ZEXPORT gztell (file)
   882			    gzFile file;
   883	      ######    {
   884	      ######        return gzseek(file, 0L, SEEK_CUR);
   885			}
   886			
   887			/* ===========================================================================
   888			     Returns 1 when EOF has previously been detected reading the given
   889			   input stream, otherwise zero.
   890			*/
   891			int ZEXPORT gzeof (file)
   892			    gzFile file;
   893	      ######    {
   894	      ######        gz_stream *s = (gz_stream*)file;
   895			
   896			    /* With concatenated compressed files that can have embedded
   897			     * crc trailers, z_eof is no longer the only/best indicator of EOF
   898			     * on a gz_stream. Handle end-of-stream error explicitly here.
   899			     */
   900	      ######        if (s == NULL || s->mode != 'r') return 0;
   901	      ######        if (s->z_eof) return 1;
   902	      ######        return s->z_err == Z_STREAM_END;
   903			}
   904			
   905			/* ===========================================================================
   906			   Outputs a long in LSB order to the given file
   907			*/
   908			local void putLong (file, x)
   909			    FILE *file;
   910			    uLong x;
   911	          48    {
   912	          48        int n;
   913	         240        for (n = 0; n < 4; n++) {
   914	         192            fputc((int)(x & 0xff), file);
   915	         192            x >>= 8;
   916			    }
   917			}
   918			
   919			/* ===========================================================================
   920			   Reads a long in LSB order from the given gz_stream. Sets z_err in case
   921			   of error.
   922			*/
   923			local uLong getLong (s)
   924			    gz_stream *s;
   925	          74    {
   926	          74        uLong x = (uLong)get_byte(s);
   927	          74        int c;
   928			
   929	          74        x += ((uLong)get_byte(s))<<8;
   930	          74        x += ((uLong)get_byte(s))<<16;
   931	          74        c = get_byte(s);
   932	          74        if (c == EOF) s->z_err = Z_DATA_ERROR;
   933	          74        x += ((uLong)c)<<24;
   934	          74        return x;
   935			}
   936			
   937			/* ===========================================================================
   938			     Flushes all pending output if necessary, closes the compressed file
   939			   and deallocates all the (de)compression state.
   940			*/
   941			int ZEXPORT gzclose (file)
   942			    gzFile file;
   943	          78    {
   944	          78        int err;
   945	          78        gz_stream *s = (gz_stream*)file;
   946			
   947	          78        if (s == NULL) return Z_STREAM_ERROR;
   948			
   949	          78        if (s->mode == 'w') {
   950			#ifdef NO_GZCOMPRESS
   951			        return Z_STREAM_ERROR;
   952			#else
   953	          24            err = do_flush (file, Z_FINISH);
   954	          24            if (err != Z_OK) return destroy((gz_stream*)file);
   955			
   956	          24            putLong (s->file, s->crc);
   957	          24            putLong (s->file, (uLong)(s->in & 0xffffffff));
   958			#endif
   959			    }
   960	          78        return destroy((gz_stream*)file);
   961			}
   962			
   963			/* ===========================================================================
   964			     Returns the error message for the last error which occured on the
   965			   given compressed file. errnum is set to zlib error number. If an
   966			   error occured in the file system and not in the compression library,
   967			   errnum is set to Z_ERRNO and the application may consult errno
   968			   to get the exact error code.
   969			*/
   970			const char * ZEXPORT gzerror (file, errnum)
   971			    gzFile file;
   972			    int *errnum;
   973	         442    {
   974	         442        char *m;
   975	         442        gz_stream *s = (gz_stream*)file;
   976			
   977	         442        if (s == NULL) {
   978	      ######            *errnum = Z_STREAM_ERROR;
   979	      ######            return (const char*)ERR_MSG(Z_STREAM_ERROR);
   980			    }
   981	         442        *errnum = s->z_err;
   982	         442        if (*errnum == Z_OK) return (const char*)"";
   983			
   984	          80        m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
   985			
   986	          80        if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
   987			
   988	          80        TRYFREE(s->msg);
   989	          80        s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
   990	          80        if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
   991	          80        strcpy(s->msg, s->path);
   992	          80        strcat(s->msg, ": ");
   993	          80        strcat(s->msg, m);
   994	          80        return (const char*)s->msg;
   995			}
   996			
   997			/* ===========================================================================
   998			     Clear the error and end-of-file flags, and do the same for the real file.
   999			*/
  1000			void ZEXPORT gzclearerr (file)
  1001			    gzFile file;
  1002	      ######    {
  1003	      ######        gz_stream *s = (gz_stream*)file;
  1004			
  1005	      ######        if (s == NULL) return;
  1006	      ######        if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
  1007	      ######        s->z_eof = 0;
  1008	      ######        clearerr(s->file);
  1009			}
