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