diff options
| -rw-r--r-- | gzlib.c | 1 | ||||
| -rw-r--r-- | gzread.c | 59 | ||||
| -rw-r--r-- | zlib.h | 21 |
3 files changed, 49 insertions, 32 deletions
| @@ -104,6 +104,7 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { | |||
| 104 | return NULL; | 104 | return NULL; |
| 105 | state->size = 0; /* no buffers allocated yet */ | 105 | state->size = 0; /* no buffers allocated yet */ |
| 106 | state->want = GZBUFSIZE; /* requested buffer size */ | 106 | state->want = GZBUFSIZE; /* requested buffer size */ |
| 107 | state->err = Z_OK; /* no error yet */ | ||
| 107 | state->msg = NULL; /* no error message yet */ | 108 | state->msg = NULL; /* no error message yet */ |
| 108 | 109 | ||
| 109 | /* interpret mode */ | 110 | /* interpret mode */ |
| @@ -166,8 +166,10 @@ local int gz_decomp(gz_statep state) { | |||
| 166 | had = strm->avail_out; | 166 | had = strm->avail_out; |
| 167 | do { | 167 | do { |
| 168 | /* get more input for inflate() */ | 168 | /* get more input for inflate() */ |
| 169 | if (strm->avail_in == 0 && gz_avail(state) == -1) | 169 | if (strm->avail_in == 0 && gz_avail(state) == -1) { |
| 170 | return -1; | 170 | ret = state->err; |
| 171 | break; | ||
| 172 | } | ||
| 171 | if (strm->avail_in == 0) { | 173 | if (strm->avail_in == 0) { |
| 172 | gz_error(state, Z_BUF_ERROR, "unexpected end of file"); | 174 | gz_error(state, Z_BUF_ERROR, "unexpected end of file"); |
| 173 | break; | 175 | break; |
| @@ -181,22 +183,23 @@ local int gz_decomp(gz_statep state) { | |||
| 181 | if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { | 183 | if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { |
| 182 | gz_error(state, Z_STREAM_ERROR, | 184 | gz_error(state, Z_STREAM_ERROR, |
| 183 | "internal error: inflate stream corrupt"); | 185 | "internal error: inflate stream corrupt"); |
| 184 | return -1; | 186 | break; |
| 185 | } | 187 | } |
| 186 | if (ret == Z_MEM_ERROR) { | 188 | if (ret == Z_MEM_ERROR) { |
| 187 | gz_error(state, Z_MEM_ERROR, "out of memory"); | 189 | gz_error(state, Z_MEM_ERROR, "out of memory"); |
| 188 | return -1; | 190 | break; |
| 189 | } | 191 | } |
| 190 | if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ | 192 | if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ |
| 191 | if (state->junk == 1) { /* trailing garbage is ok */ | 193 | if (state->junk == 1) { /* trailing garbage is ok */ |
| 192 | strm->avail_in = 0; | 194 | strm->avail_in = 0; |
| 193 | state->eof = 1; | 195 | state->eof = 1; |
| 194 | state->how = LOOK; | 196 | state->how = LOOK; |
| 197 | ret = Z_OK; | ||
| 195 | break; | 198 | break; |
| 196 | } | 199 | } |
| 197 | gz_error(state, Z_DATA_ERROR, | 200 | gz_error(state, Z_DATA_ERROR, |
| 198 | strm->msg == NULL ? "compressed data error" : strm->msg); | 201 | strm->msg == NULL ? "compressed data error" : strm->msg); |
| 199 | return -1; | 202 | break; |
| 200 | } | 203 | } |
| 201 | } while (strm->avail_out && ret != Z_STREAM_END); | 204 | } while (strm->avail_out && ret != Z_STREAM_END); |
| 202 | 205 | ||
| @@ -208,10 +211,11 @@ local int gz_decomp(gz_statep state) { | |||
| 208 | if (ret == Z_STREAM_END) { | 211 | if (ret == Z_STREAM_END) { |
| 209 | state->junk = 0; | 212 | state->junk = 0; |
| 210 | state->how = LOOK; | 213 | state->how = LOOK; |
| 214 | return 0; | ||
| 211 | } | 215 | } |
| 212 | 216 | ||
| 213 | /* good decompression */ | 217 | /* return decompression status */ |
| 214 | return 0; | 218 | return ret != Z_OK ? -1 : 0; |
| 215 | } | 219 | } |
| 216 | 220 | ||
| 217 | /* Fetch data and put it in the output buffer. Assumes state->x.have is 0. | 221 | /* Fetch data and put it in the output buffer. Assumes state->x.have is 0. |
| @@ -280,12 +284,15 @@ local int gz_skip(gz_statep state) { | |||
| 280 | } | 284 | } |
| 281 | 285 | ||
| 282 | /* Read len bytes into buf from file, or less than len up to the end of the | 286 | /* Read len bytes into buf from file, or less than len up to the end of the |
| 283 | input. Return the number of bytes read. If zero is returned, either the | 287 | input. Return the number of bytes read. If zero is returned, either the end |
| 284 | end of file was reached, or there was an error. state->err must be | 288 | of file was reached, or there was an error. state->err must be consulted in |
| 285 | consulted in that case to determine which. */ | 289 | that case to determine which. If there was an error, but some uncompressed |
| 290 | bytes were read before the error, then that count is returned. The error is | ||
| 291 | still recorded, and so is deferred until the next call. */ | ||
| 286 | local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { | 292 | local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { |
| 287 | z_size_t got; | 293 | z_size_t got; |
| 288 | unsigned n; | 294 | unsigned n; |
| 295 | int err; | ||
| 289 | 296 | ||
| 290 | /* if len is zero, avoid unnecessary operations */ | 297 | /* if len is zero, avoid unnecessary operations */ |
| 291 | if (len == 0) | 298 | if (len == 0) |
| @@ -297,6 +304,7 @@ local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { | |||
| 297 | 304 | ||
| 298 | /* get len bytes to buf, or less than len if at the end */ | 305 | /* get len bytes to buf, or less than len if at the end */ |
| 299 | got = 0; | 306 | got = 0; |
| 307 | err = 0; | ||
| 300 | do { | 308 | do { |
| 301 | /* set n to the maximum amount of len that fits in an unsigned int */ | 309 | /* set n to the maximum amount of len that fits in an unsigned int */ |
| 302 | n = (unsigned)-1; | 310 | n = (unsigned)-1; |
| @@ -310,37 +318,36 @@ local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { | |||
| 310 | memcpy(buf, state->x.next, n); | 318 | memcpy(buf, state->x.next, n); |
| 311 | state->x.next += n; | 319 | state->x.next += n; |
| 312 | state->x.have -= n; | 320 | state->x.have -= n; |
| 321 | if (state->err != Z_OK) | ||
| 322 | /* caught deferred error from gz_fetch() */ | ||
| 323 | err = -1; | ||
| 313 | } | 324 | } |
| 314 | 325 | ||
| 315 | /* output buffer empty -- return if we're at the end of the input */ | 326 | /* output buffer empty -- return if we're at the end of the input */ |
| 316 | else if (state->eof && state->strm.avail_in == 0) { | 327 | else if (state->eof && state->strm.avail_in == 0) |
| 317 | state->past = 1; /* tried to read past end */ | ||
| 318 | break; | 328 | break; |
| 319 | } | ||
| 320 | 329 | ||
| 321 | /* need output data -- for small len or new stream load up our output | 330 | /* need output data -- for small len or new stream load up our output |
| 322 | buffer */ | 331 | buffer, so that gzgetc() can be fast */ |
| 323 | else if (state->how == LOOK || n < (state->size << 1)) { | 332 | else if (state->how == LOOK || n < (state->size << 1)) { |
| 324 | /* get more output, looking for header if required */ | 333 | /* get more output, looking for header if required */ |
| 325 | if (gz_fetch(state) == -1) | 334 | if (gz_fetch(state) == -1 && state->x.have == 0) |
| 326 | return 0; | 335 | /* if state->x.have != 0, error will be caught after copy */ |
| 336 | err = -1; | ||
| 327 | continue; /* no progress yet -- go back to copy above */ | 337 | continue; /* no progress yet -- go back to copy above */ |
| 328 | /* the copy above assures that we will leave with space in the | 338 | /* the copy above assures that we will leave with space in the |
| 329 | output buffer, allowing at least one gzungetc() to succeed */ | 339 | output buffer, allowing at least one gzungetc() to succeed */ |
| 330 | } | 340 | } |
| 331 | 341 | ||
| 332 | /* large len -- read directly into user buffer */ | 342 | /* large len -- read directly into user buffer */ |
| 333 | else if (state->how == COPY) { /* read directly */ | 343 | else if (state->how == COPY) /* read directly */ |
| 334 | if (gz_load(state, (unsigned char *)buf, n, &n) == -1) | 344 | err = gz_load(state, (unsigned char *)buf, n, &n); |
| 335 | return 0; | ||
| 336 | } | ||
| 337 | 345 | ||
| 338 | /* large len -- decompress directly into user buffer */ | 346 | /* large len -- decompress directly into user buffer */ |
| 339 | else { /* state->how == GZIP */ | 347 | else { /* state->how == GZIP */ |
| 340 | state->strm.avail_out = n; | 348 | state->strm.avail_out = n; |
| 341 | state->strm.next_out = (unsigned char *)buf; | 349 | state->strm.next_out = (unsigned char *)buf; |
| 342 | if (gz_decomp(state) == -1) | 350 | err = gz_decomp(state); |
| 343 | return 0; | ||
| 344 | n = state->x.have; | 351 | n = state->x.have; |
| 345 | state->x.have = 0; | 352 | state->x.have = 0; |
| 346 | } | 353 | } |
| @@ -350,7 +357,11 @@ local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { | |||
| 350 | buf = (char *)buf + n; | 357 | buf = (char *)buf + n; |
| 351 | got += n; | 358 | got += n; |
| 352 | state->x.pos += n; | 359 | state->x.pos += n; |
| 353 | } while (len); | 360 | } while (len && !err); |
| 361 | |||
| 362 | /* note read past eof */ | ||
| 363 | if (len && state->eof) | ||
| 364 | state->past = 1; | ||
| 354 | 365 | ||
| 355 | /* return number of bytes read into user buffer */ | 366 | /* return number of bytes read into user buffer */ |
| 356 | return got; | 367 | return got; |
| @@ -537,7 +548,7 @@ char * ZEXPORT gzgets(gzFile file, char *buf, int len) { | |||
| 537 | if (left) do { | 548 | if (left) do { |
| 538 | /* assure that something is in the output buffer */ | 549 | /* assure that something is in the output buffer */ |
| 539 | if (state->x.have == 0 && gz_fetch(state) == -1) | 550 | if (state->x.have == 0 && gz_fetch(state) == -1) |
| 540 | return NULL; /* error */ | 551 | break; /* error */ |
| 541 | if (state->x.have == 0) { /* end of file */ | 552 | if (state->x.have == 0) { /* end of file */ |
| 542 | state->past = 1; /* read past end */ | 553 | state->past = 1; /* read past end */ |
| 543 | break; /* return what we have */ | 554 | break; /* return what we have */ |
| @@ -1454,7 +1454,8 @@ ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); | |||
| 1454 | gzread returns the number of uncompressed bytes actually read, less than | 1454 | gzread returns the number of uncompressed bytes actually read, less than |
| 1455 | len for end of file, or -1 for error. If len is too large to fit in an int, | 1455 | len for end of file, or -1 for error. If len is too large to fit in an int, |
| 1456 | then nothing is read, -1 is returned, and the error state is set to | 1456 | then nothing is read, -1 is returned, and the error state is set to |
| 1457 | Z_STREAM_ERROR. | 1457 | Z_STREAM_ERROR. If some data was read before an error, then that data is |
| 1458 | returned until exhausted, after which the next call will signal the error. | ||
| 1458 | */ | 1459 | */ |
| 1459 | 1460 | ||
| 1460 | ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, | 1461 | ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, |
| @@ -1536,8 +1537,9 @@ ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); | |||
| 1536 | left untouched. | 1537 | left untouched. |
| 1537 | 1538 | ||
| 1538 | gzgets returns buf which is a null-terminated string, or it returns NULL | 1539 | gzgets returns buf which is a null-terminated string, or it returns NULL |
| 1539 | for end-of-file or in case of error. If there was an error, the contents at | 1540 | for end-of-file or in case of error. If some data was read before an error, |
| 1540 | buf are indeterminate. | 1541 | then that data is returned until exhausted, after which the next call will |
| 1542 | return NULL to signal the error. | ||
| 1541 | */ | 1543 | */ |
| 1542 | 1544 | ||
| 1543 | ZEXTERN int ZEXPORT gzputc(gzFile file, int c); | 1545 | ZEXTERN int ZEXPORT gzputc(gzFile file, int c); |
| @@ -1548,11 +1550,14 @@ ZEXTERN int ZEXPORT gzputc(gzFile file, int c); | |||
| 1548 | 1550 | ||
| 1549 | ZEXTERN int ZEXPORT gzgetc(gzFile file); | 1551 | ZEXTERN int ZEXPORT gzgetc(gzFile file); |
| 1550 | /* | 1552 | /* |
| 1551 | Read and decompress one byte from file. gzgetc returns this byte or -1 | 1553 | Read and decompress one byte from file. gzgetc returns this byte or -1 in |
| 1552 | in case of end of file or error. This is implemented as a macro for speed. | 1554 | case of end of file or error. If some data was read before an error, then |
| 1553 | As such, it does not do all of the checking the other functions do. I.e. | 1555 | that data is returned until exhausted, after which the next call will return |
| 1554 | it does not check to see if file is NULL, nor whether the structure file | 1556 | -1 to signal the error. |
| 1555 | points to has been clobbered or not. | 1557 | |
| 1558 | This is implemented as a macro for speed. As such, it does not do all of | ||
| 1559 | the checking the other functions do. I.e. it does not check to see if file | ||
| 1560 | is NULL, nor whether the structure file points to has been clobbered or not. | ||
| 1556 | */ | 1561 | */ |
| 1557 | 1562 | ||
| 1558 | ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); | 1563 | ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); |
