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