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