aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2011-10-02 13:24:43 -0700
committerMark Adler <madler@alumni.caltech.edu>2011-10-02 13:34:29 -0700
commit26a99cd8957db86bdc75d9d1ebf00146cb20c87c (patch)
tree2f65d57da589c9e5475902fdf08a4aa8c4294bda
parent3c9d261809bfafc4350147ade7b74022dd144d32 (diff)
downloadzlib-26a99cd8957db86bdc75d9d1ebf00146cb20c87c.tar.gz
zlib-26a99cd8957db86bdc75d9d1ebf00146cb20c87c.tar.bz2
zlib-26a99cd8957db86bdc75d9d1ebf00146cb20c87c.zip
Add a transparent write mode to gzopen() when 'T' is in the mode.
-rw-r--r--gzguts.h2
-rw-r--r--gzlib.c13
-rw-r--r--gzread.c8
-rw-r--r--gzwrite.c72
-rw-r--r--zlib.h26
5 files changed, 82 insertions, 39 deletions
diff --git a/gzguts.h b/gzguts.h
index 8193451..4d71db0 100644
--- a/gzguts.h
+++ b/gzguts.h
@@ -136,11 +136,11 @@ typedef struct {
136 unsigned want; /* requested buffer size, default is GZBUFSIZE */ 136 unsigned want; /* requested buffer size, default is GZBUFSIZE */
137 unsigned char *in; /* input buffer */ 137 unsigned char *in; /* input buffer */
138 unsigned char *out; /* output buffer (double-sized when reading) */ 138 unsigned char *out; /* output buffer (double-sized when reading) */
139 int direct; /* 0 if processing gzip, 1 if transparent */
139 /* just for reading */ 140 /* just for reading */
140 int eof; /* true if end of input file reached */ 141 int eof; /* true if end of input file reached */
141 z_off64_t start; /* where the gzip data started, for rewinding */ 142 z_off64_t start; /* where the gzip data started, for rewinding */
142 int how; /* 0: get header, 1: copy, 2: decompress */ 143 int how; /* 0: get header, 1: copy, 2: decompress */
143 int direct; /* true if last read direct, false if gzip */
144 /* just for writing */ 144 /* just for writing */
145 int level; /* compression level */ 145 int level; /* compression level */
146 int strategy; /* compression strategy */ 146 int strategy; /* compression strategy */
diff --git a/gzlib.c b/gzlib.c
index 7b31d24..e53b6ab 100644
--- a/gzlib.c
+++ b/gzlib.c
@@ -79,7 +79,6 @@ local void gz_reset(state)
79 if (state->mode == GZ_READ) { /* for reading ... */ 79 if (state->mode == GZ_READ) { /* for reading ... */
80 state->eof = 0; /* not at end of file */ 80 state->eof = 0; /* not at end of file */
81 state->how = LOOK; /* look for gzip header */ 81 state->how = LOOK; /* look for gzip header */
82 state->direct = 1; /* default for empty file */
83 } 82 }
84 state->seek = 0; /* no seek request pending */ 83 state->seek = 0; /* no seek request pending */
85 gz_error(state, Z_OK, NULL); /* clear error */ 84 gz_error(state, Z_OK, NULL); /* clear error */
@@ -111,6 +110,7 @@ local gzFile gz_open(path, fd, mode)
111 state->mode = GZ_NONE; 110 state->mode = GZ_NONE;
112 state->level = Z_DEFAULT_COMPRESSION; 111 state->level = Z_DEFAULT_COMPRESSION;
113 state->strategy = Z_DEFAULT_STRATEGY; 112 state->strategy = Z_DEFAULT_STRATEGY;
113 state->direct = 0;
114 while (*mode) { 114 while (*mode) {
115 if (*mode >= '0' && *mode <= '9') 115 if (*mode >= '0' && *mode <= '9')
116 state->level = *mode - '0'; 116 state->level = *mode - '0';
@@ -143,6 +143,8 @@ local gzFile gz_open(path, fd, mode)
143 break; 143 break;
144 case 'F': 144 case 'F':
145 state->strategy = Z_FIXED; 145 state->strategy = Z_FIXED;
146 case 'T':
147 state->direct = 1;
146 default: /* could consider as an error, but just ignore */ 148 default: /* could consider as an error, but just ignore */
147 ; 149 ;
148 } 150 }
@@ -155,6 +157,15 @@ local gzFile gz_open(path, fd, mode)
155 return NULL; 157 return NULL;
156 } 158 }
157 159
160 /* can't force transparent read */
161 if (state->mode == GZ_READ) {
162 if (state->direct) {
163 free(state);
164 return NULL;
165 }
166 state->direct = 1; /* for empty file */
167 }
168
158 /* save the path name for error messages */ 169 /* save the path name for error messages */
159 state->path = malloc(strlen(path) + 1); 170 state->path = malloc(strlen(path) + 1);
160 if (state->path == NULL) { 171 if (state->path == NULL) {
diff --git a/gzread.c b/gzread.c
index 4701f9e..521e26f 100644
--- a/gzread.c
+++ b/gzread.c
@@ -535,16 +535,12 @@ int ZEXPORT gzdirect(file)
535 return 0; 535 return 0;
536 state = (gz_statep)file; 536 state = (gz_statep)file;
537 537
538 /* check that we're reading */
539 if (state->mode != GZ_READ)
540 return 0;
541
542 /* if the state is not known, but we can find out, then do so (this is 538 /* if the state is not known, but we can find out, then do so (this is
543 mainly for right after a gzopen() or gzdopen()) */ 539 mainly for right after a gzopen() or gzdopen()) */
544 if (state->how == LOOK && state->x.have == 0) 540 if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
545 (void)gz_look(state); 541 (void)gz_look(state);
546 542
547 /* return 1 if reading direct, 0 if decompressing a gzip stream */ 543 /* return 1 if transparent, 0 if processing a gzip stream */
548 return state->direct; 544 return state->direct;
549} 545}
550 546
diff --git a/gzwrite.c b/gzwrite.c
index 1d28807..6c991fe 100644
--- a/gzwrite.c
+++ b/gzwrite.c
@@ -18,44 +18,55 @@ local int gz_init(state)
18 int ret; 18 int ret;
19 z_streamp strm = &(state->strm); 19 z_streamp strm = &(state->strm);
20 20
21 /* allocate input and output buffers */ 21 /* allocate input buffer */
22 state->in = malloc(state->want); 22 state->in = malloc(state->want);
23 state->out = malloc(state->want); 23 if (state->in == NULL) {
24 if (state->in == NULL || state->out == NULL) {
25 if (state->out != NULL)
26 free(state->out);
27 if (state->in != NULL)
28 free(state->in);
29 gz_error(state, Z_MEM_ERROR, "out of memory"); 24 gz_error(state, Z_MEM_ERROR, "out of memory");
30 return -1; 25 return -1;
31 } 26 }
32 27
33 /* allocate deflate memory, set up for gzip compression */ 28 /* only need output buffer and deflate state if compressing */
34 strm->zalloc = Z_NULL; 29 if (!state->direct) {
35 strm->zfree = Z_NULL; 30 /* allocate output buffer */
36 strm->opaque = Z_NULL; 31 state->out = malloc(state->want);
37 ret = deflateInit2(strm, state->level, Z_DEFLATED, 32 if (state->out == NULL) {
38 15 + 16, 8, state->strategy); 33 free(state->in);
39 if (ret != Z_OK) { 34 gz_error(state, Z_MEM_ERROR, "out of memory");
40 free(state->in); 35 return -1;
41 gz_error(state, Z_MEM_ERROR, "out of memory"); 36 }
42 return -1; 37
38 /* allocate deflate memory, set up for gzip compression */
39 strm->zalloc = Z_NULL;
40 strm->zfree = Z_NULL;
41 strm->opaque = Z_NULL;
42 ret = deflateInit2(strm, state->level, Z_DEFLATED,
43 15 + 16, 8, state->strategy);
44 if (ret != Z_OK) {
45 free(state->out);
46 free(state->in);
47 gz_error(state, Z_MEM_ERROR, "out of memory");
48 return -1;
49 }
43 } 50 }
44 51
45 /* mark state as initialized */ 52 /* mark state as initialized */
46 state->size = state->want; 53 state->size = state->want;
47 54
48 /* initialize write buffer */ 55 /* initialize write buffer if compressing */
49 strm->avail_out = state->size; 56 if (!state->direct) {
50 strm->next_out = state->out; 57 strm->avail_out = state->size;
51 state->x.next = strm->next_out; 58 strm->next_out = state->out;
59 state->x.next = strm->next_out;
60 }
52 return 0; 61 return 0;
53} 62}
54 63
55/* Compress whatever is at avail_in and next_in and write to the output file. 64/* Compress whatever is at avail_in and next_in and write to the output file.
56 Return -1 if there is an error writing to the output file, otherwise 0. 65 Return -1 if there is an error writing to the output file, otherwise 0.
57 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, 66 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
58 then the deflate() state is reset to start a new gzip stream. */ 67 then the deflate() state is reset to start a new gzip stream. If gz->direct
68 is true, then simply write to the output file without compressing, and
69 ignore flush. */
59local int gz_comp(state, flush) 70local int gz_comp(state, flush)
60 gz_statep state; 71 gz_statep state;
61 int flush; 72 int flush;
@@ -68,6 +79,17 @@ local int gz_comp(state, flush)
68 if (state->size == 0 && gz_init(state) == -1) 79 if (state->size == 0 && gz_init(state) == -1)
69 return -1; 80 return -1;
70 81
82 /* write directly if requested */
83 if (state->direct) {
84 got = write(state->fd, strm->next_in, strm->avail_in);
85 if (got < 0 || (unsigned)got != strm->avail_in) {
86 gz_error(state, Z_ERRNO, zstrerror());
87 return -1;
88 }
89 strm->avail_in = 0;
90 return 0;
91 }
92
71 /* run deflate() on provided input until it produces no more output */ 93 /* run deflate() on provided input until it produces no more output */
72 ret = Z_OK; 94 ret = Z_OK;
73 do { 95 do {
@@ -526,8 +548,10 @@ int ZEXPORT gzclose_w(file)
526 /* flush, free memory, and close file */ 548 /* flush, free memory, and close file */
527 if (gz_comp(state, Z_FINISH) == -1) 549 if (gz_comp(state, Z_FINISH) == -1)
528 ret = state->err; 550 ret = state->err;
529 (void)deflateEnd(&(state->strm)); 551 if (!state->direct) {
530 free(state->out); 552 (void)deflateEnd(&(state->strm));
553 free(state->out);
554 }
531 free(state->in); 555 free(state->in);
532 gz_error(state, Z_OK, NULL); 556 gz_error(state, Z_OK, NULL);
533 free(state->path); 557 free(state->path);
diff --git a/zlib.h b/zlib.h
index 8050bdd..f77b596 100644
--- a/zlib.h
+++ b/zlib.h
@@ -696,7 +696,7 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
696 be larger than the value returned by deflateBound() if flush options other 696 be larger than the value returned by deflateBound() if flush options other
697 than Z_FINISH or Z_NO_FLUSH are used. 697 than Z_FINISH or Z_NO_FLUSH are used.
698*/ 698*/
699 699
700ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, 700ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
701 unsigned *pending, 701 unsigned *pending,
702 int *bits)); 702 int *bits));
@@ -706,7 +706,7 @@ ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
706 provided would be due to the available output space having being consumed. 706 provided would be due to the available output space having being consumed.
707 The number of bits of output not provided are between 0 and 7, where they 707 The number of bits of output not provided are between 0 and 7, where they
708 await more bits to join them in order to fill out a full byte. 708 await more bits to join them in order to fill out a full byte.
709 709
710 deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source 710 deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
711 stream state was inconsistent. 711 stream state was inconsistent.
712 */ 712 */
@@ -1196,10 +1196,13 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
1196 a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only 1196 a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
1197 compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' 1197 compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
1198 for fixed code compression as in "wb9F". (See the description of 1198 for fixed code compression as in "wb9F". (See the description of
1199 deflateInit2 for more information about the strategy parameter.) Also "a" 1199 deflateInit2 for more information about the strategy parameter.) 'T' will
1200 can be used instead of "w" to request that the gzip stream that will be 1200 request transparent writing or appending with no compression and not using
1201 written be appended to the file. "+" will result in an error, since reading 1201 the gzip format.
1202 and writing to the same gzip file is not supported. 1202
1203 "a" can be used instead of "w" to request that the gzip stream that will
1204 be written be appended to the file. "+" will result in an error, since
1205 reading and writing to the same gzip file is not supported.
1203 1206
1204 These functions, as well as gzip, will read and decode a sequence of gzip 1207 These functions, as well as gzip, will read and decode a sequence of gzip
1205 streams in a file. The append function of gzopen() can be used to create 1208 streams in a file. The append function of gzopen() can be used to create
@@ -1209,7 +1212,9 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
1209 will simply append a gzip stream to the existing file. 1212 will simply append a gzip stream to the existing file.
1210 1213
1211 gzopen can be used to read a file which is not in gzip format; in this 1214 gzopen can be used to read a file which is not in gzip format; in this
1212 case gzread will directly read from the file without decompression. 1215 case gzread will directly read from the file without decompression. When
1216 reading, this will be detected automatically by looking for the magic two-
1217 byte gzip header.
1213 1218
1214 gzopen returns NULL if the file could not be opened, if there was 1219 gzopen returns NULL if the file could not be opened, if there was
1215 insufficient memory to allocate the gzFile state, or if an invalid mode was 1220 insufficient memory to allocate the gzFile state, or if an invalid mode was
@@ -1440,6 +1445,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
1440 cause buffers to be allocated to allow reading the file to determine if it 1445 cause buffers to be allocated to allow reading the file to determine if it
1441 is a gzip file. Therefore if gzbuffer() is used, it should be called before 1446 is a gzip file. Therefore if gzbuffer() is used, it should be called before
1442 gzdirect(). 1447 gzdirect().
1448
1449 When writing, gzdirect() returns true (1) if transparent writing was
1450 requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
1451 gzdirect() is not needed when writing. Transparent writing must be
1452 explicitly requested, so the application already knows the answer. When
1453 linking statically, using gzdirect() will include all of the zlib code for
1454 gzip file reading and decompression, which may not be desired.)
1443*/ 1455*/
1444 1456
1445ZEXTERN int ZEXPORT gzclose OF((gzFile file)); 1457ZEXTERN int ZEXPORT gzclose OF((gzFile file));