Currently, the info in "gzip -l" only accounts for the last stream
in the file. For example:
$ gzip.old -l valgrind-3.10.1p9.tgz
compressed uncompressed ratio uncompressed_name
2122549 9048576 76.5% valgrind-3.10.1p9.tar
$ gzip.new -l /usr/ports/packages/amd64/all/valgrind-3.10.1p9.tgz
compressed uncompressed ratio uncompressed_name
27988837 81453568 65.6% valgrind-3.10.1p9.tar
$ ls -l valgrind-3.10.1p9.tgz
-rw-r--r-- 3 millert staff 27988837 Mar 29 10:09 valgrind-3.10.1p9.tgz
$ gunzip -c valgrind-3.10.1p9.tgz | wc -c
81453568
Index: usr.bin/compress/gzopen.c
===================================================================
RCS file: /cvs/src/usr.bin/compress/gzopen.c,v
retrieving revision 1.29
diff -u -p -u -r1.29 gzopen.c
--- usr.bin/compress/gzopen.c 20 Aug 2015 22:32:41 -0000 1.29
+++ usr.bin/compress/gzopen.c 27 Apr 2016 20:34:20 -0000
@@ -83,14 +83,15 @@
typedef
struct gz_stream {
int z_fd; /* .gz file */
- z_stream z_stream; /* libz stream */
int z_eof; /* set if end of input file */
+ z_stream z_stream; /* libz stream */
u_char z_buf[Z_BUFSIZE]; /* i/o buffer */
+ char z_mode; /* 'w' or 'r' */
u_int32_t z_time; /* timestamp (mtime) */
- u_int32_t z_hlen; /* length of the gz header */
u_int32_t z_crc; /* crc32 of uncompressed data */
- char z_mode; /* 'w' or 'r' */
-
+ u_int32_t z_hlen; /* length of the gz header */
+ u_int64_t z_total_in; /* # bytes in */
+ u_int64_t z_total_out; /* # bytes out */
} gz_stream;
static const u_char gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
@@ -128,6 +129,8 @@ gz_open(int fd, const char *mode, char *
s->z_eof = 0;
s->z_time = 0;
s->z_hlen = 0;
+ s->z_total_in = 0;
+ s->z_total_out = 0;
s->z_crc = crc32(0L, Z_NULL, 0);
s->z_mode = mode[0];
@@ -206,8 +209,8 @@ gz_close(void *cookie, struct z_info *in
info->mtime = s->z_time;
info->crc = s->z_crc;
info->hlen = s->z_hlen;
- info->total_in = (off_t)s->z_stream.total_in;
- info->total_out = (off_t)s->z_stream.total_out;
+ info->total_in = s->z_total_in;
+ info->total_out = s->z_total_out;
}
setfile(name, s->z_fd, sb);
@@ -336,7 +339,7 @@ get_header(gz_stream *s, char *name, int
(void)get_byte(s);
(void)get_byte(s);
- s->z_hlen = 10; /* magic, method, flags, time, xflags, OS code */
+ s->z_hlen += 10; /* magic, method, flags, time, xflags, OS code */
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
len = (uInt)get_byte(s);
len += ((uInt)get_byte(s))<<8;
@@ -438,11 +441,11 @@ gz_read(void *cookie, char *buf, int len
if (error == Z_DATA_ERROR) {
errno = EINVAL;
- return -1;
+ goto bad;
}
if (error == Z_BUF_ERROR) {
errno = EIO;
- return -1;
+ goto bad;
}
if (error == Z_STREAM_END) {
/* Check CRC and original size */
@@ -452,13 +455,18 @@ gz_read(void *cookie, char *buf, int len
if (get_int32(s) != s->z_crc) {
errno = EINVAL;
- return -1;
+ goto bad;
}
if (get_int32(s) != (u_int32_t)s->z_stream.total_out) {
errno = EIO;
return -1;
}
s->z_hlen += 2 * sizeof(int32_t);
+
+ /* Add byte counts from the finished stream. */
+ s->z_total_in += s->z_stream.total_in;
+ s->z_total_out += s->z_stream.total_out;
+
/* Check for the existence of an appended file. */
if (get_header(s, NULL, 0) != 0) {
s->z_eof = 1;
@@ -474,6 +482,11 @@ gz_read(void *cookie, char *buf, int len
len -= s->z_stream.avail_out;
return (len);
+bad:
+ /* Add byte counts from the finished stream. */
+ s->z_total_in += s->z_stream.total_in;
+ s->z_total_out += s->z_stream.total_out;
+ return (-1);
}
int