[net.bugs.4bsd] 4.1c restor bug

bukys@rochester.UUCP (07/06/83)

Here's a copy of a bug report I just sent in to 4bsd-bugs@Berkeley.
In summary:  for some reason I haven't guessed, one of the dumped
directories in my 4.1->4.1c conversion dump tape was a little strange,
with the result that restor ignored most of the directory structure,
hence skipped most of the files on tape.  A two-line fix got my files
back for me.  Hope I've saved somebody some work.

>From:	bukys@rochester.ARPA
>To:	4bsd-bugs@Berkeley
>Subject: 4.1c restor bug
>Index:	etc/restor 4.1c Fix

Description:
	It is possible for a dump(8) tape to have an inconsistent idea
	of the length of a file.  (It happened to me!)  Then restor(8)
	may find a data block when it is expecting a header block.  As
	the header parsing routine does a consistency check, this
	should not be much of a problem.  However, in one case the code
	does not check the value returned by the header parsing
	routine, and treats the data block as a very strange header
	block.  If this happens while reading directory files from the
	tape, it will think it has reached the end of the directory
	dump, but will not have built up the entire directory
	structure.  (This is what happened to me.)  The subsequent
	restoration will skip the files without corresponding directory
	information.

Repeat-By:
	I suppose I could send you the tape.  The problem was that the
	inode said that the file was 1056 bytes (2 blocks) long, but
	the c_addr array said there were 3 data blocks (there were).
	Furthermore, this file (a directory!) had a hole.  The most
	obvious warning was 150 "missing directory entry" messages.
	The second most obvious warning was that very few files were
	getting restored.

Fix:
	(version is "@(#)restor.c 2.17 1/8/83") (line 769) (fix in #ifdef UR)

		if ((size -= TP_BSIZE) <= 0) {
	#ifdef UR
			while (gethead(&spcl) == 0)
				fprintf(stderr, "warning: discrepancy between c_addr array and inode's di_size: data block ignored\n");
	#else
			gethead(&spcl);
	#endif
			goto out;
		}

Comments:
	A more general fix might trust the c_addr array more than the
	size stated in the inode.  That's more complicated than this
	one-line fix, though.  And this is, after all, a problem that
	"should never happen", as they say.

	While you're there, it should check all results from calloc()
	and malloc() for NULL, especially since getleaves() can build
	up quite a structure.

	And, whenever you get around to re-implementing the 'r' flag,
	it should *say something* if it skips a file on the tape (this
	should never happen on a full restore).

---------------
Liudvikas Bukys
rochester!bukys
bukys@rochester

bukys@rochester.UUCP (07/06/83)

Relay-Version:version B 2.10 5/3/83; site wjh12.UUCP
Posting-Version:version B 2.10 5/3/83; site rochester.UUCP
Path:wjh12!genrad!linus!philabs!seismo!rochester!bukys
Message-ID:<2150@rochester.UUCP>
Date:Tue, 5-Jul-83 21:06:35 EDT
Organization:University of Rochester

Here's a copy of a bug report I just sent in to 4bsd-bugs@Berkeley.
In summary:  for some reason I haven't guessed, one of the dumped
directories in my 4.1->4.1c conversion dump tape was a little strange,
with the result that restor ignored most of the directory structure,
hence skipped most of the files on tape.  A two-line fix got my files
back for me.  Hope I've saved somebody some work.

>From:	bukys@rochester.ARPA
>To:	4bsd-bugs@Berkeley
>Subject: 4.1c restor bug
>Index:	etc/restor 4.1c Fix

Description:
	It is possible for a dump(8) tape to have an inconsistent idea
	of the length of a file.  (It happened to me!)  Then restor(8)
	may find a data block when it is expecting a header block.  As
	the header parsing routine does a consistency check, this
	should not be much of a problem.  However, in one case the code
	does not check the value returned by the header parsing
	routine, and treats the data block as a very strange header
	block.  If this happens while reading directory files from the
	tape, it will think it has reached the end of the directory
	dump, but will not have built up the entire directory
	structure.  (This is what happened to me.)  The subsequent
	restoration will skip the files without corresponding directory
	information.

Repeat-By:
	I suppose I could send you the tape.  The problem was that the
	inode said that the file was 1056 bytes (2 blocks) long, but
	the c_addr array said there were 3 data blocks (there were).
	Furthermore, this file (a directory!) had a hole.  The most
	obvious warning was 150 "missing directory entry" messages.
	The second most obvious warning was that very few files were
	getting restored.

Fix:
	(version is "@(#)restor.c 2.17 1/8/83") (line 769) (fix in #ifdef UR)

		if ((size -= TP_BSIZE) <= 0) {
	#ifdef UR
			while (gethead(&spcl) == 0)
				fprintf(stderr, "warning: discrepancy between c_addr array and inode's di_size: data block ignored\n");
	#else
			gethead(&spcl);
	#endif
			goto out;
		}

Comments:
	A more general fix might trust the c_addr array more than the
	size stated in the inode.  That's more complicated than this
	one-line fix, though.  And this is, after all, a problem that
	"should never happen", as they say.

	While you're there, it should check all results from calloc()
	and malloc() for NULL, especially since getleaves() can build
	up quite a structure.

	And, whenever you get around to re-implementing the 'r' flag,
	it should *say something* if it skips a file on the tape (this
	should never happen on a full restore).

---------------
Liudvikas Bukys
rochester!bukys
bukys@rochester