1
/* gzio.c -- IO on .gz files
2
* Copyright (C) 1995-1998 Jean-loup Gailly.
3
* For conditions of distribution and use, see copyright notice in zlib.h
5
* Compile this file with -DNO_DEFLATE to avoid the compression code.
8
/* @(#) $Id: gzio.c,v 1.1.1.1 2000/11/17 14:22:46 rocco Exp $ */
14
struct internal_state {int dummy;}; /* for buggy compilers */
18
# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
20
# define Z_BUFSIZE 16384
23
#ifndef Z_PRINTF_BUFSIZE
24
# define Z_PRINTF_BUFSIZE 4096
27
#define ALLOC(size) malloc(size)
28
#define TRYFREE(p) {if (p) free(p);}
30
static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
33
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
34
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
35
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
36
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
37
#define COMMENT 0x10 /* bit 4 set: file comment present */
38
#define RESERVED 0xE0 /* bits 5..7: reserved */
40
typedef struct gz_stream {
42
int z_err; /* error code for last stream operation */
43
int z_eof; /* set if end of input file */
44
FILE *file; /* .gz file */
45
Byte *inbuf; /* input buffer */
46
Byte *outbuf; /* output buffer */
47
uLong crc; /* crc32 of uncompressed data */
48
char *msg; /* error message */
49
char *path; /* path name for debugging only */
50
int transparent; /* 1 if input file is not a .gz file */
51
char mode; /* 'w' or 'r' */
52
long startpos; /* start of compressed data in file (header skipped) */
56
local gzFile gz_open OF((const char *path, const char *mode, int fd));
57
local int do_flush OF((gzFile file, int flush));
58
local int get_byte OF((gz_stream *s));
59
local void check_header OF((gz_stream *s));
60
local int destroy OF((gz_stream *s));
61
local void putLong OF((FILE *file, uLong x));
62
local uLong getLong OF((gz_stream *s));
64
/* ===========================================================================
65
Opens a gzip (.gz) file for reading or writing. The mode parameter
66
is as in fopen ("rb" or "wb"). The file is given either by file descriptor
67
or path name (if fd == -1).
68
gz_open return NULL if the file could not be opened or if there was
69
insufficient memory to allocate the (de)compression state; errno
70
can be checked to distinguish the two cases (if errno is zero, the
71
zlib error is Z_MEM_ERROR).
73
local gzFile gz_open (path, mode, fd)
79
int level = Z_DEFAULT_COMPRESSION; /* compression level */
80
int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
81
char *p = (char*)mode;
83
char fmode[80]; /* copy of mode, without the compression level */
86
if (!path || !mode) return Z_NULL;
88
s = (gz_stream *)ALLOC(sizeof(gz_stream));
89
if (!s) return Z_NULL;
91
s->stream.zalloc = (alloc_func)0;
92
s->stream.zfree = (free_func)0;
93
s->stream.opaque = (voidpf)0;
94
s->stream.next_in = s->inbuf = Z_NULL;
95
s->stream.next_out = s->outbuf = Z_NULL;
96
s->stream.avail_in = s->stream.avail_out = 0;
100
s->crc = crc32(0L, Z_NULL, 0);
104
s->path = (char*)ALLOC(strlen(path)+1);
105
if (s->path == NULL) {
106
return destroy(s), (gzFile)Z_NULL;
108
strcpy(s->path, path); /* do this early for debugging */
112
if (*p == 'r') s->mode = 'r';
113
if (*p == 'w' || *p == 'a') s->mode = 'w';
114
if (*p >= '0' && *p <= '9') {
116
} else if (*p == 'f') {
117
strategy = Z_FILTERED;
118
} else if (*p == 'h') {
119
strategy = Z_HUFFMAN_ONLY;
121
*m++ = *p; /* copy the mode */
123
} while (*p++ && m != fmode + sizeof(fmode));
124
if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
126
if (s->mode == 'w') {
128
err = Z_STREAM_ERROR;
130
err = deflateInit2(&(s->stream), level,
131
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
132
/* windowBits is passed < 0 to suppress zlib header */
134
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
136
if (err != Z_OK || s->outbuf == Z_NULL) {
137
return destroy(s), (gzFile)Z_NULL;
140
s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
142
err = inflateInit2(&(s->stream), -MAX_WBITS);
143
/* windowBits is passed < 0 to tell that there is no zlib header.
144
* Note that in this case inflate *requires* an extra "dummy" byte
145
* after the compressed stream in order to complete decompression and
146
* return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
147
* present after the compressed stream.
149
if (err != Z_OK || s->inbuf == Z_NULL) {
150
return destroy(s), (gzFile)Z_NULL;
153
s->stream.avail_out = Z_BUFSIZE;
156
s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
158
if (s->file == NULL) {
159
return destroy(s), (gzFile)Z_NULL;
161
if (s->mode == 'w') {
162
/* Write a very simple .gz header:
164
fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
165
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
167
/* We use 10L instead of ftell(s->file) to because ftell causes an
168
* fflush on some systems. This version of the library doesn't use
169
* startpos anyway in write mode, so this initialization is not
173
check_header(s); /* skip the .gz header */
174
s->startpos = (ftell(s->file) - s->stream.avail_in);
180
/* ===========================================================================
181
Opens a gzip (.gz) file for reading or writing.
183
gzFile ZEXPORT gzopen (path, mode)
187
return gz_open (path, mode, -1);
190
/* ===========================================================================
191
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
192
to mimic the behavio(u)r of fdopen.
194
gzFile ZEXPORT gzdopen (fd, mode)
200
if (fd < 0) return (gzFile)Z_NULL;
201
sprintf(name, "<fd:%d>", fd); /* for debugging */
203
return gz_open (name, mode, fd);
206
/* ===========================================================================
207
* Update the compression level and strategy
209
int ZEXPORT gzsetparams (file, level, strategy)
214
gz_stream *s = (gz_stream*)file;
216
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
218
/* Make room to allow flushing */
219
if (s->stream.avail_out == 0) {
221
s->stream.next_out = s->outbuf;
222
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
225
s->stream.avail_out = Z_BUFSIZE;
228
return deflateParams (&(s->stream), level, strategy);
231
/* ===========================================================================
232
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
234
IN assertion: the stream s has been sucessfully opened for reading.
236
local int get_byte(s)
239
if (s->z_eof) return EOF;
240
if (s->stream.avail_in == 0) {
242
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
243
if (s->stream.avail_in == 0) {
245
if (ferror(s->file)) s->z_err = Z_ERRNO;
248
s->stream.next_in = s->inbuf;
250
s->stream.avail_in--;
251
return *(s->stream.next_in)++;
254
/* ===========================================================================
255
Check the gzip header of a gz_stream opened for reading. Set the stream
256
mode to transparent if the gzip magic header is not present; set s->err
257
to Z_DATA_ERROR if the magic header is present but the rest of the header
259
IN assertion: the stream s has already been created sucessfully;
260
s->stream.avail_in is zero for the first time, but may be non-zero
261
for concatenated .gz files.
263
local void check_header(s)
266
int method; /* method byte */
267
int flags; /* flags byte */
271
/* Check the gzip magic header */
272
for (len = 0; len < 2; len++) {
274
if (c != gz_magic[len]) {
275
if (len != 0) s->stream.avail_in++, s->stream.next_in--;
277
s->stream.avail_in++, s->stream.next_in--;
280
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
284
method = get_byte(s);
286
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
287
s->z_err = Z_DATA_ERROR;
291
/* Discard time, xflags and OS code: */
292
for (len = 0; len < 6; len++) (void)get_byte(s);
294
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
295
len = (uInt)get_byte(s);
296
len += ((uInt)get_byte(s))<<8;
297
/* len is garbage if EOF but the loop below will quit anyway */
298
while (len-- != 0 && get_byte(s) != EOF) ;
300
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
301
while ((c = get_byte(s)) != 0 && c != EOF) ;
303
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
304
while ((c = get_byte(s)) != 0 && c != EOF) ;
306
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
307
for (len = 0; len < 2; len++) (void)get_byte(s);
309
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
312
/* ===========================================================================
313
* Cleanup then free the given gz_stream. Return a zlib error code.
314
Try freeing in the reverse order of allocations.
316
local int destroy (s)
321
if (!s) return Z_STREAM_ERROR;
325
if (s->stream.state != NULL) {
326
if (s->mode == 'w') {
328
err = Z_STREAM_ERROR;
330
err = deflateEnd(&(s->stream));
332
} else if (s->mode == 'r') {
333
err = inflateEnd(&(s->stream));
336
if (s->file != NULL && fclose(s->file)) {
338
if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
342
if (s->z_err < 0) err = s->z_err;
351
/* ===========================================================================
352
Reads the given number of uncompressed bytes from the compressed file.
353
gzread returns the number of bytes actually read (0 for end of file).
355
int ZEXPORT gzread (file, buf, len)
360
gz_stream *s = (gz_stream*)file;
361
Bytef *start = (Bytef*)buf; /* starting point for crc computation */
362
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
364
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
366
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
367
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
369
next_out = (Byte*)buf;
370
s->stream.next_out = (Bytef*)buf;
371
s->stream.avail_out = len;
373
while (s->stream.avail_out != 0) {
375
if (s->transparent) {
376
/* Copy first the lookahead bytes: */
377
uInt n = s->stream.avail_in;
378
if (n > s->stream.avail_out) n = s->stream.avail_out;
380
zmemcpy(s->stream.next_out, s->stream.next_in, n);
382
s->stream.next_out = next_out;
383
s->stream.next_in += n;
384
s->stream.avail_out -= n;
385
s->stream.avail_in -= n;
387
if (s->stream.avail_out > 0) {
388
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
391
len -= s->stream.avail_out;
392
s->stream.total_in += (uLong)len;
393
s->stream.total_out += (uLong)len;
394
if (len == 0) s->z_eof = 1;
397
if (s->stream.avail_in == 0 && !s->z_eof) {
400
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
401
if (s->stream.avail_in == 0) {
403
if (ferror(s->file)) {
408
s->stream.next_in = s->inbuf;
410
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
412
if (s->z_err == Z_STREAM_END) {
413
/* Check CRC and original size */
414
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
415
start = s->stream.next_out;
417
if (getLong(s) != s->crc) {
418
s->z_err = Z_DATA_ERROR;
421
/* The uncompressed length returned by above getlong() may
422
* be different from s->stream.total_out) in case of
423
* concatenated .gz files. Check for such files:
426
if (s->z_err == Z_OK) {
427
uLong total_in = s->stream.total_in;
428
uLong total_out = s->stream.total_out;
430
inflateReset(&(s->stream));
431
s->stream.total_in = total_in;
432
s->stream.total_out = total_out;
433
s->crc = crc32(0L, Z_NULL, 0);
437
if (s->z_err != Z_OK || s->z_eof) break;
439
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
441
return (int)(len - s->stream.avail_out);
445
/* ===========================================================================
446
Reads one byte from the compressed file. gzgetc returns this byte
447
or -1 in case of end of file or error.
449
int ZEXPORT gzgetc(file)
454
return gzread(file, &c, 1) == 1 ? c : -1;
458
/* ===========================================================================
459
Reads bytes from the compressed file until len-1 characters are
460
read, or a newline character is read and transferred to buf, or an
461
end-of-file condition is encountered. The string is then terminated
462
with a null character.
463
gzgets returns buf, or Z_NULL in case of error.
465
The current implementation is not optimized at all.
467
char * ZEXPORT gzgets(file, buf, len)
473
if (buf == Z_NULL || len <= 0) return Z_NULL;
475
while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
477
return b == buf && len > 0 ? Z_NULL : b;
482
/* ===========================================================================
483
Writes the given number of uncompressed bytes into the compressed file.
484
gzwrite returns the number of bytes actually written (0 in case of error).
486
int ZEXPORT gzwrite (file, buf, len)
491
gz_stream *s = (gz_stream*)file;
493
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
495
s->stream.next_in = (Bytef*)buf;
496
s->stream.avail_in = len;
498
while (s->stream.avail_in != 0) {
500
if (s->stream.avail_out == 0) {
502
s->stream.next_out = s->outbuf;
503
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
507
s->stream.avail_out = Z_BUFSIZE;
509
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
510
if (s->z_err != Z_OK) break;
512
s->crc = crc32(s->crc, (const Bytef *)buf, len);
514
return (int)(len - s->stream.avail_in);
517
/* ===========================================================================
518
Converts, formats, and writes the args to the compressed file under
519
control of the format string, as in fprintf. gzprintf returns the number of
520
uncompressed bytes actually written (0 in case of error).
525
int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
527
char buf[Z_PRINTF_BUFSIZE];
531
va_start(va, format);
533
(void)vsnprintf(buf, sizeof(buf), format, va);
535
(void)vsprintf(buf, format, va);
538
len = strlen(buf); /* some *sprintf don't return the nb of bytes written */
539
if (len <= 0) return 0;
541
return gzwrite(file, buf, (unsigned)len);
543
#else /* not ANSI C */
545
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
546
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
549
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
550
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
552
char buf[Z_PRINTF_BUFSIZE];
556
snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
557
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
559
sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
560
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
562
len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */
563
if (len <= 0) return 0;
565
return gzwrite(file, buf, len);
569
/* ===========================================================================
570
Writes c, converted to an unsigned char, into the compressed file.
571
gzputc returns the value that was written, or -1 in case of error.
573
int ZEXPORT gzputc(file, c)
577
unsigned char cc = (unsigned char) c; /* required for big endian systems */
579
return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
583
/* ===========================================================================
584
Writes the given null-terminated string to the compressed file, excluding
585
the terminating null character.
586
gzputs returns the number of characters written, or -1 in case of error.
588
int ZEXPORT gzputs(file, s)
592
return gzwrite(file, (char*)s, (unsigned)strlen(s));
596
/* ===========================================================================
597
Flushes all pending output into the compressed file. The parameter
598
flush is as in the deflate() function.
600
local int do_flush (file, flush)
606
gz_stream *s = (gz_stream*)file;
608
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
610
s->stream.avail_in = 0; /* should be zero already anyway */
613
len = Z_BUFSIZE - s->stream.avail_out;
616
if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
620
s->stream.next_out = s->outbuf;
621
s->stream.avail_out = Z_BUFSIZE;
624
s->z_err = deflate(&(s->stream), flush);
626
/* Ignore the second of two consecutive flushes: */
627
if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
629
/* deflate has finished flushing only when it hasn't used up
630
* all the available space in the output buffer:
632
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
634
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
636
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
639
int ZEXPORT gzflush (file, flush)
643
gz_stream *s = (gz_stream*)file;
644
int err = do_flush (file, flush);
648
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
650
#endif /* NO_DEFLATE */
652
/* ===========================================================================
653
Sets the starting position for the next gzread or gzwrite on the given
654
compressed file. The offset represents a number of bytes in the
655
gzseek returns the resulting offset location as measured in bytes from
656
the beginning of the uncompressed stream, or -1 in case of error.
657
SEEK_END is not implemented, returns error.
658
In this version of the library, gzseek can be extremely slow.
660
z_off_t ZEXPORT gzseek (file, offset, whence)
665
gz_stream *s = (gz_stream*)file;
667
if (s == NULL || whence == SEEK_END ||
668
s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
672
if (s->mode == 'w') {
676
if (whence == SEEK_SET) {
677
offset -= s->stream.total_in;
679
if (offset < 0) return -1L;
681
/* At this point, offset is the number of zero bytes to write. */
682
if (s->inbuf == Z_NULL) {
683
s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
684
zmemzero(s->inbuf, Z_BUFSIZE);
687
uInt size = Z_BUFSIZE;
688
if (offset < Z_BUFSIZE) size = (uInt)offset;
690
size = gzwrite(file, s->inbuf, size);
691
if (size == 0) return -1L;
695
return (z_off_t)s->stream.total_in;
698
/* Rest of function is for reading only */
700
/* compute absolute position */
701
if (whence == SEEK_CUR) {
702
offset += s->stream.total_out;
704
if (offset < 0) return -1L;
706
if (s->transparent) {
708
s->stream.avail_in = 0;
709
s->stream.next_in = s->inbuf;
710
if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
712
s->stream.total_in = s->stream.total_out = (uLong)offset;
716
/* For a negative seek, rewind and use positive seek */
717
if ((uLong)offset >= s->stream.total_out) {
718
offset -= s->stream.total_out;
719
} else if (gzrewind(file) < 0) {
722
/* offset is now the number of bytes to skip. */
724
if (offset != 0 && s->outbuf == Z_NULL) {
725
s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
728
int size = Z_BUFSIZE;
729
if (offset < Z_BUFSIZE) size = (int)offset;
731
size = gzread(file, s->outbuf, (uInt)size);
732
if (size <= 0) return -1L;
735
return (z_off_t)s->stream.total_out;
738
/* ===========================================================================
741
int ZEXPORT gzrewind (file)
744
gz_stream *s = (gz_stream*)file;
746
if (s == NULL || s->mode != 'r') return -1;
750
s->stream.avail_in = 0;
751
s->stream.next_in = s->inbuf;
752
s->crc = crc32(0L, Z_NULL, 0);
754
if (s->startpos == 0) { /* not a compressed file */
759
(void) inflateReset(&s->stream);
760
return fseek(s->file, s->startpos, SEEK_SET);
763
/* ===========================================================================
764
Returns the starting position for the next gzread or gzwrite on the
765
given compressed file. This position represents a number of bytes in the
766
uncompressed data stream.
768
z_off_t ZEXPORT gztell (file)
771
return gzseek(file, 0L, SEEK_CUR);
774
/* ===========================================================================
775
Returns 1 when EOF has previously been detected reading the given
776
input stream, otherwise zero.
778
int ZEXPORT gzeof (file)
781
gz_stream *s = (gz_stream*)file;
783
return (s == NULL || s->mode != 'r') ? 0 : s->z_eof;
786
/* ===========================================================================
787
Outputs a long in LSB order to the given file
789
local void putLong (file, x)
794
for (n = 0; n < 4; n++) {
795
fputc((int)(x & 0xff), file);
800
/* ===========================================================================
801
Reads a long in LSB order from the given gz_stream. Sets z_err in case
804
local uLong getLong (s)
807
uLong x = (uLong)get_byte(s);
810
x += ((uLong)get_byte(s))<<8;
811
x += ((uLong)get_byte(s))<<16;
813
if (c == EOF) s->z_err = Z_DATA_ERROR;
818
/* ===========================================================================
819
Flushes all pending output if necessary, closes the compressed file
820
and deallocates all the (de)compression state.
822
int ZEXPORT gzclose (file)
826
gz_stream *s = (gz_stream*)file;
828
if (s == NULL) return Z_STREAM_ERROR;
830
if (s->mode == 'w') {
832
return Z_STREAM_ERROR;
834
err = do_flush (file, Z_FINISH);
835
if (err != Z_OK) return destroy((gz_stream*)file);
837
putLong (s->file, s->crc);
838
putLong (s->file, s->stream.total_in);
841
return destroy((gz_stream*)file);
844
/* ===========================================================================
845
Returns the error message for the last error which occured on the
846
given compressed file. errnum is set to zlib error number. If an
847
error occured in the file system and not in the compression library,
848
errnum is set to Z_ERRNO and the application may consult errno
849
to get the exact error code.
851
const char* ZEXPORT gzerror (file, errnum)
856
gz_stream *s = (gz_stream*)file;
859
*errnum = Z_STREAM_ERROR;
860
return (const char*)ERR_MSG(Z_STREAM_ERROR);
863
if (*errnum == Z_OK) return (const char*)"";
865
m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
867
if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
870
s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
871
strcpy(s->msg, s->path);
872
strcat(s->msg, ": ");
874
return (const char*)s->msg;