sahayman@watmath.UUCP (Steve Hayman) (08/19/88)
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