[alt.sources] [comp.unix.misc] Re: Recovering corrupted tar's

jpr@jpradley.uucp (Jean-Pierre Radley) (10/15/90)

Archive-name: tarskip/13-Oct-90
Original-posting-by: jpr@jpradley.uucp (Jean-Pierre Radley)
Original-subject: Re: Recovering corrupted tar's
Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)

[Reposted from comp.unix.misc.
Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti).]

In article <ENAG.90Oct4231246@svarte.ifi.uio.no> enag@ifi.uio.no (Erik Naggum) writes:
>In article <4121@neuro.med.umn.edu> alk@neuro.med.umn.edu (Anthony L Kimball) writes:
>
>   So, anyone have a handy-dandy tool to patch a tar archive which
>   has had it's leading N blocks overwritten?  I do so hate to do this
>   by hand.
>
>The files occupying the first n blocks are lost, where n >= N.  The
>problem is to find the value of n.
> ......
>                                  Searching programs shouldn't be that
>hard to write, either, but I don't think anybody has done this, yet.


Well, this often helps:


/* tarskip.c
 * taken from volume 2, number 8 of Unix World.
 * Usage: tarskip pathname [tardevice] | tar xvfn -
 * The pathname argument is the first file you can
 * think of after the bad spot on the archive.
 */
#include <stdio.h>

#define TARBLKSZ 1024	/* Block size on YOUR tar disk */
#define TRUE	 1	/* Boolean true */
#define FALSE	 0	/* Boolean false */

/* Global variables */

FILE *fp, *efopen();	/* file pointer for tar device file */
char fd;		/* file descriptor for tar device file */
char buf[TARBLKSZ];	/* buffer for "tar blocks" */
char *progname;
char *tardev = "/dev/rfd0"; /* Substitute YOUR default device name !! */

main(argc, argv)
int argc;
char *argv[];
{
	char *pathname;
	int match = FALSE;		/*Initialize to zero */
	progname = argv[0];

/* Process command line arguments */

	if (argc == 1 || argc > 3) {	/* Correct # of args? */
	     error("Usage: %s pathname [tardevice] | tar xvfn -", progname); }
	pathname = argv[1];		/* The pattern string to search for */
	if (argc == 3)
		tardev= argv[2];	/* Use device other than default */
	
		fp= efopen(tardev,"r");	/* Open for reading */
		fd= fileno(fp);		/* File descriptor */

/* Find block containing desired pathname */

	do {	getblk(tardev);
		match = strncmp(pathname, buf, strlen(pathname));
	} while (match);

/* Then read and process disk blocks "forever" */

	while (TRUE) { write(1, buf, sizeof(buf));
		       getblk(tardev); }
}

getblk(device)		/* Read the next block into the buffer */
char *device;		/* The tar disk device name */
{
	int c, done, n;
begin:	n = (read(fd, buf, sizeof(buf)));	/* Read a block */

	if (n ==0) { 				/* End of disk */
		done = query("\nEnd of disk, read another (y/n)? ");
		if (!done) {			/* Not done */
			close(fd);		/* Close previous device */
			fprintf(stderr, "Insert next disk and");
			fprintf(stderr, " press <ENTER> when ready\n");
			while ((c=getchar()) != '\n' && c != EOF)
				; 		/* Wait for ENTER */
			fp= efopen(device,"r");	/* Open for reading */
			fd= fileno(fp);		/* File descriptor */
			goto begin; /* Get first block from next disk */
		} else				/* Done */
			exit (0);
	} else if (n < 0) {			/* Tape read error */
		done = query("\nRead error, ignore (y/n)? ");
		if (done) {
			close(fd);
			fprintf(stderr, "Goodbye ... \n");
			exit(2);
		}
	}
}

query(msg)		/* Display message and prompt for continuance */
char *msg;
{
	int c, c2;
	fprintf(stderr, "%s", msg);
	c = c2 = getchar();
	while (c2 != '\n' && c2 != EOF)
		c2 = getchar(); 	/* Ignore remaining input */
	if (c == 'y' || c == 'Y') 	/* First char was y or Y */
	return(0);		 	/* Not done */
	else
	return(1);		 	/* Done */
}

error(s1, s2)		/* print error message and die */
char	*s1, *s2;
{
	extern	int	errno, sys_nerr;
	extern	char	*sys_errlist[], *progname;

	if (progname)
		fprintf(stderr, "%s: ", progname);
	fprintf(stderr, s1, s2);
	if (errno >0 && errno < sys_nerr)
			fprintf(stderr, "	(%s)", sys_errlist[errno]);
	fprintf(stderr, "\n");
	exit(1);
}

FILE *efopen(file, mode)	/* fopen file, call error() & die if can't */
char *file, *mode;
{
	FILE	*f;
	extern char *progname;
	char	str[80], *s=str;

	if	((f = fopen(file,mode)) != (FILE *)0)
		return f;
	sprintf(s, "can't open file %s mode %s\n", file, mode);
	error(s);
}
-- 
 Jean-Pierre Radley          HIGH-Q	     jpr@jpradley	CIS: 72160,1341