1
/* gzio.c -- IO on .gz files
2
* Copyright (C) 1995-2003 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.
8
/* @(#) $Id: gzio.c,v 1.1.2.2 2004/09/08 16:04:43 easysw Exp $ */
14
#ifdef NO_DEFLATE /* for compatiblity with old definition */
15
# define NO_GZCOMPRESS
19
struct internal_state {int dummy;}; /* for buggy compilers */
24
# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
26
# define Z_BUFSIZE 16384
29
#ifndef Z_PRINTF_BUFSIZE
30
# define Z_PRINTF_BUFSIZE 4096
34
# pragma map (fdopen , "\174\174FDOPEN")
35
FILE *fdopen(int, const char *);
39
extern voidp malloc OF((uInt size));
40
extern void free OF((voidpf ptr));
43
#define ALLOC(size) malloc(size)
44
#define TRYFREE(p) {if (p) free(p);}
46
static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
49
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
50
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
51
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
52
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
53
#define COMMENT 0x10 /* bit 4 set: file comment present */
54
#define RESERVED 0xE0 /* bits 5..7: reserved */
56
typedef struct gz_stream {
58
int z_err; /* error code for last stream operation */
59
int z_eof; /* set if end of input file */
60
FILE *file; /* .gz file */
61
Byte *inbuf; /* input buffer */
62
Byte *outbuf; /* output buffer */
63
uLong crc; /* crc32 of uncompressed data */
64
char *msg; /* error message */
65
char *path; /* path name for debugging only */
66
int transparent; /* 1 if input file is not a .gz file */
67
char mode; /* 'w' or 'r' */
68
z_off_t start; /* start of compressed data in file (header skipped) */
69
z_off_t in; /* bytes into deflate or inflate */
70
z_off_t out; /* bytes out of deflate or inflate */
71
int back; /* one character push-back */
72
int last; /* true if push-back is last character */
76
local gzFile gz_open OF((const char *path, const char *mode, int fd));
77
local int do_flush OF((gzFile file, int flush));
78
local int get_byte OF((gz_stream *s));
79
local void check_header OF((gz_stream *s));
80
local int destroy OF((gz_stream *s));
81
local void putLong OF((FILE *file, uLong x));
82
local uLong getLong OF((gz_stream *s));
84
/* ===========================================================================
85
Opens a gzip (.gz) file for reading or writing. The mode parameter
86
is as in fopen ("rb" or "wb"). The file is given either by file descriptor
87
or path name (if fd == -1).
88
gz_open returns NULL if the file could not be opened or if there was
89
insufficient memory to allocate the (de)compression state; errno
90
can be checked to distinguish the two cases (if errno is zero, the
91
zlib error is Z_MEM_ERROR).
93
local gzFile gz_open (path, mode, fd)
99
int level = Z_DEFAULT_COMPRESSION; /* compression level */
100
int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
101
char *p = (char*)mode;
103
char fmode[80]; /* copy of mode, without the compression level */
106
if (!path || !mode) return Z_NULL;
108
s = (gz_stream *)ALLOC(sizeof(gz_stream));
109
if (!s) return Z_NULL;
111
s->stream.zalloc = (alloc_func)0;
112
s->stream.zfree = (free_func)0;
113
s->stream.opaque = (voidpf)0;
114
s->stream.next_in = s->inbuf = Z_NULL;
115
s->stream.next_out = s->outbuf = Z_NULL;
116
s->stream.avail_in = s->stream.avail_out = 0;
123
s->crc = crc32(0L, Z_NULL, 0);
127
s->path = (char*)ALLOC(strlen(path)+1);
128
if (s->path == NULL) {
129
return destroy(s), (gzFile)Z_NULL;
131
strcpy(s->path, path); /* do this early for debugging */
135
if (*p == 'r') s->mode = 'r';
136
if (*p == 'w' || *p == 'a') s->mode = 'w';
137
if (*p >= '0' && *p <= '9') {
139
} else if (*p == 'f') {
140
strategy = Z_FILTERED;
141
} else if (*p == 'h') {
142
strategy = Z_HUFFMAN_ONLY;
143
} else if (*p == 'R') {
146
*m++ = *p; /* copy the mode */
148
} while (*p++ && m != fmode + sizeof(fmode));
149
if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
151
if (s->mode == 'w') {
153
err = Z_STREAM_ERROR;
155
err = deflateInit2(&(s->stream), level,
156
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
157
/* windowBits is passed < 0 to suppress zlib header */
159
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
161
if (err != Z_OK || s->outbuf == Z_NULL) {
162
return destroy(s), (gzFile)Z_NULL;
165
s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
167
err = inflateInit2(&(s->stream), -MAX_WBITS);
168
/* windowBits is passed < 0 to tell that there is no zlib header.
169
* Note that in this case inflate *requires* an extra "dummy" byte
170
* after the compressed stream in order to complete decompression and
171
* return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
172
* present after the compressed stream.
174
if (err != Z_OK || s->inbuf == Z_NULL) {
175
return destroy(s), (gzFile)Z_NULL;
178
s->stream.avail_out = Z_BUFSIZE;
181
s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
183
if (s->file == NULL) {
184
return destroy(s), (gzFile)Z_NULL;
186
if (s->mode == 'w') {
187
/* Write a very simple .gz header:
189
fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
190
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
192
/* We use 10L instead of ftell(s->file) to because ftell causes an
193
* fflush on some systems. This version of the library doesn't use
194
* start anyway in write mode, so this initialization is not
198
check_header(s); /* skip the .gz header */
199
s->start = ftell(s->file) - s->stream.avail_in;
205
/* ===========================================================================
206
Opens a gzip (.gz) file for reading or writing.
208
gzFile ZEXPORT gzopen (path, mode)
212
return gz_open (path, mode, -1);
215
/* ===========================================================================
216
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
217
to mimic the behavio(u)r of fdopen.
219
gzFile ZEXPORT gzdopen (fd, mode)
225
if (fd < 0) return (gzFile)Z_NULL;
226
sprintf(name, "<fd:%d>", fd); /* for debugging */
228
return gz_open (name, mode, fd);
231
/* ===========================================================================
232
* Update the compression level and strategy
234
int ZEXPORT gzsetparams (file, level, strategy)
239
gz_stream *s = (gz_stream*)file;
241
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
243
/* Make room to allow flushing */
244
if (s->stream.avail_out == 0) {
246
s->stream.next_out = s->outbuf;
247
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
250
s->stream.avail_out = Z_BUFSIZE;
253
return deflateParams (&(s->stream), level, strategy);
256
/* ===========================================================================
257
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
259
IN assertion: the stream s has been sucessfully opened for reading.
261
local int get_byte(s)
264
if (s->z_eof) return EOF;
265
if (s->stream.avail_in == 0) {
267
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
268
if (s->stream.avail_in == 0) {
270
if (ferror(s->file)) s->z_err = Z_ERRNO;
273
s->stream.next_in = s->inbuf;
275
s->stream.avail_in--;
276
return *(s->stream.next_in)++;
279
/* ===========================================================================
280
Check the gzip header of a gz_stream opened for reading. Set the stream
281
mode to transparent if the gzip magic header is not present; set s->err
282
to Z_DATA_ERROR if the magic header is present but the rest of the header
284
IN assertion: the stream s has already been created sucessfully;
285
s->stream.avail_in is zero for the first time, but may be non-zero
286
for concatenated .gz files.
288
local void check_header(s)
291
int method; /* method byte */
292
int flags; /* flags byte */
296
/* Assure two bytes in the buffer so we can peek ahead -- handle case
297
where first byte of header is at the end of the buffer after the last
299
len = s->stream.avail_in;
301
if (len) s->inbuf[0] = s->stream.next_in[0];
303
len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
304
if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
305
s->stream.avail_in += len;
306
s->stream.next_in = s->inbuf;
307
if (s->stream.avail_in < 2) {
308
s->transparent = s->stream.avail_in;
313
/* Peek ahead to check the gzip magic header */
314
if (s->stream.next_in[0] != gz_magic[0] ||
315
s->stream.next_in[1] != gz_magic[1]) {
319
s->stream.avail_in -= 2;
320
s->stream.next_in += 2;
322
/* Check the rest of the gzip header */
323
method = get_byte(s);
325
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
326
s->z_err = Z_DATA_ERROR;
330
/* Discard time, xflags and OS code: */
331
for (len = 0; len < 6; len++) (void)get_byte(s);
333
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
334
len = (uInt)get_byte(s);
335
len += ((uInt)get_byte(s))<<8;
336
/* len is garbage if EOF but the loop below will quit anyway */
337
while (len-- != 0 && get_byte(s) != EOF) ;
339
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
340
while ((c = get_byte(s)) != 0 && c != EOF) ;
342
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
343
while ((c = get_byte(s)) != 0 && c != EOF) ;
345
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
346
for (len = 0; len < 2; len++) (void)get_byte(s);
348
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
351
/* ===========================================================================
352
* Cleanup then free the given gz_stream. Return a zlib error code.
353
Try freeing in the reverse order of allocations.
355
local int destroy (s)
360
if (!s) return Z_STREAM_ERROR;
364
if (s->stream.state != NULL) {
365
if (s->mode == 'w') {
367
err = Z_STREAM_ERROR;
369
err = deflateEnd(&(s->stream));
371
} else if (s->mode == 'r') {
372
err = inflateEnd(&(s->stream));
375
if (s->file != NULL && fclose(s->file)) {
377
if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
381
if (s->z_err < 0) err = s->z_err;
390
/* ===========================================================================
391
Reads the given number of uncompressed bytes from the compressed file.
392
gzread returns the number of bytes actually read (0 for end of file).
394
int ZEXPORT gzread (file, buf, len)
399
gz_stream *s = (gz_stream*)file;
400
Bytef *start = (Bytef*)buf; /* starting point for crc computation */
401
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
403
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
405
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
406
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
408
next_out = (Byte*)buf;
409
s->stream.next_out = (Bytef*)buf;
410
s->stream.avail_out = len;
412
if (s->stream.avail_out && s->back != EOF) {
413
*next_out++ = s->back;
414
s->stream.next_out++;
415
s->stream.avail_out--;
419
s->z_err = Z_STREAM_END;
424
while (s->stream.avail_out != 0) {
426
if (s->transparent) {
427
/* Copy first the lookahead bytes: */
428
uInt n = s->stream.avail_in;
429
if (n > s->stream.avail_out) n = s->stream.avail_out;
431
zmemcpy(s->stream.next_out, s->stream.next_in, n);
433
s->stream.next_out = next_out;
434
s->stream.next_in += n;
435
s->stream.avail_out -= n;
436
s->stream.avail_in -= n;
438
if (s->stream.avail_out > 0) {
439
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
442
len -= s->stream.avail_out;
445
if (len == 0) s->z_eof = 1;
448
if (s->stream.avail_in == 0 && !s->z_eof) {
451
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
452
if (s->stream.avail_in == 0) {
454
if (ferror(s->file)) {
459
s->stream.next_in = s->inbuf;
461
s->in += s->stream.avail_in;
462
s->out += s->stream.avail_out;
463
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
464
s->in -= s->stream.avail_in;
465
s->out -= s->stream.avail_out;
467
if (s->z_err == Z_STREAM_END) {
468
/* Check CRC and original size */
469
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
470
start = s->stream.next_out;
472
if (getLong(s) != s->crc) {
473
s->z_err = Z_DATA_ERROR;
476
/* The uncompressed length returned by above getlong() may be
477
* different from s->out in case of concatenated .gz files.
478
* Check for such files:
481
if (s->z_err == Z_OK) {
482
inflateReset(&(s->stream));
483
s->crc = crc32(0L, Z_NULL, 0);
487
if (s->z_err != Z_OK || s->z_eof) break;
489
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
491
return (int)(len - s->stream.avail_out);
495
/* ===========================================================================
496
Reads one byte from the compressed file. gzgetc returns this byte
497
or -1 in case of end of file or error.
499
int ZEXPORT gzgetc(file)
504
return gzread(file, &c, 1) == 1 ? c : -1;
508
/* ===========================================================================
509
Push one byte back onto the stream.
511
int ZEXPORT gzungetc(c, file)
515
gz_stream *s = (gz_stream*)file;
517
if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
520
s->last = (s->z_err == Z_STREAM_END);
521
if (s->last) s->z_err = Z_OK;
527
/* ===========================================================================
528
Reads bytes from the compressed file until len-1 characters are
529
read, or a newline character is read and transferred to buf, or an
530
end-of-file condition is encountered. The string is then terminated
531
with a null character.
532
gzgets returns buf, or Z_NULL in case of error.
534
The current implementation is not optimized at all.
536
char * ZEXPORT gzgets(file, buf, len)
542
if (buf == Z_NULL || len <= 0) return Z_NULL;
544
while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
546
return b == buf && len > 0 ? Z_NULL : b;
550
#ifndef NO_GZCOMPRESS
551
/* ===========================================================================
552
Writes the given number of uncompressed bytes into the compressed file.
553
gzwrite returns the number of bytes actually written (0 in case of error).
555
int ZEXPORT gzwrite (file, buf, len)
560
gz_stream *s = (gz_stream*)file;
562
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
564
s->stream.next_in = (Bytef*)buf;
565
s->stream.avail_in = len;
567
while (s->stream.avail_in != 0) {
569
if (s->stream.avail_out == 0) {
571
s->stream.next_out = s->outbuf;
572
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
576
s->stream.avail_out = Z_BUFSIZE;
578
s->in += s->stream.avail_in;
579
s->out += s->stream.avail_out;
580
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
581
s->in -= s->stream.avail_in;
582
s->out -= s->stream.avail_out;
583
if (s->z_err != Z_OK) break;
585
s->crc = crc32(s->crc, (const Bytef *)buf, len);
587
return (int)(len - s->stream.avail_in);
591
/* ===========================================================================
592
Converts, formats, and writes the args to the compressed file under
593
control of the format string, as in fprintf. gzprintf returns the number of
594
uncompressed bytes actually written (0 in case of error).
599
int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
601
char buf[Z_PRINTF_BUFSIZE];
605
buf[sizeof(buf) - 1] = 0;
606
va_start(va, format);
608
# ifdef HAS_vsprintf_void
609
(void)vsprintf(buf, format, va);
611
for (len = 0; len < sizeof(buf); len++)
612
if (buf[len] == 0) break;
614
len = vsprintf(buf, format, va);
618
# ifdef HAS_vsnprintf_void
619
(void)vsnprintf(buf, sizeof(buf), format, va);
623
len = vsnprintf(buf, sizeof(buf), format, va);
627
if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
629
return gzwrite(file, buf, (unsigned)len);
631
#else /* not ANSI C */
633
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
634
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
637
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
638
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
640
char buf[Z_PRINTF_BUFSIZE];
643
buf[sizeof(buf) - 1] = 0;
645
# ifdef HAS_sprintf_void
646
sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
647
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
648
for (len = 0; len < sizeof(buf); len++)
649
if (buf[len] == 0) break;
651
len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
652
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
655
# ifdef HAS_snprintf_void
656
snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
657
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
660
len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
661
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
664
if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
666
return gzwrite(file, buf, len);
670
/* ===========================================================================
671
Writes c, converted to an unsigned char, into the compressed file.
672
gzputc returns the value that was written, or -1 in case of error.
674
int ZEXPORT gzputc(file, c)
678
unsigned char cc = (unsigned char) c; /* required for big endian systems */
680
return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
684
/* ===========================================================================
685
Writes the given null-terminated string to the compressed file, excluding
686
the terminating null character.
687
gzputs returns the number of characters written, or -1 in case of error.
689
int ZEXPORT gzputs(file, s)
693
return gzwrite(file, (char*)s, (unsigned)strlen(s));
697
/* ===========================================================================
698
Flushes all pending output into the compressed file. The parameter
699
flush is as in the deflate() function.
701
local int do_flush (file, flush)
707
gz_stream *s = (gz_stream*)file;
709
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
711
s->stream.avail_in = 0; /* should be zero already anyway */
714
len = Z_BUFSIZE - s->stream.avail_out;
717
if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
721
s->stream.next_out = s->outbuf;
722
s->stream.avail_out = Z_BUFSIZE;
725
s->out += s->stream.avail_out;
726
s->z_err = deflate(&(s->stream), flush);
727
s->out -= s->stream.avail_out;
729
/* Ignore the second of two consecutive flushes: */
730
if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
732
/* deflate has finished flushing only when it hasn't used up
733
* all the available space in the output buffer:
735
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
737
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
739
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
742
int ZEXPORT gzflush (file, flush)
746
gz_stream *s = (gz_stream*)file;
747
int err = do_flush (file, flush);
751
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
753
#endif /* NO_GZCOMPRESS */
755
/* ===========================================================================
756
Sets the starting position for the next gzread or gzwrite on the given
757
compressed file. The offset represents a number of bytes in the
758
gzseek returns the resulting offset location as measured in bytes from
759
the beginning of the uncompressed stream, or -1 in case of error.
760
SEEK_END is not implemented, returns error.
761
In this version of the library, gzseek can be extremely slow.
763
z_off_t ZEXPORT gzseek (file, offset, whence)
768
gz_stream *s = (gz_stream*)file;
770
if (s == NULL || whence == SEEK_END ||
771
s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
775
if (s->mode == 'w') {
779
if (whence == SEEK_SET) {
782
if (offset < 0) return -1L;
784
/* At this point, offset is the number of zero bytes to write. */
785
if (s->inbuf == Z_NULL) {
786
s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
787
if (s->inbuf == Z_NULL) return -1L;
788
zmemzero(s->inbuf, Z_BUFSIZE);
791
uInt size = Z_BUFSIZE;
792
if (offset < Z_BUFSIZE) size = (uInt)offset;
794
size = gzwrite(file, s->inbuf, size);
795
if (size == 0) return -1L;
802
/* Rest of function is for reading only */
804
/* compute absolute position */
805
if (whence == SEEK_CUR) {
808
if (offset < 0) return -1L;
810
if (s->transparent) {
813
s->stream.avail_in = 0;
814
s->stream.next_in = s->inbuf;
815
if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
817
s->in = s->out = offset;
821
/* For a negative seek, rewind and use positive seek */
822
if (offset >= s->out) {
824
} else if (gzrewind(file) < 0) {
827
/* offset is now the number of bytes to skip. */
829
if (offset != 0 && s->outbuf == Z_NULL) {
830
s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
831
if (s->outbuf == Z_NULL) return -1L;
833
if (offset && s->back != EOF) {
837
if (s->last) s->z_err = Z_STREAM_END;
840
int size = Z_BUFSIZE;
841
if (offset < Z_BUFSIZE) size = (int)offset;
843
size = gzread(file, s->outbuf, (uInt)size);
844
if (size <= 0) return -1L;
850
/* ===========================================================================
853
int ZEXPORT gzrewind (file)
856
gz_stream *s = (gz_stream*)file;
858
if (s == NULL || s->mode != 'r') return -1;
863
s->stream.avail_in = 0;
864
s->stream.next_in = s->inbuf;
865
s->crc = crc32(0L, Z_NULL, 0);
866
if (!s->transparent) (void)inflateReset(&s->stream);
869
return fseek(s->file, s->start, SEEK_SET);
872
/* ===========================================================================
873
Returns the starting position for the next gzread or gzwrite on the
874
given compressed file. This position represents a number of bytes in the
875
uncompressed data stream.
877
z_off_t ZEXPORT gztell (file)
880
return gzseek(file, 0L, SEEK_CUR);
883
/* ===========================================================================
884
Returns 1 when EOF has previously been detected reading the given
885
input stream, otherwise zero.
887
int ZEXPORT gzeof (file)
890
gz_stream *s = (gz_stream*)file;
892
/* With concatenated compressed files that can have embedded
893
* crc trailers, z_eof is no longer the only/best indicator of EOF
894
* on a gz_stream. Handle end-of-stream error explicitly here.
896
if (s == NULL || s->mode != 'r') return 0;
897
if (s->z_eof) return 1;
898
return s->z_err == Z_STREAM_END;
901
/* ===========================================================================
902
Outputs a long in LSB order to the given file
904
local void putLong (file, x)
909
for (n = 0; n < 4; n++) {
910
fputc((int)(x & 0xff), file);
915
/* ===========================================================================
916
Reads a long in LSB order from the given gz_stream. Sets z_err in case
919
local uLong getLong (s)
922
uLong x = (uLong)get_byte(s);
925
x += ((uLong)get_byte(s))<<8;
926
x += ((uLong)get_byte(s))<<16;
928
if (c == EOF) s->z_err = Z_DATA_ERROR;
933
/* ===========================================================================
934
Flushes all pending output if necessary, closes the compressed file
935
and deallocates all the (de)compression state.
937
int ZEXPORT gzclose (file)
941
gz_stream *s = (gz_stream*)file;
943
if (s == NULL) return Z_STREAM_ERROR;
945
if (s->mode == 'w') {
947
return Z_STREAM_ERROR;
949
err = do_flush (file, Z_FINISH);
950
if (err != Z_OK) return destroy((gz_stream*)file);
952
putLong (s->file, s->crc);
953
putLong (s->file, (uLong)(s->in & 0xffffffff));
956
return destroy((gz_stream*)file);
959
/* ===========================================================================
960
Returns the error message for the last error which occured on the
961
given compressed file. errnum is set to zlib error number. If an
962
error occured in the file system and not in the compression library,
963
errnum is set to Z_ERRNO and the application may consult errno
964
to get the exact error code.
966
const char * ZEXPORT gzerror (file, errnum)
971
gz_stream *s = (gz_stream*)file;
974
*errnum = Z_STREAM_ERROR;
975
return (const char*)ERR_MSG(Z_STREAM_ERROR);
978
if (*errnum == Z_OK) return (const char*)"";
980
m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
982
if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
985
s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
986
if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
987
strcpy(s->msg, s->path);
988
strcat(s->msg, ": ");
990
return (const char*)s->msg;
993
/* ===========================================================================
994
Clear the error and end-of-file flags, and do the same for the real file.
996
void ZEXPORT gzclearerr (file)
999
gz_stream *s = (gz_stream*)file;
1001
if (s == NULL) return;
1002
if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;