Subject: bin/31346: gzip should not give an error exit on large archives
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: seebs <seebs@vash.cel.plethora.net>
List: netbsd-bugs
Date: 09/19/2005 07:21:00
>Number:         31346
>Category:       bin
>Synopsis:       gzip erroneously indicates total failure on 4GB archives
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Sep 19 07:21:00 +0000 2005
>Originator:     seebs
>Release:        NetBSD 3.99.8
>Organization:
>Environment:
System: NetBSD vash.cel.plethora.net 3.99.8 NetBSD 3.99.8 (VASH) #0: Fri Sep 9 10:49:46 CDT 2005 seebs@vash.cel.plethora.net:/usr/src/sys/arch/i386/compile/VASH i386
Architecture: i386
Machine: i386
>Description:
	The thoughtful note that gzip cannot record an input data size
	over 4GB is useful.  Returning an error status, however, is
	catastrophic.  Programs such as amanda will THROW AWAY DATA if they
	think gzip failed!  Error status should be indicated only when
	compression has FAILED, not just because the compressed file has
	a quirk common to pretty much every large gzip data file of the
	past decade which will not prevent decompression.
>How-To-Repeat:
	Use gzip on big data.
>Fix:
	This patch adds a "maybe_gripe" feature which emits a warning message
	without setting an exit status.  It might be better to just not set
	an exit status on any warning.

Index: gzip.c
===================================================================
RCS file: /cvsroot/src/usr.bin/gzip/gzip.c,v
retrieving revision 1.73
diff -c -r1.73 gzip.c
*** gzip.c	28 Aug 2005 10:17:50 -0000	1.73
--- gzip.c	19 Sep 2005 07:17:24 -0000
***************
*** 172,177 ****
--- 172,179 ----
  static	void	maybe_errx(const char *fmt, ...)
      __attribute__((__format__(__printf__, 1, 2)));
  #endif
+ static	void	maybe_gripe(const char *fmt, ...)
+     __attribute__((__format__(__printf__, 1, 2)));
  static	void	maybe_warn(const char *fmt, ...)
      __attribute__((__format__(__printf__, 1, 2)));
  static	void	maybe_warnx(const char *fmt, ...)
***************
*** 366,371 ****
--- 368,386 ----
  	exit(exit_value);
  }
  
+ /* maybe complain, but don't touch exit status */
+ void
+ maybe_gripe(const char *fmt, ...)
+ {
+ 	va_list ap;
+ 
+ 	if (qflag == 0) {
+ 		va_start(ap, fmt);
+ 		vwarn(fmt, ap);
+ 		va_end(ap);
+ 	}
+ }
+ 
  /* maybe print a warning */
  void
  maybe_warn(const char *fmt, ...)
***************
*** 638,644 ****
  	if (i != 8)
  		maybe_err("snprintf");
  	if (in_tot > 0xffffffff)
! 		maybe_warn("input file size >= 4GB cannot be saved");
  	if (write(out, outbufp, i) != i) {
  		maybe_warn("write");
  		in_tot = -1;
--- 653,659 ----
  	if (i != 8)
  		maybe_err("snprintf");
  	if (in_tot > 0xffffffff)
! 		maybe_gripe("input file size >= 4GB cannot be saved");
  	if (write(out, outbufp, i) != i) {
  		maybe_warn("write");
  		in_tot = -1;