MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 /* Need to be included "early" to control other headers */
11 #ifdef HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14 
15 #include <stdio.h>
16 
17 #include "zutil.h"
18 
19 #ifdef NO_DEFLATE /* for compatibility with old definition */
20 # define NO_GZCOMPRESS
21 #endif
22 
23 #ifndef NO_DUMMY_DECL
24 struct internal_state {int dummy;}; /* for buggy compilers */
25 #endif
26 
27 #ifndef Z_BUFSIZE
28 # ifdef MAXSEG_64K
29 # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
30 # else
31 # define Z_BUFSIZE 16384
32 # endif
33 #endif
34 #ifndef Z_PRINTF_BUFSIZE
35 # define Z_PRINTF_BUFSIZE 4096
36 #endif
37 
38 #ifdef __MVS__
39 # pragma map (fdopen , "\174\174FDOPEN")
40  FILE *fdopen(int, const char *);
41 #endif
42 
43 #ifndef STDC
44 extern voidp malloc OF((uInt size));
45 extern void free OF((voidpf ptr));
46 #endif
47 
48 #define ALLOC(size) malloc(size)
49 #define TRYFREE(p) {if (p) free(p);}
50 
51 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
52 
53 /* gzip flag byte */
54 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
55 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
56 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
57 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
58 #define COMMENT 0x10 /* bit 4 set: file comment present */
59 #define RESERVED 0xE0 /* bits 5..7: reserved */
60 
61 typedef struct gz_stream {
62  z_stream stream;
63  int z_err; /* error code for last stream operation */
64  int z_eof; /* set if end of input file */
65  FILE *file; /* .gz file */
66  Byte *inbuf; /* input buffer */
67  Byte *outbuf; /* output buffer */
68  uLong crc; /* crc32 of uncompressed data */
69  char *msg; /* error message */
70  char *path; /* path name for debugging only */
71  int transparent; /* 1 if input file is not a .gz file */
72  char mode; /* 'w' or 'r' */
73  z_off_t start; /* start of compressed data in file (header skipped) */
74  z_off_t in; /* bytes into deflate or inflate */
75  z_off_t out; /* bytes out of deflate or inflate */
76  int back; /* one character push-back */
77  int last; /* true if push-back is last character */
78 } gz_stream;
79 
80 
81 local gzFile gz_open OF((const char *path, const char *mode, int fd));
82 local int do_flush OF((gzFile file, int flush));
83 local int get_byte OF((gz_stream *s));
84 local void check_header OF((gz_stream *s));
85 local int destroy OF((gz_stream *s));
86 local void putLong OF((FILE *file, uLong x));
87 local uLong getLong OF((gz_stream *s));
88 
89 /* ===========================================================================
90  Opens a gzip (.gz) file for reading or writing. The mode parameter
91  is as in fopen ("rb" or "wb"). The file is given either by file descriptor
92  or path name (if fd == -1).
93  gz_open returns NULL if the file could not be opened or if there was
94  insufficient memory to allocate the (de)compression state; errno
95  can be checked to distinguish the two cases (if errno is zero, the
96  zlib error is Z_MEM_ERROR).
97 */
98 local gzFile gz_open (path, mode, fd)
99  const char *path;
100  const char *mode;
101  int fd;
102 {
103  int err;
104  int level = Z_DEFAULT_COMPRESSION; /* compression level */
105  int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
106  char *p = (char*)mode;
107  gz_stream *s;
108  char fmode[80]; /* copy of mode, without the compression level */
109  char *m = fmode;
110 
111  if (!path || !mode) return Z_NULL;
112 
113  s = (gz_stream *)ALLOC(sizeof(gz_stream));
114  if (!s) return Z_NULL;
115 
116  s->stream.zalloc = (alloc_func)0;
117  s->stream.zfree = (free_func)0;
118  s->stream.opaque = (voidpf)0;
119  s->stream.next_in = s->inbuf = Z_NULL;
120  s->stream.next_out = s->outbuf = Z_NULL;
121  s->stream.avail_in = s->stream.avail_out = 0;
122  s->file = NULL;
123  s->z_err = Z_OK;
124  s->z_eof = 0;
125  s->in = 0;
126  s->out = 0;
127  s->back = EOF;
128  s->crc = crc32(0L, Z_NULL, 0);
129  s->msg = NULL;
130  s->transparent = 0;
131 
132  s->path = (char*)ALLOC(strlen(path)+1);
133  if (s->path == NULL) {
134  return destroy(s), (gzFile)Z_NULL;
135  }
136  strcpy(s->path, path); /* 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  sprintf(name, "<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  char *m;
997  gz_stream *s = (gz_stream*)file;
998 
999  if (s == NULL) {
1000  *errnum = Z_STREAM_ERROR;
1001  return (const char*)ERR_MSG(Z_STREAM_ERROR);
1002  }
1003  *errnum = s->z_err;
1004  if (*errnum == Z_OK) return (const char*)"";
1005 
1006  m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
1007 
1008  if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
1009 
1010  TRYFREE(s->msg);
1011  s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
1012  if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
1013  strcpy(s->msg, s->path);
1014  strcat(s->msg, ": ");
1015  strcat(s->msg, m);
1016  return (const char*)s->msg;
1017 }
1018 
1019 /* ===========================================================================
1020  Clear the error and end-of-file flags, and do the same for the real file.
1021 */
1022 void ZEXPORT gzclearerr (file)
1023  gzFile file;
1024 {
1025  gz_stream *s = (gz_stream*)file;
1026 
1027  if (s == NULL) return;
1028  if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
1029  s->z_eof = 0;
1030  clearerr(s->file);
1031 }