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