1 #ifndef lint 2 static char *sccsid = "@(#)tar.c 4.17 (Berkeley) 06/30/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 chdir(wdir); 337 } 338 putempty(); 339 putempty(); 340 flushtape(); 341 if (linkerrok == 0) 342 return; 343 for (; ihead != NULL; ihead = ihead->nextp) { 344 if (ihead->count == 0) 345 continue; 346 fprintf(stderr, "tar: missing links to %s\n", ihead->pathname); 347 } 348 } 349 350 endtape() 351 { 352 return (dblock.dbuf.name[0] == '\0'); 353 } 354 355 getdir() 356 { 357 register struct stat *sp; 358 int i; 359 360 top: 361 readtape((char *)&dblock); 362 if (dblock.dbuf.name[0] == '\0') 363 return; 364 sp = &stbuf; 365 sscanf(dblock.dbuf.mode, "%o", &i); 366 sp->st_mode = i; 367 sscanf(dblock.dbuf.uid, "%o", &i); 368 sp->st_uid = i; 369 sscanf(dblock.dbuf.gid, "%o", &i); 370 sp->st_gid = i; 371 sscanf(dblock.dbuf.size, "%lo", &sp->st_size); 372 sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); 373 sscanf(dblock.dbuf.chksum, "%o", &chksum); 374 if (chksum != (i = checksum())) { 375 fprintf(stderr, "tar: directory checksum error (%d != %d)\n", 376 chksum, i); 377 if (iflag) 378 goto top; 379 done(2); 380 } 381 if (tfile != NULL) 382 fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); 383 } 384 385 passtape() 386 { 387 long blocks; 388 char buf[TBLOCK]; 389 390 if (dblock.dbuf.linkflag == '1') 391 return; 392 blocks = stbuf.st_size; 393 blocks += TBLOCK-1; 394 blocks /= TBLOCK; 395 396 while (blocks-- > 0) 397 readtape(buf); 398 } 399 400 putfile(longname, shortname, parent) 401 char *longname; 402 char *shortname; 403 char *parent; 404 { 405 int infile = 0; 406 long blocks; 407 char buf[TBLOCK]; 408 register char *cp, *cp2; 409 struct direct *dp; 410 DIR *dirp; 411 int i, j; 412 char newparent[NAMSIZ+64]; 413 extern int errno; 414 415 if (!hflag) 416 i = lstat(shortname, &stbuf); 417 else 418 i = stat(shortname, &stbuf); 419 if (i < 0) { 420 switch (errno) { 421 case EACCES: 422 fprintf(stderr, "tar: %s: cannot open file\n", longname); 423 break; 424 case ENOENT: 425 fprintf(stderr, "tar: %s: no such file or directory\n", 426 longname); 427 break; 428 default: 429 fprintf(stderr, "tar: %s: cannot stat file\n", longname); 430 break; 431 } 432 return; 433 } 434 if (tfile != NULL && checkupdate(longname) == 0) 435 return; 436 if (checkw('r', longname) == 0) 437 return; 438 if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) 439 return; 440 441 switch (stbuf.st_mode & S_IFMT) { 442 case S_IFDIR: 443 for (i = 0, cp = buf; *cp++ = longname[i++];) 444 ; 445 *--cp = '/'; 446 *++cp = 0 ; 447 if (!oflag) { 448 if ((cp - buf) >= NAMSIZ) { 449 fprintf(stderr, "tar: %s: file name too long\n", 450 longname); 451 return; 452 } 453 stbuf.st_size = 0; 454 tomodes(&stbuf); 455 strcpy(dblock.dbuf.name,buf); 456 sprintf(dblock.dbuf.chksum, "%6o", checksum()); 457 writetape((char *)&dblock); 458 } 459 sprintf(newparent, "%s/%s", parent, shortname); 460 chdir(shortname); 461 if ((dirp = opendir(".")) == NULL) { 462 fprintf(stderr, "tar: %s: directory read error\n", 463 longname); 464 chdir(parent); 465 return; 466 } 467 while ((dp = readdir(dirp)) != NULL && !term) { 468 if (dp->d_ino == 0) 469 continue; 470 if (!strcmp(".", dp->d_name) || 471 !strcmp("..", dp->d_name)) 472 continue; 473 strcpy(cp, dp->d_name); 474 i = telldir(dirp); 475 closedir(dirp); 476 putfile(buf, cp, newparent); 477 dirp = opendir("."); 478 seekdir(dirp, i); 479 } 480 closedir(dirp); 481 chdir(parent); 482 break; 483 484 case S_IFLNK: 485 tomodes(&stbuf); 486 if (strlen(longname) >= NAMSIZ) { 487 fprintf(stderr, "tar: %s: file name too long\n", 488 longname); 489 return; 490 } 491 strcpy(dblock.dbuf.name, longname); 492 if (stbuf.st_size + 1 >= NAMSIZ) { 493 fprintf(stderr, "tar: %s: symbolic link too long\n", 494 longname); 495 return; 496 } 497 i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1); 498 if (i < 0) { 499 perror(longname); 500 return; 501 } 502 dblock.dbuf.linkname[i] = '\0'; 503 dblock.dbuf.linkflag = '2'; 504 if (vflag) { 505 fprintf(stderr, "a %s ", longname); 506 fprintf(stderr, "symbolic link to %s\n", 507 dblock.dbuf.linkname); 508 } 509 sprintf(dblock.dbuf.size, "%11lo", 0); 510 sprintf(dblock.dbuf.chksum, "%6o", checksum()); 511 writetape((char *)&dblock); 512 break; 513 514 case S_IFREG: 515 if ((infile = open(shortname, 0)) < 0) { 516 fprintf(stderr, "tar: %s: cannot open file\n", longname); 517 return; 518 } 519 tomodes(&stbuf); 520 if (strlen(longname) >= NAMSIZ) { 521 fprintf(stderr, "tar: %s: file name too long\n", 522 longname); 523 return; 524 } 525 strcpy(dblock.dbuf.name, longname); 526 if (stbuf.st_nlink > 1) { 527 struct linkbuf *lp; 528 int found = 0; 529 530 for (lp = ihead; lp != NULL; lp = lp->nextp) 531 if (lp->inum == stbuf.st_ino && 532 lp->devnum == stbuf.st_dev) { 533 found++; 534 break; 535 } 536 if (found) { 537 strcpy(dblock.dbuf.linkname, lp->pathname); 538 dblock.dbuf.linkflag = '1'; 539 sprintf(dblock.dbuf.chksum, "%6o", checksum()); 540 writetape( (char *) &dblock); 541 if (vflag) { 542 fprintf(stderr, "a %s ", longname); 543 fprintf(stderr, "link to %s\n", 544 lp->pathname); 545 } 546 lp->count--; 547 close(infile); 548 return; 549 } 550 lp = (struct linkbuf *) malloc(sizeof(*lp)); 551 if (lp == NULL) { 552 if (freemem) { 553 fprintf(stderr, 554 "tar: out of memory, link information lost\n"); 555 freemem = 0; 556 } 557 } else { 558 lp->nextp = ihead; 559 ihead = lp; 560 lp->inum = stbuf.st_ino; 561 lp->devnum = stbuf.st_dev; 562 lp->count = stbuf.st_nlink - 1; 563 strcpy(lp->pathname, longname); 564 } 565 } 566 blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 567 if (vflag) { 568 fprintf(stderr, "a %s ", longname); 569 fprintf(stderr, "%ld blocks\n", blocks); 570 } 571 sprintf(dblock.dbuf.chksum, "%6o", checksum()); 572 writetape((char *)&dblock); 573 574 while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { 575 writetape(buf); 576 blocks--; 577 } 578 close(infile); 579 if (blocks != 0 || i != 0) 580 fprintf(stderr, "tar: %s: file changed size\n", 581 longname); 582 while (--blocks >= 0) 583 putempty(); 584 break; 585 586 default: 587 fprintf(stderr, "tar: %s is not a file. Not dumped\n", 588 longname); 589 break; 590 } 591 } 592 593 doxtract(argv) 594 char *argv[]; 595 { 596 long blocks, bytes; 597 char buf[TBLOCK]; 598 char **cp; 599 int ofile; 600 601 for (;;) { 602 getdir(); 603 if (endtape()) 604 break; 605 if (*argv == 0) 606 goto gotit; 607 for (cp = argv; *cp; cp++) 608 if (prefix(*cp, dblock.dbuf.name)) 609 goto gotit; 610 passtape(); 611 continue; 612 613 gotit: 614 if (checkw('x', dblock.dbuf.name) == 0) { 615 passtape(); 616 continue; 617 } 618 if (Fflag) { 619 char *s; 620 621 if ((s = rindex(dblock.dbuf.name, '/')) == 0) 622 s = dblock.dbuf.name; 623 else 624 s++; 625 if (checkf(s, stbuf.st_mode, Fflag) == 0) { 626 passtape(); 627 continue; 628 } 629 } 630 if (checkdir(dblock.dbuf.name)) 631 continue; 632 if (dblock.dbuf.linkflag == '2') { 633 unlink(dblock.dbuf.name); 634 if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) { 635 fprintf(stderr, "tar: %s: symbolic link failed\n", 636 dblock.dbuf.name); 637 continue; 638 } 639 if (vflag) 640 fprintf(stderr, "x %s symbolic link to %s\n", 641 dblock.dbuf.name, dblock.dbuf.linkname); 642 #ifdef notdef 643 /* ignore alien orders */ 644 chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 645 if (mflag == 0) { 646 struct timeval tv[2]; 647 648 tv[0].tv_sec = time(0); 649 tv[0].tv_usec = 0; 650 tv[1].tv_sec = stbuf.st_mtime; 651 tv[1].tv_usec = 0; 652 utimes(dblock.dbuf.name, tv); 653 } 654 if (pflag) 655 chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 656 #endif 657 continue; 658 } 659 if (dblock.dbuf.linkflag == '1') { 660 unlink(dblock.dbuf.name); 661 if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 662 fprintf(stderr, "tar: %s: cannot link\n", 663 dblock.dbuf.name); 664 continue; 665 } 666 if (vflag) 667 fprintf(stderr, "%s linked to %s\n", 668 dblock.dbuf.name, dblock.dbuf.linkname); 669 continue; 670 } 671 if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) { 672 fprintf(stderr, "tar: %s - cannot create\n", 673 dblock.dbuf.name); 674 passtape(); 675 continue; 676 } 677 chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 678 blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 679 if (vflag) 680 fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", 681 dblock.dbuf.name, bytes, blocks); 682 for (; blocks-- > 0; bytes -= TBLOCK) { 683 readtape(buf); 684 if (bytes > TBLOCK) { 685 if (write(ofile, buf, TBLOCK) < 0) { 686 fprintf(stderr, 687 "tar: %s: HELP - extract write error\n", 688 dblock.dbuf.name); 689 done(2); 690 } 691 continue; 692 } 693 if (write(ofile, buf, (int) bytes) < 0) { 694 fprintf(stderr, 695 "tar: %s: HELP - extract write error\n", 696 dblock.dbuf.name); 697 done(2); 698 } 699 } 700 close(ofile); 701 if (mflag == 0) { 702 struct timeval tv[2]; 703 704 tv[0].tv_sec = time(0); 705 tv[0].tv_usec = 0; 706 tv[1].tv_sec = stbuf.st_mtime; 707 tv[1].tv_usec = 0; 708 utimes(dblock.dbuf.name, tv); 709 } 710 if (pflag) 711 chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 712 } 713 } 714 715 dotable() 716 { 717 for (;;) { 718 getdir(); 719 if (endtape()) 720 break; 721 if (vflag) 722 longt(&stbuf); 723 printf("%s", dblock.dbuf.name); 724 if (dblock.dbuf.linkflag == '1') 725 printf(" linked to %s", dblock.dbuf.linkname); 726 if (dblock.dbuf.linkflag == '2') 727 printf(" symbolic link to %s", dblock.dbuf.linkname); 728 printf("\n"); 729 passtape(); 730 } 731 } 732 733 putempty() 734 { 735 char buf[TBLOCK]; 736 737 bzero(buf, sizeof (buf)); 738 writetape(buf); 739 } 740 741 longt(st) 742 register struct stat *st; 743 { 744 register char *cp; 745 char *ctime(); 746 747 pmode(st); 748 printf("%3d/%1d", st->st_uid, st->st_gid); 749 printf("%7D", st->st_size); 750 cp = ctime(&st->st_mtime); 751 printf(" %-12.12s %-4.4s ", cp+4, cp+20); 752 } 753 754 #define SUID 04000 755 #define SGID 02000 756 #define ROWN 0400 757 #define WOWN 0200 758 #define XOWN 0100 759 #define RGRP 040 760 #define WGRP 020 761 #define XGRP 010 762 #define ROTH 04 763 #define WOTH 02 764 #define XOTH 01 765 #define STXT 01000 766 int m1[] = { 1, ROWN, 'r', '-' }; 767 int m2[] = { 1, WOWN, 'w', '-' }; 768 int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 769 int m4[] = { 1, RGRP, 'r', '-' }; 770 int m5[] = { 1, WGRP, 'w', '-' }; 771 int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 772 int m7[] = { 1, ROTH, 'r', '-' }; 773 int m8[] = { 1, WOTH, 'w', '-' }; 774 int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 775 776 int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 777 778 pmode(st) 779 register struct stat *st; 780 { 781 register int **mp; 782 783 for (mp = &m[0]; mp < &m[9];) 784 select(*mp++, st); 785 } 786 787 select(pairp, st) 788 int *pairp; 789 struct stat *st; 790 { 791 register int n, *ap; 792 793 ap = pairp; 794 n = *ap++; 795 while (--n>=0 && (st->st_mode&*ap++)==0) 796 ap++; 797 printf("%c", *ap); 798 } 799 800 checkdir(name) 801 register char *name; 802 { 803 register char *cp; 804 805 /* 806 * Quick check for existance of directory. 807 */ 808 if ((cp = rindex(name, '/')) == 0) 809 return (0); 810 *cp = '\0'; 811 if (access(name, 0) >= 0) { 812 *cp = '/'; 813 return (cp[1] == '\0'); 814 } 815 *cp = '/'; 816 817 /* 818 * No luck, try to make all directories in path. 819 */ 820 for (cp = name; *cp; cp++) { 821 if (*cp != '/') 822 continue; 823 *cp = '\0'; 824 if (access(name, 0) < 0) { 825 if (mkdir(name, 0777) < 0) { 826 perror(name); 827 *cp = '/'; 828 return (0); 829 } 830 chown(name, stbuf.st_uid, stbuf.st_gid); 831 if (pflag) 832 chmod(name, stbuf.st_mode & 0777); 833 } 834 *cp = '/'; 835 } 836 return (cp[-1]=='/'); 837 } 838 839 onintr() 840 { 841 signal(SIGINT, SIG_IGN); 842 term++; 843 } 844 845 onquit() 846 { 847 signal(SIGQUIT, SIG_IGN); 848 term++; 849 } 850 851 onhup() 852 { 853 signal(SIGHUP, SIG_IGN); 854 term++; 855 } 856 857 onterm() 858 { 859 signal(SIGTERM, SIG_IGN); 860 term++; 861 } 862 863 tomodes(sp) 864 register struct stat *sp; 865 { 866 register char *cp; 867 868 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 869 *cp = '\0'; 870 sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 871 sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 872 sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 873 sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 874 sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 875 } 876 877 checksum() 878 { 879 register i; 880 register char *cp; 881 882 for (cp = dblock.dbuf.chksum; 883 cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 884 *cp = ' '; 885 i = 0; 886 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 887 i += *cp; 888 return (i); 889 } 890 891 checkw(c, name) 892 char *name; 893 { 894 if (!wflag) 895 return (1); 896 printf("%c ", c); 897 if (vflag) 898 longt(&stbuf); 899 printf("%s: ", name); 900 return (response() == 'y'); 901 } 902 903 response() 904 { 905 char c; 906 907 c = getchar(); 908 if (c != '\n') 909 while (getchar() != '\n') 910 ; 911 else 912 c = 'n'; 913 return (c); 914 } 915 916 checkf(name, mode, howmuch) 917 char *name; 918 int mode, howmuch; 919 { 920 int l; 921 922 if ((mode & S_IFMT) == S_IFDIR) 923 return (strcmp(name, "SCCS") != 0); 924 if ((l = strlen(name)) < 3) 925 return (1); 926 if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 927 return (0); 928 if (strcmp(name, "core") == 0 || 929 strcmp(name, "errs") == 0 || 930 (howmuch > 1 && strcmp(name, "a.out") == 0)) 931 return (0); 932 /* SHOULD CHECK IF IT IS EXECUTABLE */ 933 return (1); 934 } 935 936 checkupdate(arg) 937 char *arg; 938 { 939 char name[100]; 940 long mtime; 941 daddr_t seekp; 942 daddr_t lookup(); 943 944 rewind(tfile); 945 for (;;) { 946 if ((seekp = lookup(arg)) < 0) 947 return (1); 948 fseek(tfile, seekp, 0); 949 fscanf(tfile, "%s %lo", name, &mtime); 950 return (stbuf.st_mtime > mtime); 951 } 952 } 953 954 done(n) 955 { 956 unlink(tname); 957 exit(n); 958 } 959 960 prefix(s1, s2) 961 register char *s1, *s2; 962 { 963 while (*s1) 964 if (*s1++ != *s2++) 965 return (0); 966 if (*s2) 967 return (*s2 == '/'); 968 return (1); 969 } 970 971 #define N 200 972 int njab; 973 974 daddr_t 975 lookup(s) 976 char *s; 977 { 978 register i; 979 daddr_t a; 980 981 for(i=0; s[i]; i++) 982 if (s[i] == ' ') 983 break; 984 a = bsrch(s, i, low, high); 985 return (a); 986 } 987 988 daddr_t 989 bsrch(s, n, l, h) 990 daddr_t l, h; 991 char *s; 992 { 993 register i, j; 994 char b[N]; 995 daddr_t m, m1; 996 997 njab = 0; 998 999 loop: 1000 if (l >= h) 1001 return (-1L); 1002 m = l + (h-l)/2 - N/2; 1003 if (m < l) 1004 m = l; 1005 fseek(tfile, m, 0); 1006 fread(b, 1, N, tfile); 1007 njab++; 1008 for(i=0; i<N; i++) { 1009 if (b[i] == '\n') 1010 break; 1011 m++; 1012 } 1013 if (m >= h) 1014 return (-1L); 1015 m1 = m; 1016 j = i; 1017 for(i++; i<N; i++) { 1018 m1++; 1019 if (b[i] == '\n') 1020 break; 1021 } 1022 i = cmp(b+j, s, n); 1023 if (i < 0) { 1024 h = m; 1025 goto loop; 1026 } 1027 if (i > 0) { 1028 l = m1; 1029 goto loop; 1030 } 1031 return (m); 1032 } 1033 1034 cmp(b, s, n) 1035 char *b, *s; 1036 { 1037 register i; 1038 1039 if (b[0] != '\n') 1040 exit(2); 1041 for(i=0; i<n; i++) { 1042 if (b[i+1] > s[i]) 1043 return (-1); 1044 if (b[i+1] < s[i]) 1045 return (1); 1046 } 1047 return (b[i+1] == ' '? 0 : -1); 1048 } 1049 1050 readtape(buffer) 1051 char *buffer; 1052 { 1053 register int i; 1054 1055 if (recno >= nblock || first == 0) { 1056 if ((i = bread(mt, tbuf, TBLOCK*nblock)) < 0) { 1057 fprintf(stderr, "tar: tape read error\n"); 1058 done(3); 1059 } 1060 if (first == 0) { 1061 if ((i % TBLOCK) != 0) { 1062 fprintf(stderr, "tar: tape blocksize error\n"); 1063 done(3); 1064 } 1065 i /= TBLOCK; 1066 if (i != nblock) { 1067 fprintf(stderr, "tar: blocksize = %d\n", i); 1068 nblock = i; 1069 } 1070 } 1071 recno = 0; 1072 } 1073 first = 1; 1074 bcopy((char *)&tbuf[recno++], buffer, TBLOCK); 1075 return (TBLOCK); 1076 } 1077 1078 writetape(buffer) 1079 char *buffer; 1080 { 1081 first = 1; 1082 if (recno >= nblock) { 1083 if (write(mt, tbuf, TBLOCK*nblock) < 0) { 1084 fprintf(stderr, "tar: tape write error\n"); 1085 done(2); 1086 } 1087 recno = 0; 1088 } 1089 bcopy(buffer, (char *)&tbuf[recno++], TBLOCK); 1090 if (recno >= nblock) { 1091 if (write(mt, tbuf, TBLOCK*nblock) < 0) { 1092 fprintf(stderr, "tar: tape write error\n"); 1093 done(2); 1094 } 1095 recno = 0; 1096 } 1097 return (TBLOCK); 1098 } 1099 1100 backtape() 1101 { 1102 static int mtdev = 1; 1103 static struct mtop mtop = {MTBSR, 1}; 1104 struct mtget mtget; 1105 1106 if (mtdev == 1) 1107 mtdev = ioctl(mt, MTIOCGET, &mtget); 1108 if (mtdev == 0) { 1109 if (ioctl(mt, MTIOCTOP, &mtop) < 0) { 1110 fprintf(stderr, "tar: tape backspace error\n"); 1111 done(4); 1112 } 1113 } else 1114 lseek(mt, (long) -TBLOCK*nblock, 1); 1115 recno--; 1116 } 1117 1118 flushtape() 1119 { 1120 write(mt, tbuf, TBLOCK*nblock); 1121 } 1122 1123 bread(fd, buf, size) 1124 int fd; 1125 char *buf; 1126 int size; 1127 { 1128 int count; 1129 static int lastread = 0; 1130 1131 if (!Bflag) 1132 return (read(fd, buf, size)); 1133 for (count = 0; count < size; count += lastread) { 1134 if (lastread < 0) { 1135 if (count > 0) 1136 return (count); 1137 return (lastread); 1138 } 1139 lastread = read(fd, buf, size - count); 1140 buf += lastread; 1141 } 1142 return (count); 1143 } 1144 1145 char * 1146 getcwd(buf) 1147 char *buf; 1148 { 1149 1150 if (getwd(buf) == NULL) { 1151 fprintf(stderr, "tar: %s\n", buf); 1152 exit(1); 1153 } 1154 return (buf); 1155 } 1156