diff options
Diffstat (limited to 'gzio.c')
-rw-r--r-- | gzio.c | 91 |
1 files changed, 50 insertions, 41 deletions
@@ -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 |
15 | struct internal_state {int dummy;}; /* for buggy compilers */ | 19 | struct 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); |