home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!rutgers!ucsd!ames!mailrus!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
- From: sahayman@watmath.UUCP (Steve Hayman)
- Newsgroups: comp.sources.misc
- Subject: v04i032: fixtar - A filter for converting absolute tar pathnames to relative
- Message-ID: <8808190250.AA12792@watmath>
- Date: 19 Aug 88 02:50:33 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: sahayman@watmath.UUCP (Steve Hayman)
- Lines: 160
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 4, Issue 32
- Submitted-by: "Steve Hayman" <sahayman@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@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@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@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
-