1 /* gzio.c -- IO on .gz files
2 * Copyright (C) 1995-2010 Jean-loup Gailly.
3 * For conditions of distribution and use, see copyright notice in zlib.h
5 * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
12 #ifdef _LARGEFILE64_SOURCE
13 # ifndef _LARGEFILE_SOURCE
14 # define _LARGEFILE_SOURCE
16 # ifdef _FILE_OFFSET_BITS
17 # undef _FILE_OFFSET_BITS
24 #ifdef NO_DEFLATE /* for compatibility with old definition */
25 # define NO_GZCOMPRESS
29 struct internal_state {int dummy;}; /* for buggy compilers */
34 # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
36 # define Z_BUFSIZE 16384
39 #ifndef Z_PRINTF_BUFSIZE
40 # define Z_PRINTF_BUFSIZE 4096
43 #if defined UNDER_CE && defined NO_ERRNO_H
46 /* Map the Windows error number in ERROR to a locale-dependent error
47 message string and return a pointer to it. Typically, the values
48 for ERROR come from GetLastError.
50 The string pointed to shall not be modified by the application,
51 but may be overwritten by a subsequent call to strwinerror
53 The strwinerror function does not change the current setting
56 local char *strwinerror (error)
59 static char buf[1024];
62 DWORD lasterr = GetLastError();
63 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
64 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
67 0, /* Default language */
72 /* If there is an \r\n appended, zap it. */
74 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
79 if (chars > sizeof (buf) - 1) {
80 chars = sizeof (buf) - 1;
84 wcstombs(buf, msgbuf, chars + 1);
88 sprintf(buf, "unknown win32 error (%ld)", error);
91 SetLastError(lasterr);
95 #endif /* UNDER_CE && NO_ERRNO_H */
98 #pragma map (fdopen , "\174\174FDOPEN")
99 FILE *fdopen(int, const char *);
103 extern voidp malloc OF((uInt size));
104 extern void free OF((voidpf ptr));
111 # define FSEEK fseeko
112 # define FTELL ftello
115 #define ALLOC(size) malloc(size)
116 #define TRYFREE(p) {if (p) free(p);}
118 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
121 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
122 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
123 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
124 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
125 #define COMMENT 0x10 /* bit 4 set: file comment present */
126 #define RESERVED 0xE0 /* bits 5..7: reserved */
128 typedef struct gz_stream {
130 int z_err; /* error code for last stream operation */
131 int z_eof; /* set if end of input file */
132 FILE *file; /* .gz file */
133 Byte *inbuf; /* input buffer */
134 Byte *outbuf; /* output buffer */
135 uLong crc; /* crc32 of uncompressed data */
136 char *msg; /* error message */
137 char *path; /* path name for debugging only */
138 int transparent; /* 1 if input file is not a .gz file */
139 char mode; /* 'w' or 'r' */
140 z_off64_t start; /* start of compressed data in file */
141 z_off64_t in; /* bytes into deflate or inflate */
142 z_off64_t out; /* bytes out of deflate or inflate */
143 int back; /* one character push-back */
144 int last; /* true if push-back is last character */
148 local gzFile gz_open OF((const char *, const char *, int, int));
149 local z_off64_t gz_seek OF((gzFile, z_off64_t, int, int));
150 local int do_flush OF((gzFile, int));
151 local int get_byte OF((gz_stream *));
152 local void check_header OF((gz_stream *));
153 local int destroy OF((gz_stream *));
154 local void putLong OF((FILE *, uLong));
155 local uLong getLong OF((gz_stream *));
157 /* ===========================================================================
158 Opens a gzip (.gz) file for reading or writing. The mode parameter
159 is as in fopen ("rb" or "wb"). The file is given either by file descriptor
160 or path name (if fd == -1).
161 gz_open returns NULL if the file could not be opened or if there was
162 insufficient memory to allocate the (de)compression state; errno
163 can be checked to distinguish the two cases (if errno is zero, the
164 zlib error is Z_MEM_ERROR).
166 local gzFile gz_open (path, mode, fd, use64)
173 int level = Z_DEFAULT_COMPRESSION; /* compression level */
174 int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
175 char *p = (char*)mode;
177 char fmode[80]; /* copy of mode, without the compression level */
180 if (!path || !mode) return Z_NULL;
182 s = (gz_stream *)ALLOC(sizeof(gz_stream));
183 if (!s) return Z_NULL;
185 s->stream.zalloc = (alloc_func)0;
186 s->stream.zfree = (free_func)0;
187 s->stream.opaque = (voidpf)0;
188 s->stream.next_in = s->inbuf = Z_NULL;
189 s->stream.next_out = s->outbuf = Z_NULL;
190 s->stream.avail_in = s->stream.avail_out = 0;
191 s->stream.state = Z_NULL;
198 s->crc = crc32(0L, Z_NULL, 0);
202 s->path = (char*)ALLOC(strlen(path)+1);
203 if (s->path == NULL) {
204 return destroy(s), (gzFile)Z_NULL;
206 strcpy(s->path, path); /* do this early for debugging */
210 if (*p == 'r') s->mode = 'r';
211 if (*p == 'w' || *p == 'a') s->mode = 'w';
212 if (*p >= '0' && *p <= '9') {
214 } else if (*p == 'f') {
215 strategy = Z_FILTERED;
216 } else if (*p == 'h') {
217 strategy = Z_HUFFMAN_ONLY;
218 } else if (*p == 'R') {
221 *m++ = *p; /* copy the mode */
223 } while (*p++ && m != fmode + sizeof(fmode));
224 if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
226 if (s->mode == 'w') {
228 err = Z_STREAM_ERROR;
230 err = deflateInit2(&(s->stream), level,
231 Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
232 /* windowBits is passed < 0 to suppress zlib header */
234 s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
236 if (err != Z_OK || s->outbuf == Z_NULL) {
237 return destroy(s), (gzFile)Z_NULL;
240 s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
242 err = inflateInit2(&(s->stream), -MAX_WBITS);
243 /* windowBits is passed < 0 to tell that there is no zlib header */
244 if (err != Z_OK || s->inbuf == Z_NULL) {
245 return destroy(s), (gzFile)Z_NULL;
248 s->stream.avail_out = Z_BUFSIZE;
252 (use64 ? F_OPEN64(path, fmode) : F_OPEN(path, fmode)) :
253 (FILE*)fdopen(fd, fmode);
255 if (s->file == NULL) {
256 return destroy(s), (gzFile)Z_NULL;
258 if (s->mode == 'w') {
259 /* Write a very simple .gz header:
261 fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
262 Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, level == 9 ? 2 :
263 (strategy >= Z_HUFFMAN_ONLY ||
264 (level != Z_DEFAULT_COMPRESSION && level < 2) ?
265 4 : 0) /*xflags*/, OS_CODE);
267 /* We use 10L instead of ftell(s->file) to because ftell causes an
268 * fflush on some systems. This version of the library doesn't use
269 * start anyway in write mode, so this initialization is not
273 check_header(s); /* skip the .gz header */
274 s->start = FTELL(s->file) - s->stream.avail_in;
280 /* ===========================================================================
281 Opens a gzip (.gz) file for reading or writing.
283 gzFile ZEXPORT gzopen (path, mode)
287 return gz_open (path, mode, -1, 0);
290 /* ===========================================================================
291 Opens a gzip (.gz) file for reading or writing for 64-bit offsets
293 gzFile ZEXPORT gzopen64 (path, mode)
297 return gz_open (path, mode, -1, 1);
300 /* ===========================================================================
301 Associate a gzFile with the file descriptor fd. fd is not dup'ed here
302 to mimic the behavio(u)r of fdopen.
304 gzFile ZEXPORT gzdopen (fd, mode)
308 char name[46]; /* allow for up to 128-bit integers */
310 if (fd == -1) return (gzFile)Z_NULL;
311 sprintf(name, "<fd:%d>", fd); /* for debugging */
313 return gz_open (name, mode, fd, 0);
316 /* ===========================================================================
317 * Update the compression level and strategy
319 int ZEXPORT gzsetparams (file, level, strategy)
324 gz_stream *s = (gz_stream*)file;
326 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
328 /* Make room to allow flushing */
329 if (s->stream.avail_out == 0) {
331 s->stream.next_out = s->outbuf;
332 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
335 s->stream.avail_out = Z_BUFSIZE;
338 return deflateParams (&(s->stream), level, strategy);
341 /* ===========================================================================
342 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
344 IN assertion: the stream s has been successfully opened for reading.
346 local int get_byte(s)
349 if (s->z_eof) return EOF;
350 if (s->stream.avail_in == 0) {
352 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
353 if (s->stream.avail_in == 0) {
355 if (ferror(s->file)) s->z_err = Z_ERRNO;
358 s->stream.next_in = s->inbuf;
360 s->stream.avail_in--;
361 return *(s->stream.next_in)++;
364 /* ===========================================================================
365 Check the gzip header of a gz_stream opened for reading. Set the stream
366 mode to transparent if the gzip magic header is not present; set s->err
367 to Z_DATA_ERROR if the magic header is present but the rest of the header
369 IN assertion: the stream s has already been created successfully;
370 s->stream.avail_in is zero for the first time, but may be non-zero
371 for concatenated .gz files.
373 local void check_header(s)
376 int method; /* method byte */
377 int flags; /* flags byte */
381 /* Assure two bytes in the buffer so we can peek ahead -- handle case
382 where first byte of header is at the end of the buffer after the last
384 len = s->stream.avail_in;
386 if (len) s->inbuf[0] = s->stream.next_in[0];
388 len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
389 if (len == 0) s->z_eof = 1;
390 if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
391 s->stream.avail_in += len;
392 s->stream.next_in = s->inbuf;
393 if (s->stream.avail_in < 2) {
394 s->transparent = s->stream.avail_in;
399 /* Peek ahead to check the gzip magic header */
400 if (s->stream.next_in[0] != gz_magic[0] ||
401 s->stream.next_in[1] != gz_magic[1]) {
405 s->stream.avail_in -= 2;
406 s->stream.next_in += 2;
408 /* Check the rest of the gzip header */
409 method = get_byte(s);
411 if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
412 s->z_err = Z_DATA_ERROR;
416 /* Discard time, xflags and OS code: */
417 for (len = 0; len < 6; len++) (void)get_byte(s);
419 if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
420 len = (uInt)get_byte(s);
421 len += ((uInt)get_byte(s))<<8;
422 /* len is garbage if EOF but the loop below will quit anyway */
423 while (len-- != 0 && get_byte(s) != EOF) ;
425 if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
426 while ((c = get_byte(s)) != 0 && c != EOF) ;
428 if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
429 while ((c = get_byte(s)) != 0 && c != EOF) ;
431 if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
432 for (len = 0; len < 2; len++) (void)get_byte(s);
434 s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
437 /* ===========================================================================
438 * Cleanup then free the given gz_stream. Return a zlib error code.
439 Try freeing in the reverse order of allocations.
441 local int destroy (s)
446 if (!s) return Z_STREAM_ERROR;
450 if (s->stream.state != NULL) {
451 if (s->mode == 'w') {
453 err = Z_STREAM_ERROR;
455 err = deflateEnd(&(s->stream));
457 } else if (s->mode == 'r') {
458 err = inflateEnd(&(s->stream));
461 if (s->file != NULL && fclose(s->file)) {
463 if (zerrno() != ESPIPE) /* fclose is broken for pipes in HP/UX */
467 if (s->z_err < 0) err = s->z_err;
476 /* ===========================================================================
477 Reads the given number of uncompressed bytes from the compressed file.
478 gzread returns the number of bytes actually read (0 for end of file).
480 int ZEXPORT gzread (file, buf, len)
485 gz_stream *s = (gz_stream*)file;
486 Bytef *start = (Bytef*)buf; /* starting point for crc computation */
487 Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
489 if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
491 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
492 if (s->z_err == Z_STREAM_END) return 0; /* EOF */
494 next_out = (Byte*)buf;
495 s->stream.next_out = (Bytef*)buf;
496 s->stream.avail_out = len;
498 if (s->stream.avail_out && s->back != EOF) {
499 *next_out++ = s->back;
500 s->stream.next_out++;
501 s->stream.avail_out--;
506 s->z_err = Z_STREAM_END;
511 while (s->stream.avail_out != 0) {
513 if (s->transparent) {
514 /* Copy first the lookahead bytes: */
515 uInt n = s->stream.avail_in;
516 if (n > s->stream.avail_out) n = s->stream.avail_out;
518 zmemcpy(s->stream.next_out, s->stream.next_in, n);
520 s->stream.next_out = next_out;
521 s->stream.next_in += n;
522 s->stream.avail_out -= n;
523 s->stream.avail_in -= n;
525 if (s->stream.avail_out > 0 && !feof(s->file)) {
526 s->stream.avail_out -=
527 (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
529 len -= s->stream.avail_out;
532 if (len == 0 && feof(s->file)) s->z_eof = 1;
535 if (s->stream.avail_in == 0 && !s->z_eof) {
538 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
539 if (s->stream.avail_in == 0) {
541 if (ferror(s->file)) {
546 s->stream.next_in = s->inbuf;
548 s->in += s->stream.avail_in;
549 s->out += s->stream.avail_out;
550 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
551 s->in -= s->stream.avail_in;
552 s->out -= s->stream.avail_out;
554 if (s->z_err == Z_STREAM_END) {
555 /* Check CRC and original size */
556 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
557 start = s->stream.next_out;
559 if (getLong(s) != s->crc) {
560 s->z_err = Z_DATA_ERROR;
563 /* The uncompressed length returned by above getlong() may be
564 * different from s->out in case of concatenated .gz files.
565 * Check for such files:
568 if (s->z_err == Z_OK) {
569 inflateReset(&(s->stream));
570 s->crc = crc32(0L, Z_NULL, 0);
574 if (s->z_err != Z_OK || s->z_eof) break;
576 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
578 if (len == s->stream.avail_out &&
579 (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
581 return (int)(len - s->stream.avail_out);
585 /* ===========================================================================
586 Reads one byte from the compressed file. gzgetc returns this byte
587 or -1 in case of end of file or error.
589 int ZEXPORT gzgetc(file)
594 return gzread(file, &c, 1) == 1 ? c : -1;
598 /* ===========================================================================
599 Push one byte back onto the stream.
601 int ZEXPORT gzungetc(c, file)
605 gz_stream *s = (gz_stream*)file;
607 if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
610 s->last = (s->z_err == Z_STREAM_END);
611 if (s->last) s->z_err = Z_OK;
617 /* ===========================================================================
618 Reads bytes from the compressed file until len-1 characters are
619 read, or a newline character is read and transferred to buf, or an
620 end-of-file condition is encountered. The string is then terminated
621 with a null character.
622 gzgets returns buf, or Z_NULL in case of error.
624 The current implementation is not optimized at all.
626 char * ZEXPORT gzgets(file, buf, len)
632 if (buf == Z_NULL || len <= 0) return Z_NULL;
634 while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
636 return b == buf && len > 0 ? Z_NULL : b;
640 #ifndef NO_GZCOMPRESS
641 /* ===========================================================================
642 Writes the given number of uncompressed bytes into the compressed file.
643 gzwrite returns the number of bytes actually written (0 in case of error).
645 int ZEXPORT gzwrite (file, buf, len)
650 gz_stream *s = (gz_stream*)file;
652 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
654 s->stream.next_in = (Bytef*)buf;
655 s->stream.avail_in = len;
657 while (s->stream.avail_in != 0) {
659 if (s->stream.avail_out == 0) {
661 s->stream.next_out = s->outbuf;
662 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
666 s->stream.avail_out = Z_BUFSIZE;
668 s->in += s->stream.avail_in;
669 s->out += s->stream.avail_out;
670 s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
671 s->in -= s->stream.avail_in;
672 s->out -= s->stream.avail_out;
673 if (s->z_err != Z_OK) break;
675 s->crc = crc32(s->crc, (const Bytef *)buf, len);
677 return (int)(len - s->stream.avail_in);
681 /* ===========================================================================
682 Converts, formats, and writes the args to the compressed file under
683 control of the format string, as in fprintf. gzprintf returns the number of
684 uncompressed bytes actually written (0 in case of error).
689 int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
691 char buf[Z_PRINTF_BUFSIZE];
695 buf[sizeof(buf) - 1] = 0;
696 va_start(va, format);
698 # ifdef HAS_vsprintf_void
699 (void)vsprintf(buf, format, va);
701 for (len = 0; len < sizeof(buf); len++)
702 if (buf[len] == 0) break;
704 len = vsprintf(buf, format, va);
708 # ifdef HAS_vsnprintf_void
709 (void)vsnprintf(buf, sizeof(buf), format, va);
713 len = vsnprintf(buf, sizeof(buf), format, va);
717 if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
719 return gzwrite(file, buf, (unsigned)len);
721 #else /* not ANSI C */
723 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
724 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
727 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
728 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
730 char buf[Z_PRINTF_BUFSIZE];
733 buf[sizeof(buf) - 1] = 0;
735 # ifdef HAS_sprintf_void
736 sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
737 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
738 for (len = 0; len < sizeof(buf); len++)
739 if (buf[len] == 0) break;
741 len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
742 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
745 # ifdef HAS_snprintf_void
746 snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
747 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
750 len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
751 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
754 if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
756 return gzwrite(file, buf, len);
760 /* ===========================================================================
761 Writes c, converted to an unsigned char, into the compressed file.
762 gzputc returns the value that was written, or -1 in case of error.
764 int ZEXPORT gzputc(file, c)
768 unsigned char cc = (unsigned char) c; /* required for big endian systems */
770 return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
774 /* ===========================================================================
775 Writes the given null-terminated string to the compressed file, excluding
776 the terminating null character.
777 gzputs returns the number of characters written, or -1 in case of error.
779 int ZEXPORT gzputs(file, s)
783 return gzwrite(file, (char*)s, (unsigned)strlen(s));
787 /* ===========================================================================
788 Flushes all pending output into the compressed file. The parameter
789 flush is as in the deflate() function.
791 local int do_flush (file, flush)
797 gz_stream *s = (gz_stream*)file;
799 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
801 s->stream.avail_in = 0; /* should be zero already anyway */
804 len = Z_BUFSIZE - s->stream.avail_out;
807 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
811 s->stream.next_out = s->outbuf;
812 s->stream.avail_out = Z_BUFSIZE;
815 s->out += s->stream.avail_out;
816 s->z_err = deflate(&(s->stream), flush);
817 s->out -= s->stream.avail_out;
819 /* Ignore the second of two consecutive flushes: */
820 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
822 /* deflate has finished flushing only when it hasn't used up
823 * all the available space in the output buffer:
825 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
827 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
829 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
832 int ZEXPORT gzflush (file, flush)
836 gz_stream *s = (gz_stream*)file;
837 int err = do_flush (file, flush);
841 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
843 #endif /* NO_GZCOMPRESS */
845 /* ===========================================================================
846 Sets the starting position for the next gzread or gzwrite on the given
847 compressed file. The offset represents a number of bytes in the
848 gzseek returns the resulting offset location as measured in bytes from
849 the beginning of the uncompressed stream, or -1 in case of error.
850 SEEK_END is not implemented, returns error.
851 In this version of the library, gzseek can be extremely slow.
853 local z_off64_t gz_seek (file, offset, whence, use64)
859 gz_stream *s = (gz_stream*)file;
861 if (s == NULL || whence == SEEK_END ||
862 s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
866 if (s->mode == 'w') {
870 if (whence == SEEK_SET) {
873 if (offset < 0) return -1L;
875 /* At this point, offset is the number of zero bytes to write. */
876 if (s->inbuf == Z_NULL) {
877 s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
878 if (s->inbuf == Z_NULL) return -1L;
879 zmemzero(s->inbuf, Z_BUFSIZE);
882 uInt size = Z_BUFSIZE;
883 if (offset < Z_BUFSIZE) size = (uInt)offset;
885 size = gzwrite(file, s->inbuf, size);
886 if (size == 0) return -1L;
893 /* Rest of function is for reading only */
895 /* compute absolute position */
896 if (whence == SEEK_CUR) {
899 if (offset < 0) return -1L;
901 if (s->transparent) {
904 s->stream.avail_in = 0;
905 s->stream.next_in = s->inbuf;
906 #ifdef _LARGEFILE64_SOURCE
907 if ((use64 ? fseeko64(s->file, offset, SEEK_SET) :
908 FSEEK(s->file, offset, SEEK_SET)) < 0)
911 if (FSEEK(s->file, offset, SEEK_SET) < 0) return -1L;
914 s->in = s->out = offset;
918 /* For a negative seek, rewind and use positive seek */
919 if (offset >= s->out) {
921 } else if (gzrewind(file) < 0) {
924 /* offset is now the number of bytes to skip. */
926 if (offset != 0 && s->outbuf == Z_NULL) {
927 s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
928 if (s->outbuf == Z_NULL) return -1L;
930 if (offset && s->back != EOF) {
934 if (s->last) s->z_err = Z_STREAM_END;
937 int size = Z_BUFSIZE;
938 if (offset < Z_BUFSIZE) size = (int)offset;
940 size = gzread(file, s->outbuf, (uInt)size);
941 if (size <= 0) return -1L;
947 /* ===========================================================================
948 Define external functions gzseek() and gzseek64() using local gz_seek().
950 z_off_t ZEXPORT gzseek (file, offset, whence)
955 return (z_off_t)gz_seek(file, offset, whence, 0);
958 z_off64_t ZEXPORT gzseek64 (file, offset, whence)
963 #ifdef _LARGEFILE64_SOURCE
964 return gz_seek(file, offset, whence, 1);
966 return gz_seek(file, offset, whence, 0);
970 /* ===========================================================================
973 int ZEXPORT gzrewind (file)
976 gz_stream *s = (gz_stream*)file;
978 if (s == NULL || s->mode != 'r') return -1;
983 s->stream.avail_in = 0;
984 s->stream.next_in = s->inbuf;
985 s->crc = crc32(0L, Z_NULL, 0);
986 if (!s->transparent) (void)inflateReset(&s->stream);
989 return FSEEK(s->file, s->start, SEEK_SET);
992 /* ===========================================================================
993 Returns the starting position for the next gzread or gzwrite on the
994 given compressed file. This position represents a number of bytes in the
995 uncompressed data stream.
997 z_off_t ZEXPORT gztell (file)
1000 return gzseek(file, 0L, SEEK_CUR);
1003 /* ===========================================================================
1006 z_off64_t ZEXPORT gztell64 (file)
1009 return gzseek64(file, 0L, SEEK_CUR);
1012 /* ===========================================================================
1013 Returns 1 when EOF has previously been detected reading the given
1014 input stream, otherwise zero.
1016 int ZEXPORT gzeof (file)
1019 gz_stream *s = (gz_stream*)file;
1021 /* With concatenated compressed files that can have embedded
1022 * crc trailers, z_eof is no longer the only/best indicator of EOF
1023 * on a gz_stream. Handle end-of-stream error explicitly here.
1025 if (s == NULL || s->mode != 'r') return 0;
1026 if (s->z_eof) return 1;
1027 return s->z_err == Z_STREAM_END;
1030 /* ===========================================================================
1031 Returns 1 if reading and doing so transparently, otherwise zero.
1033 int ZEXPORT gzdirect (file)
1036 gz_stream *s = (gz_stream*)file;
1038 if (s == NULL || s->mode != 'r') return 0;
1039 return s->transparent;
1042 /* ===========================================================================
1043 Outputs a long in LSB order to the given file
1045 local void putLong (file, x)
1050 for (n = 0; n < 4; n++) {
1051 fputc((int)(x & 0xff), file);
1056 /* ===========================================================================
1057 Reads a long in LSB order from the given gz_stream. Sets z_err in case
1060 local uLong getLong (s)
1063 uLong x = (uLong)get_byte(s);
1066 x += ((uLong)get_byte(s))<<8;
1067 x += ((uLong)get_byte(s))<<16;
1069 if (c == EOF) s->z_err = Z_DATA_ERROR;
1070 x += ((uLong)c)<<24;
1074 /* ===========================================================================
1075 Flushes all pending output if necessary, closes the compressed file
1076 and deallocates all the (de)compression state.
1078 int ZEXPORT gzclose (file)
1081 gz_stream *s = (gz_stream*)file;
1083 if (s == NULL) return Z_STREAM_ERROR;
1085 if (s->mode == 'w') {
1086 #ifdef NO_GZCOMPRESS
1087 return Z_STREAM_ERROR;
1089 if (do_flush (file, Z_FINISH) != Z_OK)
1090 return destroy((gz_stream*)file);
1092 putLong (s->file, s->crc);
1093 putLong (s->file, (uLong)(s->in & 0xffffffff));
1096 return destroy((gz_stream*)file);
1099 #if defined UNDER_CE && defined NO_ERRNO_H
1100 # define zstrerror(errnum) strwinerror((DWORD)errnum)
1103 # define zstrerror(errnum) strerror(errnum)
1105 # define zstrerror(errnum) ""
1109 /* ===========================================================================
1110 Returns the error message for the last error which occurred on the
1111 given compressed file. errnum is set to zlib error number. If an
1112 error occurred in the file system and not in the compression library,
1113 errnum is set to Z_ERRNO and the application may consult errno
1114 to get the exact error code.
1116 const char * ZEXPORT gzerror (file, errnum)
1121 gz_stream *s = (gz_stream*)file;
1124 *errnum = Z_STREAM_ERROR;
1125 return (const char*)ERR_MSG(Z_STREAM_ERROR);
1128 if (*errnum == Z_OK) return (const char*)"";
1130 m = (char*)(*errnum == Z_ERRNO ? zstrerror(zerrno()) : s->stream.msg);
1132 if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
1135 s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
1136 if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
1137 strcpy(s->msg, s->path);
1138 strcat(s->msg, ": ");
1140 return (const char*)s->msg;
1143 /* ===========================================================================
1144 Clear the error and end-of-file flags, and do the same for the real file.
1146 void ZEXPORT gzclearerr (file)
1149 gz_stream *s = (gz_stream*)file;
1151 if (s == NULL) return;
1152 if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
1157 /* new functions in gzlib, but only partially implemented here */
1159 int ZEXPORT gzbuffer (file, size)
1166 z_off_t ZEXPORT gzoffset (file)
1172 z_off64_t ZEXPORT gzoffset64 (file)
1178 int ZEXPORT gzclose_r (file)
1181 return gzclose(file);
1184 int ZEXPORT gzclose_w (file)
1187 return gzclose(file);
1192 #else /* !OLD_GZIO */
1196 #endif /* OLD_GZIO */