/* gzread.c -- zlib functions for reading gzip files
- * Copyright (C) 2004, 2005, 2010, 2011 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
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;
/* 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);
if (gz_decomp(state) == -1)
return -1;
}
- } while (state->x.have == 0);
+ } while (state->x.have == 0 && (!state->eof || strm->avail_in));
return 0;
}
/* 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;
}
}
/* 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 */
/* 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;
}
/* -- 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;
(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++;
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;
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;
}
state->x.next--;
state->x.next[0] = c;
state->x.pos--;
+ state->past = 0;
return c;
}
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;
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;
}
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;
}
int ZEXPORT gzclose_r(file)
gzFile file;
{
- int ret;
+ int ret, err;
gz_statep state;
/* get internal structure */
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;
}