]> git.lizzy.rs Git - zlib.git/blobdiff - gzread.c
Use const for static tree descriptions in deflate.
[zlib.git] / gzread.c
index a41e5d940e9e71449e93a8444e8d53c9b0fcfc4d..bf4538eb274245ad118edd3eaac38ee9e697c2b5 100644 (file)
--- a/gzread.c
+++ b/gzread.c
@@ -1,5 +1,5 @@
 /* gzread.c -- zlib functions for reading gzip files
- * Copyright (C) 2004, 2005, 2010 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -57,8 +57,14 @@ local int gz_avail(state)
     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
         return -1;
     if (state->eof == 0) {
-        if (strm->avail_in)
-            memmove(state->in, strm->next_in, strm->avail_in);
+        if (strm->avail_in) {       /* copy what's there to the start */
+            unsigned char *p = state->in;
+            unsigned const char *q = strm->next_in;
+            unsigned n = strm->avail_in;
+            do {
+                *p++ = *q++;
+            } while (--n);
+        }
         if (gz_load(state, state->in + strm->avail_in,
                     state->size - strm->avail_in, &got) == -1)
             return -1;
@@ -68,7 +74,7 @@ local int gz_avail(state)
     return 0;
 }
 
-/* Look for gzip header, set up for inflate or copy.  state->have must be zero.
+/* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.
    If this is the first time in, allocate required memory.  state->how will be
    left unchanged if there is no more input data available, will be set to COPY
    if there is no gzip header and direct copying will be performed, or it will
@@ -85,8 +91,8 @@ local int gz_look(state)
     /* allocate read buffers and inflate memory */
     if (state->size == 0) {
         /* allocate buffers */
-        state->in = malloc(state->want);
-        state->out = malloc(state->want << 1);
+        state->in = (unsigned char *)malloc(state->want);
+        state->out = (unsigned char *)malloc(state->want << 1);
         if (state->in == NULL || state->out == NULL) {
             if (state->out != NULL)
                 free(state->out);
@@ -140,17 +146,17 @@ local int gz_look(state)
     if (state->direct == 0) {
         strm->avail_in = 0;
         state->eof = 1;
-        state->have = 0;
+        state->x.have = 0;
         return 0;
     }
 
     /* doing raw i/o, copy any leftover input to output -- this assumes that
        the output buffer is larger than the input buffer, which also assures
        space for gzungetc() */
-    state->next = state->out;
+    state->x.next = state->out;
     if (strm->avail_in) {
-        memcpy(state->next, strm->next_in, strm->avail_in);
-        state->have = strm->avail_in;
+        memcpy(state->x.next, strm->next_in, strm->avail_in);
+        state->x.have = strm->avail_in;
         strm->avail_in = 0;
     }
     state->how = COPY;
@@ -159,10 +165,10 @@ local int gz_look(state)
 }
 
 /* Decompress from input to the provided next_out and avail_out in the state.
-   state->have and state->next are set to point to the just decompressed data,
-   If the gzip stream completes, state->how is reset to LOOK to look for the
-   next gzip stream or raw data, once state->have is depleted.  Returns 0 on
-   success, -1 on failure. */
+   On return, state->x.have and state->x.next point to the just decompressed
+   data.  If the gzip stream completes, state->how is reset to LOOK to look for
+   the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
+   on success, -1 on failure. */
 local int gz_decomp(state)
     gz_statep state;
 {
@@ -200,8 +206,8 @@ local int gz_decomp(state)
     } while (strm->avail_out && ret != Z_STREAM_END);
 
     /* update available output */
-    state->have = had - strm->avail_out;
-    state->next = strm->next_out - state->have;
+    state->x.have = had - strm->avail_out;
+    state->x.next = strm->next_out - state->x.have;
 
     /* if the gzip stream completed successfully, look for another */
     if (ret == Z_STREAM_END)
@@ -211,7 +217,7 @@ local int gz_decomp(state)
     return 0;
 }
 
-/* Fetch data and put it in the output buffer.  Assumes that state->have == 0.
+/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
    Data is either copied from the input file or decompressed from the input
    file depending on state->how.  If state->how is LOOK, then a gzip header is
    looked for to determine whether to copy or decompress.  Returns -1 on error,
@@ -231,10 +237,10 @@ local int gz_fetch(state)
                 return 0;
             break;
         case COPY:      /* -> COPY */
