1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* gzread.c -- zlib functions for reading gzip files 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * For conditions of distribution and use, see copyright notice in zlib.h 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "gzguts.h" 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Local functions */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_avail OF((gz_statep)); 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_look OF((gz_statep)); 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_decomp OF((gz_statep)); 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_fetch OF((gz_statep)); 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_skip OF((gz_statep, z_off64_t)); 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->fd, and update state->eof, state->err, and state->msg as appropriate. 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov This function needs to loop on read(), since read() is not guaranteed to 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov read the number of bytes requested, depending on the type of descriptor. */ 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_load( 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state, 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *buf, 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned len, 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned *have) 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int ret; 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *have = 0; 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do { 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret = read(state->fd, buf + *have, len - *have); 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret <= 0) 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *have += ret; 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (*have < len); 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret < 0) { 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_ERRNO, zstrerror()); 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret == 0) 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->eof = 1; 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Load up input buffer and set eof flag if last data loaded -- return -1 on 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error, 0 otherwise. Note that the eof flag is set when the end of the input 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov file is reached, even though there may be unused data in the buffer. Once 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov that data has been used, no more attempts will be made to read the file. 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov If strm->avail_in != 0, then the current data is moved to the beginning of 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov the input buffer, and then the remainder of the buffer is loaded with the 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov available data from the input file. */ 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_avail( 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state) 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned got; 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov z_streamp strm = &(state->strm); 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->err != Z_OK && state->err != Z_BUF_ERROR) 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->eof == 0) { 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (strm->avail_in) { /* copy what's there to the start */ 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *p = state->in; 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned const char *q = strm->next_in; 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned n = strm->avail_in; 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do { 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p++ = *q++; 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (--n); 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_load(state, state->in + strm->avail_in, 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->size - strm->avail_in, &got) == -1) 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->avail_in += got; 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->next_in = state->in; 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov If this is the first time in, allocate required memory. state->how will be 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left unchanged if there is no more input data available, will be set to COPY 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if there is no gzip header and direct copying will be performed, or it will 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov be set to GZIP for decompression. If direct copying, then leftover input 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data from the input buffer will be copied to the output buffer. In that 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case, all further file reads will be directly to either the output buffer or 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a user buffer. If decompressing, the inflate state will be initialized. 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_look() will return 0 on success or -1 on failure. */ 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_look( 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state) 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov z_streamp strm = &(state->strm); 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* allocate read buffers and inflate memory */ 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->size == 0) { 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* allocate buffers */ 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->in = (unsigned char *)malloc(state->want); 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->out = (unsigned char *)malloc(state->want << 1); 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->in == NULL || state->out == NULL) { 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->out != NULL) 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state->out); 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->in != NULL) 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state->in); 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_MEM_ERROR, "out of memory"); 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->size = state->want; 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* allocate inflate memory */ 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->strm.zalloc = Z_NULL; 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->strm.zfree = Z_NULL; 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->strm.opaque = Z_NULL; 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->strm.avail_in = 0; 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->strm.next_in = Z_NULL; 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state->out); 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state->in); 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->size = 0; 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_MEM_ERROR, "out of memory"); 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get at least the magic bytes in the input buffer */ 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (strm->avail_in < 2) { 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_avail(state) == -1) 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (strm->avail_in == 0) 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* look for gzip magic bytes -- if there, do gzip decoding (note: there is 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a logical dilemma here when considering the case of a partially written 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gzip file, to wit, if a single 31 byte is written, then we cannot tell 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov whether this is a single-byte file, or just a partially written gzip 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov file -- for here we assume that if a gzip file is being written, then 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov the header will be written in a single operation, so that reading a 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov single byte is sufficient indication that it is not a gzip file) */ 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (strm->avail_in > 1 && 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->next_in[0] == 31 && strm->next_in[1] == 139) { 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov inflateReset(strm); 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->how = GZIP; 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->direct = 0; 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no gzip header -- if we were decoding gzip before, then this is trailing 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov garbage. Ignore the trailing garbage and finish. */ 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->direct == 0) { 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->avail_in = 0; 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->eof = 1; 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have = 0; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* doing raw i/o, copy any leftover input to output -- this assumes that 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov the output buffer is larger than the input buffer, which also assures 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov space for gzungetc() */ 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next = state->out; 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (strm->avail_in) { 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(state->x.next, strm->next_in, strm->avail_in); 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have = strm->avail_in; 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->avail_in = 0; 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->how = COPY; 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->direct = 1; 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Decompress from input to the provided next_out and avail_out in the state. 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov On return, state->x.have and state->x.next point to the just decompressed 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data. If the gzip stream completes, state->how is reset to LOOK to look for 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov the next gzip stream or raw data, once state->x.have is depleted. Returns 0 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov on success, -1 on failure. */ 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_decomp( 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state) 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int ret = Z_OK; 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned had; 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov z_streamp strm = &(state->strm); 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* fill output buffer up to end of deflate stream */ 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov had = strm->avail_out; 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do { 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get more input for inflate() */ 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (strm->avail_in == 0 && gz_avail(state) == -1) 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (strm->avail_in == 0) { 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_BUF_ERROR, "unexpected end of file"); 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* decompress and handle errors */ 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret = inflate(strm, Z_NO_FLUSH); 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_STREAM_ERROR, 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "internal error: inflate stream corrupt"); 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret == Z_MEM_ERROR) { 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_MEM_ERROR, "out of memory"); 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_DATA_ERROR, 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->msg == NULL ? "compressed data error" : strm->msg); 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (strm->avail_out && ret != Z_STREAM_END); 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* update available output */ 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have = had - strm->avail_out; 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next = strm->next_out - state->x.have; 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if the gzip stream completed successfully, look for another */ 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret == Z_STREAM_END) 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->how = LOOK; 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* good decompression */ 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Data is either copied from the input file or decompressed from the input 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov file depending on state->how. If state->how is LOOK, then a gzip header is 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov looked for to determine whether to copy or decompress. Returns -1 on error, 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end of the input file has been reached and all data has been processed. */ 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_fetch( 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state) 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov z_streamp strm = &(state->strm); 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do { 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch(state->how) { 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_look(state) == -1) 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->how == LOOK) 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case COPY: /* -> COPY */ 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_load(state, state->out, state->size << 1, &(state->x.have)) 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov == -1) 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next = state->out; 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->avail_out = state->size << 1; 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->next_out = state->out; 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_decomp(state) == -1) 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (state->x.have == 0 && (!state->eof || strm->avail_in)); 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovlocal int gz_skip( 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state, 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov z_off64_t len) 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned n; 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* skip over len bytes or reach end-of-file, whichever comes first */ 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while (len) 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* skip over whatever is in output buffer */ 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.have) { 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (unsigned)len : state->x.have; 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have -= n; 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next += n; 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.pos += n; 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov len -= n; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* output buffer empty -- return if we're at the end of the input */ 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if (state->eof && state->strm.avail_in == 0) 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* need more data to skip -- load up output buffer */ 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get more output, looking for header if required */ 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_fetch(state) == -1) 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* -- see zlib.h -- */ 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint ZEXPORT gzread( 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gzFile file, 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov voidp buf, 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned len) 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned got, n; 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state; 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov z_streamp strm; 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get internal structure */ 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (file == NULL) 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state = (gz_statep)file; 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm = &(state->strm); 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that we're reading and that there's no (serious) error */ 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->mode != GZ_READ || 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (state->err != Z_OK && state->err != Z_BUF_ERROR)) 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* since an int is returned, make sure len fits in one, otherwise return 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov with an error (this avoids the flaw in the interface) */ 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((int)len < 0) { 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if len is zero, avoid unnecessary operations */ 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (len == 0) 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* process a skip request */ 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->seek) { 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->seek = 0; 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_skip(state, state->skip) == -1) 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get len bytes to buf, or less than len if at the end */ 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov got = 0; 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do { 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first just try copying data from the output buffer */ 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.have) { 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = state->x.have > len ? len : state->x.have; 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(buf, state->x.next, n); 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next += n; 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have -= n; 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* output buffer empty -- return if we're at the end of the input */ 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if (state->eof && strm->avail_in == 0) { 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->past = 1; /* tried to read past end */ 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* need output data -- for small len or new stream load up our output 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buffer */ 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if (state->how == LOOK || len < (state->size << 1)) { 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get more output, looking for header if required */ 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_fetch(state) == -1) 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; /* no progress yet -- go back to copy above */ 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the copy above assures that we will leave with space in the 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output buffer, allowing at least one gzungetc() to succeed */ 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* large len -- read directly into user buffer */ 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if (state->how == COPY) { /* read directly */ 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_load(state, (unsigned char *)buf, len, &n) == -1) 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* large len -- decompress directly into user buffer */ 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { /* state->how == GZIP */ 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->avail_out = len; 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strm->next_out = (unsigned char *)buf; 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_decomp(state) == -1) 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = state->x.have; 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have = 0; 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* update progress */ 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov len -= n; 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf = (char *)buf + n; 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov got += n; 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.pos += n; 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (len); 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return number of bytes read into user buffer (will fit in int) */ 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (int)got; 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* -- see zlib.h -- */ 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef Z_PREFIX_SET 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov# undef z_gzgetc 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov# undef gzgetc 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint ZEXPORT gzgetc( 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gzFile file) 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int ret; 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char buf[1]; 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state; 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get internal structure */ 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (file == NULL) 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state = (gz_statep)file; 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that we're reading and that there's no (serious) error */ 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->mode != GZ_READ || 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (state->err != Z_OK && state->err != Z_BUF_ERROR)) 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* try output buffer (no need to check for skip request) */ 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.have) { 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have--; 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.pos++; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return *(state->x.next)++; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* nothing there -- try gzread() */ 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret = gzread(file, buf, 1); 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ret < 1 ? -1 : buf[0]; 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint ZEXPORT gzgetc_( 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovgzFile file) 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gzgetc(file); 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* -- see zlib.h -- */ 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint ZEXPORT gzungetc( 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int c, 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gzFile file) 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state; 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get internal structure */ 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (file == NULL) 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state = (gz_statep)file; 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that we're reading and that there's no (serious) error */ 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->mode != GZ_READ || 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (state->err != Z_OK && state->err != Z_BUF_ERROR)) 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* process a skip request */ 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->seek) { 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->seek = 0; 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_skip(state, state->skip) == -1) 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* can't push EOF */ 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (c < 0) 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if output buffer empty, put byte at end (allows more pushing) */ 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.have == 0) { 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have = 1; 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next = state->out + (state->size << 1) - 1; 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next[0] = c; 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.pos--; 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->past = 0; 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return c; 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if no room, give up (must have already done a gzungetc()) */ 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.have == (state->size << 1)) { 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_DATA_ERROR, "out of room to push characters"); 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* slide output data if needed and insert byte before existing data */ 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.next == state->out) { 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *src = state->out + state->x.have; 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *dest = state->out + (state->size << 1); 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while (src > state->out) 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *--dest = *--src; 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next = dest; 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have++; 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next--; 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next[0] = c; 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.pos--; 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->past = 0; 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return c; 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* -- see zlib.h -- */ 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovchar * ZEXPORT gzgets( 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gzFile file, 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char *buf, 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int len) 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned left, n; 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char *str; 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *eol; 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state; 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check parameters and get internal structure */ 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (file == NULL || buf == NULL || len < 1) 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state = (gz_statep)file; 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that we're reading and that there's no (serious) error */ 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->mode != GZ_READ || 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (state->err != Z_OK && state->err != Z_BUF_ERROR)) 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* process a skip request */ 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->seek) { 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->seek = 0; 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gz_skip(state, state->skip) == -1) 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* copy output bytes up to new line or len - 1, whichever comes first -- 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov append a terminating zero to the string (we don't check for a zero in 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov the contents, let the user worry about that) */ 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov str = buf; 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = (unsigned)len - 1; 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (left) do { 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* assure that something is in the output buffer */ 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.have == 0 && gz_fetch(state) == -1) 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; /* error */ 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->x.have == 0) { /* end of file */ 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->past = 1; /* read past end */ 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; /* return what we have */ 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* look for end-of-line in current output buffer */ 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = state->x.have > left ? left : state->x.have; 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov eol = (unsigned char *)memchr(state->x.next, '\n', n); 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (eol != NULL) 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = (unsigned)(eol - state->x.next) + 1; 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* copy through end-of-line, or remainder if not found */ 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(buf, state->x.next, n); 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.have -= n; 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.next += n; 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state->x.pos += n; 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left -= n; 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf += n; 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (left && eol == NULL); 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return terminated string, or if nothing, end of file */ 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (buf == str) 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf[0] = 0; 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return str; 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* -- see zlib.h -- */ 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint ZEXPORT gzdirect( 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gzFile file) 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state; 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get internal structure */ 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (file == NULL) 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state = (gz_statep)file; 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if the state is not known, but we can find out, then do so (this is 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mainly for right after a gzopen() or gzdopen()) */ 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (void)gz_look(state); 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return 1 if transparent, 0 if processing a gzip stream */ 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return state->direct; 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* -- see zlib.h -- */ 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint ZEXPORT gzclose_r( 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gzFile file) 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int ret, err; 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_statep state; 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get internal structure */ 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (file == NULL) 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Z_STREAM_ERROR; 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov state = (gz_statep)file; 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that we're reading */ 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->mode != GZ_READ) 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Z_STREAM_ERROR; 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* free memory and close file */ 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (state->size) { 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov inflateEnd(&(state->strm)); 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state->out); 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state->in); 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gz_error(state, Z_OK, NULL); 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state->path); 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret = close(state->fd); 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free(state); 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ret ? Z_ERRNO : err; 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 595