v07i002: Tools to read damaged tar tapes (tar_aids)

sources-request at mirror.UUCP sources-request at mirror.UUCP
Tue Aug 26 06:35:49 AEST 1986


Submitted by: pyramid!utzoo!henry
Mod.sources: Volume 7, Issue 2
Archive-name: tar_aids


[  I wrote the Makefile and repacked the archive.  These tools are
   very useful!  --r$  ]

#!/bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".

# Exit status; set to 1 on "wc" errors or if would overwrite.
STATUS=0
# Contents:  README Makefile targ.1 targ.c tarl.c
 
echo x - README
if test -f README ; then
    echo README exists, putting output in $$README
    OUT=$$README
    STATUS=1
else
    OUT=README
fi
sed 's/^XX//' > $OUT <<'@//E*O*F README//'
XXHere are two small public-domain programs for scavenging files from
XXdamaged tar tapes.  They don't sing or dance, but they are highly
XXportable, and they are simple enough that they are readily understood
XXand changed to meet special requirements.  They aren't the most
XXbeautiful code on Earth, since they are basically cleaned-up versions
XXof quick-and-dirty improvisations.  They do, however, work.
@//E*O*F README//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - Makefile
if test -f Makefile ; then
    echo Makefile exists, putting output in $$Makefile
    OUT=$$Makefile
    STATUS=1
else
    OUT=Makefile
fi
sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//'
XXall:	targ tarl

XXtarg:	targ.c
XX	cc $(CFLAGS) -o $@ $<

XXtarl:	tarl.c
XX	cc $(CFLAGS) -o $@ $<

XX# The 'echo' causes the "right thing" to happen on 4.[23]BSD systems.
XXDEST	= /usr/local/bin
XXMAN	= /usr/man/man1
XXinstall:	all
XX	cp targ tarl $DEST
XX	cp targ.1 $MAN/targ.1
XX	echo ".so man1/tarl.1" >$MAN/targ.1
@//E*O*F Makefile//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - targ.1
if test -f targ.1 ; then
    echo targ.1 exists, putting output in $$targ.1
    OUT=$$targ.1
    STATUS=1
else
    OUT=targ.1
fi
sed 's/^XX//' > $OUT <<'@//E*O*F targ.1//'
XX.TH TARG 1 local
XX.DA 23 July 1986
XX.SH NAME
XXtarg, tarl \- recover files from damaged tar-format archives
XX.SH SYNOPSIS
XX\fBtarg\fR file ...
XX.PP
XX\fBtarl\fR
XX.SH DESCRIPTION
XX\fITarg\fR and \fItarl\fR are used to list and recover files from a
XXdamaged \fItar\fR(1) archive.
XXThey use a simplistic pattern-matching
XXapproach to identify \fItar\fR header blocks.
XXBoth will cheerfully ignore all sorts of bad things about the archive
XX(such as wrong checksums, read errors, and scraped-off magnetic surface...),
XXup to a maximum of twenty hard errors in a row.
XXThey report on such things as apparent end-of-file.
XXBoth programs read the \fItar\fR archive from standard input.
XX.PP
XX\fITarl\fR lists the file names it sees in the archive.
XXIt is particularly useful for 
XXpreparing a file of names for use with \fItarg\fR.
XX.PP
XX\fITarg\fR takes file or directory names as arguments
XXand attempts to extract them from the archive.
XX\fITarg\fR is not willing to create directories, however,
XXso these must be made manually beforehand if they do not already exist.
XXFiles are owned by the user, and have his default permissions.
XX.SH EXAMPLE
XX``tarl < /dev/rmt8 > filelist'' lists all files on the tape
XXmounted on /dev/rmt8 and places the results in ``filelist''.
XX.PP
XX``targ joe/precious < /dev/rmt0'' restores the file
XX``joe/precious'' from the tape mounted on /dev/rmt0.
XXThe directory ``joe'' must already exist.
XX.SH SEE ALSO
XXtar(1)
XX.SH HISTORY
XXWritten by Henry Spencer, Univ. of Toronto Zoology.
XXThis software is public domain.
XXManual page by Chris Robertson.
XX.SH BUGS
XX\fITarg\fR should be smarter about directories and permissions.
XX.PP
XXThey really should use the \fItar\fR header-block checksum,
XXinstead of the slightly-arcane pattern matcher, to identify header blocks.
@//E*O*F targ.1//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - targ.c
if test -f targ.c ; then
    echo targ.c exists, putting output in $$targ.c
    OUT=$$targ.c
    STATUS=1
else
    OUT=targ.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F targ.c//'
XX#include <stdio.h>

XX#define NAMSIZ 100
XXstruct matches {
XX	int offset;
XX	char value;
XX} matches[] = {
XX	NAMSIZ+6,	' ',
XX	NAMSIZ+7,	'\0',
XX	NAMSIZ+8+6,	' ',
XX	NAMSIZ+8+7,	'\0',
XX	NAMSIZ+16+6,	' ',
XX	NAMSIZ+16+7,	'\0',
XX	NAMSIZ+24+11,	' ',
XX	NAMSIZ+36+11,	' ',
XX	NAMSIZ+48+6,	'\0',
XX	0,		0,
XX};

XXint
XXistar(block)
XXchar *block;
XX{
XX	int loop;

XX	for (loop = 0; matches[loop].offset != 0; loop++)
XX		if (block[matches[loop].offset] != matches[loop].value)
XX			return(0);
XX	return(1);
XX}

XXchar buf[10240];
XXint bad;
XXint nleft = 0;
XXint whichnow;

