root/lib/zlib/gzio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gz_open
  2. gzopen
  3. gzdopen
  4. gzsetparams
  5. get_byte
  6. check_header
  7. destroy
  8. gzread
  9. gzgetc
  10. gzungetc
  11. gzgets
  12. gzwrite
  13. gzprintf
  14. gzprintf
  15. gzputc
  16. gzputs
  17. do_flush
  18. gzflush
  19. gzseek
  20. gzrewind
  21. gztell
  22. gzeof
  23. gzdirect
  24. putLong
  25. getLong
  26. gzclose
  27. gzerror
  28. gzclearerr

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

/* [<][>][^][v][top][bottom][index][help] */