summaryrefslogtreecommitdiff
path: root/gzio.c
diff options
context:
space:
mode:
Diffstat (limited to 'gzio.c')
-rw-r--r--gzio.c91
1 files changed, 50 insertions, 41 deletions
diff --git a/gzio.c b/gzio.c
index f10ade3..fc5eb50 100644
--- a/gzio.c
+++ b/gzio.c
@@ -2,7 +2,7 @@
2 * Copyright (C) 1995-2003 Jean-loup Gailly. 2 * Copyright (C) 1995-2003 Jean-loup Gailly.
3 * For conditions of distribution and use, see copyright notice in zlib.h 3 * For conditions of distribution and use, see copyright notice in zlib.h
4 * 4 *
5 * Compile this file with -DNO_DEFLATE to avoid the compression code. 5 * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
6 */ 6 */
7 7
8/* @(#) $Id$ */ 8/* @(#) $Id$ */
@@ -11,6 +11,10 @@
11 11
12#include "zutil.h" 12#include "zutil.h"
13 13
14#ifdef NO_DEFLATE /* for compatiblity with old definition */
15# define NO_GZCOMPRESS
16#endif
17
14#ifndef NO_DUMMY_DECL 18#ifndef NO_DUMMY_DECL
15struct internal_state {int dummy;}; /* for buggy compilers */ 19struct internal_state {int dummy;}; /* for buggy compilers */
16#endif 20#endif
@@ -56,7 +60,9 @@ typedef struct gz_stream {
56 char *path; /* path name for debugging only */ 60 char *path; /* path name for debugging only */
57 int transparent; /* 1 if input file is not a .gz file */ 61 int transparent; /* 1 if input file is not a .gz file */
58 char mode; /* 'w' or 'r' */ 62 char mode; /* 'w' or 'r' */
59 long startpos; /* start of compressed data in file (header skipped) */ 63 z_off_t start; /* start of compressed data in file (header skipped) */
64 z_off_t in; /* bytes into deflate or inflate */
65 z_off_t out; /* bytes out of deflate or inflate */
60 int back; /* one character push-back */ 66 int back; /* one character push-back */
61 int last; /* true if push-back is last character */ 67 int last; /* true if push-back is last character */
62} gz_stream; 68} gz_stream;
@@ -74,7 +80,7 @@ local uLong getLong OF((gz_stream *s));
74 Opens a gzip (.gz) file for reading or writing. The mode parameter 80 Opens a gzip (.gz) file for reading or writing. The mode parameter
75 is as in fopen ("rb" or "wb"). The file is given either by file descriptor 81 is as in fopen ("rb" or "wb"). The file is given either by file descriptor
76 or path name (if fd == -1). 82 or path name (if fd == -1).
77 gz_open return NULL if the file could not be opened or if there was 83 gz_open returns NULL if the file could not be opened or if there was
78 insufficient memory to allocate the (de)compression state; errno 84 insufficient memory to allocate the (de)compression state; errno
79 can be checked to distinguish the two cases (if errno is zero, the 85 can be checked to distinguish the two cases (if errno is zero, the
80 zlib error is Z_MEM_ERROR). 86 zlib error is Z_MEM_ERROR).
@@ -106,6 +112,8 @@ local gzFile gz_open (path, mode, fd)
106 s->file = NULL; 112 s->file = NULL;
107 s->z_err = Z_OK; 113 s->z_err = Z_OK;
108 s->z_eof = 0; 114 s->z_eof = 0;
115 s->in = 0;
116 s->out = 0;
109 s->back = EOF; 117 s->back = EOF;
110 s->crc = crc32(0L, Z_NULL, 0); 118 s->crc = crc32(0L, Z_NULL, 0);
111 s->msg = NULL; 119 s->msg = NULL;
@@ -136,7 +144,7 @@ local gzFile gz_open (path, mode, fd)
136 if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; 144 if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
137 145
138 if (s->mode == 'w') { 146 if (s->mode == 'w') {
139#ifdef NO_DEFLATE 147#ifdef NO_GZCOMPRESS
140 err = Z_STREAM_ERROR; 148 err = Z_STREAM_ERROR;
141#else 149#else
142 err = deflateInit2(&(s->stream), level, 150 err = deflateInit2(&(s->stream), level,
@@ -175,15 +183,15 @@ local gzFile gz_open (path, mode, fd)
175 */ 183 */
176 fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], 184 fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
177 Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); 185 Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
178 s->startpos = 10L; 186 s->start = 10L;
179 /* We use 10L instead of ftell(s->file) to because ftell causes an 187 /* We use 10L instead of ftell(s->file) to because ftell causes an
180 * fflush on some systems. This version of the library doesn't use 188 * fflush on some systems. This version of the library doesn't use
181 * startpos anyway in write mode, so this initialization is not 189 * start anyway in write mode, so this initialization is not
182 * necessary. 190 * necessary.
183 */ 191 */
184 } else { 192 } else {
185 check_header(s); /* skip the .gz header */ 193 check_header(s); /* skip the .gz header */
186 s->startpos = (ftell(s->file) - s->stream.avail_in); 194 s->start = ftell(s->file) - s->stream.avail_in;
187 } 195 }
188 196
189 return (gzFile)s; 197 return (gzFile)s;
@@ -350,7 +358,7 @@ local int destroy (s)
350 358
351 if (s->stream.state != NULL) { 359 if (s->stream.state != NULL) {
352 if (s->mode == 'w') { 360 if (s->mode == 'w') {
353#ifdef NO_DEFLATE 361#ifdef NO_GZCOMPRESS
354 err = Z_STREAM_ERROR; 362 err = Z_STREAM_ERROR;
355#else 363#else
356 err = deflateEnd(&(s->stream)); 364 err = deflateEnd(&(s->stream));
@@ -401,7 +409,7 @@ int ZEXPORT gzread (file, buf, len)
401 s->stream.next_out++; 409 s->stream.next_out++;
402 s->stream.avail_out--; 410 s->stream.avail_out--;
403 s->back = EOF; 411 s->back = EOF;
404 s->stream.total_out++; 412 s->out++;
405 if (s->last) { 413 if (s->last) {
406 s->z_err = Z_STREAM_END; 414 s->z_err = Z_STREAM_END;
407 return 1; 415 return 1;
@@ -427,8 +435,8 @@ int ZEXPORT gzread (file, buf, len)
427 s->file); 435 s->file);
428 } 436 }
429 len -= s->stream.avail_out; 437 len -= s->stream.avail_out;
430 s->stream.total_in += (uLong)len; 438 s->in += len;
431 s->stream.total_out += (uLong)len; 439 s->out += len;
432 if (len == 0) s->z_eof = 1; 440 if (len == 0) s->z_eof = 1;
433 return (int)len; 441 return (int)len;
434 } 442 }
@@ -445,7 +453,11 @@ int ZEXPORT gzread (file, buf, len)
445 } 453 }
446 s->stream.next_in = s->inbuf; 454 s->stream.next_in = s->inbuf;
447 } 455 }
456 s->in += s->stream.avail_in;
457 s->out += s->stream.avail_out;
448 s->z_err = inflate(&(s->stream), Z_NO_FLUSH); 458 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
459 s->in -= s->stream.avail_in;
460 s->out -= s->stream.avail_out;
449 461
450 if (s->z_err == Z_STREAM_END) { 462 if (s->z_err == Z_STREAM_END) {
451 /* Check CRC and original size */ 463 /* Check CRC and original size */
@@ -456,18 +468,13 @@ int ZEXPORT gzread (file, buf, len)
456 s->z_err = Z_DATA_ERROR; 468 s->z_err = Z_DATA_ERROR;
457 } else { 469 } else {
458 (void)getLong(s); 470 (void)getLong(s);
459 /* The uncompressed length returned by above getlong() may 471 /* The uncompressed length returned by above getlong() may be
460 * be different from s->stream.total_out) in case of 472 * different from s->out in case of concatenated .gz files.
461 * concatenated .gz files. Check for such files: 473 * Check for such files:
462 */ 474 */
463 check_header(s); 475 check_header(s);
464 if (s->z_err == Z_OK) { 476 if (s->z_err == Z_OK) {
465 uLong total_in = s->stream.total_in;
466 uLong total_out = s->stream.total_out;
467
468 inflateReset(&(s->stream)); 477 inflateReset(&(s->stream));
469 s->stream.total_in = total_in;
470 s->stream.total_out = total_out;
471 s->crc = crc32(0L, Z_NULL, 0); 478 s->crc = crc32(0L, Z_NULL, 0);
472 } 479 }
473 } 480 }
@@ -504,7 +511,7 @@ int ZEXPORT gzungetc(c, file)
504 511
505 if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; 512 if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
506 s->back = c; 513 s->back = c;
507 s->stream.total_out--; 514 s->out--;
508 s->last = (s->z_err == Z_STREAM_END); 515 s->last = (s->z_err == Z_STREAM_END);
509 if (s->last) s->z_err = Z_OK; 516 if (s->last) s->z_err = Z_OK;
510 s->z_eof = 0; 517 s->z_eof = 0;
@@ -535,7 +542,7 @@ char * ZEXPORT gzgets(file, buf, len)
535} 542}
536 543
537 544
538#ifndef NO_DEFLATE 545#ifndef NO_GZCOMPRESS
539/* =========================================================================== 546/* ===========================================================================
540 Writes the given number of uncompressed bytes into the compressed file. 547 Writes the given number of uncompressed bytes into the compressed file.
541 gzwrite returns the number of bytes actually written (0 in case of error). 548 gzwrite returns the number of bytes actually written (0 in case of error).
@@ -563,7 +570,11 @@ int ZEXPORT gzwrite (file, buf, len)
563 } 570 }
564 s->stream.avail_out = Z_BUFSIZE; 571 s->stream.avail_out = Z_BUFSIZE;
565 } 572 }
573 s->in += s->stream.avail_in;
574 s->out += s->stream.avail_out;
566 s->z_err = deflate(&(s->stream), Z_NO_FLUSH); 575 s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
576 s->in -= s->stream.avail_in;
577 s->out -= s->stream.avail_out;
567 if (s->z_err != Z_OK) break; 578 if (s->z_err != Z_OK) break;
568 } 579 }
569 s->crc = crc32(s->crc, (const Bytef *)buf, len); 580 s->crc = crc32(s->crc, (const Bytef *)buf, len);
@@ -706,7 +717,9 @@ local int do_flush (file, flush)
706 s->stream.avail_out = Z_BUFSIZE; 717 s->stream.avail_out = Z_BUFSIZE;
707 } 718 }
708 if (done) break; 719 if (done) break;
720 s->out += s->stream.avail_out;
709 s->z_err = deflate(&(s->stream), flush); 721 s->z_err = deflate(&(s->stream), flush);
722 s->out -= s->stream.avail_out;
710 723
711 /* Ignore the second of two consecutive flushes: */ 724 /* Ignore the second of two consecutive flushes: */
712 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; 725 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
@@ -732,7 +745,7 @@ int ZEXPORT gzflush (file, flush)
732 fflush(s->file); 745 fflush(s->file);
733 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 746 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
734} 747}
735#endif /* NO_DEFLATE */ 748#endif /* NO_GZCOMPRESS */
736 749
737/* =========================================================================== 750/* ===========================================================================
738 Sets the starting position for the next gzread or gzwrite on the given 751 Sets the starting position for the next gzread or gzwrite on the given
@@ -755,11 +768,11 @@ z_off_t ZEXPORT gzseek (file, offset, whence)
755 } 768 }
756 769
757 if (s->mode == 'w') { 770 if (s->mode == 'w') {
758#ifdef NO_DEFLATE 771#ifdef NO_GZCOMPRESS
759 return -1L; 772 return -1L;
760#else 773#else
761 if (whence == SEEK_SET) { 774 if (whence == SEEK_SET) {
762 offset -= s->stream.total_in; 775 offset -= s->in;
763 } 776 }
764 if (offset < 0) return -1L; 777 if (offset < 0) return -1L;
765 778
@@ -778,14 +791,14 @@ z_off_t ZEXPORT gzseek (file, offset, whence)
778 791
779 offset -= size; 792 offset -= size;
780 } 793 }
781 return (z_off_t)s->stream.total_in; 794 return s->in;
782#endif 795#endif
783 } 796 }
784 /* Rest of function is for reading only */ 797 /* Rest of function is for reading only */
785 798
786 /* compute absolute position */ 799 /* compute absolute position */
787 if (whence == SEEK_CUR) { 800 if (whence == SEEK_CUR) {
788 offset += s->stream.total_out; 801 offset += s->out;
789 } 802 }
790 if (offset < 0) return -1L; 803 if (offset < 0) return -1L;
791 804
@@ -796,13 +809,13 @@ z_off_t ZEXPORT gzseek (file, offset, whence)
796 s->stream.next_in = s->inbuf; 809 s->stream.next_in = s->inbuf;
797 if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; 810 if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
798 811
799 s->stream.total_in = s->stream.total_out = (uLong)offset; 812 s->in = s->out = offset;
800 return offset; 813 return offset;
801 } 814 }
802 815
803 /* For a negative seek, rewind and use positive seek */ 816 /* For a negative seek, rewind and use positive seek */
804 if ((uLong)offset >= s->stream.total_out) { 817 if (offset >= s->out) {
805 offset -= s->stream.total_out; 818 offset -= s->out;
806 } else if (gzrewind(file) < 0) { 819 } else if (gzrewind(file) < 0) {
807 return -1L; 820 return -1L;
808 } 821 }
@@ -814,7 +827,7 @@ z_off_t ZEXPORT gzseek (file, offset, whence)
814 } 827 }
815 if (offset && s->back != EOF) { 828 if (offset && s->back != EOF) {
816 s->back = EOF; 829 s->back = EOF;
817 s->stream.total_out++; 830 s->out++;
818 offset--; 831 offset--;
819 if (s->last) s->z_err = Z_STREAM_END; 832 if (s->last) s->z_err = Z_STREAM_END;
820 } 833 }
@@ -826,7 +839,7 @@ z_off_t ZEXPORT gzseek (file, offset, whence)
826 if (size <= 0) return -1L; 839 if (size <= 0) return -1L;
827 offset -= size; 840 offset -= size;
828 } 841 }
829 return (z_off_t)s->stream.total_out; 842 return s->out;
830} 843}
831 844
832/* =========================================================================== 845/* ===========================================================================
@@ -845,14 +858,10 @@ int ZEXPORT gzrewind (file)
845 s->stream.avail_in = 0; 858 s->stream.avail_in = 0;
846 s->stream.next_in = s->inbuf; 859 s->stream.next_in = s->inbuf;
847 s->crc = crc32(0L, Z_NULL, 0); 860 s->crc = crc32(0L, Z_NULL, 0);
848 861 if (!s->transparent) (void)inflateReset(&s->stream);
849 if (s->startpos == 0) { /* not a compressed file */ 862 s->in = 0;
850 fseek(s->file, 0L, SEEK_SET); /* rewind() is not always available */ 863 s->out = 0;
851 return 0; 864 return fseek(s->file, s->start, SEEK_SET);
852 }
853
854 (void) inflateReset(&s->stream);
855 return fseek(s->file, s->startpos, SEEK_SET);
856} 865}
857 866
858/* =========================================================================== 867/* ===========================================================================
@@ -923,14 +932,14 @@ int ZEXPORT gzclose (file)
923 if (s == NULL) return Z_STREAM_ERROR; 932 if (s == NULL) return Z_STREAM_ERROR;
924 933
925 if (s->mode == 'w') { 934 if (s->mode == 'w') {
926#ifdef NO_DEFLATE 935#ifdef NO_GZCOMPRESS
927 return Z_STREAM_ERROR; 936 return Z_STREAM_ERROR;
928#else 937#else
929 err = do_flush (file, Z_FINISH); 938 err = do_flush (file, Z_FINISH);
930 if (err != Z_OK) return destroy((gz_stream*)file); 939 if (err != Z_OK) return destroy((gz_stream*)file);
931 940
932 putLong (s->file, s->crc); 941 putLong (s->file, s->crc);
933 putLong (s->file, s->stream.total_in); 942 putLong (s->file, (uLong)(s->in & 0xffffffff));
934#endif 943#endif
935 } 944 }
936 return destroy((gz_stream*)file); 945 return destroy((gz_stream*)file);