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