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