|
|
|
@ -12,6 +12,7 @@ local int gz_look OF((gz_statep)); |
|
|
|
|
local int gz_decomp OF((gz_statep)); |
|
|
|
|
local int gz_fetch OF((gz_statep)); |
|
|
|
|
local int gz_skip OF((gz_statep, z_off64_t)); |
|
|
|
|
local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); |
|
|
|
|
|
|
|
|
|
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
|
|
|
|
|
state->fd, and update state->eof, state->err, and state->msg as appropriate. |
|
|
|
@ -284,33 +285,17 @@ local int gz_skip(state, len) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* -- see zlib.h -- */ |
|
|
|
|
int ZEXPORT gzread(file, buf, len) |
|
|
|
|
gzFile file; |
|
|
|
|
/* Read len bytes into buf from file, or less than len up to the end of the
|
|
|
|
|
input. Return the number of bytes read. If zero is returned, either the |
|
|
|
|
end of file was reached, or there was an error. state->err must be |
|
|
|
|
consulted in that case to determine which. */ |
|
|
|
|
local z_size_t gz_read(state, buf, len) |
|
|
|
|
gz_statep state; |
|
|
|
|
voidp buf; |
|
|
|
|
unsigned len; |
|
|
|
|
z_size_t len; |
|
|
|
|
{ |
|
|
|
|
unsigned got, n; |
|
|
|
|
gz_statep state; |
|
|
|
|
z_streamp strm; |
|
|
|
|
|
|
|
|
|
/* get internal structure */ |
|
|
|
|
if (file == NULL) |
|
|
|
|
return -1; |
|
|
|
|
state = (gz_statep)file; |
|
|
|
|
strm = &(state->strm); |
|
|
|
|
|
|
|
|
|
/* check that we're reading and that there's no (serious) error */ |
|
|
|
|
if (state->mode != GZ_READ || |
|
|
|
|
(state->err != Z_OK && state->err != Z_BUF_ERROR)) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
/* since an int is returned, make sure len fits in one, otherwise return
|
|
|
|
|
with an error (this avoids the flaw in the interface) */ |
|
|
|
|
if ((int)len < 0) { |
|
|
|
|
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
z_size_t got; |
|
|
|
|
unsigned n; |
|
|
|
|
|
|
|
|
|
/* if len is zero, avoid unnecessary operations */ |
|
|
|
|
if (len == 0) |
|
|
|
@ -320,32 +305,38 @@ int ZEXPORT gzread(file, buf, len) |
|
|
|
|
if (state->seek) { |
|
|
|
|
state->seek = 0; |
|
|
|
|
if (gz_skip(state, state->skip) == -1) |
|
|
|
|
return -1; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* get len bytes to buf, or less than len if at the end */ |
|
|
|
|
got = 0; |
|
|
|
|
do { |
|
|
|
|
/* set n to the maximum amount of len that fits in an unsigned int */ |
|
|
|
|
n = -1; |
|
|
|
|
if (n > len) |
|
|
|
|
n = len; |
|
|
|
|
|
|
|
|
|
/* first just try copying data from the output buffer */ |
|
|
|
|
if (state->x.have) { |
|
|
|
|
n = state->x.have > len ? len : state->x.have; |
|
|
|
|
if (state->x.have < n) |
|
|
|
|
n = state->x.have; |
|
|
|
|
memcpy(buf, state->x.next, n); |
|
|
|
|
state->x.next += n; |
|
|
|
|
state->x.have -= n; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* output buffer empty -- return if we're at the end of the input */ |
|
|
|
|
else if (state->eof && strm->avail_in == 0) { |
|
|
|
|
else if (state->eof && state->strm.avail_in == 0) { |
|
|
|
|
state->past = 1; /* tried to read past end */ |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* need output data -- for small len or new stream load up our output
|
|
|
|
|
buffer */ |
|
|
|
|
else if (state->how == LOOK || len < (state->size << 1)) { |
|
|
|
|
else if (state->how == LOOK || n < (state->size << 1)) { |
|
|
|
|
/* get more output, looking for header if required */ |
|
|
|
|
if (gz_fetch(state) == -1) |
|
|
|
|
return -1; |
|
|
|
|
return 0; |
|
|
|
|
continue; /* no progress yet -- go back to copy above */ |
|
|
|
|
/* the copy above assures that we will leave with space in the
|
|
|
|
|
output buffer, allowing at least one gzungetc() to succeed */ |
|
|
|
@ -353,16 +344,16 @@ int ZEXPORT gzread(file, buf, len) |
|
|
|
|
|
|
|
|
|
/* large len -- read directly into user buffer */ |
|
|
|
|
else if (state->how == COPY) { /* read directly */ |
|
|
|
|
if (gz_load(state, (unsigned char *)buf, len, &n) == -1) |
|
|
|
|
return -1; |
|
|
|
|
if (gz_load(state, (unsigned char *)buf, n, &n) == -1) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* large len -- decompress directly into user buffer */ |
|
|
|
|
else { /* state->how == GZIP */ |
|
|
|
|
strm->avail_out = len; |
|
|
|
|
strm->next_out = (unsigned char *)buf; |
|
|
|
|
state->strm.avail_out = n; |
|
|
|
|
state->strm.next_out = (unsigned char *)buf; |
|
|
|
|
if (gz_decomp(state) == -1) |
|
|
|
|
return -1; |
|
|
|
|
return 0; |
|
|
|
|
n = state->x.have; |
|
|
|
|
state->x.have = 0; |
|
|
|
|
} |
|
|
|
@ -374,8 +365,75 @@ int ZEXPORT gzread(file, buf, len) |
|
|
|
|
state->x.pos += n; |
|
|
|
|
} while (len); |
|
|
|
|
|
|
|
|
|
/* return number of bytes read into user buffer (will fit in int) */ |
|
|
|
|
return (int)got; |
|
|
|
|
/* return number of bytes read into user buffer */ |
|
|
|
|
return got; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* -- see zlib.h -- */ |
|
|
|
|
int ZEXPORT gzread(file, buf, len) |
|
|
|
|
gzFile file; |
|
|
|
|
voidp buf; |
|
|
|
|
unsigned len; |
|
|
|
|
{ |
|
|
|
|
gz_statep state; |
|
|
|
|
|
|
|
|
|
/* get internal structure */ |
|
|
|
|
if (file == NULL) |
|
|
|
|
return -1; |
|
|
|
|
state = (gz_statep)file; |
|
|
|
|
|
|
|
|
|
/* check that we're reading and that there's no (serious) error */ |
|
|
|
|
if (state->mode != GZ_READ || |
|
|
|
|
(state->err != Z_OK && state->err != Z_BUF_ERROR)) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
/* since an int is returned, make sure len fits in one, otherwise return
|
|
|
|
|
with an error (this avoids a flaw in the interface) */ |
|
|
|
|
if ((int)len < 0) { |
|
|
|
|
gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* read len or fewer bytes to buf */ |
|
|
|
|
len = gz_read(state, buf, len); |
|
|
|
|
|
|
|
|
|
/* check for an error */ |
|
|
|
|
if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
/* return the number of bytes read (this is assured to fit in an int) */ |
|
|
|
|
return (int)len; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* -- see zlib.h -- */ |
|
|
|
|
z_size_t ZEXPORT gzfread(buf, size, nitems, file) |
|
|
|
|
voidp buf; |
|
|
|
|
z_size_t size; |
|
|
|
|
z_size_t nitems; |
|
|
|
|
gzFile file; |
|
|
|
|
{ |
|
|
|
|
z_size_t len; |
|
|
|
|
gz_statep state; |
|
|
|
|
|
|
|
|
|
/* get internal structure */ |
|
|
|
|
if (file == NULL) |
|
|
|
|
return 0; |
|
|
|
|
state = (gz_statep)file; |
|
|
|
|
|
|
|
|
|
/* check that we're reading and that there's no (serious) error */ |
|
|
|
|
if (state->mode != GZ_READ || |
|
|
|
|
(state->err != Z_OK && state->err != Z_BUF_ERROR)) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
/* compute bytes to read -- error on overflow */ |
|
|
|
|
len = nitems * size; |
|
|
|
|
if (size && len / size != nitems) { |
|
|
|
|
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* read len or fewer bytes to buf, return the number of full items read */ |
|
|
|
|
return len ? gz_read(state, buf, len) / size : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* -- see zlib.h -- */ |
|
|
|
@ -408,8 +466,8 @@ int ZEXPORT gzgetc(file) |
|
|
|
|
return *(state->x.next)++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* nothing there -- try gzread() */ |
|
|
|
|
ret = gzread(file, buf, 1); |
|
|
|
|
/* nothing there -- try gz_read() */ |
|
|
|
|
ret = gz_read(state, buf, 1); |
|
|
|
|
return ret < 1 ? -1 : buf[0]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|