]> git.lizzy.rs Git - zlib.git/blobdiff - gzread.c
zlib 1.2.7.1
[zlib.git] / gzread.c
index 22eb6271a1534002f96ff68a8bc9b21613a3e6ed..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;
@@ -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);
@@ -242,7 +248,7 @@ local int gz_fetch(state)
             if (gz_decomp(state) == -1)
                 return -1;
         }
-    } while (state->x.have == 0);
+    } while (state->x.have == 0 && (!state->eof || strm->avail_in));
     return 0;
 }
 
@@ -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;
     }
 
@@ -329,8 +335,10 @@ int ZEXPORT gzread(file, buf, len)
         }
 
         /* 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,21 +346,21 @@ 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->x.have;
@@ -371,7 +379,12 @@ int ZEXPORT gzread(file, buf, len)
 }
 
 /* -- see zlib.h -- */
-int ZEXPORT gzgetc_(file)
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#else
+#  undef gzgetc
+#endif
+int ZEXPORT gzgetc(file)
     gzFile file;
 {
     int ret;
@@ -388,10 +401,7 @@ int ZEXPORT gzgetc_(file)
         (state->err != Z_OK && state->err != Z_BUF_ERROR))
         return -1;
 
-    /* try output buffer (no need to check for skip request) -- while
-       this check really isn't required since the gzgetc() macro has
-       already determined that x.have is zero, we leave it in for
-       completeness. */
+    /* try output buffer (no need to check for skip request) */
     if (state->x.have) {
         state->x.have--;
         state->x.pos++;
@@ -403,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;
@@ -437,12 +453,13 @@ int ZEXPORT gzungetc(c, file)
         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->x.have == (state->size << 1)) {
-        gz_error(state, Z_BUF_ERROR, "out of room to push characters");
+        gz_error(state, Z_DATA_ERROR, "out of room to push characters");
         return -1;
     }
 
@@ -458,6 +475,7 @@ int ZEXPORT gzungetc(c, file)
     state->x.next--;
     state->x.next[0] = c;
     state->x.pos--;
+    state->past = 0;
     return c;
 }
 
@@ -499,14 +517,13 @@ char * ZEXPORT gzgets(file, buf, len)
         if (state->x.have == 0 && gz_fetch(state) == -1)
             return NULL;                /* error */
         if (state->x.have == 0) {       /* end of file */
-            if (buf == str)             /* got bupkus */
-                return NULL;
-            break;                      /* got something -- return it */
+            state->past = 1;            /* read past end */
+            break;                      /* return what we have */
         }
 
         /* look for end-of-line in current output buffer */
         n = state->x.have > left ? left : state->x.have;
-        eol = memchr(state->x.next, '\n', n);
+        eol = (unsigned char *)memchr(state->x.next, '\n', n);
         if (eol != NULL)
             n = (unsigned)(eol - state->x.next) + 1;
 
@@ -519,7 +536,9 @@ char * ZEXPORT gzgets(file, buf, len)
         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;
 }
@@ -535,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->x.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;
 }
 
@@ -552,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 */
@@ -570,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;
 }