aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2025-02-21 14:22:16 -0800
committerMark Adler <madler@alumni.caltech.edu>2025-02-25 00:31:37 -0800
commita4e4521ee1303b756a8f96c18cdf4729327b687d (patch)
tree6f2e178d078a420fe9731976944874cbaf10f438
parentaa27ba467717707881e4ae925849e6229ceabf38 (diff)
downloadzlib-a4e4521ee1303b756a8f96c18cdf4729327b687d.tar.gz
zlib-a4e4521ee1303b756a8f96c18cdf4729327b687d.tar.bz2
zlib-a4e4521ee1303b756a8f96c18cdf4729327b687d.zip
Have gz_skip() update how far it got for later continuation.
This also simplifies seek processing in general.
-rw-r--r--gzguts.h1
-rw-r--r--gzlib.c18
-rw-r--r--gzread.c36
-rw-r--r--gzwrite.c67
4 files changed, 46 insertions, 76 deletions
diff --git a/gzguts.h b/gzguts.h
index 71dea74..69c77eb 100644
--- a/gzguts.h
+++ b/gzguts.h
@@ -193,7 +193,6 @@ typedef struct {
193 int reset; /* true if a reset is pending after a Z_FINISH */ 193 int reset; /* true if a reset is pending after a Z_FINISH */
194 /* seek request */ 194 /* seek request */
195 z_off64_t skip; /* amount to skip (already rewound if backwards) */ 195 z_off64_t skip; /* amount to skip (already rewound if backwards) */
196 int seek; /* true if seek request pending */
197 /* error information */ 196 /* error information */
198 int err; /* error code */ 197 int err; /* error code */
199 char *msg; /* error message */ 198 char *msg; /* error message */
diff --git a/gzlib.c b/gzlib.c
index baa3e79..2f9cdd4 100644
--- a/gzlib.c
+++ b/gzlib.c
@@ -75,7 +75,7 @@ local void gz_reset(gz_statep state) {
75 } 75 }
76 else /* for writing ... */ 76 else /* for writing ... */
77 state->reset = 0; /* no deflateReset pending */ 77 state->reset = 0; /* no deflateReset pending */
78 state->seek = 0; /* no seek request pending */ 78 state->skip = 0; /* no seek request pending */
79 gz_error(state, Z_OK, NULL); /* clear error */ 79 gz_error(state, Z_OK, NULL); /* clear error */
80 state->x.pos = 0; /* no uncompressed data yet */ 80 state->x.pos = 0; /* no uncompressed data yet */
81 state->strm.avail_in = 0; /* no input data yet */ 81 state->strm.avail_in = 0; /* no input data yet */
@@ -362,9 +362,10 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
362 /* normalize offset to a SEEK_CUR specification */ 362 /* normalize offset to a SEEK_CUR specification */
363 if (whence == SEEK_SET) 363 if (whence == SEEK_SET)
364 offset -= state->x.pos; 364 offset -= state->x.pos;
365 else if (state->seek) 365 else {
366 offset += state->skip; 366 offset += state->past ? 0 : state->skip;
367 state->seek = 0; 367 state->skip = 0;
368 }
368 369
369 /* if within raw area while reading, just go there */ 370 /* if within raw area while reading, just go there */
370 if (state->mode == GZ_READ && state->how == COPY && 371 if (state->mode == GZ_READ && state->how == COPY &&
@@ -375,7 +376,7 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
375 state->x.have = 0; 376 state->x.have = 0;
376 state->eof = 0; 377 state->eof = 0;
377 state->past = 0; 378 state->past = 0;
378 state->seek = 0; 379 state->skip = 0;
379 gz_error(state, Z_OK, NULL); 380 gz_error(state, Z_OK, NULL);
380 state->strm.avail_in = 0; 381 state->strm.avail_in = 0;
381 state->x.pos += offset; 382 state->x.pos += offset;
@@ -404,10 +405,7 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
404 } 405 }
405 406
406 /* request skip (if not zero) */ 407 /* request skip (if not zero) */
407 if (offset) { 408 state->skip = offset;
408 state->seek = 1;
409 state->skip = offset;
410 }
411 return state->x.pos + offset; 409 return state->x.pos + offset;
412} 410}
413 411
@@ -431,7 +429,7 @@ z_off64_t ZEXPORT gztell64(gzFile file) {
431 return -1; 429 return -1;
432 430
433 /* return position */ 431 /* return position */
434 return state->x.pos + (state->seek ? state->skip : 0); 432 return state->x.pos + (state->past ? 0 : state->skip);
435} 433}
436 434
437/* -- see zlib.h -- */ 435/* -- see zlib.h -- */
diff --git a/gzread.c b/gzread.c
index d2ab6b1..5edecbf 100644
--- a/gzread.c
+++ b/gzread.c
@@ -234,20 +234,22 @@ local int gz_fetch(gz_statep state) {
234 return 0; 234 return 0;
235} 235}
236 236
237/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ 237/* Skip state->skip (> 0) uncompressed bytes of output. Return -1 on error, 0
238local int gz_skip(gz_statep state, z_off64_t len) { 238 on success. */
239local int gz_skip(gz_statep state) {
239 unsigned n; 240 unsigned n;
240 241
241 /* skip over len bytes or reach end-of-file, whichever comes first */ 242 /* skip over len bytes or reach end-of-file, whichever comes first */
242 while (len) 243 do {
243 /* skip over whatever is in output buffer */ 244 /* skip over whatever is in output buffer */
244 if (state->x.have) { 245 if (state->x.have) {
245 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? 246 n = GT_OFF(state->x.have) ||
246 (unsigned)len : state->x.have; 247 (z_off64_t)state->x.have > state->skip ?
248 (unsigned)state->skip : state->x.have;
247 state->x.have -= n; 249 state->x.have -= n;
248 state->x.next += n; 250 state->x.next += n;
249 state->x.pos += n; 251 state->x.pos += n;
250 len -= n; 252 state->skip -= n;
251 } 253 }
252 254
253 /* output buffer empty -- return if we're at the end of the input */ 255 /* output buffer empty -- return if we're at the end of the input */
@@ -260,6 +262,7 @@ local int gz_skip(gz_statep state, z_off64_t len) {
260 if (gz_fetch(state) == -1) 262 if (gz_fetch(state) == -1)
261 return -1; 263 return -1;
262 } 264 }
265 } while (state->skip);
263 return 0; 266 return 0;
264} 267}
265 268
@@ -276,11 +279,8 @@ local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
276 return 0; 279 return 0;
277 280
278 /* process a skip request */ 281 /* process a skip request */
279 if (state->seek) { 282 if (state->skip && gz_skip(state) == -1)
280 state->seek = 0; 283 return 0;
281 if (gz_skip(state, state->skip) == -1)
282 return 0;
283 }
284 284
285 /* get len bytes to buf, or less than len if at the end */ 285 /* get len bytes to buf, or less than len if at the end */
286 got = 0; 286 got = 0;
@@ -456,11 +456,8 @@ int ZEXPORT gzungetc(int c, gzFile file) {
456 return -1; 456 return -1;
457 457
458 /* process a skip request */ 458 /* process a skip request */
459 if (state->seek) { 459 if (state->skip && gz_skip(state) == -1)
460 state->seek = 0; 460 return -1;
461 if (gz_skip(state, state->skip) == -1)
462 return -1;
463 }
464 461
465 /* can't push EOF */ 462 /* can't push EOF */
466 if (c < 0) 463 if (c < 0)
@@ -516,11 +513,8 @@ char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
516 return NULL; 513 return NULL;
517 514
518 /* process a skip request */ 515 /* process a skip request */
519 if (state->seek) { 516 if (state->skip && gz_skip(state) == -1)
520 state->seek = 0; 517 return NULL;
521 if (gz_skip(state, state->skip) == -1)
522 return NULL;
523 }
524 518
525 /* copy output bytes up to new line or len - 1, whichever comes first -- 519 /* copy output bytes up to new line or len - 1, whichever comes first --
526 append a terminating zero to the string (we don't check for a zero in 520 append a terminating zero to the string (we don't check for a zero in
diff --git a/gzwrite.c b/gzwrite.c
index 435b462..ef9ffee 100644
--- a/gzwrite.c
+++ b/gzwrite.c
@@ -138,9 +138,9 @@ local int gz_comp(gz_statep state, int flush) {
138 return 0; 138 return 0;
139} 139}
140 140
141/* Compress len zeros to output. Return -1 on a write error or memory 141/* Compress state->skip (> 0) zeros to output. Return -1 on a write error or
142 allocation failure by gz_comp(), or 0 on success. */ 142 memory allocation failure by gz_comp(), or 0 on success. */
143local int gz_zero(gz_statep state, z_off64_t len) { 143local int gz_zero(gz_statep state) {
144 int first; 144 int first;
145 unsigned n; 145 unsigned n;
146 z_streamp strm = &(state->strm); 146 z_streamp strm = &(state->strm);
@@ -149,11 +149,11 @@ local int gz_zero(gz_statep state, z_off64_t len) {
149 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 149 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
150 return -1; 150 return -1;
151 151
152 /* compress len zeros (len guaranteed > 0) */ 152 /* compress state->skip zeros */
153 first = 1; 153 first = 1;
154 while (len) { 154 do {
155 n = GT_OFF(state->size) || (z_off64_t)state->size > len ? 155 n = GT_OFF(state->size) || (z_off64_t)state->size > state->skip ?
156 (unsigned)len : state->size; 156 (unsigned)state->skip : state->size;
157 if (first) { 157 if (first) {
158 memset(state->in, 0, n); 158 memset(state->in, 0, n);
159 first = 0; 159 first = 0;
@@ -163,8 +163,8 @@ local int gz_zero(gz_statep state, z_off64_t len) {
163 state->x.pos += n; 163 state->x.pos += n;
164 if (gz_comp(state, Z_NO_FLUSH) == -1) 164 if (gz_comp(state, Z_NO_FLUSH) == -1)
165 return -1; 165 return -1;
166 len -= n; 166 state->skip -= n;
167 } 167 } while (state->skip);
168 return 0; 168 return 0;
169} 169}
170 170
@@ -182,11 +182,8 @@ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
182 return 0; 182 return 0;
183 183
184 /* check for seek request */ 184 /* check for seek request */
185 if (state->seek) { 185 if (state->skip && gz_zero(state) == -1)
186 state->seek = 0; 186 return 0;
187 if (gz_zero(state, state->skip) == -1)
188 return 0;
189 }
190 187
191 /* for small len, copy to input buffer, otherwise compress directly */ 188 /* for small len, copy to input buffer, otherwise compress directly */
192 if (len < state->size) { 189 if (len < state->size) {
@@ -301,11 +298,8 @@ int ZEXPORT gzputc(gzFile file, int c) {
301 return -1; 298 return -1;
302 299
303 /* check for seek request */ 300 /* check for seek request */
304 if (state->seek) { 301 if (state->skip && gz_zero(state) == -1)
305 state->seek = 0; 302 return -1;
306 if (gz_zero(state, state->skip) == -1)
307 return -1;
308 }
309 303
310 /* try writing to input buffer for speed (state->size == 0 if buffer not 304 /* try writing to input buffer for speed (state->size == 0 if buffer not
311 initialized) */ 305 initialized) */
@@ -378,11 +372,8 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
378 return state->err; 372 return state->err;
379 373
380 /* check for seek request */ 374 /* check for seek request */
381 if (state->seek) { 375 if (state->skip && gz_zero(state) == -1)
382 state->seek = 0; 376 return state->err;
383 if (gz_zero(state, state->skip) == -1)
384 return state->err;
385 }
386 377
387 /* do the printf() into the input buffer, put length in len -- the input 378 /* do the printf() into the input buffer, put length in len -- the input
388 buffer is double-sized just for this function, so there is guaranteed to 379 buffer is double-sized just for this function, so there is guaranteed to
@@ -468,11 +459,8 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
468 return state->error; 459 return state->error;
469 460
470 /* check for seek request */ 461 /* check for seek request */
471 if (state->seek) { 462 if (state->skip && gz_zero(state) == -1)
472 state->seek = 0; 463 return state->error;
473 if (gz_zero(state, state->skip) == -1)
474 return state->error;
475 }
476 464
477 /* do the printf() into the input buffer, put length in len -- the input 465 /* do the printf() into the input buffer, put length in len -- the input
478 buffer is double-sized just for this function, so there is guaranteed to 466 buffer is double-sized just for this function, so there is guaranteed to
@@ -542,11 +530,8 @@ int ZEXPORT gzflush(gzFile file, int flush) {
542 return Z_STREAM_ERROR; 530 return Z_STREAM_ERROR;
543 531
544 /* check for seek request */ 532 /* check for seek request */
545 if (state->seek) { 533 if (state->skip && gz_zero(state) == -1)
546 state->seek = 0; 534 return state->err;
547 if (gz_zero(state, state->skip) == -1)
548 return state->err;
549 }
550 535
551 /* compress remaining data with requested flush */ 536 /* compress remaining data with requested flush */
552 (void)gz_comp(state, flush); 537 (void)gz_comp(state, flush);
@@ -573,11 +558,8 @@ int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
573 return Z_OK; 558 return Z_OK;
574 559
575 /* check for seek request */ 560 /* check for seek request */
576 if (state->seek) { 561 if (state->skip && gz_zero(state) == -1)
577 state->seek = 0; 562 return state->err;
578 if (gz_zero(state, state->skip) == -1)
579 return state->err;
580 }
581 563
582 /* change compression parameters for subsequent input */ 564 /* change compression parameters for subsequent input */
583 if (state->size) { 565 if (state->size) {
@@ -606,11 +588,8 @@ int ZEXPORT gzclose_w(gzFile file) {
606 return Z_STREAM_ERROR; 588 return Z_STREAM_ERROR;
607 589
608 /* check for seek request */ 590 /* check for seek request */
609 if (state->seek) { 591 if (state->skip && gz_zero(state) == -1)
610 state->seek = 0; 592 ret = state->err;
611 if (gz_zero(state, state->skip) == -1)
612 ret = state->err;
613 }
614 593
615 /* flush, free memory, and close file */ 594 /* flush, free memory, and close file */
616 if (gz_comp(state, Z_FINISH) == -1) 595 if (gz_comp(state, Z_FINISH) == -1)