XXint opened = 0;
XXint f;
XXlong nwrite;

XXmain(argc, argv)
XXint argc;
XXchar **argv;
XX{
XX	int loop;
XX	char *block;
XX	extern char *readblock();

XX	bad = 0;

XX	for(;;) {
XX		block = readblock(0);

XX		if (block != NULL)
XX			doblock(block, argc, argv);
XX	}
XX}

XXdoblock(block, argc, argv)
XXchar *block;
XXint argc;
XXchar **argv;
XX{
XX	int count;

XX	if (istar(block)) {
XX		if (opened) {
XX			printf("--- premature end\n");
XX			close(f);
XX			opened = 0;
XX		}
XX		if (match(block, argc, argv)) {
XX			f = creat(block, 0666);
XX			if (f < 0)
XX				printf("--- unable to create %s\n", block);
XX			else {
XX				opened = 1;
XX				sscanf(block+NAMSIZ+24, "%lo", &nwrite);
XX				printf("--- reading %s %ld\n", block, nwrite);
XX				if (nwrite <= 0) {
XX					close(f);
XX					opened = 0;
XX					printf("--- done\n");
XX				}
XX			}
XX		}
XX	} else {
XX		if (opened) {
XX			count = (nwrite > 512) ? 512 : (int)nwrite;
XX			write(f, block, count);
XX			nwrite -= count;
XX			if (nwrite <= 0) {
XX				opened = 0;
XX				close(f);
XX				printf("--- done\n");
XX			}
XX		}
XX	}
XX}

XXint
XXmatch(s, argc, argv)
XXchar *s;
XXint argc;
XXchar **argv;
XX{
XX	int i;
XX	int c;

XX	for (i = 1; i < argc; i++) {
XX		if (strncmp(s, argv[i], strlen(argv[i])) == 0) {
XX			c = s[strlen(argv[i])];
XX			if (c == '\0' || c == '/')
XX				return(1);
XX		}
XX	}
XX	return(0);
XX}

XXchar *
XXreadblock(desc)
XXint desc;
XX{
XX	int count;

XX	if (nleft > 0) {
XX		whichnow++;
XX		nleft--;
XX		return(buf+whichnow*512);
XX	}

XX	count = read(desc, buf, (int)sizeof(buf));
XX	if (count <= 0 || count%512 != 0) {
XX		if (count == 0)
XX			printf("---apparent EOF\n");
XX		else
XX			printf("---error\n");
XX		if (bad > 20)
XX			exit(1);
XX		bad++;
XX		return(NULL);
XX	}
XX	bad = 0;
XX	whichnow = 0;
XX	nleft = count/512 - 1;
XX	return(buf);
XX}
@//E*O*F targ.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - tarl.c
if test -f tarl.c ; then
    echo tarl.c exists, putting output in $$tarl.c
    OUT=$$tarl.c
    STATUS=1
else
    OUT=tarl.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F tarl.c//'
XX#include <stdio.h>

XX#define NAMSIZ 100
XXstruct matches {
XX	int offset;
XX	char value;
XX} matches[] = {
XX	NAMSIZ+6,	' ',
XX	NAMSIZ+7,	'\0',
XX	NAMSIZ+8+6,	' ',
XX	NAMSIZ+8+7,	'\0',
XX	NAMSIZ+16+6,	' ',
XX	NAMSIZ+16+7,	'\0',
XX	NAMSIZ+24+11,	' ',
XX	NAMSIZ+36+11,	' ',
XX	NAMSIZ+48+6,	'\0',
XX	0,		0,
XX};

XXint
XXistar(block)
XXchar *block;
XX{
XX	int loop;

XX	for (loop = 0; matches[loop].offset != 0; loop++)
XX		if (block[matches[loop].offset] != matches[loop].value)
XX			return(0);
XX	return(1);
XX}

XXchar buf[10240];
XXint bad;
XXint nleft = 0;
XXint whichnow;

XXmain()
XX{
XX	int loop;
XX	int dir;
XX	char *block;
XX	extern char *readblock();

XX	bad = 0;

XX	for(;;) {
XX		block = readblock(0);

XX		if (block != NULL && istar(block))
XX			printf("%s\n", block);
XX	}
XX}

XXchar *
XXreadblock(desc)
XXint desc;
XX{
XX	int count;

XX	if (nleft > 0) {
XX		whichnow++;
XX		nleft--;
XX		return(buf+whichnow*512);
XX	}

XX	count = read(desc, buf, (int)sizeof(buf));
XX	if (count <= 0 || count%512 != 0) {
XX		if (count == 0)
XX			printf("---apparent EOF\n");
XX		else
XX			printf("---error\n");
XX		if (bad > 20)
XX			exit(1);
XX		bad++;
XX		return(NULL);
XX	}
XX	bad = 0;
XX	whichnow = 0;
XX	nleft = count/512 - 1;
XX	return(buf);
XX}
@//E*O*F tarl.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo Inspecting for damage in transit...
temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
       6      60     398 README
      15      48     295 Makefile
      46     274    1744 targ.1
     147     329    2148 targ.c
      81     163    1112 tarl.c
     295     874    5697 total
!!!
wc $FILES | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if test -s $dtemp ; then
    echo "Ouch [diff of wc output]:"
    cat $dtemp
    STATUS=1
elif test $STATUS = 0 ; then
    echo "No problems found."
else
    echo "WARNING -- PROBLEMS WERE FOUND..."
fi
exit $STATUS



More information about the Mod.sources mailing list