summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2021-12-01 15:38:02 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2021-12-15 15:04:50 -0800
commitcf26200380585019e927fe3cf5c0ecb7c8b3ef14 (patch)
tree0601d06babe8944698e14b7fc3889a06bdb942f9 /util.c
parent1440bdbd16cc40f3ef3d0d91106373e29611f528 (diff)
downloadgzip-cf26200380585019e927fe3cf5c0ecb7c8b3ef14.tar.gz
gzip: gzip -l now outputs accurate size
gzip -l now decompresses to see how long the uncompressed file was. This fixes what is by far the most common bug report for gzip. It has a significant performance cost, but it’s worth it nowadays. * gzip.c (main): -l now sets 'test' too. All uses of 'test' changed. (treat_stdin, treat_file): Call do_list after decompressing, so that the length is known. (do_list): Omit arg IFD, since it is no longer needed. All callers changed. Get the CRC and uncompressed size from input_crc and bytes_out instead of using lseek. * tests/list-big: New test. * unzip.c (unzip): Set unzip_crc before returning. * util.c (write_buf): If 'test', output nothing. Update bytes_out with output byte count, regardless of 'test'. All callers changed.
Diffstat (limited to 'util.c')
-rw-r--r--util.c18
1 files changed, 8 insertions, 10 deletions
diff --git a/util.c b/util.c
index 4e73036..cd43886 100644
--- a/util.c
+++ b/util.c
@@ -112,7 +112,6 @@ int copy(in, out)
errno = 0;
while (insize > inptr) {
write_buf(out, (char*)inbuf + inptr, insize - inptr);
- bytes_out += insize - inptr;
got = read_buffer (in, (char *) inbuf, INBUFSIZ);
if (got == -1)
read_error();
@@ -255,9 +254,7 @@ void flush_outbuf()
{
if (outcnt == 0) return;
- if (!test)
- write_buf (ofd, outbuf, outcnt);
- bytes_out += (off_t)outcnt;
+ write_buf (ofd, outbuf, outcnt);
outcnt = 0;
}
@@ -270,16 +267,13 @@ void flush_window()
if (outcnt == 0) return;
updcrc(window, outcnt);
- if (!test) {
- write_buf(ofd, (char *)window, outcnt);
- }
- bytes_out += (off_t)outcnt;
+ write_buf (ofd, window, outcnt);
outcnt = 0;
}
/* ===========================================================================
- * Does the same as write(), but also handles partial pipe writes and checks
- * for error return.
+ * Update the count of output bytes. If testing, do not do any
+ * output. Otherwise, write the buffer, checking for errors.
*/
void write_buf(fd, buf, cnt)
int fd;
@@ -288,6 +282,10 @@ void write_buf(fd, buf, cnt)
{
unsigned n;
+ bytes_out += cnt;
+ if (test)
+ return;
+
while ((n = write_buffer (fd, buf, cnt)) != cnt) {
if (n == (unsigned)(-1)) {
write_error();