]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/zlib/gzio.c
Applied #15375 to stop event-sending in generic wxSpinCtrl ctor (eco)
[wxWidgets.git] / src / zlib / gzio.c
... / ...
CommitLineData
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
9#include <stdio.h>
10
11#include "zutil.h"
12
13#ifdef NO_DEFLATE /* for compatibility with old definition */
14# define NO_GZCOMPRESS
15#endif
16
17#ifndef NO_DUMMY_DECL
18struct internal_state {int dummy;}; /* for buggy compilers */
19#endif
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
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
42#define ALLOC(size) malloc(size)
43#define TRYFREE(p) {if (p) free(p);}
44
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
51static 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
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' */
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
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).
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*/
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;
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*/
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{
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 */
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
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*/
266local 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*/
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
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 */
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) {
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*/
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
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*/
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
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
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
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*/
564int 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
608int 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
642int 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*/
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;
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
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}
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*/
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 ||
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*/
862int 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*/
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;
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*/
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
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/* ===========================================================================
937 Reads a long in LSB order from the given gz_stream. Sets z_err in case
938 of error.
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{
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*/
992const 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*/
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}