1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/zlib/gzread.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,653 @@ 1.4 +/* gzread.c -- zlib functions for reading gzip files 1.5 + * Copyright (C) 2004, 2005, 2010 Mark Adler 1.6 + * For conditions of distribution and use, see copyright notice in zlib.h 1.7 + */ 1.8 + 1.9 +#include "gzguts.h" 1.10 + 1.11 +/* Local functions */ 1.12 +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); 1.13 +local int gz_avail OF((gz_statep)); 1.14 +local int gz_next4 OF((gz_statep, unsigned long *)); 1.15 +local int gz_head OF((gz_statep)); 1.16 +local int gz_decomp OF((gz_statep)); 1.17 +local int gz_make OF((gz_statep)); 1.18 +local int gz_skip OF((gz_statep, z_off64_t)); 1.19 + 1.20 +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from 1.21 + state->fd, and update state->eof, state->err, and state->msg as appropriate. 1.22 + This function needs to loop on read(), since read() is not guaranteed to 1.23 + read the number of bytes requested, depending on the type of descriptor. */ 1.24 +local int gz_load(state, buf, len, have) 1.25 + gz_statep state; 1.26 + unsigned char *buf; 1.27 + unsigned len; 1.28 + unsigned *have; 1.29 +{ 1.30 + int ret; 1.31 + 1.32 + *have = 0; 1.33 + do { 1.34 + ret = read(state->fd, buf + *have, len - *have); 1.35 + if (ret <= 0) 1.36 + break; 1.37 + *have += ret; 1.38 + } while (*have < len); 1.39 + if (ret < 0) { 1.40 + gz_error(state, Z_ERRNO, zstrerror()); 1.41 + return -1; 1.42 + } 1.43 + if (ret == 0) 1.44 + state->eof = 1; 1.45 + return 0; 1.46 +} 1.47 + 1.48 +/* Load up input buffer and set eof flag if last data loaded -- return -1 on 1.49 + error, 0 otherwise. Note that the eof flag is set when the end of the input 1.50 + file is reached, even though there may be unused data in the buffer. Once 1.51 + that data has been used, no more attempts will be made to read the file. 1.52 + gz_avail() assumes that strm->avail_in == 0. */ 1.53 +local int gz_avail(state) 1.54 + gz_statep state; 1.55 +{ 1.56 + z_streamp strm = &(state->strm); 1.57 + 1.58 + if (state->err != Z_OK) 1.59 + return -1; 1.60 + if (state->eof == 0) { 1.61 + if (gz_load(state, state->in, state->size, 1.62 + (unsigned *)&(strm->avail_in)) == -1) 1.63 + return -1; 1.64 + strm->next_in = state->in; 1.65 + } 1.66 + return 0; 1.67 +} 1.68 + 1.69 +/* Get next byte from input, or -1 if end or error. */ 1.70 +#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ 1.71 + (strm->avail_in == 0 ? -1 : \ 1.72 + (strm->avail_in--, *(strm->next_in)++))) 1.73 + 1.74 +/* Get a four-byte little-endian integer and return 0 on success and the value 1.75 + in *ret. Otherwise -1 is returned and *ret is not modified. */ 1.76 +local int gz_next4(state, ret) 1.77 + gz_statep state; 1.78 + unsigned long *ret; 1.79 +{ 1.80 + int ch; 1.81 + unsigned long val; 1.82 + z_streamp strm = &(state->strm); 1.83 + 1.84 + val = NEXT(); 1.85 + val += (unsigned)NEXT() << 8; 1.86 + val += (unsigned long)NEXT() << 16; 1.87 + ch = NEXT(); 1.88 + if (ch == -1) 1.89 + return -1; 1.90 + val += (unsigned long)ch << 24; 1.91 + *ret = val; 1.92 + return 0; 1.93 +} 1.94 + 1.95 +/* Look for gzip header, set up for inflate or copy. state->have must be zero. 1.96 + If this is the first time in, allocate required memory. state->how will be 1.97 + left unchanged if there is no more input data available, will be set to COPY 1.98 + if there is no gzip header and direct copying will be performed, or it will 1.99 + be set to GZIP for decompression, and the gzip header will be skipped so 1.100 + that the next available input data is the raw deflate stream. If direct 1.101 + copying, then leftover input data from the input buffer will be copied to 1.102 + the output buffer. In that case, all further file reads will be directly to 1.103 + either the output buffer or a user buffer. If decompressing, the inflate 1.104 + state and the check value will be initialized. gz_head() will return 0 on 1.105 + success or -1 on failure. Failures may include read errors or gzip header 1.106 + errors. */ 1.107 +local int gz_head(state) 1.108 + gz_statep state; 1.109 +{ 1.110 + z_streamp strm = &(state->strm); 1.111 + int flags; 1.112 + unsigned len; 1.113 + 1.114 + /* allocate read buffers and inflate memory */ 1.115 + if (state->size == 0) { 1.116 + /* allocate buffers */ 1.117 + state->in = malloc(state->want); 1.118 + state->out = malloc(state->want << 1); 1.119 + if (state->in == NULL || state->out == NULL) { 1.120 + if (state->out != NULL) 1.121 + free(state->out); 1.122 + if (state->in != NULL) 1.123 + free(state->in); 1.124 + gz_error(state, Z_MEM_ERROR, "out of memory"); 1.125 + return -1; 1.126 + } 1.127 + state->size = state->want; 1.128 + 1.129 + /* allocate inflate memory */ 1.130 + state->strm.zalloc = Z_NULL; 1.131 + state->strm.zfree = Z_NULL; 1.132 + state->strm.opaque = Z_NULL; 1.133 + state->strm.avail_in = 0; 1.134 + state->strm.next_in = Z_NULL; 1.135 + if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ 1.136 + free(state->out); 1.137 + free(state->in); 1.138 + state->size = 0; 1.139 + gz_error(state, Z_MEM_ERROR, "out of memory"); 1.140 + return -1; 1.141 + } 1.142 + } 1.143 + 1.144 + /* get some data in the input buffer */ 1.145 + if (strm->avail_in == 0) { 1.146 + if (gz_avail(state) == -1) 1.147 + return -1; 1.148 + if (strm->avail_in == 0) 1.149 + return 0; 1.150 + } 1.151 + 1.152 + /* look for the gzip magic header bytes 31 and 139 */ 1.153 + if (strm->next_in[0] == 31) { 1.154 + strm->avail_in--; 1.155 + strm->next_in++; 1.156 + if (strm->avail_in == 0 && gz_avail(state) == -1) 1.157 + return -1; 1.158 + if (strm->avail_in && strm->next_in[0] == 139) { 1.159 + /* we have a gzip header, woo hoo! */ 1.160 + strm->avail_in--; 1.161 + strm->next_in++; 1.162 + 1.163 + /* skip rest of header */ 1.164 + if (NEXT() != 8) { /* compression method */ 1.165 + gz_error(state, Z_DATA_ERROR, "unknown compression method"); 1.166 + return -1; 1.167 + } 1.168 + flags = NEXT(); 1.169 + if (flags & 0xe0) { /* reserved flag bits */ 1.170 + gz_error(state, Z_DATA_ERROR, "unknown header flags set"); 1.171 + return -1; 1.172 + } 1.173 + NEXT(); /* modification time */ 1.174 + NEXT(); 1.175 + NEXT(); 1.176 + NEXT(); 1.177 + NEXT(); /* extra flags */ 1.178 + NEXT(); /* operating system */ 1.179 + if (flags & 4) { /* extra field */ 1.180 + len = (unsigned)NEXT(); 1.181 + len += (unsigned)NEXT() << 8; 1.182 + while (len--) 1.183 + if (NEXT() < 0) 1.184 + break; 1.185 + } 1.186 + if (flags & 8) /* file name */ 1.187 + while (NEXT() > 0) 1.188 + ; 1.189 + if (flags & 16) /* comment */ 1.190 + while (NEXT() > 0) 1.191 + ; 1.192 + if (flags & 2) { /* header crc */ 1.193 + NEXT(); 1.194 + NEXT(); 1.195 + } 1.196 + /* an unexpected end of file is not checked for here -- it will be 1.197 + noticed on the first request for uncompressed data */ 1.198 + 1.199 + /* set up for decompression */ 1.200 + inflateReset(strm); 1.201 + strm->adler = crc32(0L, Z_NULL, 0); 1.202 + state->how = GZIP; 1.203 + state->direct = 0; 1.204 + return 0; 1.205 + } 1.206 + else { 1.207 + /* not a gzip file -- save first byte (31) and fall to raw i/o */ 1.208 + state->out[0] = 31; 1.209 + state->have = 1; 1.210 + } 1.211 + } 1.212 + 1.213 + /* doing raw i/o, save start of raw data for seeking, copy any leftover 1.214 + input to output -- this assumes that the output buffer is larger than 1.215 + the input buffer, which also assures space for gzungetc() */ 1.216 + state->raw = state->pos; 1.217 + state->next = state->out; 1.218 + if (strm->avail_in) { 1.219 + memcpy(state->next + state->have, strm->next_in, strm->avail_in); 1.220 + state->have += strm->avail_in; 1.221 + strm->avail_in = 0; 1.222 + } 1.223 + state->how = COPY; 1.224 + state->direct = 1; 1.225 + return 0; 1.226 +} 1.227 + 1.228 +/* Decompress from input to the provided next_out and avail_out in the state. 1.229 + If the end of the compressed data is reached, then verify the gzip trailer 1.230 + check value and length (modulo 2^32). state->have and state->next are set 1.231 + to point to the just decompressed data, and the crc is updated. If the 1.232 + trailer is verified, state->how is reset to LOOK to look for the next gzip 1.233 + stream or raw data, once state->have is depleted. Returns 0 on success, -1 1.234 + on failure. Failures may include invalid compressed data or a failed gzip 1.235 + trailer verification. */ 1.236 +local int gz_decomp(state) 1.237 + gz_statep state; 1.238 +{ 1.239 + int ret; 1.240 + unsigned had; 1.241 + unsigned long crc, len; 1.242 + z_streamp strm = &(state->strm); 1.243 + 1.244 + /* fill output buffer up to end of deflate stream */ 1.245 + had = strm->avail_out; 1.246 + do { 1.247 + /* get more input for inflate() */ 1.248 + if (strm->avail_in == 0 && gz_avail(state) == -1) 1.249 + return -1; 1.250 + if (strm->avail_in == 0) { 1.251 + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); 1.252 + return -1; 1.253 + } 1.254 + 1.255 + /* decompress and handle errors */ 1.256 + ret = inflate(strm, Z_NO_FLUSH); 1.257 + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 1.258 + gz_error(state, Z_STREAM_ERROR, 1.259 + "internal error: inflate stream corrupt"); 1.260 + return -1; 1.261 + } 1.262 + if (ret == Z_MEM_ERROR) { 1.263 + gz_error(state, Z_MEM_ERROR, "out of memory"); 1.264 + return -1; 1.265 + } 1.266 + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ 1.267 + gz_error(state, Z_DATA_ERROR, 1.268 + strm->msg == NULL ? "compressed data error" : strm->msg); 1.269 + return -1; 1.270 + } 1.271 + } while (strm->avail_out && ret != Z_STREAM_END); 1.272 + 1.273 + /* update available output and crc check value */ 1.274 + state->have = had - strm->avail_out; 1.275 + state->next = strm->next_out - state->have; 1.276 + strm->adler = crc32(strm->adler, state->next, state->have); 1.277 + 1.278 + /* check gzip trailer if at end of deflate stream */ 1.279 + if (ret == Z_STREAM_END) { 1.280 + if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { 1.281 + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); 1.282 + return -1; 1.283 + } 1.284 + if (crc != strm->adler) { 1.285 + gz_error(state, Z_DATA_ERROR, "incorrect data check"); 1.286 + return -1; 1.287 + } 1.288 + if (len != (strm->total_out & 0xffffffffL)) { 1.289 + gz_error(state, Z_DATA_ERROR, "incorrect length check"); 1.290 + return -1; 1.291 + } 1.292 + state->how = LOOK; /* ready for next stream, once have is 0 (leave 1.293 + state->direct unchanged to remember how) */ 1.294 + } 1.295 + 1.296 + /* good decompression */ 1.297 + return 0; 1.298 +} 1.299 + 1.300 +/* Make data and put in the output buffer. Assumes that state->have == 0. 1.301 + Data is either copied from the input file or decompressed from the input 1.302 + file depending on state->how. If state->how is LOOK, then a gzip header is 1.303 + looked for (and skipped if found) to determine wither to copy or decompress. 1.304 + Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY 1.305 + or GZIP unless the end of the input file has been reached and all data has 1.306 + been processed. */ 1.307 +local int gz_make(state) 1.308 + gz_statep state; 1.309 +{ 1.310 + z_streamp strm = &(state->strm); 1.311 + 1.312 + if (state->how == LOOK) { /* look for gzip header */ 1.313 + if (gz_head(state) == -1) 1.314 + return -1; 1.315 + if (state->have) /* got some data from gz_head() */ 1.316 + return 0; 1.317 + } 1.318 + if (state->how == COPY) { /* straight copy */ 1.319 + if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) 1.320 + return -1; 1.321 + state->next = state->out; 1.322 + } 1.323 + else if (state->how == GZIP) { /* decompress */ 1.324 + strm->avail_out = state->size << 1; 1.325 + strm->next_out = state->out; 1.326 + if (gz_decomp(state) == -1) 1.327 + return -1; 1.328 + } 1.329 + return 0; 1.330 +} 1.331 + 1.332 +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ 1.333 +local int gz_skip(state, len) 1.334 + gz_statep state; 1.335 + z_off64_t len; 1.336 +{ 1.337 + unsigned n; 1.338 + 1.339 + /* skip over len bytes or reach end-of-file, whichever comes first */ 1.340 + while (len) 1.341 + /* skip over whatever is in output buffer */ 1.342 + if (state->have) { 1.343 + n = GT_OFF(state->have) || (z_off64_t)state->have > len ? 1.344 + (unsigned)len : state->have; 1.345 + state->have -= n; 1.346 + state->next += n; 1.347 + state->pos += n; 1.348 + len -= n; 1.349 + } 1.350 + 1.351 + /* output buffer empty -- return if we're at the end of the input */ 1.352 + else if (state->eof && state->strm.avail_in == 0) 1.353 + break; 1.354 + 1.355 + /* need more data to skip -- load up output buffer */ 1.356 + else { 1.357 + /* get more output, looking for header if required */ 1.358 + if (gz_make(state) == -1) 1.359 + return -1; 1.360 + } 1.361 + return 0; 1.362 +} 1.363 + 1.364 +/* -- see zlib.h -- */ 1.365 +int ZEXPORT gzread(file, buf, len) 1.366 + gzFile file; 1.367 + voidp buf; 1.368 + unsigned len; 1.369 +{ 1.370 + unsigned got, n; 1.371 + gz_statep state; 1.372 + z_streamp strm; 1.373 + 1.374 + /* get internal structure */ 1.375 + if (file == NULL) 1.376 + return -1; 1.377 + state = (gz_statep)file; 1.378 + strm = &(state->strm); 1.379 + 1.380 + /* check that we're reading and that there's no error */ 1.381 + if (state->mode != GZ_READ || state->err != Z_OK) 1.382 + return -1; 1.383 + 1.384 + /* since an int is returned, make sure len fits in one, otherwise return 1.385 + with an error (this avoids the flaw in the interface) */ 1.386 + if ((int)len < 0) { 1.387 + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); 1.388 + return -1; 1.389 + } 1.390 + 1.391 + /* if len is zero, avoid unnecessary operations */ 1.392 + if (len == 0) 1.393 + return 0; 1.394 + 1.395 + /* process a skip request */ 1.396 + if (state->seek) { 1.397 + state->seek = 0; 1.398 + if (gz_skip(state, state->skip) == -1) 1.399 + return -1; 1.400 + } 1.401 + 1.402 + /* get len bytes to buf, or less than len if at the end */ 1.403 + got = 0; 1.404 + do { 1.405 + /* first just try copying data from the output buffer */ 1.406 + if (state->have) { 1.407 + n = state->have > len ? len : state->have; 1.408 + memcpy(buf, state->next, n); 1.409 + state->next += n; 1.410 + state->have -= n; 1.411 + } 1.412 + 1.413 + /* output buffer empty -- return if we're at the end of the input */ 1.414 + else if (state->eof && strm->avail_in == 0) 1.415 + break; 1.416 + 1.417 + /* need output data -- for small len or new stream load up our output 1.418 + buffer */ 1.419 + else if (state->how == LOOK || len < (state->size << 1)) { 1.420 + /* get more output, looking for header if required */ 1.421 + if (gz_make(state) == -1) 1.422 + return -1; 1.423 + continue; /* no progress yet -- go back to memcpy() above */ 1.424 + /* the copy above assures that we will leave with space in the 1.425 + output buffer, allowing at least one gzungetc() to succeed */ 1.426 + } 1.427 + 1.428 + /* large len -- read directly into user buffer */ 1.429 + else if (state->how == COPY) { /* read directly */ 1.430 + if (gz_load(state, buf, len, &n) == -1) 1.431 + return -1; 1.432 + } 1.433 + 1.434 + /* large len -- decompress directly into user buffer */ 1.435 + else { /* state->how == GZIP */ 1.436 + strm->avail_out = len; 1.437 + strm->next_out = buf; 1.438 + if (gz_decomp(state) == -1) 1.439 + return -1; 1.440 + n = state->have; 1.441 + state->have = 0; 1.442 + } 1.443 + 1.444 + /* update progress */ 1.445 + len -= n; 1.446 + buf = (char *)buf + n; 1.447 + got += n; 1.448 + state->pos += n; 1.449 + } while (len); 1.450 + 1.451 + /* return number of bytes read into user buffer (will fit in int) */ 1.452 + return (int)got; 1.453 +} 1.454 + 1.455 +/* -- see zlib.h -- */ 1.456 +int ZEXPORT gzgetc(file) 1.457 + gzFile file; 1.458 +{ 1.459 + int ret; 1.460 + unsigned char buf[1]; 1.461 + gz_statep state; 1.462 + 1.463 + /* get internal structure */ 1.464 + if (file == NULL) 1.465 + return -1; 1.466 + state = (gz_statep)file; 1.467 + 1.468 + /* check that we're reading and that there's no error */ 1.469 + if (state->mode != GZ_READ || state->err != Z_OK) 1.470 + return -1; 1.471 + 1.472 + /* try output buffer (no need to check for skip request) */ 1.473 + if (state->have) { 1.474 + state->have--; 1.475 + state->pos++; 1.476 + return *(state->next)++; 1.477 + } 1.478 + 1.479 + /* nothing there -- try gzread() */ 1.480 + ret = gzread(file, buf, 1); 1.481 + return ret < 1 ? -1 : buf[0]; 1.482 +} 1.483 + 1.484 +/* -- see zlib.h -- */ 1.485 +int ZEXPORT gzungetc(c, file) 1.486 + int c; 1.487 + gzFile file; 1.488 +{ 1.489 + gz_statep state; 1.490 + 1.491 + /* get internal structure */ 1.492 + if (file == NULL) 1.493 + return -1; 1.494 + state = (gz_statep)file; 1.495 + 1.496 + /* check that we're reading and that there's no error */ 1.497 + if (state->mode != GZ_READ || state->err != Z_OK) 1.498 + return -1; 1.499 + 1.500 + /* process a skip request */ 1.501 + if (state->seek) { 1.502 + state->seek = 0; 1.503 + if (gz_skip(state, state->skip) == -1) 1.504 + return -1; 1.505 + } 1.506 + 1.507 + /* can't push EOF */ 1.508 + if (c < 0) 1.509 + return -1; 1.510 + 1.511 + /* if output buffer empty, put byte at end (allows more pushing) */ 1.512 + if (state->have == 0) { 1.513 + state->have = 1; 1.514 + state->next = state->out + (state->size << 1) - 1; 1.515 + state->next[0] = c; 1.516 + state->pos--; 1.517 + return c; 1.518 + } 1.519 + 1.520 + /* if no room, give up (must have already done a gzungetc()) */ 1.521 + if (state->have == (state->size << 1)) { 1.522 + gz_error(state, Z_BUF_ERROR, "out of room to push characters"); 1.523 + return -1; 1.524 + } 1.525 + 1.526 + /* slide output data if needed and insert byte before existing data */ 1.527 + if (state->next == state->out) { 1.528 + unsigned char *src = state->out + state->have; 1.529 + unsigned char *dest = state->out + (state->size << 1); 1.530 + while (src > state->out) 1.531 + *--dest = *--src; 1.532 + state->next = dest; 1.533 + } 1.534 + state->have++; 1.535 + state->next--; 1.536 + state->next[0] = c; 1.537 + state->pos--; 1.538 + return c; 1.539 +} 1.540 + 1.541 +/* -- see zlib.h -- */ 1.542 +char * ZEXPORT gzgets(file, buf, len) 1.543 + gzFile file; 1.544 + char *buf; 1.545 + int len; 1.546 +{ 1.547 + unsigned left, n; 1.548 + char *str; 1.549 + unsigned char *eol; 1.550 + gz_statep state; 1.551 + 1.552 + /* check parameters and get internal structure */ 1.553 + if (file == NULL || buf == NULL || len < 1) 1.554 + return NULL; 1.555 + state = (gz_statep)file; 1.556 + 1.557 + /* check that we're reading and that there's no error */ 1.558 + if (state->mode != GZ_READ || state->err != Z_OK) 1.559 + return NULL; 1.560 + 1.561 + /* process a skip request */ 1.562 + if (state->seek) { 1.563 + state->seek = 0; 1.564 + if (gz_skip(state, state->skip) == -1) 1.565 + return NULL; 1.566 + } 1.567 + 1.568 + /* copy output bytes up to new line or len - 1, whichever comes first -- 1.569 + append a terminating zero to the string (we don't check for a zero in 1.570 + the contents, let the user worry about that) */ 1.571 + str = buf; 1.572 + left = (unsigned)len - 1; 1.573 + if (left) do { 1.574 + /* assure that something is in the output buffer */ 1.575 + if (state->have == 0) { 1.576 + if (gz_make(state) == -1) 1.577 + return NULL; /* error */ 1.578 + if (state->have == 0) { /* end of file */ 1.579 + if (buf == str) /* got bupkus */ 1.580 + return NULL; 1.581 + break; /* got something -- return it */ 1.582 + } 1.583 + } 1.584 + 1.585 + /* look for end-of-line in current output buffer */ 1.586 + n = state->have > left ? left : state->have; 1.587 + eol = memchr(state->next, '\n', n); 1.588 + if (eol != NULL) 1.589 + n = (unsigned)(eol - state->next) + 1; 1.590 + 1.591 + /* copy through end-of-line, or remainder if not found */ 1.592 + memcpy(buf, state->next, n); 1.593 + state->have -= n; 1.594 + state->next += n; 1.595 + state->pos += n; 1.596 + left -= n; 1.597 + buf += n; 1.598 + } while (left && eol == NULL); 1.599 + 1.600 + /* found end-of-line or out of space -- terminate string and return it */ 1.601 + buf[0] = 0; 1.602 + return str; 1.603 +} 1.604 + 1.605 +/* -- see zlib.h -- */ 1.606 +int ZEXPORT gzdirect(file) 1.607 + gzFile file; 1.608 +{ 1.609 + gz_statep state; 1.610 + 1.611 + /* get internal structure */ 1.612 + if (file == NULL) 1.613 + return 0; 1.614 + state = (gz_statep)file; 1.615 + 1.616 + /* check that we're reading */ 1.617 + if (state->mode != GZ_READ) 1.618 + return 0; 1.619 + 1.620 + /* if the state is not known, but we can find out, then do so (this is 1.621 + mainly for right after a gzopen() or gzdopen()) */ 1.622 + if (state->how == LOOK && state->have == 0) 1.623 + (void)gz_head(state); 1.624 + 1.625 + /* return 1 if reading direct, 0 if decompressing a gzip stream */ 1.626 + return state->direct; 1.627 +} 1.628 + 1.629 +/* -- see zlib.h -- */ 1.630 +int ZEXPORT gzclose_r(file) 1.631 + gzFile file; 1.632 +{ 1.633 + int ret; 1.634 + gz_statep state; 1.635 + 1.636 + /* get internal structure */ 1.637 + if (file == NULL) 1.638 + return Z_STREAM_ERROR; 1.639 + state = (gz_statep)file; 1.640 + 1.641 + /* check that we're reading */ 1.642 + if (state->mode != GZ_READ) 1.643 + return Z_STREAM_ERROR; 1.644 + 1.645 + /* free memory and close file */ 1.646 + if (state->size) { 1.647 + inflateEnd(&(state->strm)); 1.648 + free(state->out); 1.649 + free(state->in); 1.650 + } 1.651 + gz_error(state, Z_OK, NULL); 1.652 + free(state->path); 1.653 + ret = close(state->fd); 1.654 + free(state); 1.655 + return ret ? Z_ERRNO : Z_OK; 1.656 +}