plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

tar.c (24113B)


      1 /*
      2  * tar - `tape archiver', actually usable on any medium.
      3  *	POSIX "ustar" compliant when extracting, and by default when creating.
      4  *	this tar attempts to read and write multiple Tblock-byte blocks
      5  *	at once to and from the filesystem, and does not copy blocks
      6  *	around internally.
      7  */
      8 
      9 #include <u.h>
     10 #include <libc.h>
     11 #include <fcall.h>		/* for %M */
     12 #include <libString.h>
     13 
     14 /*
     15  * modified versions of those in libc.h; scans only the first arg for
     16  * keyletters and options.
     17  */
     18 #define	TARGBEGIN {\
     19 	if (!argv0) argv0 = *argv; \
     20 	argv++, argc--;\
     21 	if (argv[0]) {\
     22 		char *_args, *_argt;\
     23 		Rune _argc;\
     24 		_args = &argv[0][0];\
     25 		_argc = 0;\
     26 		while(*_args && (_args += chartorune(&_argc, _args)))\
     27 			switch(_argc)
     28 #define	TARGEND	SET(_argt); USED(_argt);USED(_argc);USED(_args); \
     29 	argc--, argv++; } \
     30 	USED(argv); USED(argc); }
     31 #define	TARGC() (_argc)
     32 
     33 #define ROUNDUP(a, b)	(((a) + (b) - 1)/(b))
     34 #define BYTES2TBLKS(bytes) ROUNDUP(bytes, Tblock)
     35 
     36 /* read big-endian binary integers; args must be (uchar *) */
     37 #define	G2BEBYTE(x)	(((x)[0]<<8)  |  (x)[1])
     38 #define	G3BEBYTE(x)	(((x)[0]<<16) | ((x)[1]<<8)  |  (x)[2])
     39 #define	G4BEBYTE(x)	(((x)[0]<<24) | ((x)[1]<<16) | ((x)[2]<<8) | (x)[3])
     40 #define	G8BEBYTE(x)	(((vlong)G4BEBYTE(x)<<32) | (u32int)G4BEBYTE((x)+4))
     41 
     42 typedef vlong Off;
     43 typedef char *(*Refill)(int ar, char *bufs, int justhdr);
     44 
     45 enum { Stdin, Stdout, Stderr };
     46 enum { Rd, Wr };			/* pipe fd-array indices */
     47 enum { Output, Input };
     48 enum { None, Toc, Xtract, Replace };
     49 enum { Alldata, Justnxthdr };
     50 enum {
     51 	Tblock = 512,
     52 	Namsiz = 100,
     53 	Maxpfx = 155,		/* from POSIX */
     54 	Maxname = Namsiz + 1 + Maxpfx,
     55 	Binsize = 0x80,		/* flag in size[0], from gnu: positive binary size */
     56 	Binnegsz = 0xff,	/* flag in size[0]: negative binary size */
     57 
     58 	Nblock = 40,		/* maximum blocksize */
     59 	Dblock = 20,		/* default blocksize */
     60 	DEBUG = 0
     61 };
     62 
     63 /* POSIX link flags */
     64 enum {
     65 	LF_PLAIN1 =	'\0',
     66 	LF_PLAIN2 =	'0',
     67 	LF_LINK =	'1',
     68 	LF_SYMLINK1 =	'2',
     69 	LF_SYMLINK2 =	's',		/* 4BSD used this */
     70 	LF_CHR =	'3',
     71 	LF_BLK =	'4',
     72 	LF_DIR =	'5',
     73 	LF_FIFO =	'6',
     74 	LF_CONTIG =	'7'
     75 	/* 'A' - 'Z' are reserved for custom implementations */
     76 };
     77 
     78 #define islink(lf)	(isreallink(lf) || issymlink(lf))
     79 #define isreallink(lf)	((lf) == LF_LINK)
     80 #define issymlink(lf)	((lf) == LF_SYMLINK1 || (lf) == LF_SYMLINK2)
     81 
     82 typedef struct Hdr {
     83 	char	name[Namsiz];
     84 	char	mode[8];
     85 	char	uid[8];
     86 	char	gid[8];
     87 	char	size[12];
     88 	char	mtime[12];
     89 	char	chksum[8];
     90 	char	linkflag;
     91 	char	linkname[Namsiz];
     92 
     93 	/* rest are defined by POSIX's ustar format; see p1003.2b */
     94 	char	magic[6];	/* "ustar" */
     95 	char	version[2];
     96 	char	uname[32];
     97 	char	gname[32];
     98 	char	devmajor[8];
     99 	char	devminor[8];
    100 	char	prefix[Maxpfx]; /* if non-null, path= prefix "/" name */
    101 
    102 	char pad[12];
    103 } Hdr;
    104 
    105 typedef struct Compress {
    106 	char	*comp;
    107 	char	*decomp;
    108 	char	*sfx[4];
    109 } Compress;
    110 
    111 static Compress comps[] = {
    112 	"gzip",		"gunzip",	{ ".tar.gz", ".tgz" },	/* default */
    113 	"compress",	"uncompress",	{ ".tar.Z",  ".tz" },
    114 	"bzip2",	"bunzip2",	{ ".tar.bz", ".tbz",
    115 					  ".tar.bz2",".tbz2" },
    116 };
    117 
    118 typedef struct Pushstate {
    119 	int	kid;
    120 	int	fd;	/* original fd */
    121 	int	rfd;	/* replacement fd */
    122 	int	input;
    123 	int	open;
    124 } Pushstate;
    125 
    126 #define OTHER(rdwr) (rdwr == Rd? Wr: Rd)
    127 
    128 /* static int debug; */
    129 static int verb;
    130 static int posix = 1;
    131 static int docreate;
    132 static int aruid;
    133 static int argid;
    134 static int relative = 1;
    135 static int settime;
    136 static int verbose;
    137 static int docompress;
    138 static int keepexisting;
    139 static Off blkoff;	/* offset of the current archive block (not Tblock) */
    140 static Off nexthdr;
    141 
    142 static int nblock = Dblock;
    143 static char *usefile;
    144 static char origdir[Maxname*2];
    145 static Hdr *tpblk, *endblk;
    146 static Hdr *curblk;
    147 
    148 static void
    149 usage(void)
    150 {
    151 	fprint(2, "usage: %s {crtx}[PRTfgkmpuvz] [archive] file1 file2...\n",
    152 		argv0);
    153 	exits("usage");
    154 }
    155 
    156 /* compression */
    157 
    158 static Compress *
    159 compmethod(char *name)
    160 {
    161 	int i, nmlen = strlen(name), sfxlen;
    162 	Compress *cp;
    163 
    164 	for (cp = comps; cp < comps + nelem(comps); cp++)
    165 		for (i = 0; i < nelem(cp->sfx) && cp->sfx[i]; i++) {
    166 			sfxlen = strlen(cp->sfx[i]);
    167 			if (nmlen > sfxlen &&
    168 			    strcmp(cp->sfx[i], name + nmlen - sfxlen) == 0)
    169 				return cp;
    170 		}
    171 	return docompress? comps: nil;
    172 }
    173 
    174 /*
    175  * push a filter, cmd, onto fd.  if input, it's an input descriptor.
    176  * returns a descriptor to replace fd, or -1 on error.
    177  */
    178 static int
    179 push(int fd, char *cmd, int input, Pushstate *ps)
    180 {
    181 	int nfd, pifds[2];
    182 
    183 	ps->open = 0;
    184 	ps->fd = fd;
    185 	ps->input = input;
    186 	if (fd < 0 || pipe(pifds) < 0)
    187 		return -1;
    188 	ps->kid = fork();
    189 	switch (ps->kid) {
    190 	case -1:
    191 		return -1;
    192 	case 0:
    193 		if (input)
    194 			dup(pifds[Wr], Stdout);
    195 		else
    196 			dup(pifds[Rd], Stdin);
    197 		close(pifds[input? Rd: Wr]);
    198 		dup(fd, (input? Stdin: Stdout));
    199 		execl(cmd, cmd, nil);
    200 		sysfatal("can't exec %s: %r", cmd);
    201 	default:
    202 		nfd = pifds[input? Rd: Wr];
    203 		close(pifds[input? Wr: Rd]);
    204 		break;
    205 	}
    206 	ps->rfd = nfd;
    207 	ps->open = 1;
    208 	return nfd;
    209 }
    210 
    211 static char *
    212 pushclose(Pushstate *ps)
    213 {
    214 	Waitmsg *wm;
    215 
    216 	if (ps->fd < 0 || ps->rfd < 0 || !ps->open)
    217 		return "not open";
    218 	close(ps->rfd);
    219 	ps->rfd = -1;
    220 	ps->open = 0;
    221 	while ((wm = wait()) != nil && wm->pid != ps->kid)
    222 		continue;
    223 	return wm? wm->msg: nil;
    224 }
    225 
    226 /*
    227  * block-buffer management
    228  */
    229 
    230 static void
    231 initblks(void)
    232 {
    233 	free(tpblk);
    234 	tpblk = malloc(Tblock * nblock);
    235 	assert(tpblk != nil);
    236 	endblk = tpblk + nblock;
    237 }
    238 
    239 /*
    240  * (re)fill block buffers from archive.  `justhdr' means we don't care
    241  * about the data before the next header block.
    242  */
    243 static char *
    244 refill(int ar, char *bufs, int justhdr)
    245 {
    246 	int i, n;
    247 	unsigned bytes = Tblock * nblock;
    248 	static int done, first = 1, seekable;
    249 
    250 	if (done)
    251 		return nil;
    252 
    253 	if (first)
    254 		seekable = seek(ar, 0, 1) >= 0;
    255 	blkoff = seek(ar, 0, 1);		/* note position for `tar r' */
    256 	/* try to size non-pipe input at first read */
    257 	if (first && usefile) {
    258 		n = read(ar, bufs, bytes);
    259 		if (n <= 0)
    260 			sysfatal("error reading archive: %r");
    261 		i = n;
    262 		if (i % Tblock != 0) {
    263 			fprint(2, "%s: archive block size (%d) error\n",
    264 				argv0, i);
    265 			exits("blocksize");
    266 		}
    267 		i /= Tblock;
    268 		if (i != nblock) {
    269 			nblock = i;
    270 			fprint(2, "%s: blocking = %d\n", argv0, nblock);
    271 			endblk = (Hdr *)bufs + nblock;
    272 			bytes = n;
    273 		}
    274 	} else if (justhdr && seekable && nexthdr - seek(ar, 0, 1) >= bytes) {
    275 		/* optimisation for huge archive members on seekable media */
    276 		if (seek(ar, bytes, 1) < 0)
    277 			sysfatal("can't seek on archive: %r");
    278 		n = bytes;
    279 	} else
    280 		n = readn(ar, bufs, bytes);
    281 	first = 0;
    282 
    283 	if (n == 0)
    284 		sysfatal("unexpected EOF reading archive");
    285 	else if (n < 0)
    286 		sysfatal("error reading archive: %r");
    287 	else if (n%Tblock != 0)
    288 		sysfatal("partial block read from archive");
    289 	if (n != bytes) {
    290 		done = 1;
    291 		memset(bufs + n, 0, bytes - n);
    292 	}
    293 	return bufs;
    294 }
    295 
    296 static Hdr *
    297 getblk(int ar, Refill rfp, int justhdr)
    298 {
    299 	if (curblk == nil || curblk >= endblk) {  /* input block exhausted? */
    300 		if (rfp != nil && (*rfp)(ar, (char *)tpblk, justhdr) == nil)
    301 			return nil;
    302 		curblk = tpblk;
    303 	}
    304 	return curblk++;
    305 }
    306 
    307 static Hdr *
    308 getblkrd(int ar, int justhdr)
    309 {
    310 	return getblk(ar, refill, justhdr);
    311 }
    312 
    313 static Hdr *
    314 getblke(int ar)
    315 {
    316 	return getblk(ar, nil, Alldata);
    317 }
    318 
    319 static Hdr *
    320 getblkz(int ar)
    321 {
    322 	Hdr *hp = getblke(ar);
    323 
    324 	if (hp != nil)
    325 		memset(hp, 0, Tblock);
    326 	return hp;
    327 }
    328 
    329 /*
    330  * how many block buffers are available, starting at the address
    331  * just returned by getblk*?
    332  */
    333 static int
    334 gothowmany(int max)
    335 {
    336 	int n = endblk - (curblk - 1);
    337 
    338 	return n > max? max: n;
    339 }
    340 
    341 /*
    342  * indicate that one is done with the last block obtained from getblke
    343  * and it is now available to be written into the archive.
    344  */
    345 static void
    346 putlastblk(int ar)
    347 {
    348 	unsigned bytes = Tblock * nblock;
    349 
    350 	/* if writing end-of-archive, aid compression (good hygiene too) */
    351 	if (curblk < endblk)
    352 		memset(curblk, 0, (char *)endblk - (char *)curblk);
    353 	if (write(ar, tpblk, bytes) != bytes)
    354 		sysfatal("error writing archive: %r");
    355 }
    356 
    357 static void
    358 putblk(int ar)
    359 {
    360 	if (curblk >= endblk)
    361 		putlastblk(ar);
    362 }
    363 
    364 static void
    365 putbackblk(int ar)
    366 {
    367 	curblk--;
    368 	USED(ar);
    369 }
    370 
    371 static void
    372 putreadblks(int ar, int blks)
    373 {
    374 	curblk += blks - 1;
    375 	USED(ar);
    376 }
    377 
    378 static void
    379 putblkmany(int ar, int blks)
    380 {
    381 	curblk += blks - 1;
    382 	putblk(ar);
    383 }
    384 
    385 /*
    386  * common routines
    387  */
    388 
    389 /*
    390  * modifies hp->chksum but restores it; important for the last block of the
    391  * old archive when updating with `tar rf archive'
    392  */
    393 static long
    394 chksum(Hdr *hp)
    395 {
    396 	int n = Tblock;
    397 	long i = 0;
    398 	uchar *cp = (uchar*)hp;
    399 	char oldsum[sizeof hp->chksum];
    400 
    401 	memmove(oldsum, hp->chksum, sizeof oldsum);
    402 	memset(hp->chksum, ' ', sizeof hp->chksum);
    403 	while (n-- > 0)
    404 		i += *cp++;
    405 	memmove(hp->chksum, oldsum, sizeof oldsum);
    406 	return i;
    407 }
    408 
    409 static int
    410 isustar(Hdr *hp)
    411 {
    412 	return strcmp(hp->magic, "ustar") == 0;
    413 }
    414 
    415 /*
    416  * s is at most n bytes long, but need not be NUL-terminated.
    417  * if shorter than n bytes, all bytes after the first NUL must also
    418  * be NUL.
    419  */
    420 static int
    421 tar_sstrnlen(char *s, int n)
    422 {
    423 	return s[n - 1] != '\0'? n: strlen(s);
    424 }
    425 
    426 /* set fullname from header */
    427 static char *
    428 name(Hdr *hp)
    429 {
    430 	int pfxlen, namlen;
    431 	static char fullnamebuf[2 + Maxname + 1];	/* 2 at beginning for ./ on relative names */
    432 	char *fullname;
    433 
    434 	fullname = fullnamebuf+2;
    435 	namlen = tar_sstrnlen(hp->name, sizeof hp->name);
    436 	if (hp->prefix[0] == '\0' || !isustar(hp)) {	/* old-style name? */
    437 		memmove(fullname, hp->name, namlen);
    438 		fullname[namlen] = '\0';
    439 		return fullname;
    440 	}
    441 
    442 	/* name is in two pieces */
    443 	pfxlen = tar_sstrnlen(hp->prefix, sizeof hp->prefix);
    444 	memmove(fullname, hp->prefix, pfxlen);
    445 	fullname[pfxlen] = '/';
    446 	memmove(fullname + pfxlen + 1, hp->name, namlen);
    447 	fullname[pfxlen + 1 + namlen] = '\0';
    448 	return fullname;
    449 }
    450 
    451 static int
    452 isdir(Hdr *hp)
    453 {
    454 	/* the mode test is ugly but sometimes necessary */
    455 	return hp->linkflag == LF_DIR ||
    456 		strrchr(name(hp), '\0')[-1] == '/' ||
    457 		(strtoul(hp->mode, nil, 8)&0170000) == 040000;
    458 }
    459 
    460 static int
    461 eotar(Hdr *hp)
    462 {
    463 	return name(hp)[0] == '\0';
    464 }
    465 
    466 /*
    467 static uvlong
    468 getbe(uchar *src, int size)
    469 {
    470 	uvlong vl = 0;
    471 
    472 	while (size-- > 0) {
    473 		vl <<= 8;
    474 		vl |= *src++;
    475 	}
    476 	return vl;
    477 }
    478  */
    479 
    480 static void
    481 putbe(uchar *dest, uvlong vl, int size)
    482 {
    483 	for (dest += size; size-- > 0; vl >>= 8)
    484 		*--dest = vl;
    485 }
    486 
    487 /*
    488  * return the nominal size from the header block, which is not always the
    489  * size in the archive (the archive size may be zero for some file types
    490  * regardless of the nominal size).
    491  *
    492  * gnu and freebsd tars are now recording vlongs as big-endian binary
    493  * with a flag in byte 0 to indicate this, which permits file sizes up to
    494  * 2^64-1 (actually 2^80-1 but our file sizes are vlongs) rather than 2^33-1.
    495  */
    496 static Off
    497 hdrsize(Hdr *hp)
    498 {
    499 	uchar *p;
    500 
    501 	if((uchar)hp->size[0] == Binnegsz) {
    502 		fprint(2, "%s: %s: negative length, which is insane\n",
    503 			argv0, name(hp));
    504 		return 0;
    505 	} else if((uchar)hp->size[0] == Binsize) {
    506 		p = (uchar *)hp->size + sizeof hp->size - 1 -
    507 			sizeof(vlong);		/* -1 for terminating space */
    508 		return G8BEBYTE(p);
    509 	} else
    510 		return strtoull(hp->size, nil, 8);
    511 }
    512 
    513 /*
    514  * return the number of bytes recorded in the archive.
    515  */
    516 static Off
    517 arsize(Hdr *hp)
    518 {
    519 	if(isdir(hp) || islink(hp->linkflag))
    520 		return 0;
    521 	return hdrsize(hp);
    522 }
    523 
    524 static Hdr *
    525 readhdr(int ar)
    526 {
    527 	long hdrcksum;
    528 	Hdr *hp;
    529 
    530 	hp = getblkrd(ar, Alldata);
    531 	if (hp == nil)
    532 		sysfatal("unexpected EOF instead of archive header");
    533 	if (eotar(hp))			/* end-of-archive block? */
    534 		return nil;
    535 	hdrcksum = strtoul(hp->chksum, nil, 8);
    536 	if (chksum(hp) != hdrcksum)
    537 		sysfatal("bad archive header checksum: name %.64s... %ld %ld",
    538 			hp->name, chksum(hp), hdrcksum);
    539 	nexthdr += Tblock*(1 + BYTES2TBLKS(arsize(hp)));
    540 	return hp;
    541 }
    542 
    543 /*
    544  * tar r[c]
    545  */
    546 
    547 /*
    548  * if name is longer than Namsiz bytes, try to split it at a slash and fit the
    549  * pieces into hp->prefix and hp->name.
    550  */
    551 static int
    552 putfullname(Hdr *hp, char *name)
    553 {
    554 	int namlen, pfxlen;
    555 	char *sl, *osl;
    556 	String *slname = nil;
    557 
    558 	if (isdir(hp)) {
    559 		slname = s_new();
    560 		s_append(slname, name);
    561 		s_append(slname, "/");		/* posix requires this */
    562 		name = s_to_c(slname);
    563 	}
    564 
    565 	namlen = strlen(name);
    566 	if (namlen <= Namsiz) {
    567 		strncpy(hp->name, name, Namsiz);
    568 		hp->prefix[0] = '\0';		/* ustar paranoia */
    569 		return 0;
    570 	}
    571 
    572 	if (!posix || namlen > Maxname) {
    573 		fprint(2, "%s: name too long for tar header: %s\n",
    574 			argv0, name);
    575 		return -1;
    576 	}
    577 	/*
    578 	 * try various splits until one results in pieces that fit into the
    579 	 * appropriate fields of the header.  look for slashes from right
    580 	 * to left, in the hopes of putting the largest part of the name into
    581 	 * hp->prefix, which is larger than hp->name.
    582 	 */
    583 	sl = strrchr(name, '/');
    584 	while (sl != nil) {
    585 		pfxlen = sl - name;
    586 		if (pfxlen <= sizeof hp->prefix && namlen-1 - pfxlen <= Namsiz)
    587 			break;
    588 		osl = sl;
    589 		*osl = '\0';
    590 		sl = strrchr(name, '/');
    591 		*osl = '/';
    592 	}
    593 	if (sl == nil) {
    594 		fprint(2, "%s: name can't be split to fit tar header: %s\n",
    595 			argv0, name);
    596 		return -1;
    597 	}
    598 	*sl = '\0';
    599 	strncpy(hp->prefix, name, sizeof hp->prefix);
    600 	*sl++ = '/';
    601 	strncpy(hp->name, sl, sizeof hp->name);
    602 	if (slname)
    603 		s_free(slname);
    604 	return 0;
    605 }
    606 
    607 static int
    608 mkhdr(Hdr *hp, Dir *dir, char *file)
    609 {
    610 	/*
    611 	 * these fields run together, so we format them in order and don't use
    612 	 * snprint.
    613 	 */
    614 	sprint(hp->mode, "%6lo ", dir->mode & 0777);
    615 	sprint(hp->uid, "%6o ", aruid);
    616 	sprint(hp->gid, "%6o ", argid);
    617 	if (dir->length >= (Off)1<<32) {
    618 		static int printed;
    619 
    620 		if (!printed) {
    621 			printed = 1;
    622 			fprint(2, "%s: storing large sizes in \"base 256\"\n", argv0);
    623 		}
    624 		hp->size[0] = (char)Binsize;
    625 		/* emit so-called `base 256' representation of size */
    626 		putbe((uchar *)hp->size+1, dir->length, sizeof hp->size - 2);
    627 		hp->size[sizeof hp->size - 1] = ' ';
    628 	} else
    629 		sprint(hp->size, "%11lluo ", dir->length);
    630 	sprint(hp->mtime, "%11luo ", dir->mtime);
    631 	hp->linkflag = (dir->mode&DMDIR? LF_DIR: LF_PLAIN1);
    632 	putfullname(hp, file);
    633 	if (posix) {
    634 		strncpy(hp->magic, "ustar", sizeof hp->magic);
    635 		strncpy(hp->version, "00", sizeof hp->version);
    636 		strncpy(hp->uname, dir->uid, sizeof hp->uname);
    637 		strncpy(hp->gname, dir->gid, sizeof hp->gname);
    638 	}
    639 	sprint(hp->chksum, "%6luo", chksum(hp));
    640 	return 0;
    641 }
    642 
    643 static void addtoar(int ar, char *file, char *shortf);
    644 
    645 static void
    646 addtreetoar(int ar, char *file, char *shortf, int fd)
    647 {
    648 	int n;
    649 	Dir *dent, *dirents;
    650 	String *name = s_new();
    651 
    652 	n = dirreadall(fd, &dirents);
    653 	close(fd);
    654 	if (n == 0)
    655 		return;
    656 
    657 	if (chdir(shortf) < 0)
    658 		sysfatal("chdir %s: %r", file);
    659 	if (DEBUG)
    660 		fprint(2, "chdir %s\t# %s\n", shortf, file);
    661 
    662 	for (dent = dirents; dent < dirents + n; dent++) {
    663 		s_reset(name);
    664 		s_append(name, file);
    665 		s_append(name, "/");
    666 		s_append(name, dent->name);
    667 		addtoar(ar, s_to_c(name), dent->name);
    668 	}
    669 	s_free(name);
    670 	free(dirents);
    671 
    672 	/*
    673 	 * this assumes that shortf is just one component, which is true
    674 	 * during directory descent, but not necessarily true of command-line
    675 	 * arguments.  Our caller (or addtoar's) must reset the working
    676 	 * directory if necessary.
    677 	 */
    678 	if (chdir("..") < 0)
    679 		sysfatal("chdir %s/..: %r", file);
    680 	if (DEBUG)
    681 		fprint(2, "chdir ..\n");
    682 }
    683 
    684 static void
    685 addtoar(int ar, char *file, char *shortf)
    686 {
    687 	int n, fd, isdir;
    688 	long bytes;
    689 	ulong blksleft, blksread;
    690 	Hdr *hbp;
    691 	Dir *dir;
    692 	String *name = nil;
    693 
    694 	if (shortf[0] == '#') {
    695 		name = s_new();
    696 		s_append(name, "./");
    697 		s_append(name, shortf);
    698 		shortf = s_to_c(name);
    699 	}
    700 
    701 	fd = open(shortf, OREAD);
    702 	if (fd < 0) {
    703 		fprint(2, "%s: can't open %s: %r\n", argv0, file);
    704 		if (name)
    705 			s_free(name);
    706 		return;
    707 	}
    708 	dir = dirfstat(fd);
    709 	if (dir == nil)
    710 		sysfatal("can't fstat %s: %r", file);
    711 
    712 	hbp = getblkz(ar);
    713 	isdir = !!(dir->qid.type&QTDIR);
    714 	if (mkhdr(hbp, dir, file) < 0) {
    715 		putbackblk(ar);
    716 		free(dir);
    717 		close(fd);
    718 		if (name)
    719 			s_free(name);
    720 		return;
    721 	}
    722 	putblk(ar);
    723 
    724 	blksleft = BYTES2TBLKS(dir->length);
    725 	free(dir);
    726 
    727 	if (isdir)
    728 		addtreetoar(ar, file, shortf, fd);
    729 	else {
    730 		for (; blksleft > 0; blksleft -= blksread) {
    731 			hbp = getblke(ar);
    732 			blksread = gothowmany(blksleft);
    733 			bytes = blksread * Tblock;
    734 			n = readn(fd, hbp, bytes);
    735 			if (n < 0)
    736 				sysfatal("error reading %s: %r", file);
    737 			/*
    738 			 * ignore EOF.  zero any partial block to aid
    739 			 * compression and emergency recovery of data.
    740 			 */
    741 			if (n < Tblock)
    742 				memset((uchar*)hbp + n, 0, bytes - n);
    743 			putblkmany(ar, blksread);
    744 		}
    745 		close(fd);
    746 		if (verbose)
    747 			fprint(2, "%s\n", file);
    748 	}
    749 	if (name)
    750 		s_free(name);
    751 }
    752 
    753 static char *
    754 replace(char **argv)
    755 {
    756 	int i, ar;
    757 	ulong blksleft, blksread;
    758 	Off bytes;
    759 	Hdr *hp;
    760 	Compress *comp = nil;
    761 	Pushstate ps;
    762 
    763 	if (usefile && docreate) {
    764 		ar = create(usefile, OWRITE, 0666);
    765 		if (docompress)
    766 			comp = compmethod(usefile);
    767 	} else if (usefile)
    768 		ar = open(usefile, ORDWR);
    769 	else
    770 		ar = Stdout;
    771 	if (comp)
    772 		ar = push(ar, comp->comp, Output, &ps);
    773 	if (ar < 0)
    774 		sysfatal("can't open archive %s: %r", usefile);
    775 
    776 	if (usefile && !docreate) {
    777 		/* skip quickly to the end */
    778 		while ((hp = readhdr(ar)) != nil) {
    779 			bytes = arsize(hp);
    780 			for (blksleft = BYTES2TBLKS(bytes);
    781 			     blksleft > 0 && getblkrd(ar, Justnxthdr) != nil;
    782 			     blksleft -= blksread) {
    783 				blksread = gothowmany(blksleft);
    784 				putreadblks(ar, blksread);
    785 			}
    786 		}
    787 		/*
    788 		 * we have just read the end-of-archive Tblock.
    789 		 * now seek back over the (big) archive block containing it,
    790 		 * and back up curblk ptr over end-of-archive Tblock in memory.
    791 		 */
    792 		if (seek(ar, blkoff, 0) < 0)
    793 			sysfatal("can't seek back over end-of-archive: %r");
    794 		curblk--;
    795 	}
    796 
    797 	for (i = 0; argv[i] != nil; i++) {
    798 		addtoar(ar, argv[i], argv[i]);
    799 		chdir(origdir);		/* for correctness & profiling */
    800 	}
    801 
    802 	/* write end-of-archive marker */
    803 	getblkz(ar);
    804 	putblk(ar);
    805 	getblkz(ar);
    806 	putlastblk(ar);
    807 
    808 	if (comp)
    809 		return pushclose(&ps);
    810 	if (ar > Stderr)
    811 		close(ar);
    812 	return nil;
    813 }
    814 
    815 /*
    816  * tar [xt]
    817  */
    818 
    819 /* is pfx a file-name prefix of name? */
    820 static int
    821 prefix(char *name, char *pfx)
    822 {
    823 	int pfxlen = strlen(pfx);
    824 	char clpfx[Maxname+1];
    825 
    826 	if (pfxlen > Maxname)
    827 		return 0;
    828 	strcpy(clpfx, pfx);
    829 	cleanname(clpfx);
    830 	return strncmp(pfx, name, pfxlen) == 0 &&
    831 		(name[pfxlen] == '\0' || name[pfxlen] == '/');
    832 }
    833 
    834 static int
    835 match(char *name, char **argv)
    836 {
    837 	int i;
    838 	char clname[Maxname+1];
    839 
    840 	if (argv[0] == nil)
    841 		return 1;
    842 	strcpy(clname, name);
    843 	cleanname(clname);
    844 	for (i = 0; argv[i] != nil; i++)
    845 		if (prefix(clname, argv[i]))
    846 			return 1;
    847 	return 0;
    848 }
    849 
    850 static void
    851 cantcreate(char *s, int mode)
    852 {
    853 	int len;
    854 	static char *last;
    855 
    856 	/*
    857 	 * Always print about files.  Only print about directories
    858 	 * we haven't printed about.  (Assumes archive is ordered
    859 	 * nicely.)
    860 	 */
    861 	if(mode&DMDIR){
    862 		if(last){
    863 			/* already printed this directory */
    864 			if(strcmp(s, last) == 0)
    865 				return;
    866 			/* printed a higher directory, so printed this one */
    867 			len = strlen(s);
    868 			if(memcmp(s, last, len) == 0 && last[len] == '/')
    869 				return;
    870 		}
    871 		/* save */
    872 		free(last);
    873 		last = strdup(s);
    874 	}
    875 	fprint(2, "%s: can't create %s: %r\n", argv0, s);
    876 }
    877 
    878 static int
    879 makedir(char *s)
    880 {
    881 	int f;
    882 
    883 	if (access(s, AEXIST) == 0)
    884 		return -1;
    885 	f = create(s, OREAD, DMDIR | 0777);
    886 	if (f >= 0)
    887 		close(f);
    888 	else
    889 		cantcreate(s, DMDIR);
    890 	return f;
    891 }
    892 
    893 static int
    894 mkpdirs(char *s)
    895 {
    896 	int err;
    897 	char *p;
    898 
    899 	p = s;
    900 	err = 0;
    901 	while (!err && (p = strchr(p+1, '/')) != nil) {
    902 		*p = '\0';
    903 		err = (access(s, AEXIST) < 0 && makedir(s) < 0);
    904 		*p = '/';
    905 	}
    906 	return -err;
    907 }
    908 
    909 /* Call access but preserve the error string. */
    910 static int
    911 xaccess(char *name, int mode)
    912 {
    913 	char err[ERRMAX];
    914 	int rv;
    915 
    916 	err[0] = 0;
    917 	errstr(err, sizeof err);
    918 	rv = access(name, mode);
    919 	errstr(err, sizeof err);
    920 	return rv;
    921 }
    922 
    923 /* copy a file from the archive into the filesystem */
    924 /* fname is result of name(), so has two extra bytes at beginning */
    925 static void
    926 extract1(int ar, Hdr *hp, char *fname)
    927 {
    928 	int wrbytes, fd = -1, dir = 0;
    929 	long mtime = strtol(hp->mtime, nil, 8);
    930 	ulong mode = strtoul(hp->mode, nil, 8) & 0777;
    931 	Off bytes = hdrsize(hp);		/* for printing */
    932 	ulong blksread, blksleft = BYTES2TBLKS(arsize(hp));
    933 	Hdr *hbp;
    934 
    935 	if (isdir(hp)) {
    936 		mode |= DMDIR|0700;
    937 		dir = 1;
    938 	}
    939 	switch (hp->linkflag) {
    940 	case LF_LINK:
    941 	case LF_SYMLINK1:
    942 	case LF_SYMLINK2:
    943 	case LF_FIFO:
    944 		blksleft = 0;
    945 		break;
    946 	}
    947 	if (relative) {
    948 		if(fname[0] == '/')
    949 			*--fname = '.';
    950 		else if(fname[0] == '#'){
    951 			*--fname = '/';
    952 			*--fname = '.';
    953 		}
    954 	}
    955 	if (verb == Xtract) {
    956 		cleanname(fname);
    957 		switch (hp->linkflag) {
    958 		case LF_LINK:
    959 		case LF_SYMLINK1:
    960 		case LF_SYMLINK2:
    961 			fprint(2, "%s: can't make (sym)link %s\n",
    962 				argv0, fname);
    963 			break;
    964 		case LF_FIFO:
    965 			fprint(2, "%s: can't make fifo %s\n", argv0, fname);
    966 			break;
    967 		default:
    968 			if (!keepexisting || access(fname, AEXIST) < 0) {
    969 				int rw = (dir? OREAD: OWRITE);
    970 
    971 				fd = create(fname, rw, mode);
    972 				if (fd < 0) {
    973 					mkpdirs(fname);
    974 					fd = create(fname, rw, mode);
    975 				}
    976 				if (fd < 0 &&
    977 				    (!dir || xaccess(fname, AEXIST) < 0))
    978 				    	cantcreate(fname, mode);
    979 			}
    980 			if (fd >= 0 && verbose)
    981 				fprint(2, "%s\n", fname);
    982 			break;
    983 		}
    984 	} else if (verbose) {
    985 		char *cp = ctime(mtime);
    986 
    987 		print("%M %8lld %-12.12s %-4.4s %s\n",
    988 			mode, bytes, cp+4, cp+24, fname);
    989 	} else
    990 		print("%s\n", fname);
    991 
    992 	if (blksleft == 0)
    993 		bytes = 0;
    994 	for (; blksleft > 0; blksleft -= blksread) {
    995 		hbp = getblkrd(ar, (fd >= 0? Alldata: Justnxthdr));
    996 		if (hbp == nil)
    997 			sysfatal("unexpected EOF on archive extracting %s",
    998 				fname);
    999 		blksread = gothowmany(blksleft);
   1000 		if (blksread <= 0)
   1001 			fprint(2, "%s: got %ld blocks reading %s!\n",
   1002 				argv0, blksread, fname);
   1003 		wrbytes = Tblock*blksread;
   1004 		if(wrbytes > bytes)
   1005 			wrbytes = bytes;
   1006 		if (fd >= 0 && write(fd, hbp, wrbytes) != wrbytes)
   1007 			sysfatal("write error on %s: %r", fname);
   1008 		putreadblks(ar, blksread);
   1009 		bytes -= wrbytes;
   1010 	}
   1011 	if (bytes > 0)
   1012 		fprint(2,
   1013 		    "%s: %lld bytes uncopied at eof; %s not fully extracted\n",
   1014 			argv0, bytes, fname);
   1015 	if (fd >= 0) {
   1016 		/*
   1017 		 * directories should be wstated after we're done
   1018 		 * creating files in them.
   1019 		 */
   1020 		if (settime) {
   1021 			Dir nd;
   1022 
   1023 			nulldir(&nd);
   1024 			nd.mtime = mtime;
   1025 			dirfwstat(fd, &nd);
   1026 			if (isustar(hp)) {
   1027 				nulldir(&nd);
   1028 				nd.gid = hp->gname;
   1029 				dirfwstat(fd, &nd);
   1030 			}
   1031 		}
   1032 		close(fd);
   1033 	}
   1034 }
   1035 
   1036 static void
   1037 skip(int ar, Hdr *hp, char *fname)
   1038 {
   1039 	ulong blksleft, blksread;
   1040 	Hdr *hbp;
   1041 
   1042 	for (blksleft = BYTES2TBLKS(arsize(hp)); blksleft > 0;
   1043 	     blksleft -= blksread) {
   1044 		hbp = getblkrd(ar, Justnxthdr);
   1045 		if (hbp == nil)
   1046 			sysfatal("unexpected EOF on archive extracting %s",
   1047 				fname);
   1048 		blksread = gothowmany(blksleft);
   1049 		putreadblks(ar, blksread);
   1050 	}
   1051 }
   1052 
   1053 static char *
   1054 extract(char **argv)
   1055 {
   1056 	int ar;
   1057 	char *longname;
   1058 	Hdr *hp;
   1059 	Compress *comp = nil;
   1060 	Pushstate ps;
   1061 
   1062 	if (usefile) {
   1063 		ar = open(usefile, OREAD);
   1064 		comp = compmethod(usefile);
   1065 	} else
   1066 		ar = Stdin;
   1067 	if (comp)
   1068 		ar = push(ar, comp->decomp, Input, &ps);
   1069 	if (ar < 0)
   1070 		sysfatal("can't open archive %s: %r", usefile);
   1071 
   1072 	while ((hp = readhdr(ar)) != nil) {
   1073 		longname = name(hp);
   1074 		if (match(longname, argv))
   1075 			extract1(ar, hp, longname);
   1076 		else
   1077 			skip(ar, hp, longname);
   1078 	}
   1079 
   1080 	if (comp)
   1081 		return pushclose(&ps);
   1082 	if (ar > Stderr)
   1083 		close(ar);
   1084 	return nil;
   1085 }
   1086 
   1087 void
   1088 main(int argc, char *argv[])
   1089 {
   1090 	int errflg = 0;
   1091 	char *ret = nil;
   1092 
   1093 	fmtinstall('M', dirmodefmt);
   1094 
   1095 	if(sizeof(Hdr) != Tblock)
   1096 		sysfatal("padding in hdr should be %d", Tblock-sizeof(Hdr)+sizeof(curblk->pad));
   1097 	TARGBEGIN {
   1098 	case 'c':
   1099 		docreate++;
   1100 		verb = Replace;
   1101 		break;
   1102 	case 'f':
   1103 		usefile = EARGF(usage());
   1104 		break;
   1105 	case 'g':
   1106 		argid = strtoul(EARGF(usage()), 0, 0);
   1107 		break;
   1108 	case 'k':
   1109 		keepexisting++;
   1110 		break;
   1111 	case 'm':	/* compatibility */
   1112 		settime = 0;
   1113 		break;
   1114 	case 'p':
   1115 		posix++;
   1116 		break;
   1117 	case 'P':
   1118 		posix = 0;
   1119 		break;
   1120 	case 'r':
   1121 		verb = Replace;
   1122 		break;
   1123 	case 'R':
   1124 		relative = 0;
   1125 		break;
   1126 	case 't':
   1127 		verb = Toc;
   1128 		break;
   1129 	case 'T':
   1130 		settime++;
   1131 		break;
   1132 	case 'u':
   1133 		aruid = strtoul(EARGF(usage()), 0, 0);
   1134 		break;
   1135 	case 'v':
   1136 		verbose++;
   1137 		break;
   1138 	case 'x':
   1139 		verb = Xtract;
   1140 		break;
   1141 	case 'z':
   1142 		docompress++;
   1143 		break;
   1144 	case '-':
   1145 		break;
   1146 	default:
   1147 		fprint(2, "tar: unknown letter %C\n", TARGC());
   1148 		errflg++;
   1149 		break;
   1150 	} TARGEND
   1151 
   1152 	if (argc < 0 || errflg)
   1153 		usage();
   1154 
   1155 	initblks();
   1156 	switch (verb) {
   1157 	case Toc:
   1158 	case Xtract:
   1159 		ret = extract(argv);
   1160 		break;
   1161 	case Replace:
   1162 		if (getwd(origdir, sizeof origdir) == nil)
   1163 			strcpy(origdir, "/tmp");
   1164 		ret = replace(argv);
   1165 		break;
   1166 	default:
   1167 		usage();
   1168 		break;
   1169 	}
   1170 	exits(ret);
   1171 }