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