-            if (gz_load(state, state->out, state->size << 1, &(state->have))
+            if (gz_load(state, state->out, state->size << 1, &(state->x.have))
                     == -1)
                 return -1;
-            state->next = state->out;
+            state->x.next = state->out;
             return 0;
         case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */
             strm->avail_out = state->size << 1;
@@ -242,7 +248,7 @@ local int gz_fetch(state)
             if (gz_decomp(state) == -1)
                 return -1;
         }
-    } while (state->have == 0);
+    } while (state->x.have == 0 && (!state->eof || strm->avail_in));
     return 0;
 }
 
@@ -256,12 +262,12 @@ local int gz_skip(state, len)
     /* skip over len bytes or reach end-of-file, whichever comes first */
     while (len)
         /* skip over whatever is in output buffer */
-        if (state->have) {
-            n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
-                (unsigned)len : state->have;
-            state->have -= n;
-            state->next += n;
-            state->pos += n;
+        if (state->x.have) {
+            n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
+                (unsigned)len : state->x.have;
+            state->x.have -= n;
+            state->x.next += n;
+            state->x.pos += n;
             len -= n;
         }
 
@@ -302,7 +308,7 @@ int ZEXPORT gzread(file, buf, len)
     /* since an int is returned, make sure len fits in one, otherwise return
        with an error (this avoids the flaw in the interface) */
     if ((int)len < 0) {
-        gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
+        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
         return -1;
     }
 
@@ -321,16 +327,18 @@ int ZEXPORT gzread(file, buf, len)
     got = 0;
     do {
         /* first just try copying data from the output buffer */
-        if (state->have) {
-            n = state->have > len ? len : state->have;
-            memcpy(buf, state->next, n);
-            state->next += n;
-            state->have -= n;
+        if (state->x.have) {
+            n = state->x.have > len ? len : state->x.have;
+            memcpy(buf, state->x.next, n);
+            state->x.next += n;
+            state->x.have -= n;
         }
 
         /* output buffer empty -- return if we're at the end of the input */
-        else if (state->eof && strm->avail_in == 0)
+        else if (state->eof && strm->avail_in == 0) {
+            state->past = 1;        /* tried to read past end */
             break;
+        }
 
         /* need output data -- for small len or new stream load up our output
            buffer */
@@ -338,32 +346,32 @@ int ZEXPORT gzread(file, buf, len)
             /* get more output, looking for header if required */
             if (gz_fetch(state) == -1)
                 return -1;
-            continue;       /* no progress yet -- go back to memcpy() above */
+            continue;       /* no progress yet -- go back to copy above */
             /* the copy above assures that we will leave with space in the
                output buffer, allowing at least one gzungetc() to succeed */
         }
 
         /* large len -- read directly into user buffer */
         else if (state->how == COPY) {      /* read directly */
-            if (gz_load(state, buf, len, &n) == -1)
+            if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
                 return -1;
         }
 
         /* large len -- decompress directly into user buffer */
         else {  /* state->how == GZIP */
             strm->avail_out = len;
-            strm->next_out = buf;
+            strm->next_out = (unsigned char *)buf;
             if (gz_decomp(state) == -1)
                 return -1;
-            n = state->have;
-            state->have = 0;
+            n = state->x.have;
+            state->x.have = 0;
         }
 
         /* update progress */
         len -= n;
         buf = (char *)buf + n;
         got += n;
-        state->pos += n;
+        state->x.pos += n;
     } while (len);
 
     /* return number of bytes read into user buffer (will fit in int) */
@@ -371,6 +379,11 @@ int ZEXPORT gzread(file, buf, len)
 }
 
 /* -- see zlib.h -- */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#else
