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