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