Subject: bin/8227: pax is too aggressive in avoiding old gnutar archive damage
To: None <gnats-bugs@gnats.netbsd.org>
From: Seebs <seebs@lobe.fleet.plethora.net>
List: netbsd-bugs
Date: 08/18/1999 10:50:55
>Number:         8227
>Category:       bin
>Synopsis:       pax has workarounds for GNU tar damage that are too complete
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Aug 18 10:50:01 1999
>Last-Modified:
>Originator:     Seebs
>Organization:
>Release:        Aug 1999
>Environment:
System: NetBSD lobe.fleet.plethora.net 1.4J NetBSD 1.4J (LOBE) #0: Tue Aug 17 10:44:59 PDT 1999 seebs@lobe.fleet.plethora.net:/usr/src/sys/arch/i386/compile/LOBE i386

>Description:
	There's a chunk of code in pax to work around "oldgnutar" (up through
	the version released last week, actually) damage, where you'd see
	spurious early end-of-archive.  It turns out it's too aggressive; the
	only "legitimate" failure mode is that GNU tar only writes one
	512-byte "trailer" block.  (Modulo padding, which means you only see
	this flaw one time in 20.)

>How-To-Repeat:
	Spend 3 hours studying tar archives and figuring out when they break.

>Fix:
	I have enclosed diffs which still don't complain about the "defective"
	GNU tar archives, but which will catch any *other* premature end of
	archive problems.

	GNU has accepted a bug report, and the next release of GNU tar should
	not have this problem.
*** ar_io.c.orig	Wed Aug 18 10:03:27 1999
--- ar_io.c	Wed Aug 18 10:04:14 1999
***************
*** 614,620 ****
  	lstrval = res;
  	if (res < 0)
  		syswarn(1, errno, "Failed read on archive volume %d", arvol);
! 	else if (!is_oldgnutar)
  		tty_warn(0, "End of archive volume %d reached", arvol);
  	return(res);
  } 
--- 614,620 ----
  	lstrval = res;
  	if (res < 0)
  		syswarn(1, errno, "Failed read on archive volume %d", arvol);
! 	else
  		tty_warn(0, "End of archive volume %d reached", arvol);
  	return(res);
  } 
***************
*** 1195,1201 ****
  	if (sigprocmask(SIG_SETMASK, &o_mask, (sigset_t *)NULL) < 0)
  		syswarn(0, errno, "Unable to restore signal mask");
  
! 	if (done || !wr_trail || is_oldgnutar)
  		return(-1);
  
  	tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
--- 1195,1201 ----
  	if (sigprocmask(SIG_SETMASK, &o_mask, (sigset_t *)NULL) < 0)
  		syswarn(0, errno, "Unable to restore signal mask");
  
! 	if (done || !wr_trail)
  		return(-1);
  
  	tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
*** ar_subs.c.orig	Wed Aug 18 10:03:32 1999
--- ar_subs.c	Wed Aug 18 10:03:58 1999
***************
*** 1009,1017 ****
  			 * storage device, better give the user the bad news.
  			 */
  			if ((ret == 0) || (rd_sync() < 0)) {
! 				if (!is_oldgnutar)
! 					tty_warn(1,
! 					    "Premature end of file on archive read");
  				return(-1);
  			}
  			if (!in_resync) {
--- 1009,1016 ----
  			 * storage device, better give the user the bad news.
  			 */
  			if ((ret == 0) || (rd_sync() < 0)) {
! 				tty_warn(1,
! 					"Premature end of file on archive read");
  				return(-1);
  			}
  			if (!in_resync) {
*** tar.c.orig	Wed Aug 18 10:03:35 1999
--- tar.c	Wed Aug 18 10:04:46 1999
***************
*** 164,170 ****
  	 * might as well throw this block out since a valid header can NEVER be
  	 * a block of all 0 (we must have a valid file name).
  	 */
! 	if (!in_resync && (++*cnt >= NULLCNT))
  		return(0);
  	return(1);
  }
--- 164,176 ----
  	 * might as well throw this block out since a valid header can NEVER be
  	 * a block of all 0 (we must have a valid file name).
  	 */
! 	++*cnt;
! 	/* old GNU tar (up through 1.13) only writes one block of trailers,
! 	 * so we pretend we got another
! 	 */
! 	if (is_oldgnutar)
! 		++*cnt;
! 	if (!in_resync && (*cnt >= NULLCNT))
  		return(0);
  	return(1);
  }
>Audit-Trail:
>Unformatted: