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