🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

2 total messages Started by Bill Vaughn Tue, 19 Mar 1985 22:05
Tar EOT bug and fix
#422
Author: Bill Vaughn
Date: Tue, 19 Mar 1985 22:05
109 lines
3866 bytes
After several people ran tape reels on the end of the drive with tar
over the last few months, it became clear that tar wasn't dealing with
the EOT mark properly. I know, I know, nobody should use a whole tape,
but some persons have VERY large files which I am happy to see archived,
and anything to makes life easier for them makes it easier for me. (Rewinding
spun-off reels is a pain too.)  Tar should be more robust in principle anyway.

The problem is the 'write' in the 'writetape' routine.  It assumes errors have
occured ONLY when 'write' returns a negative value.  But tests (and looking at
code) confirm that 'write' returns a 0 when the tape driver hits EOT. It's
telling a lie, of course, because the record really was written. The fix is
easy.  Just have tar's 'write' check that the # bytes requested == # bytes
written.  If not, we either have a write error or are at EOT. In the
latter case one can even write out a zeroed block to keep subsequent 'reads'
happy.

(Tests also confirmed that 'reads' across EOT's don't return errors. They return
the actual record that 'write' denied it had written. If it makes any
difference, we have a 750 with a TU-80. The driver is /sys/vaxuba/ts.c)

'Tar' has had several fixes and enhancements since the original distribution
so I'm only giving the context diff relative to the original 4.2bsd version.
Fixes for other versions are very similar.

*** tar.org.c
--- tar.fix.c	Tue Mar 19 16:25:19 1985
***************
*** 1092,1101
  {
  	first = 1;
  	if (recno >= nblock) {
! 		if (write(mt, tbuf, TBLOCK*nblock) < 0) {
! 			fprintf(stderr, "tar: tape write error\n");
! 			done(2);
! 		}
  		recno = 0;
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);

--- 1092,1098 -----
  {
  	first = 1;
  	if (recno >= nblock) {
! 		flushtape();
  		recno = 0;
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);
***************
*** 1100,1109
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);
  	if (recno >= nblock) {
! 		if (write(mt, tbuf, TBLOCK*nblock) < 0) {
! 			fprintf(stderr, "tar: tape write error\n");
! 			done(2);
! 		}
  		recno = 0;
  	}
  	return (TBLOCK);

--- 1097,1103 -----
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);
  	if (recno >= nblock) {
! 		flushtape();
  		recno = 0;
  	}
  	return (TBLOCK);
***************
*** 1129,1135
  
  flushtape()
  {
! 	write(mt, tbuf, TBLOCK*nblock);
  }
  
  bread(fd, buf, size)

--- 1123,1147 -----
  
  flushtape()
  {
! 	register int n;
! 
! 	if ((n=write(mt, tbuf, TBLOCK*nblock)) != TBLOCK*nblock) {
! 		if (n)
! 			fprintf(stderr, "tar: tape write error\n");
! 		else
! 			fprintf(stderr, "tar: EOT mark encountered. ");
! 			/*
! 			 * With a little work one could decide if the
! 			 * following is really true. Be conservative.
! 			 */
! 			fprintf(stderr, "Last file is incomplete.\n");
! 			/*
! 			 * The following keeps subsequent reads happy.
! 			 */
! 			bzero(tbuf, TBLOCK*nblock);
! 			write(mt, tbuf, TBLOCK*nblock);
! 		done(2);
! 	}
  }
  
  bread(fd, buf, size)

***********************

Bill Vaughn, UNIV. OF ROCHESTER, Center for Visual Science, Rochester NY
{allegra,seismo,decvax}!rochester!ur-cvsvax!bill
Re: Tar EOT bug and fix (with correction)
#423
Author: Bill Vaughn
Date: Thu, 21 Mar 1985 05:36
94 lines
2818 bytes
Sorry, I screwed up my first bug-fix posting. No excuses.
Here it is again. (Actually, this is not exactlly the way I fixed
my version. But the way I did it works.  This method should work also.)
Corrections are noted by !!--->  .

*** tar.org.c
--- tar.fix.c	Tue Mar 19 16:25:19 1985
***************
*** 1092,1101
  {
  	first = 1;
  	if (recno >= nblock) {
! 		if (write(mt, tbuf, TBLOCK*nblock) < 0) {
! 			fprintf(stderr, "tar: tape write error\n");
! 			done(2);
! 		}
  		recno = 0;
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);

--- 1092,1098 -----
  {
  	first = 1;
  	if (recno >= nblock) {
! 		flushtape();
  		recno = 0;
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);
***************
*** 1100,1109
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);
  	if (recno >= nblock) {
! 		if (write(mt, tbuf, TBLOCK*nblock) < 0) {
! 			fprintf(stderr, "tar: tape write error\n");
! 			done(2);
! 		}
  		recno = 0;
  	}
  	return (TBLOCK);

--- 1097,1103 -----
  	}
  	bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);
  	if (recno >= nblock) {
! 		flushtape();
  		recno = 0;
  	}
  	return (TBLOCK);
***************
*** 1129,1135
  
  flushtape()
  {
! 	write(mt, tbuf, TBLOCK*nblock);
  }
  
  bread(fd, buf, size)

--- 1123,1147 -----
  
  flushtape()
  {
! 	register int n;
! 
! 	if ((n=write(mt, tbuf, TBLOCK*nblock)) != TBLOCK*nblock) {
! 		if (n)
! 			fprintf(stderr, "tar: tape write error\n");
!!---> 		else {
! 			fprintf(stderr, "tar: EOT mark encountered. ");
! 			/*
! 			 * With a little work one could decide if the
! 			 * following is really true. Be conservative.
! 			 */
! 			fprintf(stderr, "Last file is incomplete.\n");
! 			/*
! 			 * The following keeps subsequent reads happy.
! 			 */
! 			bzero(tbuf, TBLOCK*nblock);
! 			write(mt, tbuf, TBLOCK*nblock);
!!--->		}
! 		done(2);
! 	}
  }
  
  bread(fd, buf, size)
***********************

 Bill Vaughn, U. of Rochester
 {allegra,seismo,decvax}!rochester!ur-cvsvax!bill

"Hey, you're going to love this program now that
 I've added all of these new bu ... er, features."
					Anonymous Hacker
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads