v04i032: fixtar - A filter for converting absolute tar pathnames to relative

Steve Hayman sahayman at watmath.UUCP
Fri Aug 19 12:50:33 AEST 1988


Posting-number: Volume 4, Issue 32
Submitted-by: "Steve Hayman" <sahayman at watmath.UUCP>
Archive-name: fixtar

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by sahayman at math.waterloo.edu on Thu Aug 18 22:49:24 EDT 1988
# Contents:  README fixtar.c
 
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
"fixtar" is a filter that knows what tar-format looks like, and removes
leading '/' from any absolute pathnames in the tar file.  This can
be handy if you have a tar tape with absolute paths and want to
extract the files into other locations.  You can do something like

	dd if=$TAPE ibs=10k | fixtar | tar xf -

and all the /path/names will be extracted as "path/names".

I hope this is of use to somebody.  On the whole you're probably
better off getting John Gilmore's public-domain "tar", which
also handles this problem and has many other nice features.  This
is just a quick hack solution... I've used it on 4.3 BSD, it
ought to work elsewhere but unfortunately I can't be sure.

@..Steve Hayman, U. of Waterloo
  sahayman at math.waterloo.edu

P.S. No makefile (just "cc -o fixtar fixtar.c" should do it), no man page,
  no apologies :-)
@//E*O*F README//
chmod u=rw,g=r,o=r README
 
echo x - fixtar.c
sed 's/^@//' > "fixtar.c" <<'@//E*O*F fixtar.c//'
#include <stdio.h>
/*
 * fixtar - a filter to convert absolute pathnames
 * in tar to relative, by shifting them left one byte..
 * this filter changes "/path/name" to "path/name"
 *
 * Usage: something like
 * dd if=$TAPE | fixtar | tar xf -
 *
 * If the tar tape has "/path/name" in it, fixtar will
 * convert that to "path/name" and tar will extract it
 * relative to the current directory.
 *
 * You might want something like "dd if=$TAPE ibs=10k" to read
 * the tape properly.
 * I have used this on 4.3 BSD only.  It ought to work on
 * other versions of Unix but unfortunately I have no way of knowing.
 *
 * This program knows about tar format and is careful to diddle
 * only the header blocks, not the data blocks.
 *
 * You're probably better off using John Gilmore's public-domain "tar",
 * which always extracts with relative pathnames.  (And which has
 * many other nice features.)
 *
 * .. Steve Hayman, U. of Waterloo
 *    sahayman at math.waterloo.edu
 */

/*
 * these definitions are straight out of "man 5 tar"
 */
#define TBLOCK	512
#define NAMSIZ	100

union hblock {
	char dummy[TBLOCK];
	struct header {
		char name[NAMSIZ];
		char mode[8];
		char uid[8];
		char gid[8];
		char size[12];
		char mtime[12];
		char chksum[8];
		char linkflag;
		char linkname[NAMSIZ];
	} dbuf;
};

union hblock hb;

main()
{
	register int i;
	char *p;
	int size;
	int chksum;
	int zerob = 0;

	while ( ( i = read(0, hb.dummy, (int)sizeof(hb.dummy))) > 0   ) {
		if ( hb.dbuf.name[0] == '\0' ) {
			zerob++;
			write(1, hb.dummy, i);
			/*
			 * two zero blocks in a row means end-of-archive
			 */
			if ( zerob == 2 ) {
				/*
				 * read and write anything that's left,
				 * what the heck.
				 */
				while ( (i = read(0, hb.dummy,
						(int)sizeof(hb.dummy))) > 0 ) {
					write(1, hb.dummy, i);
				}
				exit(0);
			}
			continue;
		}
		zerob = 0;
		p = hb.dbuf.name;
		if ( *p == '/' ) {
			/*
			 * Shift the name left one char, which
			 * removes the leading '/'
			 */
			p++;
			do {
				*(p-1) = *p;
			} while ( *p++ );	/* up to and including '\0' */

			fprintf(stderr, "Adjusted: /%s\n", hb.dbuf.name );

			/*
			 * Fix the checksum - we have one less '/' in the
			 * header (and one more '\0' that doesn't change
			 * the checksum)
			 */
			sscanf(hb.dbuf.chksum, " %o", &chksum );
			chksum -= '/';
			/*
			 * "each field of width w has w-2 digits,
			 *  a space and a null, except chksum which
			 *  has a null followed by a space"
			 */
			sprintf( hb.dbuf.chksum, "%6o", chksum);
			
		}
		write( 1, hb.dummy, i);
		sscanf(hb.dbuf.size, " %o", &size);
		while ( size > 0 ) {
			i = read(0, hb.dummy, (int)sizeof(hb.dummy) );
			write( 1, hb.dummy, i);
			size -= sizeof(hb.dummy);
		}
	}
	exit(0);
}
@//E*O*F fixtar.c//
chmod u=rw,g=r,o=r fixtar.c
 
exit 0



More information about the Comp.sources.misc mailing list