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