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