• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/zlib/gzread.c

00001 /* gzread.c -- zlib functions for reading gzip files
00002  * Copyright (C) 2004, 2005, 2010 Mark Adler
00003  * For conditions of distribution and use, see copyright notice in zlib.h
00004  */
00005 
00006 #include "gzguts.h"
00007 
00008 /* Local functions */
00009 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
00010 local int gz_avail OF((gz_statep));
00011 local int gz_next4 OF((gz_statep, unsigned long *));
00012 local int gz_head OF((gz_statep));
00013 local int gz_decomp OF((gz_statep));
00014 local int gz_make OF((gz_statep));
00015 local int gz_skip OF((gz_statep, z_off64_t));
00016 
00017 /* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
00018    state->fd, and update state->eof, state->err, and state->msg as appropriate.
00019    This function needs to loop on read(), since read() is not guaranteed to
00020    read the number of bytes requested, depending on the type of descriptor. */
00021 local int gz_load(state, buf, len, have)
00022     gz_statep state;
00023     unsigned char *buf;
00024     unsigned len;
00025     unsigned *have;
00026 {
00027     int ret;
00028 
00029     *have = 0;
00030     do {
00031         ret = read(state->fd, buf + *have, len - *have);
00032         if (ret <= 0)
00033             break;
00034         *have += ret;
00035     } while (*have < len);
00036     if (ret < 0) {
00037         gz_error(state, Z_ERRNO, zstrerror());
00038         return -1;
00039     }
00040     if (ret == 0)
00041         state->eof = 1;
00042     return 0;
00043 }
00044 
00045 /* Load up input buffer and set eof flag if last data loaded -- return -1 on
00046    error, 0 otherwise.  Note that the eof flag is set when the end of the input
00047    file is reached, even though there may be unused data in the buffer.  Once
00048    that data has been used, no more attempts will be made to read the file.
00049    gz_avail() assumes that strm->avail_in == 0. */
00050 local int gz_avail(state)
00051     gz_statep state;
00052 {
00053     z_streamp strm = &(state->strm);
00054 
00055     if (state->err != Z_OK)
00056         return -1;
00057     if (state->eof == 0) {
00058         if (gz_load(state, state->in, state->size,
00059                 (unsigned *)&(strm->avail_in)) == -1)
00060             return -1;
00061         strm->next_in = state->in;
00062     }
00063     return 0;
00064 }
00065 
00066 /* Get next byte from input, or -1 if end or error. */
00067 #define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
00068                 (strm->avail_in == 0 ? -1 : \
00069                  (strm->avail_in--, *(strm->next_in)++)))
00070 
00071 /* Get a four-byte little-endian integer and return 0 on success and the value
00072    in *ret.  Otherwise -1 is returned and *ret is not modified. */
00073 local int gz_next4(state, ret)
00074     gz_statep state;
00075     unsigned long *ret;
00076 {
00077     int ch;
00078     unsigned long val;
00079     z_streamp strm = &(state->strm);
00080 
00081     val = NEXT();
00082     val += (unsigned)NEXT() << 8;
00083     val += (unsigned long)NEXT() << 16;
00084     ch = NEXT();
00085     if (ch == -1)
00086         return -1;
00087     val += (unsigned long)ch << 24;
00088     *ret = val;
00089     return 0;
00090 }
00091 
00092 /* Look for gzip header, set up for inflate or copy.  state->have must be zero.
00093    If this is the first time in, allocate required memory.  state->how will be
00094    left unchanged if there is no more input data available, will be set to COPY
00095    if there is no gzip header and direct copying will be performed, or it will
00096    be set to GZIP for decompression, and the gzip header will be skipped so
00097    that the next available input data is the raw deflate stream.  If direct
00098    copying, then leftover input data from the input buffer will be copied to
00099    the output buffer.  In that case, all further file reads will be directly to
00100    either the output buffer or a user buffer.  If decompressing, the inflate
00101    state and the check value will be initialized.  gz_head() will return 0 on
00102    success or -1 on failure.  Failures may include read errors or gzip header
00103    errors.  */
00104 local int gz_head(state)
00105     gz_statep state;
00106 {
00107     z_streamp strm = &(state->strm);
00108     int flags;
00109     unsigned len;
00110 
00111     /* allocate read buffers and inflate memory */
00112     if (state->size == 0) {
00113         /* allocate buffers */
00114         state->in = malloc(state->want);
00115         state->out = malloc(state->want << 1);
00116         if (state->in == NULL || state->out == NULL) {
00117             if (state->out != NULL)
00118                 free(state->out);
00119             if (state->in != NULL)
00120                 free(state->in);
00121             gz_error(state, Z_MEM_ERROR, "out of memory");
00122             return -1;
00123         }
00124         state->size = state->want;
00125 
00126         /* allocate inflate memory */
00127         state->strm.zalloc = Z_NULL;
00128         state->strm.zfree = Z_NULL;
00129         state->strm.opaque = Z_NULL;
00130         state->strm.avail_in = 0;
00131         state->strm.next_in = Z_NULL;
00132         if (inflateInit2(&(state->strm), -15) != Z_OK) {    /* raw inflate */
00133             free(state->out);
00134             free(state->in);
00135             state->size = 0;
00136             gz_error(state, Z_MEM_ERROR, "out of memory");
00137             return -1;
00138         }
00139     }
00140 
00141     /* get some data in the input buffer */
00142     if (strm->avail_in == 0) {
00143         if (gz_avail(state) == -1)
00144             return -1;
00145         if (strm->avail_in == 0)
00146             return 0;
00147     }
00148 
00149     /* look for the gzip magic header bytes 31 and 139 */
00150     if (strm->next_in[0] == 31) {
00151         strm->avail_in--;
00152         strm->next_in++;
00153         if (strm->avail_in == 0 && gz_avail(state) == -1)
00154             return -1;
00155         if (strm->avail_in && strm->next_in[0] == 139) {
00156             /* we have a gzip header, woo hoo! */
00157             strm->avail_in--;
00158             strm->next_in++;
00159 
00160             /* skip rest of header */
00161             if (NEXT() != 8) {      /* compression method */
00162                 gz_error(state, Z_DATA_ERROR, "unknown compression method");
00163                 return -1;
00164             }
00165             flags = NEXT();
00166             if (flags & 0xe0) {     /* reserved flag bits */
00167                 gz_error(state, Z_DATA_ERROR, "unknown header flags set");
00168                 return -1;
00169             }
00170             NEXT();                 /* modification time */
00171             NEXT();
00172             NEXT();
00173             NEXT();
00174             NEXT();                 /* extra flags */
00175             NEXT();                 /* operating system */
00176             if (flags & 4) {        /* extra field */
00177                 len = (unsigned)NEXT();
00178                 len += (unsigned)NEXT() << 8;
00179                 while (len--)
00180                     if (NEXT() < 0)
00181                         break;
00182             }
00183             if (flags & 8)          /* file name */
00184                 while (NEXT() > 0)
00185                     ;
00186             if (flags & 16)         /* comment */
00187                 while (NEXT() > 0)
00188                     ;
00189             if (flags & 2) {        /* header crc */
00190                 NEXT();
00191                 NEXT();
00192             }
00193             /* an unexpected end of file is not checked for here -- it will be
00194                noticed on the first request for uncompressed data */
00195 
00196             /* set up for decompression */
00197             inflateReset(strm);
00198             strm->adler = crc32(0L, Z_NULL, 0);
00199             state->how = GZIP;
00200             state->direct = 0;
00201             return 0;
00202         }
00203         else {
00204             /* not a gzip file -- save first byte (31) and fall to raw i/o */
00205             state->out[0] = 31;
00206             state->have = 1;
00207         }
00208     }
00209 
00210     /* doing raw i/o, save start of raw data for seeking, copy any leftover
00211        input to output -- this assumes that the output buffer is larger than
00212        the input buffer, which also assures space for gzungetc() */
00213     state->raw = state->pos;
00214     state->next = state->out;
00215     if (strm->avail_in) {
00216         memcpy(state->next + state->have, strm->next_in, strm->avail_in);
00217         state->have += strm->avail_in;
00218         strm->avail_in = 0;
00219     }
00220     state->how = COPY;
00221     state->direct = 1;
00222     return 0;
00223 }
00224 
00225 /* Decompress from input to the provided next_out and avail_out in the state.
00226    If the end of the compressed data is reached, then verify the gzip trailer
00227    check value and length (modulo 2^32).  state->have and state->next are set
00228    to point to the just decompressed data, and the crc is updated.  If the
00229    trailer is verified, state->how is reset to LOOK to look for the next gzip
00230    stream or raw data, once state->have is depleted.  Returns 0 on success, -1
00231    on failure.  Failures may include invalid compressed data or a failed gzip
00232    trailer verification. */
00233 local int gz_decomp(state)
00234     gz_statep state;
00235 {
00236     int ret;
00237     unsigned had;
00238     unsigned long crc, len;
00239     z_streamp strm = &(state->strm);
00240 
00241     /* fill output buffer up to end of deflate stream */
00242     had = strm->avail_out;
00243     do {
00244         /* get more input for inflate() */
00245         if (strm->avail_in == 0 && gz_avail(state) == -1)
00246             return -1;
00247         if (strm->avail_in == 0) {
00248             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
00249             return -1;
00250         }
00251 
00252         /* decompress and handle errors */
00253         ret = inflate(strm, Z_NO_FLUSH);
00254         if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
00255             gz_error(state, Z_STREAM_ERROR,
00256                       "internal error: inflate stream corrupt");
00257             return -1;
00258         }
00259         if (ret == Z_MEM_ERROR) {
00260             gz_error(state, Z_MEM_ERROR, "out of memory");
00261             return -1;
00262         }
00263         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
00264             gz_error(state, Z_DATA_ERROR,
00265                       strm->msg == NULL ? "compressed data error" : strm->msg);
00266             return -1;
00267         }
00268     } while (strm->avail_out && ret != Z_STREAM_END);
00269 
00270     /* update available output and crc check value */
00271     state->have = had - strm->avail_out;
00272     state->next = strm->next_out - state->have;
00273     strm->adler = crc32(strm->adler, state->next, state->have);
00274 
00275     /* check gzip trailer if at end of deflate stream */
00276     if (ret == Z_STREAM_END) {
00277         if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
00278             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
00279             return -1;
00280         }
00281         if (crc != strm->adler) {
00282             gz_error(state, Z_DATA_ERROR, "incorrect data check");
00283             return -1;
00284         }
00285         if (len != (strm->total_out & 0xffffffffL)) {
00286             gz_error(state, Z_DATA_ERROR, "incorrect length check");
00287             return -1;
00288         }
00289         state->how = LOOK;      /* ready for next stream, once have is 0 (leave
00290                                    state->direct unchanged to remember how) */
00291     }
00292 
00293     /* good decompression */
00294     return 0;
00295 }
00296 
00297 /* Make data and put in the output buffer.  Assumes that state->have == 0.
00298    Data is either copied from the input file or decompressed from the input
00299    file depending on state->how.  If state->how is LOOK, then a gzip header is
00300    looked for (and skipped if found) to determine wither to copy or decompress.
00301    Returns -1 on error, otherwise 0.  gz_make() will leave state->have as COPY
00302    or GZIP unless the end of the input file has been reached and all data has
00303    been processed.  */
00304 local int gz_make(state)
00305     gz_statep state;
00306 {
00307     z_streamp strm = &(state->strm);
00308 
00309     if (state->how == LOOK) {           /* look for gzip header */
00310         if (gz_head(state) == -1)
00311             return -1;
00312         if (state->have)                /* got some data from gz_head() */
00313             return 0;
00314     }
00315     if (state->how == COPY) {           /* straight copy */
00316         if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
00317             return -1;
00318         state->next = state->out;
00319     }
00320     else if (state->how == GZIP) {      /* decompress */
00321         strm->avail_out = state->size << 1;
00322         strm->next_out = state->out;
00323         if (gz_decomp(state) == -1)
00324             return -1;
00325     }
00326     return 0;
00327 }
00328 
00329 /* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
00330 local int gz_skip(state, len)
00331     gz_statep state;
00332     z_off64_t len;
00333 {
00334     unsigned n;
00335 
00336     /* skip over len bytes or reach end-of-file, whichever comes first */
00337     while (len)
00338         /* skip over whatever is in output buffer */
00339         if (state->have) {
00340             n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
00341                 (unsigned)len : state->have;
00342             state->have -= n;
00343             state->next += n;
00344             state->pos += n;
00345             len -= n;
00346         }
00347 
00348         /* output buffer empty -- return if we're at the end of the input */
00349         else if (state->eof && state->strm.avail_in == 0)
00350             break;
00351 
00352         /* need more data to skip -- load up output buffer */
00353         else {
00354             /* get more output, looking for header if required */
00355             if (gz_make(state) == -1)
00356                 return -1;
00357         }
00358     return 0;
00359 }
00360 
00361 /* -- see zlib.h -- */
00362 int ZEXPORT gzread(file, buf, len)
00363     gzFile file;
00364     voidp buf;
00365     unsigned len;
00366 {
00367     unsigned got, n;
00368     gz_statep state;
00369     z_streamp strm;
00370 
00371     /* get internal structure */
00372     if (file == NULL)
00373         return -1;
00374     state = (gz_statep)file;
00375     strm = &(state->strm);
00376 
00377     /* check that we're reading and that there's no error */
00378     if (state->mode != GZ_READ || state->err != Z_OK)
00379         return -1;
00380 
00381     /* since an int is returned, make sure len fits in one, otherwise return
00382        with an error (this avoids the flaw in the interface) */
00383     if ((int)len < 0) {
00384         gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
00385         return -1;
00386     }
00387 
00388     /* if len is zero, avoid unnecessary operations */
00389     if (len == 0)
00390         return 0;
00391 
00392     /* process a skip request */
00393     if (state->seek) {
00394         state->seek = 0;
00395         if (gz_skip(state, state->skip) == -1)
00396             return -1;
00397     }
00398 
00399     /* get len bytes to buf, or less than len if at the end */
00400     got = 0;
00401     do {
00402         /* first just try copying data from the output buffer */
00403         if (state->have) {
00404             n = state->have > len ? len : state->have;
00405             memcpy(buf, state->next, n);
00406             state->next += n;
00407             state->have -= n;
00408         }
00409 
00410         /* output buffer empty -- return if we're at the end of the input */
00411         else if (state->eof && strm->avail_in == 0)
00412             break;
00413 
00414         /* need output data -- for small len or new stream load up our output
00415            buffer */
00416         else if (state->how == LOOK || len < (state->size << 1)) {
00417             /* get more output, looking for header if required */
00418             if (gz_make(state) == -1)
00419                 return -1;
00420             continue;       /* no progress yet -- go back to memcpy() above */
00421             /* the copy above assures that we will leave with space in the
00422                output buffer, allowing at least one gzungetc() to succeed */
00423         }
00424 
00425         /* large len -- read directly into user buffer */
00426         else if (state->how == COPY) {      /* read directly */
00427             if (gz_load(state, buf, len, &n) == -1)
00428                 return -1;
00429         }
00430 
00431         /* large len -- decompress directly into user buffer */
00432         else {  /* state->how == GZIP */
00433             strm->avail_out = len;
00434             strm->next_out = buf;
00435             if (gz_decomp(state) == -1)
00436                 return -1;
00437             n = state->have;
00438             state->have = 0;
00439         }
00440 
00441         /* update progress */
00442         len -= n;
00443         buf = (char *)buf + n;
00444         got += n;
00445         state->pos += n;
00446     } while (len);
00447 
00448     /* return number of bytes read into user buffer (will fit in int) */
00449     return (int)got;
00450 }
00451 
00452 /* -- see zlib.h -- */
00453 int ZEXPORT gzgetc(file)
00454     gzFile file;
00455 {
00456     int ret;
00457     unsigned char buf[1];
00458     gz_statep state;
00459 
00460     /* get internal structure */
00461     if (file == NULL)
00462         return -1;
00463     state = (gz_statep)file;
00464 
00465     /* check that we're reading and that there's no error */
00466     if (state->mode != GZ_READ || state->err != Z_OK)
00467         return -1;
00468 
00469     /* try output buffer (no need to check for skip request) */
00470     if (state->have) {
00471         state->have--;
00472         state->pos++;
00473         return *(state->next)++;
00474     }
00475 
00476     /* nothing there -- try gzread() */
00477     ret = gzread(file, buf, 1);
00478     return ret < 1 ? -1 : buf[0];
00479 }
00480 
00481 /* -- see zlib.h -- */
00482 int ZEXPORT gzungetc(c, file)
00483     int c;
00484     gzFile file;
00485 {
00486     gz_statep state;
00487 
00488     /* get internal structure */
00489     if (file == NULL)
00490         return -1;
00491     state = (gz_statep)file;
00492 
00493     /* check that we're reading and that there's no error */
00494     if (state->mode != GZ_READ || state->err != Z_OK)
00495         return -1;
00496 
00497     /* process a skip request */
00498     if (state->seek) {
00499         state->seek = 0;
00500         if (gz_skip(state, state->skip) == -1)
00501             return -1;
00502     }
00503 
00504     /* can't push EOF */
00505     if (c < 0)
00506         return -1;
00507 
00508     /* if output buffer empty, put byte at end (allows more pushing) */
00509     if (state->have == 0) {
00510         state->have = 1;
00511         state->next = state->out + (state->size << 1) - 1;
00512         state->next[0] = c;
00513         state->pos--;
00514         return c;
00515     }
00516 
00517     /* if no room, give up (must have already done a gzungetc()) */
00518     if (state->have == (state->size << 1)) {
00519         gz_error(state, Z_BUF_ERROR, "out of room to push characters");
00520         return -1;
00521     }
00522 
00523     /* slide output data if needed and insert byte before existing data */
00524     if (state->next == state->out) {
00525         unsigned char *src = state->out + state->have;
00526         unsigned char *dest = state->out + (state->size << 1);
00527         while (src > state->out)
00528             *--dest = *--src;
00529         state->next = dest;
00530     }
00531     state->have++;
00532     state->next--;
00533     state->next[0] = c;
00534     state->pos--;
00535     return c;
00536 }
00537 
00538 /* -- see zlib.h -- */
00539 char * ZEXPORT gzgets(file, buf, len)
00540     gzFile file;
00541     char *buf;
00542     int len;
00543 {
00544     unsigned left, n;
00545     char *str;
00546     unsigned char *eol;
00547     gz_statep state;
00548 
00549     /* check parameters and get internal structure */
00550     if (file == NULL || buf == NULL || len < 1)
00551         return NULL;
00552     state = (gz_statep)file;
00553 
00554     /* check that we're reading and that there's no error */
00555     if (state->mode != GZ_READ || state->err != Z_OK)
00556         return NULL;
00557 
00558     /* process a skip request */
00559     if (state->seek) {
00560         state->seek = 0;
00561         if (gz_skip(state, state->skip) == -1)
00562             return NULL;
00563     }
00564 
00565     /* copy output bytes up to new line or len - 1, whichever comes first --
00566        append a terminating zero to the string (we don't check for a zero in
00567        the contents, let the user worry about that) */
00568     str = buf;
00569     left = (unsigned)len - 1;
00570     if (left) do {
00571         /* assure that something is in the output buffer */
00572         if (state->have == 0) {
00573             if (gz_make(state) == -1)
00574                 return NULL;            /* error */
00575             if (state->have == 0) {     /* end of file */
00576                 if (buf == str)         /* got bupkus */
00577                     return NULL;
00578                 break;                  /* got something -- return it */
00579             }
00580         }
00581 
00582         /* look for end-of-line in current output buffer */
00583         n = state->have > left ? left : state->have;
00584         eol = memchr(state->next, '\n', n);
00585         if (eol != NULL)
00586             n = (unsigned)(eol - state->next) + 1;
00587 
00588         /* copy through end-of-line, or remainder if not found */
00589         memcpy(buf, state->next, n);
00590         state->have -= n;
00591         state->next += n;
00592         state->pos += n;
00593         left -= n;
00594         buf += n;
00595     } while (left && eol == NULL);
00596 
00597     /* found end-of-line or out of space -- terminate string and return it */
00598     buf[0] = 0;
00599     return str;
00600 }
00601 
00602 /* -- see zlib.h -- */
00603 int ZEXPORT gzdirect(file)
00604     gzFile file;
00605 {
00606     gz_statep state;
00607 
00608     /* get internal structure */
00609     if (file == NULL)
00610         return 0;
00611     state = (gz_statep)file;
00612 
00613     /* check that we're reading */
00614     if (state->mode != GZ_READ)
00615         return 0;
00616 
00617     /* if the state is not known, but we can find out, then do so (this is
00618        mainly for right after a gzopen() or gzdopen()) */
00619     if (state->how == LOOK && state->have == 0)
00620         (void)gz_head(state);
00621 
00622     /* return 1 if reading direct, 0 if decompressing a gzip stream */
00623     return state->direct;
00624 }
00625 
00626 /* -- see zlib.h -- */
00627 int ZEXPORT gzclose_r(file)
00628     gzFile file;
00629 {
00630     int ret;
00631     gz_statep state;
00632 
00633     /* get internal structure */
00634     if (file == NULL)
00635         return Z_STREAM_ERROR;
00636     state = (gz_statep)file;
00637 
00638     /* check that we're reading */
00639     if (state->mode != GZ_READ)
00640         return Z_STREAM_ERROR;
00641 
00642     /* free memory and close file */
00643     if (state->size) {
00644         inflateEnd(&(state->strm));
00645         free(state->out);
00646         free(state->in);
00647     }
00648     gz_error(state, Z_OK, NULL);
00649     free(state->path);
00650     ret = close(state->fd);
00651     free(state);
00652     return ret ? Z_ERRNO : Z_OK;
00653 }

Generated on Wed Oct 20 2010 11:12:18 for APBS by  doxygen 1.7.2