1381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* gzread.c -- zlib functions for reading gzip files 2381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * Copyright (C) 2004, 2005, 2010 Mark Adler 3381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * For conditions of distribution and use, see copyright notice in zlib.h 4381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes */ 5381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 6381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#include "gzguts.h" 7381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 8381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Local functions */ 9381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); 10381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_avail OF((gz_statep)); 11381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_next4 OF((gz_statep, unsigned long *)); 12381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_head OF((gz_statep)); 13381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_decomp OF((gz_statep)); 14381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_make OF((gz_statep)); 15381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_skip OF((gz_statep, z_off64_t)); 16381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 17381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from 18381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->fd, and update state->eof, state->err, and state->msg as appropriate. 19381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes This function needs to loop on read(), since read() is not guaranteed to 20381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes read the number of bytes requested, depending on the type of descriptor. */ 21381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_load(state, buf, len, have) 22381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 23381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char *buf; 24381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned len; 25381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned *have; 26381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 27381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int ret; 28381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 29381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes *have = 0; 30381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes do { 31381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = read(state->fd, buf + *have, len - *have); 32381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret <= 0) 33381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 34381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes *have += ret; 35381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } while (*have < len); 36381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret < 0) { 37381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_ERRNO, zstrerror()); 38381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 39381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 40381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret == 0) 41381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->eof = 1; 42381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 43381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 44381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 45381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Load up input buffer and set eof flag if last data loaded -- return -1 on 46381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes error, 0 otherwise. Note that the eof flag is set when the end of the input 47381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes file is reached, even though there may be unused data in the buffer. Once 48381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes that data has been used, no more attempts will be made to read the file. 49381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_avail() assumes that strm->avail_in == 0. */ 50381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_avail(state) 51381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 52381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 53381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_streamp strm = &(state->strm); 54381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 55381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->err != Z_OK) 56381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 57381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->eof == 0) { 58381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_load(state, state->in, state->size, 59381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (unsigned *)&(strm->avail_in)) == -1) 60381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 61381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->next_in = state->in; 62381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 63381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 64381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 65381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 66381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Get next byte from input, or -1 if end or error. */ 67381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ 68381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (strm->avail_in == 0 ? -1 : \ 69381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (strm->avail_in--, *(strm->next_in)++))) 70381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 71381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Get a four-byte little-endian integer and return 0 on success and the value 72381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes in *ret. Otherwise -1 is returned and *ret is not modified. */ 73381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_next4(state, ret) 74381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 75381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned long *ret; 76381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 77381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int ch; 78381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned long val; 79381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_streamp strm = &(state->strm); 80381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 81381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes val = NEXT(); 82381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes val += (unsigned)NEXT() << 8; 83381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes val += (unsigned long)NEXT() << 16; 84381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ch = NEXT(); 85381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ch == -1) 86381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 87381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes val += (unsigned long)ch << 24; 88381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes *ret = val; 89381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 90381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 91381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 92381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Look for gzip header, set up for inflate or copy. state->have must be zero. 93381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes If this is the first time in, allocate required memory. state->how will be 94381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes left unchanged if there is no more input data available, will be set to COPY 95381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if there is no gzip header and direct copying will be performed, or it will 96381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes be set to GZIP for decompression, and the gzip header will be skipped so 97381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes that the next available input data is the raw deflate stream. If direct 98381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes copying, then leftover input data from the input buffer will be copied to 99381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes the output buffer. In that case, all further file reads will be directly to 100381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes either the output buffer or a user buffer. If decompressing, the inflate 101381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state and the check value will be initialized. gz_head() will return 0 on 102381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes success or -1 on failure. Failures may include read errors or gzip header 103381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes errors. */ 104381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_head(state) 105381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 106381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 107381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_streamp strm = &(state->strm); 108381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int flags; 109381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned len; 110381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 111381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* allocate read buffers and inflate memory */ 112381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->size == 0) { 113381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* allocate buffers */ 114381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->in = malloc(state->want); 115381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->out = malloc(state->want << 1); 116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->in == NULL || state->out == NULL) { 117381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->out != NULL) 118381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->out); 119381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->in != NULL) 120381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->in); 121381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_MEM_ERROR, "out of memory"); 122381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 123381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 124381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->size = state->want; 125381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 126381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* allocate inflate memory */ 127381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strm.zalloc = Z_NULL; 128381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strm.zfree = Z_NULL; 129381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strm.opaque = Z_NULL; 130381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strm.avail_in = 0; 131381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strm.next_in = Z_NULL; 132381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ 133381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->out); 134381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->in); 135381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->size = 0; 136381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_MEM_ERROR, "out of memory"); 137381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 138381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 139381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 140381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 141381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get some data in the input buffer */ 142381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->avail_in == 0) { 143381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_avail(state) == -1) 144381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 145381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->avail_in == 0) 146381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 147381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 148381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 149381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* look for the gzip magic header bytes 31 and 139 */ 150381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->next_in[0] == 31) { 151381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->avail_in--; 152381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->next_in++; 153381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->avail_in == 0 && gz_avail(state) == -1) 154381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 155381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->avail_in && strm->next_in[0] == 139) { 156381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* we have a gzip header, woo hoo! */ 157381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->avail_in--; 158381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->next_in++; 159381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 160381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* skip rest of header */ 161381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (NEXT() != 8) { /* compression method */ 162381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_DATA_ERROR, "unknown compression method"); 163381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 164381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 165381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes flags = NEXT(); 166381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (flags & 0xe0) { /* reserved flag bits */ 167381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_DATA_ERROR, "unknown header flags set"); 168381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 169381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 170381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); /* modification time */ 171381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); 172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); 173381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); 174381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); /* extra flags */ 175381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); /* operating system */ 176381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (flags & 4) { /* extra field */ 177381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes len = (unsigned)NEXT(); 178381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes len += (unsigned)NEXT() << 8; 179381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes while (len--) 180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (NEXT() < 0) 181381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 182381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 183381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (flags & 8) /* file name */ 184381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes while (NEXT() > 0) 185381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ; 186381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (flags & 16) /* comment */ 187381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes while (NEXT() > 0) 188381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ; 189381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (flags & 2) { /* header crc */ 190381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); 191381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEXT(); 192381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 193381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* an unexpected end of file is not checked for here -- it will be 194381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes noticed on the first request for uncompressed data */ 195381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 196381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* set up for decompression */ 197381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes inflateReset(strm); 198381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->adler = crc32(0L, Z_NULL, 0); 199381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->how = GZIP; 200381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->direct = 0; 201381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 202381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 203381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else { 204381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* not a gzip file -- save first byte (31) and fall to raw i/o */ 205381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->out[0] = 31; 206381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have = 1; 207381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 208381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 209381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 210381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* doing raw i/o, save start of raw data for seeking, copy any leftover 211381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes input to output -- this assumes that the output buffer is larger than 212381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes the input buffer, which also assures space for gzungetc() */ 213381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->raw = state->pos; 214381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next = state->out; 215381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->avail_in) { 216381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes memcpy(state->next + state->have, strm->next_in, strm->avail_in); 217381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have += strm->avail_in; 218381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->avail_in = 0; 219381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 220381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->how = COPY; 221381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->direct = 1; 222381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 223381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 224381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 225381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Decompress from input to the provided next_out and avail_out in the state. 226381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes If the end of the compressed data is reached, then verify the gzip trailer 227381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes check value and length (modulo 2^32). state->have and state->next are set 228381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes to point to the just decompressed data, and the crc is updated. If the 229381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes trailer is verified, state->how is reset to LOOK to look for the next gzip 230381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes stream or raw data, once state->have is depleted. Returns 0 on success, -1 231381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes on failure. Failures may include invalid compressed data or a failed gzip 232381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes trailer verification. */ 233381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_decomp(state) 234381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 235381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 236381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int ret; 237381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned had; 238381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned long crc, len; 239381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_streamp strm = &(state->strm); 240381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 241381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* fill output buffer up to end of deflate stream */ 242381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes had = strm->avail_out; 243381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes do { 244381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get more input for inflate() */ 245381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->avail_in == 0 && gz_avail(state) == -1) 246381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 247381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (strm->avail_in == 0) { 248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_DATA_ERROR, "unexpected end of file"); 249381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 250381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 251381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 252381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* decompress and handle errors */ 253381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = inflate(strm, Z_NO_FLUSH); 254381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 255381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_STREAM_ERROR, 256381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes "internal error: inflate stream corrupt"); 257381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 258381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 259381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret == Z_MEM_ERROR) { 260381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_MEM_ERROR, "out of memory"); 261381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 262381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 263381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ 264381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_DATA_ERROR, 265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->msg == NULL ? "compressed data error" : strm->msg); 266381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 267381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 268381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } while (strm->avail_out && ret != Z_STREAM_END); 269381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* update available output and crc check value */ 271381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have = had - strm->avail_out; 272381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next = strm->next_out - state->have; 273381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->adler = crc32(strm->adler, state->next, state->have); 274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 275381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check gzip trailer if at end of deflate stream */ 276381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret == Z_STREAM_END) { 277381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { 278381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_DATA_ERROR, "unexpected end of file"); 279381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 280381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 281381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (crc != strm->adler) { 282381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_DATA_ERROR, "incorrect data check"); 283381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 284381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 285381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (len != (strm->total_out & 0xffffffffL)) { 286381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_DATA_ERROR, "incorrect length check"); 287381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 288381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 289381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->how = LOOK; /* ready for next stream, once have is 0 (leave 290381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->direct unchanged to remember how) */ 291381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 292381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 293381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* good decompression */ 294381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 295381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 296381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 297381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Make data and put in the output buffer. Assumes that state->have == 0. 298381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes Data is either copied from the input file or decompressed from the input 299381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes file depending on state->how. If state->how is LOOK, then a gzip header is 300381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes looked for (and skipped if found) to determine wither to copy or decompress. 301381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY 302381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes or GZIP unless the end of the input file has been reached and all data has 303381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes been processed. */ 304381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_make(state) 305381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 306381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 307381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_streamp strm = &(state->strm); 308381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 309381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->how == LOOK) { /* look for gzip header */ 310381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_head(state) == -1) 311381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 312381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have) /* got some data from gz_head() */ 313381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 314381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 315381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->how == COPY) { /* straight copy */ 316381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) 317381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 318381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next = state->out; 319381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 320381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else if (state->how == GZIP) { /* decompress */ 321381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->avail_out = state->size << 1; 322381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->next_out = state->out; 323381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_decomp(state) == -1) 324381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 325381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 326381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 327381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 328381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 329381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ 330381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_skip(state, len) 331381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 332381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off64_t len; 333381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 334381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned n; 335381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 336381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* skip over len bytes or reach end-of-file, whichever comes first */ 337381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes while (len) 338381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* skip over whatever is in output buffer */ 339381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have) { 340381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes n = GT_OFF(state->have) || (z_off64_t)state->have > len ? 341381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (unsigned)len : state->have; 342381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have -= n; 343381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next += n; 344381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos += n; 345381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes len -= n; 346381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 347381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 348381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* output buffer empty -- return if we're at the end of the input */ 349381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else if (state->eof && state->strm.avail_in == 0) 350381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 351381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 352381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* need more data to skip -- load up output buffer */ 353381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else { 354381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get more output, looking for header if required */ 355381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_make(state) == -1) 356381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 357381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 358381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 359381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 360381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzread(file, buf, len) 363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 364381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes voidp buf; 365381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned len; 366381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 367381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned got, n; 368381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 369381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_streamp strm; 370381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 371381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure */ 372381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 373381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 374381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 375381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm = &(state->strm); 376381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 377381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that we're reading and that there's no error */ 378381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ || state->err != Z_OK) 379381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 380381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 381381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* since an int is returned, make sure len fits in one, otherwise return 382381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes with an error (this avoids the flaw in the interface) */ 383381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((int)len < 0) { 384381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); 385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 387381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 388381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* if len is zero, avoid unnecessary operations */ 389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (len == 0) 390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* process a skip request */ 393381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->seek) { 394381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->seek = 0; 395381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_skip(state, state->skip) == -1) 396381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 398381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 399381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get len bytes to buf, or less than len if at the end */ 400381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes got = 0; 401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes do { 402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* first just try copying data from the output buffer */ 403381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have) { 404381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes n = state->have > len ? len : state->have; 405381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes memcpy(buf, state->next, n); 406381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next += n; 407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have -= n; 408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* output buffer empty -- return if we're at the end of the input */ 411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else if (state->eof && strm->avail_in == 0) 412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 413381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 414381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* need output data -- for small len or new stream load up our output 415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes buffer */ 416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else if (state->how == LOOK || len < (state->size << 1)) { 417381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get more output, looking for header if required */ 418381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_make(state) == -1) 419381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 420381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes continue; /* no progress yet -- go back to memcpy() above */ 421381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* the copy above assures that we will leave with space in the 422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes output buffer, allowing at least one gzungetc() to succeed */ 423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 425381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* large len -- read directly into user buffer */ 426381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else if (state->how == COPY) { /* read directly */ 427381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_load(state, buf, len, &n) == -1) 428381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 429381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* large len -- decompress directly into user buffer */ 432381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else { /* state->how == GZIP */ 433381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->avail_out = len; 434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->next_out = buf; 435381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_decomp(state) == -1) 436381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 437381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes n = state->have; 438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have = 0; 439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 441381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* update progress */ 442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes len -= n; 443381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes buf = (char *)buf + n; 444381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes got += n; 445381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos += n; 446381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } while (len); 447381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 448381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* return number of bytes read into user buffer (will fit in int) */ 449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return (int)got; 450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzgetc(file) 454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int ret; 457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char buf[1]; 458381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 459381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 460381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure */ 461381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 462381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 463381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 464381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 465381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that we're reading and that there's no error */ 466381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ || state->err != Z_OK) 467381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 468381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 469381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* try output buffer (no need to check for skip request) */ 470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have) { 471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have--; 472381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos++; 473381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return *(state->next)++; 474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 476381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* nothing there -- try gzread() */ 477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = gzread(file, buf, 1); 478381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return ret < 1 ? -1 : buf[0]; 479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 480381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 481381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 482381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzungetc(c, file) 483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int c; 484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 487381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure */ 489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 490381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 492381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 493381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that we're reading and that there's no error */ 494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ || state->err != Z_OK) 495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 497381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* process a skip request */ 498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->seek) { 499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->seek = 0; 500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_skip(state, state->skip) == -1) 501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 502381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 504381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* can't push EOF */ 505381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (c < 0) 506381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* if output buffer empty, put byte at end (allows more pushing) */ 509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have == 0) { 510381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have = 1; 511381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next = state->out + (state->size << 1) - 1; 512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next[0] = c; 513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos--; 514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return c; 515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 516381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 517381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* if no room, give up (must have already done a gzungetc()) */ 518381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have == (state->size << 1)) { 519381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_BUF_ERROR, "out of room to push characters"); 520381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 521381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 522381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 523381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* slide output data if needed and insert byte before existing data */ 524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->next == state->out) { 525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char *src = state->out + state->have; 526381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char *dest = state->out + (state->size << 1); 527381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes while (src > state->out) 528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes *--dest = *--src; 529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next = dest; 530381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have++; 532381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next--; 533381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next[0] = c; 534381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos--; 535381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return c; 536381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 537381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 538381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 539381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheschar * ZEXPORT gzgets(file, buf, len) 540381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 541381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes char *buf; 542381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int len; 543381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 544381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned left, n; 545381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes char *str; 546381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char *eol; 547381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 548381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 549381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check parameters and get internal structure */ 550381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL || buf == NULL || len < 1) 551381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 552381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 553381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 554381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that we're reading and that there's no error */ 555381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ || state->err != Z_OK) 556381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 557381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 558381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* process a skip request */ 559381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->seek) { 560381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->seek = 0; 561381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_skip(state, state->skip) == -1) 562381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 563381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 564381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 565381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* copy output bytes up to new line or len - 1, whichever comes first -- 566381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes append a terminating zero to the string (we don't check for a zero in 567381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes the contents, let the user worry about that) */ 568381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes str = buf; 569381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes left = (unsigned)len - 1; 570381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (left) do { 571381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* assure that something is in the output buffer */ 572381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have == 0) { 573381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gz_make(state) == -1) 574381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; /* error */ 575381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->have == 0) { /* end of file */ 576381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (buf == str) /* got bupkus */ 577381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 578381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; /* got something -- return it */ 579381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 580381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 581381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 582381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* look for end-of-line in current output buffer */ 583381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes n = state->have > left ? left : state->have; 584381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes eol = memchr(state->next, '\n', n); 585381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (eol != NULL) 586381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes n = (unsigned)(eol - state->next) + 1; 587381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 588381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* copy through end-of-line, or remainder if not found */ 589381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes memcpy(buf, state->next, n); 590381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have -= n; 591381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next += n; 592381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos += n; 593381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes left -= n; 594381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes buf += n; 595381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } while (left && eol == NULL); 596381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 597381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* found end-of-line or out of space -- terminate string and return it */ 598381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes buf[0] = 0; 599381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return str; 600381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 601381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 602381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 603381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzdirect(file) 604381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 605381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 606381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 607381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 608381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure */ 609381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 610381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 611381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 612381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 613381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that we're reading */ 614381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ) 615381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 616381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 617381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* if the state is not known, but we can find out, then do so (this is 618381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes mainly for right after a gzopen() or gzdopen()) */ 619381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->how == LOOK && state->have == 0) 620381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (void)gz_head(state); 621381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 622381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* return 1 if reading direct, 0 if decompressing a gzip stream */ 623381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return state->direct; 624381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 625381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 626381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 627381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzclose_r(file) 628381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 629381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 630381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int ret; 631381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 632381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 633381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure */ 634381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 635381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return Z_STREAM_ERROR; 636381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 637381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 638381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that we're reading */ 639381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ) 640381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return Z_STREAM_ERROR; 641381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 642381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* free memory and close file */ 643381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->size) { 644381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes inflateEnd(&(state->strm)); 645381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->out); 646381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->in); 647381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 648381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_OK, NULL); 649381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->path); 650381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = close(state->fd); 651381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state); 652381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return ret ? Z_ERRNO : Z_OK; 653381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 654