aboutsummaryrefslogtreecommitdiff
path: root/lib/libstand/gzipfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libstand/gzipfs.c')
-rw-r--r--lib/libstand/gzipfs.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/lib/libstand/gzipfs.c b/lib/libstand/gzipfs.c
index 02195d80f4fd..9cc9ad9957f7 100644
--- a/lib/libstand/gzipfs.c
+++ b/lib/libstand/gzipfs.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
struct z_file
{
int zf_rawfd;
+ off_t zf_dataoffset;
z_stream zf_zstream;
char zf_buf[Z_BUFSIZE];
};
@@ -98,11 +99,12 @@ zf_fill(struct z_file *zf)
* Returns 0 if the header is OK, nonzero if not.
*/
static int
-get_byte(struct z_file *zf)
+get_byte(struct z_file *zf, off_t *curoffp)
{
if ((zf->zf_zstream.avail_in == 0) && (zf_fill(zf) == -1))
return(-1);
zf->zf_zstream.avail_in--;
+ ++*curoffp;
return(*(zf->zf_zstream.next_in)++);
}
@@ -124,36 +126,37 @@ check_header(struct z_file *zf)
uInt len;
int c;
+ zf->zf_dataoffset = 0;
/* Check the gzip magic header */
for (len = 0; len < 2; len++) {
- c = get_byte(zf);
+ c = get_byte(zf, &zf->zf_dataoffset);
if (c != gz_magic[len]) {
return(1);
}
}
- method = get_byte(zf);
- flags = get_byte(zf);
+ method = get_byte(zf, &zf->zf_dataoffset);
+ flags = get_byte(zf, &zf->zf_dataoffset);
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
return(1);
}
/* Discard time, xflags and OS code: */
- for (len = 0; len < 6; len++) (void)get_byte(zf);
+ for (len = 0; len < 6; len++) (void)get_byte(zf, &zf->zf_dataoffset);
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
- len = (uInt)get_byte(zf);
- len += ((uInt)get_byte(zf))<<8;
+ len = (uInt)get_byte(zf, &zf->zf_dataoffset);
+ len += ((uInt)get_byte(zf, &zf->zf_dataoffset))<<8;
/* len is garbage if EOF but the loop below will quit anyway */
- while (len-- != 0 && get_byte(zf) != -1) ;
+ while (len-- != 0 && get_byte(zf, &zf->zf_dataoffset) != -1) ;
}
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
- while ((c = get_byte(zf)) != 0 && c != -1) ;
+ while ((c = get_byte(zf, &zf->zf_dataoffset)) != 0 && c != -1) ;
}
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
- while ((c = get_byte(zf)) != 0 && c != -1) ;
+ while ((c = get_byte(zf, &zf->zf_dataoffset)) != 0 && c != -1) ;
}
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
- for (len = 0; len < 2; len++) c = get_byte(zf);
+ for (len = 0; len < 2; len++) c = get_byte(zf, &zf->zf_dataoffset);
}
/* if there's data left, we're in business */
return((c == -1) ? 1 : 0);
@@ -274,6 +277,20 @@ zf_read(struct open_file *f, void *buf, size_t size, size_t *resid)
return(0);
}
+static int
+zf_rewind(struct open_file *f)
+{
+ struct z_file *zf = (struct z_file *)f->f_fsdata;
+
+ if (lseek(zf->zf_rawfd, zf->zf_dataoffset, SEEK_SET) == -1)
+ return -1;
+ zf->zf_zstream.avail_in = 0;
+ zf->zf_zstream.next_in = NULL;
+ (void)inflateReset(&zf->zf_zstream);
+
+ return 0;
+}
+
static off_t
zf_seek(struct open_file *f, off_t offset, int where)
{
@@ -292,11 +309,9 @@ zf_seek(struct open_file *f, off_t offset, int where)
target = -1;
}
- /* Can we get there from here? */
- if (target < zf->zf_zstream.total_out) {
- errno = EOFFSET;
+ /* rewind if required */
+ if (target < zf->zf_zstream.total_out && zf_rewind(f) != 0)
return -1;
- }
/* skip forwards if required */
while (target > zf->zf_zstream.total_out) {