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