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