+#  undef gzgetc
+#endif
 int ZEXPORT gzgetc(file)
     gzFile file;
 {
@@ -389,10 +402,10 @@ int ZEXPORT gzgetc(file)
         return -1;
 
     /* try output buffer (no need to check for skip request) */
-    if (state->have) {
-        state->have--;
-        state->pos++;
-        return *(state->next)++;
+    if (state->x.have) {
+        state->x.have--;
+        state->x.pos++;
+        return *(state->x.next)++;
     }
 
     /* nothing there -- try gzread() */
@@ -400,6 +413,12 @@ int ZEXPORT gzgetc(file)
     return ret < 1 ? -1 : buf[0];
 }
 
+int ZEXPORT gzgetc_(file)
+gzFile file;
+{
+    return gzgetc(file);
+}
+
 /* -- see zlib.h -- */
 int ZEXPORT gzungetc(c, file)
     int c;
@@ -429,32 +448,34 @@ int ZEXPORT gzungetc(c, file)
         return -1;
 
     /* if output buffer empty, put byte at end (allows more pushing) */
-    if (state->have == 0) {
-        state->have = 1;
-        state->next = state->out + (state->size << 1) - 1;
-        state->next[0] = c;
-        state->pos--;
+    if (state->x.have == 0) {
+        state->x.have = 1;
+        state->x.next = state->out + (state->size << 1) - 1;
+        state->x.next[0] = c;
+        state->x.pos--;
+        state->past = 0;
         return c;
     }
 
     /* if no room, give up (must have already done a gzungetc()) */
-    if (state->have == (state->size << 1)) {
-        gz_error(state, Z_BUF_ERROR, "out of room to push characters");
+    if (state->x.have == (state->size << 1)) {
+        gz_error(state, Z_DATA_ERROR, "out of room to push characters");
         return -1;
     }
 
     /* slide output data if needed and insert byte before existing data */
-    if (state->next == state->out) {
-        unsigned char *src = state->out + state->have;
+    if (state->x.next == state->out) {
+        unsigned char *src = state->out + state->x.have;
         unsigned char *dest = state->out + (state->size << 1);
         while (src > state->out)
             *--dest = *--src;
-        state->next = dest;
+        state->x.next = dest;
     }
-    state->have++;
-    state->next--;
-    state->next[0] = c;
-    state->pos--;
+    state->x.have++;
+    state->x.next--;
+    state->x.next[0] = c;
+    state->x.pos--;
+    state->past = 0;
     return c;
 }
 
@@ -493,30 +514,31 @@ char * ZEXPORT gzgets(file, buf, len)
     left = (unsigned)len - 1;
     if (left) do {
         /* assure that something is in the output buffer */
-        if (state->have == 0 && gz_fetch(state) == -1)
+        if (state->x.have == 0 && gz_fetch(state) == -1)
             return NULL;                /* error */
-        if (state->have == 0) {         /* end of file */
-            if (buf == str)             /* got bupkus */
-                return NULL;
-            break;                      /* got something -- return it */
+        if (state->x.have == 0) {       /* end of file */
+            state->past = 1;            /* read past end */
+            break;                      /* return what we have */
         }
 
         /* look for end-of-line in current output buffer */
-        n = state->have > left ? left : state->have;
-        eol = memchr(state->next, '\n', n);
+        n = state->x.have > left ? left : state->x.have;
+        eol = (unsigned char *)memchr(state->x.next, '\n', n);
         if (eol != NULL)
-            n = (unsigned)(eol - state->next) + 1;
+            n = (unsigned)(eol - state->x.next) + 1;
 
         /* copy through end-of-line, or remainder if not found */
-        memcpy(buf, state->next, n);
-        state->have -= n;
-        state->next += n;
-        state->pos += n;
+        memcpy(buf, state->x.next, n);
+        state->x.have -= n;
+        state->x.next += n;
+        state->x.pos += n;
         left -= n;
         buf += n;
     } while (left && eol == NULL);
 
-    /* found end-of-line or out of space -- terminate string and return it */
+    /* return terminated string, or if nothing, end of file */
+    if (buf == str)
+        return NULL;
     buf[0] = 0;
     return str;
 }
@@ -532,16 +554,12 @@ int ZEXPORT gzdirect(file)
         return 0;
     state = (gz_statep)file;
 
-    /* check that we're reading */
-    if (state->mode != GZ_READ)
-        return 0;
-
     /* if the state is not known, but we can find out, then do so (this is
        mainly for right after a gzopen() or gzdopen()) */
-    if (state->how == LOOK && state->have == 0)
+    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
         (void)gz_look(state);
 
-    /* return 1 if reading direct, 0 if decompressing a gzip stream */
+    /* return 1 if transparent, 0 if processing a gzip stream */
     return state->direct;
 }
 
@@ -549,7 +567,7 @@ int ZEXPORT gzdirect(file)
 int ZEXPORT gzclose_r(file)
     gzFile file;
 {
-    int ret;
+    int ret, err;
     gz_statep state;
 
     /* get internal structure */
@@ -567,9 +585,10 @@ int ZEXPORT gzclose_r(file)
         free(state->out);
         free(state->in);
     }
+    err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
     gz_error(state, Z_OK, NULL);
     free(state->path);
     ret = close(state->fd);
     free(state);
-    return ret ? Z_ERRNO : Z_OK;
+    return ret ? Z_ERRNO : err;
 }