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