diff options
| author | Mark Adler <madler@alumni.caltech.edu> | 2025-02-21 14:22:16 -0800 |
|---|---|---|
| committer | Mark Adler <madler@alumni.caltech.edu> | 2025-02-25 00:31:37 -0800 |
| commit | a4e4521ee1303b756a8f96c18cdf4729327b687d (patch) | |
| tree | 6f2e178d078a420fe9731976944874cbaf10f438 | |
| parent | aa27ba467717707881e4ae925849e6229ceabf38 (diff) | |
| download | zlib-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.h | 1 | ||||
| -rw-r--r-- | gzlib.c | 18 | ||||
| -rw-r--r-- | gzread.c | 36 | ||||
| -rw-r--r-- | gzwrite.c | 67 |
4 files changed, 46 insertions, 76 deletions
| @@ -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 */ |
| @@ -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 -- */ |
| @@ -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 |
| 238 | local int gz_skip(gz_statep state, z_off64_t len) { | 238 | on success. */ |
| 239 | local 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 |
| @@ -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. */ |
| 143 | local int gz_zero(gz_statep state, z_off64_t len) { | 143 | local 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) |
