]> git.saurik.com Git - wxWidgets.git/blame - src/zlib/gzio.c
Applied #15375 to stop event-sending in generic wxSpinCtrl ctor (eco)
[wxWidgets.git] / src / zlib / gzio.c
CommitLineData
c801d85f 1/* gzio.c -- IO on .gz files
41faf807 2 * Copyright (C) 1995-2005 Jean-loup Gailly.
c801d85f
KB
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 *
51dbdf87 5 * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
c801d85f
KB
6 */
7
c801d85f
KB
8
9#include <stdio.h>
10
11#include "zutil.h"
12
41faf807 13#ifdef NO_DEFLATE /* for compatibility with old definition */
51dbdf87
VS
14# define NO_GZCOMPRESS
15#endif
16
17#ifndef NO_DUMMY_DECL
c801d85f 18struct internal_state {int dummy;}; /* for buggy compilers */
51dbdf87 19#endif
c801d85f
KB
20
21#ifndef Z_BUFSIZE
22# ifdef MAXSEG_64K
23# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
24# else
25# define Z_BUFSIZE 16384
26# endif
27#endif
28#ifndef Z_PRINTF_BUFSIZE
29# define Z_PRINTF_BUFSIZE 4096
30#endif
31
51dbdf87
VS
32#ifdef __MVS__
33# pragma map (fdopen , "\174\174FDOPEN")
34 FILE *fdopen(int, const char *);
35#endif
36
37#ifndef STDC
38extern voidp malloc OF((uInt size));
39extern void free OF((voidpf ptr));
40#endif
41
c801d85f
KB
42#define ALLOC(size) malloc(size)
43#define TRYFREE(p) {if (p) free(p);}
44
b0744f80
VZ
45/* there is no errno under Windows CE, provide a dummy one to avoid modifying
46 too much code in this file */
47#ifdef _WIN32_WCE
48static int errno;
49#endif
50
51dbdf87 51static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
c801d85f
KB
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
61typedef 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' */
51dbdf87
VS
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 */
c801d85f
KB
78} gz_stream;
79
80
81local gzFile gz_open OF((const char *path, const char *mode, int fd));
82local int do_flush OF((gzFile file, int flush));
83local int get_byte OF((gz_stream *s));
84local void check_header OF((gz_stream *s));
85local int destroy OF((gz_stream *s));
86local void putLong OF((FILE *file, uLong x));
87local 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).
51dbdf87 93 gz_open returns NULL if the file could not be opened or if there was
c801d85f
KB
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*/
98local 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;
51dbdf87
VS
125 s->in = 0;
126 s->out = 0;
127 s->back = EOF;
c801d85f
KB
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') {
51dbdf87
VS
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 }
c801d85f
KB
153 } while (*p++ && m != fmode + sizeof(fmode));
154 if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
e6ebb514 155
c801d85f 156 if (s->mode == 'w') {
51dbdf87 157#ifdef NO_GZCOMPRESS
c801d85f
KB
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);
51dbdf87
VS
196 s->start = 10L;
197 /* We use 10L instead of ftell(s->file) to because ftell causes an
c801d85f 198 * fflush on some systems. This version of the library doesn't use
51dbdf87 199 * start anyway in write mode, so this initialization is not
c801d85f
KB
200 * necessary.
201 */
202 } else {
51dbdf87
VS
203 check_header(s); /* skip the .gz header */
204 s->start = ftell(s->file) - s->stream.avail_in;
c801d85f 205 }
e6ebb514 206
c801d85f
KB
207 return (gzFile)s;
208}
209
210/* ===========================================================================
211 Opens a gzip (.gz) file for reading or writing.
212*/
213gzFile 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*/
224gzFile ZEXPORT gzdopen (fd, mode)
225 int fd;
226 const char *mode;
227{
41faf807 228 char name[46]; /* allow for up to 128-bit integers */
c801d85f
KB
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 */
239int 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
51dbdf87
VS
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;
c801d85f
KB
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*/
266local int get_byte(s)
267 gz_stream *s;
268{
269 if (s->z_eof) return EOF;
270 if (s->stream.avail_in == 0) {
51dbdf87 271 errno = 0;
41faf807 272 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
51dbdf87
VS
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;
c801d85f
KB
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*/
293local 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
51dbdf87
VS
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;
41faf807 308 len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
51dbdf87
VS
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;
c801d85f 323 }
51dbdf87
VS
324 s->stream.avail_in -= 2;
325 s->stream.next_in += 2;
326
327 /* Check the rest of the gzip header */
c801d85f
KB
328 method = get_byte(s);
329 flags = get_byte(s);
330 if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
51dbdf87
VS
331 s->z_err = Z_DATA_ERROR;
332 return;
c801d85f
KB
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 */
51dbdf87
VS
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) ;
c801d85f
KB
343 }
344 if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
51dbdf87 345 while ((c = get_byte(s)) != 0 && c != EOF) ;
c801d85f
KB
346 }
347 if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
51dbdf87 348 while ((c = get_byte(s)) != 0 && c != EOF) ;
c801d85f
KB
349 }
350 if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
51dbdf87 351 for (len = 0; len < 2; len++) (void)get_byte(s);
c801d85f
KB
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 */
360local 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) {
51dbdf87
VS
370 if (s->mode == 'w') {
371#ifdef NO_GZCOMPRESS
372 err = Z_STREAM_ERROR;
c801d85f 373#else
51dbdf87 374 err = deflateEnd(&(s->stream));
c801d85f 375#endif
51dbdf87
VS
376 } else if (s->mode == 'r') {
377 err = inflateEnd(&(s->stream));
378 }
c801d85f
KB
379 }
380 if (s->file != NULL && fclose(s->file)) {
381#ifdef ESPIPE
51dbdf87 382 if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
c801d85f 383#endif
51dbdf87 384 err = Z_ERRNO;
c801d85f
KB
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*/
399int 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
51dbdf87
VS
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++;
41faf807 423 start++;
51dbdf87
VS
424 if (s->last) {
425 s->z_err = Z_STREAM_END;
426 return 1;
427 }
428 }
429
c801d85f
KB
430 while (s->stream.avail_out != 0) {
431
51dbdf87
VS
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) {
41faf807
MW
445 s->stream.avail_out -=
446 (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
51dbdf87
VS
447 }
448 len -= s->stream.avail_out;
449 s->in += len;
450 s->out += len;
c801d85f 451 if (len == 0) s->z_eof = 1;
51dbdf87
VS
452 return (int)len;
453 }
c801d85f
KB
454 if (s->stream.avail_in == 0 && !s->z_eof) {
455
456 errno = 0;
41faf807 457 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
c801d85f
KB
458 if (s->stream.avail_in == 0) {
459 s->z_eof = 1;
51dbdf87
VS
460 if (ferror(s->file)) {
461 s->z_err = Z_ERRNO;
462 break;
463 }
c801d85f
KB
464 }
465 s->stream.next_in = s->inbuf;
466 }
51dbdf87
VS
467 s->in += s->stream.avail_in;
468 s->out += s->stream.avail_out;
c801d85f 469 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
51dbdf87
VS
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;
c801d85f
KB
494 }
495 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
496
41faf807
MW
497 if (len == s->stream.avail_out &&
498 (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
499 return -1;
c801d85f
KB
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*/
508int ZEXPORT gzgetc(file)
509 gzFile file;
510{
511 unsigned char c;
512
513 return gzread(file, &c, 1) == 1 ? c : -1;
514}
515
516
51dbdf87
VS
517/* ===========================================================================
518 Push one byte back onto the stream.
519*/
520int 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
c801d85f
KB
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*/
545char * 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
51dbdf87 559#ifndef NO_GZCOMPRESS
c801d85f
KB
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*/
564int ZEXPORT gzwrite (file, buf, len)
565 gzFile file;
51dbdf87 566 voidpc buf;
c801d85f
KB
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 }
51dbdf87
VS
587 s->in += s->stream.avail_in;
588 s->out += s->stream.avail_out;
c801d85f 589 s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
51dbdf87
VS
590 s->in -= s->stream.avail_in;
591 s->out -= s->stream.avail_out;
c801d85f
KB
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
51dbdf87 599
c801d85f
KB
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
608int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
609{
610 char buf[Z_PRINTF_BUFSIZE];
611 va_list va;
612 int len;
613
51dbdf87 614 buf[sizeof(buf) - 1] = 0;
c801d85f 615 va_start(va, format);
51dbdf87
VS
616#ifdef NO_vsnprintf
617# ifdef HAS_vsprintf_void
c801d85f 618 (void)vsprintf(buf, format, va);
c801d85f 619 va_end(va);
51dbdf87
VS
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;
c801d85f
KB
638 return gzwrite(file, buf, (unsigned)len);
639}
640#else /* not ANSI C */
641
642int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
51dbdf87 643 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
c801d85f
KB
644 gzFile file;
645 const char *format;
646 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
51dbdf87 647 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
c801d85f
KB
648{
649 char buf[Z_PRINTF_BUFSIZE];
650 int len;
651
51dbdf87
VS
652 buf[sizeof(buf) - 1] = 0;
653#ifdef NO_snprintf
654# ifdef HAS_sprintf_void
c801d85f 655 sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
51dbdf87
VS
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
c801d85f 672#endif
51dbdf87
VS
673 if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
674 return 0;
c801d85f
KB
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*/
683int 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*/
698int 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*/
710local 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;
51dbdf87 734 s->out += s->stream.avail_out;
c801d85f 735 s->z_err = deflate(&(s->stream), flush);
51dbdf87 736 s->out -= s->stream.avail_out;
c801d85f 737
51dbdf87
VS
738 /* Ignore the second of two consecutive flushes: */
739 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
c801d85f
KB
740
741 /* deflate has finished flushing only when it hasn't used up
e6ebb514 742 * all the available space in the output buffer:
c801d85f
KB
743 */
744 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
e6ebb514 745
c801d85f
KB
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
751int 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}
51dbdf87 762#endif /* NO_GZCOMPRESS */
c801d85f
KB
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*/
772z_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 ||
51dbdf87
VS
780 s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
781 return -1L;
c801d85f 782 }
e6ebb514 783
c801d85f 784 if (s->mode == 'w') {
51dbdf87
VS
785#ifdef NO_GZCOMPRESS
786 return -1L;
c801d85f 787#else
51dbdf87
VS
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;
c801d85f
KB
809#endif
810 }
811 /* Rest of function is for reading only */
812
813 /* compute absolute position */
814 if (whence == SEEK_CUR) {
51dbdf87 815 offset += s->out;
c801d85f
KB
816 }
817 if (offset < 0) return -1L;
818
819 if (s->transparent) {
51dbdf87
VS
820 /* map to fseek */
821 s->back = EOF;
822 s->stream.avail_in = 0;
823 s->stream.next_in = s->inbuf;
c801d85f
KB
824 if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
825
51dbdf87
VS
826 s->in = s->out = offset;
827 return offset;
c801d85f
KB
828 }
829
830 /* For a negative seek, rewind and use positive seek */
51dbdf87
VS
831 if (offset >= s->out) {
832 offset -= s->out;
c801d85f 833 } else if (gzrewind(file) < 0) {
51dbdf87 834 return -1L;
c801d85f
KB
835 }
836 /* offset is now the number of bytes to skip. */
837
838 if (offset != 0 && s->outbuf == Z_NULL) {
51dbdf87
VS
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;
c801d85f
KB
847 }
848 while (offset > 0) {
51dbdf87
VS
849 int size = Z_BUFSIZE;
850 if (offset < Z_BUFSIZE) size = (int)offset;
c801d85f 851
51dbdf87
VS
852 size = gzread(file, s->outbuf, (uInt)size);
853 if (size <= 0) return -1L;
854 offset -= size;
c801d85f 855 }
51dbdf87 856 return s->out;
c801d85f
KB
857}
858
859/* ===========================================================================
e6ebb514 860 Rewinds input file.
c801d85f
KB
861*/
862int ZEXPORT gzrewind (file)
863 gzFile file;
864{
865 gz_stream *s = (gz_stream*)file;
e6ebb514 866
c801d85f
KB
867 if (s == NULL || s->mode != 'r') return -1;
868
869 s->z_err = Z_OK;
870 s->z_eof = 0;
51dbdf87 871 s->back = EOF;
c801d85f
KB
872 s->stream.avail_in = 0;
873 s->stream.next_in = s->inbuf;
a4019ec2 874 s->crc = crc32(0L, Z_NULL, 0);
51dbdf87
VS
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);
c801d85f
KB
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*/
886z_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*/
896int ZEXPORT gzeof (file)
897 gzFile file;
898{
899 gz_stream *s = (gz_stream*)file;
e6ebb514 900
51dbdf87
VS
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;
c801d85f
KB
908}
909
41faf807
MW
910/* ===========================================================================
911 Returns 1 if reading and doing so transparently, otherwise zero.
912*/
913int 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
c801d85f
KB
922/* ===========================================================================
923 Outputs a long in LSB order to the given file
924*/
925local 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/* ===========================================================================
a4019ec2
SC
937 Reads a long in LSB order from the given gz_stream. Sets z_err in case
938 of error.
c801d85f
KB
939*/
940local 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*/
958int ZEXPORT gzclose (file)
959 gzFile file;
960{
c801d85f
KB
961 gz_stream *s = (gz_stream*)file;
962
963 if (s == NULL) return Z_STREAM_ERROR;
964
965 if (s->mode == 'w') {
51dbdf87
VS
966#ifdef NO_GZCOMPRESS
967 return Z_STREAM_ERROR;
c801d85f 968#else
41faf807
MW
969 if (do_flush (file, Z_FINISH) != Z_OK)
970 return destroy((gz_stream*)file);
c801d85f
KB
971
972 putLong (s->file, s->crc);
51dbdf87 973 putLong (s->file, (uLong)(s->in & 0xffffffff));
c801d85f
KB
974#endif
975 }
976 return destroy((gz_stream*)file);
977}
978
41faf807
MW
979#ifdef STDC
980# define zstrerror(errnum) strerror(errnum)
981#else
982# define zstrerror(errnum) ""
983#endif
984
c801d85f 985/* ===========================================================================
41faf807 986 Returns the error message for the last error which occurred on the
c801d85f 987 given compressed file. errnum is set to zlib error number. If an
41faf807 988 error occurred in the file system and not in the compression library,
c801d85f
KB
989 errnum is set to Z_ERRNO and the application may consult errno
990 to get the exact error code.
991*/
51dbdf87 992const char * ZEXPORT gzerror (file, errnum)
c801d85f
KB
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
51dbdf87 1006 m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
c801d85f
KB
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);
51dbdf87 1012 if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
c801d85f
KB
1013 strcpy(s->msg, s->path);
1014 strcat(s->msg, ": ");
1015 strcat(s->msg, m);
1016 return (const char*)s->msg;
1017}
51dbdf87
VS
1018
1019/* ===========================================================================
1020 Clear the error and end-of-file flags, and do the same for the real file.
1021*/
1022void 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}