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