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