1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)tar.c 5.19 (Berkeley) 06/21/92"; 16 #endif /* not lint */ 17 18 /* 19 * Tape Archival Program 20 */ 21 #include <sys/param.h> 22 #include <sys/stat.h> 23 #include <sys/ioctl.h> 24 #include <sys/mtio.h> 25 #include <sys/time.h> 26 #include <dirent.h> 27 #include <fcntl.h> 28 #include <signal.h> 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <stdlib.h> 35 #include "pathnames.h" 36 37 #define TBLOCK 512 38 #define NBLOCK 20 39 #define NAMSIZ 100 40 41 #define ARGV 0 42 #define PUTFILE 1 43 44 #define writetape(b) writetbuf(b, 1) 45 #define min(a,b) ((a) < (b) ? (a) : (b)) 46 #define max(a,b) ((a) > (b) ? (a) : (b)) 47 48 union hblock { 49 char dummy[TBLOCK]; 50 struct header { 51 char name[NAMSIZ]; 52 char mode[8]; 53 char uid[8]; 54 char gid[8]; 55 char size[12]; 56 char mtime[12]; 57 char chksum[8]; 58 char linkflag; 59 char linkname[NAMSIZ]; 60 } dbuf; 61 }; 62 63 struct linkbuf { 64 ino_t inum; 65 dev_t devnum; 66 int count; 67 char pathname[NAMSIZ]; 68 struct linkbuf *nextp; 69 }; 70 71 union hblock dblock; 72 union hblock *tbuf; 73 struct linkbuf *ihead; 74 struct stat stbuf; 75 76 int rflag; 77 int sflag; 78 int xflag; 79 int vflag; 80 int tflag; 81 int cflag; 82 int mflag; 83 int fflag; 84 int iflag; 85 int oflag; 86 int pflag; 87 int wflag; 88 int hflag; 89 int Hflag; 90 int Bflag; 91 int Fflag; 92 93 int mt; 94 int term; 95 int chksum; 96 int recno; 97 int first; 98 int prtlinkerr; 99 int freemem = 1; 100 int nblock = 0; 101 void onintr(), onquit(), onhup(); 102 #ifdef notdef 103 void onterm(); 104 #endif 105 106 daddr_t low; 107 daddr_t high; 108 daddr_t bsrch(); 109 110 FILE *vfile = stdout; 111 FILE *tfile; 112 char tname[] = _PATH_TMP; 113 char *usefile; 114 char magtape[] = _PATH_MAGTAPE; 115 char *cwd(); 116 char *getmem(); 117 118 extern int errno; 119 120 main(argc, argv) 121 int argc; 122 char **argv; 123 { 124 char *cp; 125 126 if (argc < 2) 127 usage(); 128 129 tfile = NULL; 130 usefile = magtape; 131 argv[argc] = 0; 132 argv++; 133 for (cp = *argv++; *cp; cp++) 134 switch(*cp) { 135 136 case 'H': 137 Hflag++; 138 break; 139 case 'f': 140 if (*argv == 0) { 141 fprintf(stderr, 142 "tar: tapefile must be specified with 'f' option\n"); 143 usage(); 144 } 145 usefile = *argv++; 146 fflag++; 147 break; 148 149 case 'c': 150 cflag++; 151 rflag++; 152 break; 153 154 case 'o': 155 oflag++; 156 break; 157 158 case 'p': 159 pflag++; 160 break; 161 162 case 'u': 163 (void)mktemp(tname); 164 if ((tfile = fopen(tname, "w")) == NULL) { 165 fprintf(stderr, 166 "tar: cannot create temporary file (%s)\n", 167 tname); 168 done(1); 169 } 170 fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); 171 /*FALL THRU*/ 172 173 case 'r': 174 rflag++; 175 break; 176 177 case 's': 178 sflag++; 179 break; 180 181 case 'v': 182 vflag++; 183 break; 184 185 case 'w': 186 wflag++; 187 break; 188 189 case 'x': 190 xflag++; 191 break; 192 193 case 't': 194 tflag++; 195 break; 196 197 case 'm': 198 mflag++; 199 break; 200 201 case '-': 202 break; 203 204 case '0': 205 case '1': 206 case '4': 207 case '5': 208 case '7': 209 case '8': 210 magtape[8] = *cp; 211 usefile = magtape; 212 break; 213 214 case 'b': 215 if (*argv == 0) { 216 fprintf(stderr, 217 "tar: blocksize must be specified with 'b' option\n"); 218 usage(); 219 } 220 nblock = atoi(*argv); 221 if (nblock <= 0) { 222 fprintf(stderr, 223 "tar: invalid blocksize \"%s\"\n", *argv); 224 done(1); 225 } 226 argv++; 227 break; 228 229 case 'l': 230 prtlinkerr++; 231 break; 232 233 case 'h': 234 hflag++; 235 break; 236 237 case 'i': 238 iflag++; 239 break; 240 241 case 'B': 242 Bflag++; 243 break; 244 245 case 'F': 246 Fflag++; 247 break; 248 249 default: 250 fprintf(stderr, "tar: %c: unknown option\n", *cp); 251 usage(); 252 } 253 254 if (!rflag && !xflag && !tflag) 255 usage(); 256 if (rflag) { 257 if (cflag && tfile != NULL) 258 usage(); 259 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 260 (void) signal(SIGINT, onintr); 261 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 262 (void) signal(SIGHUP, onhup); 263 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 264 (void) signal(SIGQUIT, onquit); 265 #ifdef notdef 266 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 267 (void) signal(SIGTERM, onterm); 268 #endif 269 mt = openmt(usefile, 1); 270 dorep(argv); 271 done(0); 272 } 273 mt = openmt(usefile, 0); 274 if (xflag) 275 doxtract(argv); 276 else 277 dotable(argv); 278 done(0); 279 } 280 281 usage() 282 { 283 fprintf(stderr, 284 "tar: usage: tar -{txru}[cvfblmhopwBi] [tapefile] [blocksize] file1 file2...\n"); 285 done(1); 286 } 287 288 int 289 openmt(tape, writing) 290 char *tape; 291 int writing; 292 { 293 if (strcmp(tape, "-") == 0) { 294 /* 295 * Read from standard input or write to standard output. 296 */ 297 if (writing) { 298 if (cflag == 0) { 299 fprintf(stderr, 300 "tar: can only create standard output archives\n"); 301 done(1); 302 } 303 vfile = stderr; 304 setlinebuf(vfile); 305 mt = dup(1); 306 } else { 307 mt = dup(0); 308 Bflag++; 309 } 310 } else { 311 /* 312 * Use file or tape on local machine. 313 */ 314 if (writing) { 315 if (cflag) 316 mt = open(tape, O_RDWR|O_CREAT|O_TRUNC, 0666); 317 else 318 mt = open(tape, O_RDWR); 319 } else 320 mt = open(tape, O_RDONLY); 321 if (mt < 0) { 322 fprintf(stderr, "tar: %s: %s\n", tape, strerror(errno)); 323 done(1); 324 } 325 } 326 return(mt); 327 } 328 329 dorep(argv) 330 char *argv[]; 331 { 332 register char *cp, *cp2; 333 char *parent, *wdir; 334 335 if (!cflag) { 336 getdir(); 337 do { 338 passtape(); 339 if (term) 340 done(0); 341 getdir(); 342 } while (!endtape()); 343 backtape(); 344 if (tfile != NULL) { 345 char buf[200]; 346 347 (void)sprintf(buf, 348 "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s", 349 tname, tname, tname, tname, tname, tname); 350 fflush(tfile); 351 system(buf); 352 freopen(tname, "r", tfile); 353 fstat(fileno(tfile), &stbuf); 354 high = stbuf.st_size; 355 } 356 } 357 358 wdir = cwd(); 359 while (*argv && ! term) { 360 cp2 = *argv; 361 if (!strcmp(cp2, "-C") && argv[1]) { 362 argv++; 363 if (chdir(*argv) < 0) { 364 fprintf(stderr, 365 "tar: can't change directories to %s: %s\n", 366 *argv, strerror(errno)); 367 } else { 368 free(wdir); 369 wdir = cwd(); 370 } 371 argv++; 372 continue; 373 } 374 parent = wdir; 375 for (cp = *argv; *cp; cp++) 376 if (*cp == '/') 377 cp2 = cp; 378 if (cp2 != *argv) { 379 *cp2 = '\0'; 380 if (chdir(*argv) < 0) { 381 fprintf(stderr, 382 "tar: can't change directories to %s: %s\n", 383 *argv, strerror(errno)); 384 continue; 385 } 386 parent = cwd(); 387 *cp2 = '/'; 388 cp2++; 389 } 390 putfile(*argv++, cp2, parent, ARGV); 391 if (chdir(wdir) < 0) 392 fprintf(stderr, "tar: cannot change back?: %s: %s\n", 393 wdir, strerror(errno)); 394 } 395 putempty(); 396 putempty(); 397 flushtape(); 398 if (prtlinkerr == 0) 399 return; 400 for (; ihead != NULL; ihead = ihead->nextp) { 401 if (ihead->count == 0) 402 continue; 403 fprintf(stderr, "tar: missing links to %s\n", ihead->pathname); 404 } 405 } 406 407 endtape() 408 { 409 return (dblock.dbuf.name[0] == '\0'); 410 } 411 412 getdir() 413 { 414 register struct stat *sp; 415 long tempquad; 416 int i; 417 418 top: 419 readtape((char *)&dblock); 420 if (dblock.dbuf.name[0] == '\0') 421 return; 422 sp = &stbuf; 423 sscanf(dblock.dbuf.mode, "%o", &i); 424 sp->st_mode = i; 425 sscanf(dblock.dbuf.uid, "%o", &i); 426 sp->st_uid = i; 427 sscanf(dblock.dbuf.gid, "%o", &i); 428 sp->st_gid = i; 429 sscanf(dblock.dbuf.size, "%lo", &tempquad); 430 sp->st_size = tempquad; 431 sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); 432 sscanf(dblock.dbuf.chksum, "%o", &chksum); 433 if (chksum != (i = checksum())) { 434 fprintf(stderr, "tar: directory checksum error (%d != %d)\n", 435 chksum, i); 436 if (iflag) 437 goto top; 438 done(2); 439 } 440 /* strip off leading "/" if present */ 441 if (sflag && dblock.dbuf.name[0] == '/') { 442 register char *cp1, *cp2; 443 for (cp1 = cp2 = dblock.dbuf.name; *cp2 && *cp2 == '/'; ++cp2); 444 if (!*cp2) 445 goto top; 446 while (*cp1++ = *cp2++); 447 } 448 if (tfile != NULL) 449 fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); 450 } 451 452 passtape() 453 { 454 long blocks; 455 char *bufp; 456 457 if (dblock.dbuf.linkflag == '1') 458 return; 459 blocks = stbuf.st_size; 460 blocks += TBLOCK-1; 461 blocks /= TBLOCK; 462 463 while (blocks-- > 0) 464 (void) readtbuf(&bufp, TBLOCK); 465 } 466 467 putfile(longname, shortname, parent, source) 468 char *longname; 469 char *shortname; 470 char *parent; 471 { 472 int infile = 0; 473 long blocks; 474 char buf[TBLOCK]; 475 char *bigbuf; 476 register char *cp; 477 struct dirent *dp; 478 DIR *dirp; 479 register int i; 480 long l; 481 char newparent[NAMSIZ+64]; 482 int maxread; 483 int hint; /* amount to write to get "in sync" */ 484 485 if (hflag || (Hflag && source == ARGV)) 486 i = stat(shortname, &stbuf); 487 else 488 i = lstat(shortname, &stbuf); 489 490 if (i < 0) { 491 fprintf(stderr, "tar: %s: %s\n", longname, strerror(errno)); 492 return; 493 } 494 if (tfile != NULL && checkupdate(longname) == 0) 495 return; 496 if (checkw('r', longname) == 0) 497 return; 498 if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) 499 return; 500 501 switch (stbuf.st_mode & S_IFMT) { 502 case S_IFDIR: 503 for (i = 0, cp = buf; *cp++ = longname[i++];) 504 ; 505 *--cp = '/'; 506 *++cp = 0 ; 507 if (!oflag) { 508 if ((cp - buf) >= NAMSIZ) { 509 fprintf(stderr, "tar: %s: file name too long\n", 510 longname); 511 return; 512 } 513 stbuf.st_size = 0; 514 tomodes(&stbuf); 515 strcpy(dblock.dbuf.name,buf); 516 (void)sprintf(dblock.dbuf.chksum, "%6o", checksum()); 517 (void) writetape((char *)&dblock); 518 } 519 (void)sprintf(newparent, "%s/%s", parent, shortname); 520 if (chdir(shortname) < 0) { 521 fprintf(stderr, "tar: chdir %s: %s\n", 522 shortname, strerror(errno)); 523 return; 524 } 525 if ((dirp = opendir(".")) == NULL) { 526 fprintf(stderr, "tar: %s: directory read error\n", 527 longname); 528 if (chdir(parent) < 0) { 529 fprintf(stderr, 530 "tar: cannot change back?: %s: %s\n", 531 parent, strerror(errno)); 532 } 533 return; 534 } 535 while ((dp = readdir(dirp)) != NULL && !term) { 536 if (!strcmp(".", dp->d_name) || 537 !strcmp("..", dp->d_name)) 538 continue; 539 strcpy(cp, dp->d_name); 540 l = telldir(dirp); 541 closedir(dirp); 542 putfile(buf, cp, newparent, PUTFILE); 543 dirp = opendir("."); 544 seekdir(dirp, l); 545 } 546 closedir(dirp); 547 if (chdir(parent) < 0) { 548 fprintf(stderr, 549 "tar: cannot change back?: %s: %s\n", 550 parent, strerror(errno)); 551 } 552 break; 553 554 case S_IFLNK: 555 tomodes(&stbuf); 556 if (strlen(longname) >= NAMSIZ) { 557 fprintf(stderr, "tar: %s: file name too long\n", 558 longname); 559 return; 560 } 561 strcpy(dblock.dbuf.name, longname); 562 if (stbuf.st_size + 1 >= NAMSIZ) { 563 fprintf(stderr, "tar: %s: symbolic link too long\n", 564 longname); 565 return; 566 } 567 i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1); 568 if (i < 0) { 569 fprintf(stderr, 570 "tar: can't read symbolic link %s: %s\n", 571 longname, strerror(errno)); 572 return; 573 } 574 dblock.dbuf.linkname[i] = '\0'; 575 dblock.dbuf.linkflag = '2'; 576 if (vflag) 577 fprintf(vfile, "a %s symbolic link to %s\n", 578 longname, dblock.dbuf.linkname); 579 (void)sprintf(dblock.dbuf.size, "%11lo", 0L); 580 (void)sprintf(dblock.dbuf.chksum, "%6o", checksum()); 581 (void) writetape((char *)&dblock); 582 break; 583 584 case S_IFREG: 585 if ((infile = open(shortname, 0)) < 0) { 586 fprintf(stderr, "tar: %s: %s\n", 587 longname, strerror(errno)); 588 return; 589 } 590 tomodes(&stbuf); 591 if (strlen(longname) >= NAMSIZ) { 592 fprintf(stderr, "tar: %s: file name too long\n", 593 longname); 594 close(infile); 595 return; 596 } 597 strcpy(dblock.dbuf.name, longname); 598 if (stbuf.st_nlink > 1) { 599 struct linkbuf *lp; 600 int found = 0; 601 602 for (lp = ihead; lp != NULL; lp = lp->nextp) 603 if (lp->inum == stbuf.st_ino && 604 lp->devnum == stbuf.st_dev) { 605 found++; 606 break; 607 } 608 if (found) { 609 strcpy(dblock.dbuf.linkname, lp->pathname); 610 dblock.dbuf.linkflag = '1'; 611 (void)sprintf(dblock.dbuf.chksum, "%6o", checksum()); 612 (void) writetape( (char *) &dblock); 613 if (vflag) 614 fprintf(vfile, "a %s link to %s\n", 615 longname, lp->pathname); 616 lp->count--; 617 close(infile); 618 return; 619 } 620 lp = (struct linkbuf *) getmem(sizeof(*lp)); 621 if (lp != NULL) { 622 lp->nextp = ihead; 623 ihead = lp; 624 lp->inum = stbuf.st_ino; 625 lp->devnum = stbuf.st_dev; 626 lp->count = stbuf.st_nlink - 1; 627 strcpy(lp->pathname, longname); 628 } 629 } 630 blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 631 if (vflag) 632 fprintf(vfile, "a %s %ld blocks\n", longname, blocks); 633 (void)sprintf(dblock.dbuf.chksum, "%6o", checksum()); 634 hint = writetape((char *)&dblock); 635 maxread = max(stbuf.st_blksize, (nblock * TBLOCK)); 636 if ((bigbuf = malloc((unsigned)maxread)) == 0) { 637 maxread = TBLOCK; 638 bigbuf = buf; 639 } 640 641 while ((i = read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0 642 && blocks > 0) { 643 register int nblks; 644 645 nblks = ((i-1)/TBLOCK)+1; 646 if (nblks > blocks) 647 nblks = blocks; 648 hint = writetbuf(bigbuf, nblks); 649 blocks -= nblks; 650 } 651 close(infile); 652 if (bigbuf != buf) 653 free(bigbuf); 654 if (i < 0) { 655 fprintf(stderr, "tar: Read error on %s: %s\n", 656 longname, strerror(errno)); 657 } else if (blocks != 0 || i != 0) 658 fprintf(stderr, "tar: %s: file changed size\n", 659 longname); 660 while (--blocks >= 0) 661 putempty(); 662 break; 663 664 default: 665 fprintf(stderr, "tar: %s is not a file. Not dumped\n", 666 longname); 667 break; 668 } 669 } 670 671 doxtract(argv) 672 char *argv[]; 673 { 674 long blocks, bytes; 675 int ofile, i; 676 677 for (;;) { 678 if ((i = wantit(argv)) == 0) 679 continue; 680 if (i == -1) 681 break; /* end of tape */ 682 if (checkw('x', dblock.dbuf.name) == 0) { 683 passtape(); 684 continue; 685 } 686 if (Fflag) { 687 char *s; 688 689 if ((s = rindex(dblock.dbuf.name, '/')) == 0) 690 s = dblock.dbuf.name; 691 else 692 s++; 693 if (checkf(s, stbuf.st_mode, Fflag) == 0) { 694 passtape(); 695 continue; 696 } 697 } 698 if (checkdir(dblock.dbuf.name)) { /* have a directory */ 699 if (mflag == 0) 700 dodirtimes(&dblock); 701 continue; 702 } 703 if (dblock.dbuf.linkflag == '2') { /* symlink */ 704 /* 705 * only unlink non directories or empty 706 * directories 707 */ 708 if (rmdir(dblock.dbuf.name) < 0) { 709 if (errno == ENOTDIR) 710 unlink(dblock.dbuf.name); 711 } 712 if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) { 713 fprintf(stderr, 714 "tar: %s: symbolic link failed: %s\n", 715 dblock.dbuf.name, strerror(errno)); 716 continue; 717 } 718 if (vflag) 719 fprintf(vfile, "x %s symbolic link to %s\n", 720 dblock.dbuf.name, dblock.dbuf.linkname); 721 #ifdef notdef 722 /* ignore alien orders */ 723 chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 724 if (mflag == 0) 725 setimes(dblock.dbuf.name, stbuf.st_mtime); 726 if (pflag) 727 chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 728 #endif 729 continue; 730 } 731 if (dblock.dbuf.linkflag == '1') { /* regular link */ 732 /* 733 * only unlink non directories or empty 734 * directories 735 */ 736 if (rmdir(dblock.dbuf.name) < 0) { 737 if (errno == ENOTDIR) 738 unlink(dblock.dbuf.name); 739 } 740 if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 741 fprintf(stderr, 742 "tar: can't link %s to %s: %s\n", 743 dblock.dbuf.name, dblock.dbuf.linkname, 744 strerror(errno)); 745 continue; 746 } 747 if (vflag) 748 fprintf(vfile, "%s linked to %s\n", 749 dblock.dbuf.name, dblock.dbuf.linkname); 750 continue; 751 } 752 if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) { 753 fprintf(stderr, "tar: can't create %s: %s\n", 754 dblock.dbuf.name, strerror(errno)); 755 passtape(); 756 continue; 757 } 758 chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 759 blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 760 if (vflag) 761 fprintf(vfile, "x %s, %ld bytes, %ld tape blocks\n", 762 dblock.dbuf.name, bytes, blocks); 763 for (; blocks > 0;) { 764 register int nread; 765 char *bufp; 766 register int nwant; 767 768 nwant = NBLOCK*TBLOCK; 769 if (nwant > (blocks*TBLOCK)) 770 nwant = (blocks*TBLOCK); 771 nread = readtbuf(&bufp, nwant); 772 if (write(ofile, bufp, (int)min(nread, bytes)) < 0) { 773 fprintf(stderr, 774 "tar: %s: HELP - extract write error: %s\n", 775 dblock.dbuf.name, strerror(errno)); 776 done(2); 777 } 778 bytes -= nread; 779 blocks -= (((nread-1)/TBLOCK)+1); 780 } 781 close(ofile); 782 if (mflag == 0) 783 setimes(dblock.dbuf.name, stbuf.st_mtime); 784 if (pflag) 785 chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 786 } 787 if (mflag == 0) { 788 dblock.dbuf.name[0] = '\0'; /* process the whole stack */ 789 dodirtimes(&dblock); 790 } 791 } 792 793 dotable(argv) 794 char *argv[]; 795 { 796 register int i; 797 798 for (;;) { 799 if ((i = wantit(argv)) == 0) 800 continue; 801 if (i == -1) 802 break; /* end of tape */ 803 if (vflag) 804 longt(&stbuf); 805 printf("%s", dblock.dbuf.name); 806 if (dblock.dbuf.linkflag == '1') 807 printf(" linked to %s", dblock.dbuf.linkname); 808 if (dblock.dbuf.linkflag == '2') 809 printf(" symbolic link to %s", dblock.dbuf.linkname); 810 printf("\n"); 811 passtape(); 812 } 813 } 814 815 putempty() 816 { 817 char buf[TBLOCK]; 818 819 bzero(buf, sizeof (buf)); 820 (void) writetape(buf); 821 } 822 823 longt(st) 824 register struct stat *st; 825 { 826 register char *cp; 827 char *ctime(); 828 829 pmode(st); 830 printf("%3u/%1u", st->st_uid, st->st_gid); 831 printf("%7qd", st->st_size); 832 cp = ctime(&st->st_mtime); 833 printf(" %-12.12s %-4.4s ", cp+4, cp+20); 834 } 835 836 #define SUID 04000 837 #define SGID 02000 838 #define ROWN 0400 839 #define WOWN 0200 840 #define XOWN 0100 841 #define RGRP 040 842 #define WGRP 020 843 #define XGRP 010 844 #define ROTH 04 845 #define WOTH 02 846 #define XOTH 01 847 #define STXT 01000 848 int m1[] = { 1, ROWN, 'r', '-' }; 849 int m2[] = { 1, WOWN, 'w', '-' }; 850 int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 851 int m4[] = { 1, RGRP, 'r', '-' }; 852 int m5[] = { 1, WGRP, 'w', '-' }; 853 int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 854 int m7[] = { 1, ROTH, 'r', '-' }; 855 int m8[] = { 1, WOTH, 'w', '-' }; 856 int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 857 858 int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 859 860 pmode(st) 861 register struct stat *st; 862 { 863 register int **mp; 864 865 for (mp = &m[0]; mp < &m[9];) 866 selectbits(*mp++, st); 867 } 868 869 selectbits(pairp, st) 870 int *pairp; 871 struct stat *st; 872 { 873 register int n, *ap; 874 875 ap = pairp; 876 n = *ap++; 877 while (--n>=0 && (st->st_mode&*ap++)==0) 878 ap++; 879 putchar(*ap); 880 } 881 882 /* 883 * Make all directories needed by `name'. If `name' is itself 884 * a directory on the tar tape (indicated by a trailing '/'), 885 * return 1; else 0. 886 */ 887 checkdir(name) 888 register char *name; 889 { 890 register char *cp; 891 892 /* 893 * Quick check for existence of directory. 894 */ 895 if ((cp = rindex(name, '/')) == 0) 896 return (0); 897 *cp = '\0'; 898 if (access(name, F_OK) == 0) { /* already exists */ 899 *cp = '/'; 900 return (cp[1] == '\0'); /* return (lastchar == '/') */ 901 } 902 *cp = '/'; 903 904 /* 905 * No luck, try to make all directories in path. 906 */ 907 for (cp = name; *cp; cp++) { 908 if (*cp != '/') 909 continue; 910 *cp = '\0'; 911 if (access(name, F_OK) < 0) { 912 if (mkdir(name, 0777) < 0) { 913 fprintf(stderr, "tar: mkdir: %s: %s\n", 914 name, strerror(errno)); 915 *cp = '/'; 916 return (0); 917 } 918 chown(name, stbuf.st_uid, stbuf.st_gid); 919 if (pflag && cp[1] == '\0') /* dir on the tape */ 920 chmod(name, stbuf.st_mode & 07777); 921 } 922 *cp = '/'; 923 } 924 return (cp[-1]=='/'); 925 } 926 927 void 928 onintr() 929 { 930 (void) signal(SIGINT, SIG_IGN); 931 term++; 932 } 933 934 void 935 onquit() 936 { 937 (void) signal(SIGQUIT, SIG_IGN); 938 term++; 939 } 940 941 void 942 onhup() 943 { 944 (void) signal(SIGHUP, SIG_IGN); 945 term++; 946 } 947 948 #ifdef notdef 949 void 950 onterm() 951 { 952 (void) signal(SIGTERM, SIG_IGN); 953 term++; 954 } 955 #endif 956 957 tomodes(sp) 958 register struct stat *sp; 959 { 960 register char *cp; 961 962 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 963 *cp = '\0'; 964 (void)sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 965 (void)sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 966 (void)sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 967 (void)sprintf(dblock.dbuf.size, "%11qo ", sp->st_size); 968 (void)sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 969 } 970 971 checksum() 972 { 973 register i; 974 register char *cp; 975 976 for (cp = dblock.dbuf.chksum; 977 cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 978 *cp = ' '; 979 i = 0; 980 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 981 i += *cp; 982 return (i); 983 } 984 985 checkw(c, name) 986 char *name; 987 { 988 if (!wflag) 989 return (1); 990 printf("%c ", c); 991 if (vflag) 992 longt(&stbuf); 993 printf("%s: ", name); 994 return (response() == 'y'); 995 } 996 997 response() 998 { 999 char c; 1000 1001 c = getchar(); 1002 if (c != '\n') 1003 while (getchar() != '\n') 1004 ; 1005 else 1006 c = 'n'; 1007 return (c); 1008 } 1009 1010 checkf(name, mode, howmuch) 1011 char *name; 1012 int mode, howmuch; 1013 { 1014 int l; 1015 1016 if ((mode & S_IFMT) == S_IFDIR){ 1017 if ((strcmp(name, "SCCS")==0) || (strcmp(name, "RCS")==0)) 1018 return(0); 1019 return(1); 1020 } 1021 if ((l = strlen(name)) < 3) 1022 return (1); 1023 if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 1024 return (0); 1025 if (strcmp(name, "core") == 0 || 1026 strcmp(name, "errs") == 0 || 1027 (howmuch > 1 && strcmp(name, "a.out") == 0)) 1028 return (0); 1029 /* SHOULD CHECK IF IT IS EXECUTABLE */ 1030 return (1); 1031 } 1032 1033 /* Is the current file a new file, or the newest one of the same name? */ 1034 checkupdate(arg) 1035 char *arg; 1036 { 1037 char name[100]; 1038 long mtime; 1039 daddr_t seekp; 1040 daddr_t lookup(); 1041 1042 rewind(tfile); 1043 for (;;) { 1044 if ((seekp = lookup(arg)) < 0) 1045 return (1); 1046 fseek(tfile, seekp, 0); 1047 fscanf(tfile, "%s %lo", name, &mtime); 1048 return (stbuf.st_mtime > mtime); 1049 } 1050 } 1051 1052 done(n) 1053 { 1054 unlink(tname); 1055 exit(n); 1056 } 1057 1058 /* 1059 * Do we want the next entry on the tape, i.e. is it selected? If 1060 * not, skip over the entire entry. Return -1 if reached end of tape. 1061 */ 1062 wantit(argv) 1063 char *argv[]; 1064 { 1065 register char **cp; 1066 1067 getdir(); 1068 if (endtape()) 1069 return (-1); 1070 if (*argv == 0) 1071 return (1); 1072 for (cp = argv; *cp; cp++) 1073 if (prefix(*cp, dblock.dbuf.name)) 1074 return (1); 1075 passtape(); 1076 return (0); 1077 } 1078 1079 /* 1080 * Does s2 begin with the string s1, on a directory boundary? 1081 */ 1082 prefix(s1, s2) 1083 register char *s1, *s2; 1084 { 1085 while (*s1) 1086 if (*s1++ != *s2++) 1087 return (0); 1088 if (*s2) 1089 return (*s2 == '/'); 1090 return (1); 1091 } 1092 1093 #define N 200 1094 int njab; 1095 1096 daddr_t 1097 lookup(s) 1098 char *s; 1099 { 1100 register i; 1101 daddr_t a; 1102 1103 for(i=0; s[i]; i++) 1104 if (s[i] == ' ') 1105 break; 1106 a = bsrch(s, i, low, high); 1107 return (a); 1108 } 1109 1110 daddr_t 1111 bsrch(s, n, l, h) 1112 daddr_t l, h; 1113 char *s; 1114 { 1115 register i, j; 1116 char b[N]; 1117 daddr_t m, m1; 1118 1119 njab = 0; 1120 1121 loop: 1122 if (l >= h) 1123 return ((daddr_t) -1); 1124 m = l + (h-l)/2 - N/2; 1125 if (m < l) 1126 m = l; 1127 fseek(tfile, m, 0); 1128 fread(b, 1, N, tfile); 1129 njab++; 1130 for(i=0; i<N; i++) { 1131 if (b[i] == '\n') 1132 break; 1133 m++; 1134 } 1135 if (m >= h) 1136 return ((daddr_t) -1); 1137 m1 = m; 1138 j = i; 1139 for(i++; i<N; i++) { 1140 m1++; 1141 if (b[i] == '\n') 1142 break; 1143 } 1144 i = cmp(b+j, s, n); 1145 if (i < 0) { 1146 h = m; 1147 goto loop; 1148 } 1149 if (i > 0) { 1150 l = m1; 1151 goto loop; 1152 } 1153 return (m); 1154 } 1155 1156 cmp(b, s, n) 1157 char *b, *s; 1158 { 1159 register i; 1160 1161 if (b[0] != '\n') 1162 exit(2); 1163 for(i=0; i<n; i++) { 1164 if (b[i+1] > s[i]) 1165 return (-1); 1166 if (b[i+1] < s[i]) 1167 return (1); 1168 } 1169 return (b[i+1] == ' '? 0 : -1); 1170 } 1171 1172 readtape(buffer) 1173 char *buffer; 1174 { 1175 char *bufp; 1176 1177 if (first == 0) 1178 getbuf(); 1179 (void) readtbuf(&bufp, TBLOCK); 1180 bcopy(bufp, buffer, TBLOCK); 1181 return(TBLOCK); 1182 } 1183 1184 readtbuf(bufpp, size) 1185 char **bufpp; 1186 int size; 1187 { 1188 register int i; 1189 1190 if (recno >= nblock || first == 0) { 1191 if ((i = bread(mt, (char *)tbuf, TBLOCK*nblock)) < 0) 1192 mterr("read", i, 3); 1193 if (first == 0) { 1194 if ((i % TBLOCK) != 0) { 1195 fprintf(stderr, "tar: tape blocksize error\n"); 1196 done(3); 1197 } 1198 i /= TBLOCK; 1199 if (i != nblock) { 1200 fprintf(stderr, "tar: blocksize = %d\n", i); 1201 nblock = i; 1202 } 1203 first = 1; 1204 } 1205 recno = 0; 1206 } 1207 if (size > ((nblock-recno)*TBLOCK)) 1208 size = (nblock-recno)*TBLOCK; 1209 *bufpp = (char *)&tbuf[recno]; 1210 recno += (size/TBLOCK); 1211 return (size); 1212 } 1213 1214 writetbuf(buffer, n) 1215 register char *buffer; 1216 register int n; 1217 { 1218 int i; 1219 1220 if (first == 0) { 1221 getbuf(); 1222 first = 1; 1223 } 1224 if (recno >= nblock) { 1225 i = write(mt, (char *)tbuf, TBLOCK*nblock); 1226 if (i != TBLOCK*nblock) 1227 mterr("write", i, 2); 1228 recno = 0; 1229 } 1230 1231 /* 1232 * Special case: We have an empty tape buffer, and the 1233 * users data size is >= the tape block size: Avoid 1234 * the bcopy and dma direct to tape. BIG WIN. Add the 1235 * residual to the tape buffer. 1236 */ 1237 while (recno == 0 && n >= nblock) { 1238 i = write(mt, buffer, TBLOCK*nblock); 1239 if (i != TBLOCK*nblock) 1240 mterr("write", i, 2); 1241 n -= nblock; 1242 buffer += (nblock * TBLOCK); 1243 } 1244 1245 while (n-- > 0) { 1246 bcopy(buffer, (char *)&tbuf[recno++], TBLOCK); 1247 buffer += TBLOCK; 1248 if (recno >= nblock) { 1249 i = write(mt, (char *)tbuf, TBLOCK*nblock); 1250 if (i != TBLOCK*nblock) 1251 mterr("write", i, 2); 1252 recno = 0; 1253 } 1254 } 1255 1256 /* Tell the user how much to write to get in sync */ 1257 return (nblock - recno); 1258 } 1259 1260 backtape() 1261 { 1262 static int mtdev = 1; 1263 static struct mtop mtop = {MTBSR, 1}; 1264 struct mtget mtget; 1265 1266 if (mtdev == 1) 1267 mtdev = ioctl(mt, MTIOCGET, (char *)&mtget); 1268 if (mtdev == 0) { 1269 if (ioctl(mt, MTIOCTOP, (char *)&mtop) < 0) { 1270 fprintf(stderr, "tar: tape backspace error: %s\n", 1271 strerror(errno)); 1272 done(4); 1273 } 1274 } else 1275 (void)lseek(mt, (off_t) -TBLOCK*nblock, 1); 1276 recno--; 1277 } 1278 1279 flushtape() 1280 { 1281 int i; 1282 1283 i = write(mt, (char *)tbuf, TBLOCK*nblock); 1284 if (i != TBLOCK*nblock) 1285 mterr("write", i, 2); 1286 } 1287 1288 mterr(operation, i, exitcode) 1289 char *operation; 1290 int i; 1291 { 1292 fprintf(stderr, "tar: tape %s error: %s\n", 1293 operation, i < 0 ? strerror(errno) : "unexpected EOF"); 1294 done(exitcode); 1295 } 1296 1297 bread(fd, buf, size) 1298 int fd; 1299 char *buf; 1300 int size; 1301 { 1302 int count; 1303 static int lastread = 0; 1304 1305 if (!Bflag) 1306 return (read(fd, buf, size)); 1307 1308 for (count = 0; count < size; count += lastread) { 1309 lastread = read(fd, buf, size - count); 1310 if (lastread <= 0) { 1311 if (count > 0) 1312 return (count); 1313 return (lastread); 1314 } 1315 buf += lastread; 1316 } 1317 return (count); 1318 } 1319 1320 char * 1321 cwd() 1322 { 1323 char *p; 1324 1325 p = getcwd((char *)NULL, 0); 1326 if (p == NULL) { 1327 (void)fprintf(stderr, "tar: %s\n", strerror(errno)); 1328 exit(1); 1329 } 1330 return (p); 1331 } 1332 1333 getbuf() 1334 { 1335 1336 if (nblock == 0) { 1337 fstat(mt, &stbuf); 1338 if ((stbuf.st_mode & S_IFMT) == S_IFCHR) 1339 nblock = NBLOCK; 1340 else { 1341 nblock = stbuf.st_blksize / TBLOCK; 1342 if (nblock == 0) 1343 nblock = NBLOCK; 1344 } 1345 } 1346 tbuf = (union hblock *)malloc((unsigned)nblock*TBLOCK); 1347 if (tbuf == NULL) { 1348 fprintf(stderr, "tar: blocksize %d too big, can't get memory\n", 1349 nblock); 1350 done(1); 1351 } 1352 } 1353 1354 /* 1355 * Save this directory and its mtime on the stack, popping and setting 1356 * the mtimes of any stacked dirs which aren't parents of this one. 1357 * A null directory causes the entire stack to be unwound and set. 1358 * 1359 * Since all the elements of the directory "stack" share a common 1360 * prefix, we can make do with one string. We keep only the current 1361 * directory path, with an associated array of mtime's, one for each 1362 * '/' in the path. A negative mtime means no mtime. The mtime's are 1363 * offset by one (first index 1, not 0) because calling this with a null 1364 * directory causes mtime[0] to be set. 1365 * 1366 * This stack algorithm is not guaranteed to work for tapes created 1367 * with the 'r' option, but the vast majority of tapes with 1368 * directories are not. This avoids saving every directory record on 1369 * the tape and setting all the times at the end. 1370 */ 1371 char dirstack[NAMSIZ]; 1372 #define NTIM (NAMSIZ/2+1) /* a/b/c/d/... */ 1373 time_t mtime[NTIM]; 1374 1375 dodirtimes(hp) 1376 union hblock *hp; 1377 { 1378 register char *p = dirstack; 1379 register char *q = hp->dbuf.name; 1380 register int ndir = 0; 1381 char *savp; 1382 int savndir; 1383 1384 /* Find common prefix */ 1385 while (*p == *q && *p) { 1386 if (*p++ == '/') 1387 ++ndir; 1388 q++; 1389 } 1390 1391 savp = p; 1392 savndir = ndir; 1393 while (*p) { 1394 /* 1395 * Not a child: unwind the stack, setting the times. 1396 * The order we do this doesn't matter, so we go "forward." 1397 */ 1398 if (*p++ == '/') 1399 if (mtime[++ndir] >= 0) { 1400 *--p = '\0'; /* zap the slash */ 1401 setimes(dirstack, mtime[ndir]); 1402 *p++ = '/'; 1403 } 1404 } 1405 p = savp; 1406 ndir = savndir; 1407 1408 /* Push this one on the "stack" */ 1409 while (*p = *q++) /* append the rest of the new dir */ 1410 if (*p++ == '/') 1411 mtime[++ndir] = -1; 1412 mtime[ndir] = stbuf.st_mtime; /* overwrite the last one */ 1413 } 1414 1415 setimes(path, mt) 1416 char *path; 1417 time_t mt; 1418 { 1419 struct timeval tv[2]; 1420 1421 tv[0].tv_sec = time((time_t *) 0); 1422 tv[1].tv_sec = mt; 1423 tv[0].tv_usec = tv[1].tv_usec = 0; 1424 if (utimes(path, tv) < 0) 1425 fprintf(stderr, "tar: can't set time on %s: %s\n", 1426 path, strerror(errno)); 1427 } 1428 1429 char * 1430 getmem(size) 1431 { 1432 char *p = malloc((unsigned) size); 1433 1434 if (p == NULL && freemem) { 1435 fprintf(stderr, 1436 "tar: out of memory, link and directory modtime info lost\n"); 1437 freemem = 0; 1438 } 1439 return (p); 1440 } 1441