|
|
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 = 0; ! 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 dfmagtape[] = "/dev/rcy0s"; ! 86: char *malloc(); ! 87: char *sprintf(); ! 88: char *strcat(); ! 89: char *rindex(); ! 90: char *getcwd(); ! 91: char *getwd(); ! 92: char *index(); ! 93: ! 94: main(argc, argv) ! 95: int argc; ! 96: char *argv[]; ! 97: { ! 98: char *cp; ! 99: char *host, *magtape; /* RTAR */ ! 100: ! 101: if (argc < 2) ! 102: usage(); ! 103: ! 104: tfile = NULL; ! 105: ! 106: /* add for rtar */ ! 107: ! 108: host = argv[argc-1]; ! 109: magtape = index(host, ':'); ! 110: if (magtape == 0) ! 111: magtape = dfmagtape; ! 112: else ! 113: *magtape++ = '\0'; ! 114: ! 115: if (rmthost(host) == 0) ! 116: done(1); ! 117: setuid(getuid()); /* no longer need or want root privileges */ ! 118: ! 119: /* end of add */ ! 120: ! 121: usefile = magtape; ! 122: argv[argc-1] = 0; ! 123: argv++; ! 124: for (cp = *argv++; *cp; cp++) ! 125: switch(*cp) { ! 126: ! 127: case 'f': ! 128: if (*argv == 0) { ! 129: fprintf(stderr, ! 130: "tar: tapefile must be specified with 'f' option\n"); ! 131: usage(); ! 132: } ! 133: usefile = *argv++; ! 134: fflag++; ! 135: break; ! 136: ! 137: case 'c': ! 138: cflag++; ! 139: rflag++; ! 140: break; ! 141: ! 142: case 'o': ! 143: oflag++; ! 144: break; ! 145: ! 146: case 'p': ! 147: pflag++; ! 148: break; ! 149: ! 150: case 'u': ! 151: mktemp(tname); ! 152: if ((tfile = fopen(tname, "w")) == NULL) { ! 153: fprintf(stderr, ! 154: "Tar: cannot create temporary file (%s)\n", ! 155: tname); ! 156: done(1); ! 157: } ! 158: fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); ! 159: /*FALL THRU*/ ! 160: ! 161: case 'r': ! 162: rflag++; ! 163: break; ! 164: ! 165: case 'v': ! 166: vflag++; ! 167: break; ! 168: ! 169: case 'w': ! 170: wflag++; ! 171: break; ! 172: ! 173: case 'x': ! 174: xflag++; ! 175: break; ! 176: ! 177: case 't': ! 178: tflag++; ! 179: break; ! 180: ! 181: case 'm': ! 182: mflag++; ! 183: break; ! 184: ! 185: case '-': ! 186: break; ! 187: ! 188: case '0': ! 189: case '1': ! 190: case '4': ! 191: case '5': ! 192: case '7': ! 193: case '8': ! 194: magtape[8] = *cp; ! 195: usefile = magtape; ! 196: break; ! 197: ! 198: case 'b': ! 199: if (*argv == 0) { ! 200: fprintf(stderr, ! 201: "tar: blocksize must be specified with 'b' option\n"); ! 202: usage(); ! 203: } ! 204: nblock = atoi(*argv); ! 205: if (nblock <= 0) { ! 206: fprintf(stderr, ! 207: "tar: invalid blocksize \"%s\"\n", *argv); ! 208: done(1); ! 209: } ! 210: argv++; ! 211: break; ! 212: ! 213: case 'l': ! 214: linkerrok++; ! 215: break; ! 216: ! 217: case 'h': ! 218: hflag++; ! 219: break; ! 220: ! 221: case 'i': ! 222: iflag++; ! 223: break; ! 224: ! 225: case 'B': ! 226: Bflag++; ! 227: break; ! 228: ! 229: case 'F': ! 230: Fflag++; ! 231: break; ! 232: ! 233: default: ! 234: fprintf(stderr, "tar: %c: unknown option\n", *cp); ! 235: usage(); ! 236: } ! 237: ! 238: if (!rflag && !xflag && !tflag) ! 239: usage(); ! 240: tbuf = (union hblock *)malloc(nblock*TBLOCK); ! 241: if (tbuf == NULL) { ! 242: fprintf(stderr, "tar: blocksize %d too big, can't get memory\n", ! 243: nblock); ! 244: done(1); ! 245: } ! 246: if (rflag) { ! 247: if (cflag && tfile != NULL) ! 248: usage(); ! 249: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 250: signal(SIGINT, onintr); ! 251: if (signal(SIGHUP, SIG_IGN) != SIG_IGN) ! 252: signal(SIGHUP, onhup); ! 253: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) ! 254: signal(SIGQUIT, onquit); ! 255: #ifdef notdef ! 256: if (signal(SIGTERM, SIG_IGN) != SIG_IGN) ! 257: signal(SIGTERM, onterm); ! 258: #endif ! 259: ! 260: /* open the second dev if the first failed ---- for RTAR */ ! 261: ! 262: if (rmtopen(usefile, 2) < 0) { ! 263: if (cflag == 0 || (rmtcreat(usefile, 0666)) < 0) { ! 264: fprintf(stderr, ! 265: "tar: cannot open %s\n", usefile); ! 266: done(1); ! 267: } ! 268: } ! 269: dorep(argv); ! 270: done(0); ! 271: } ! 272: if (rmtopen(usefile, 0) < 0) { ! 273: fprintf(stderr, "tar: cannot open %s\n", usefile); ! 274: done(1); ! 275: } ! 276: ! 277: if (xflag) ! 278: doxtract(argv); ! 279: else ! 280: dotable(); ! 281: done(0); ! 282: } ! 283: ! 284: usage() ! 285: { ! 286: fprintf(stderr, ! 287: "tar: usage: tar -{txru}[cvfblmhopwBi] [tapefile] [blocksize] file1 file2...\n"); ! 288: done(1); ! 289: } ! 290: ! 291: dorep(argv) ! 292: char *argv[]; ! 293: { ! 294: register char *cp, *cp2; ! 295: char wdir[MAXPATHLEN], tempdir[MAXPATHLEN], *parent; ! 296: ! 297: if (!cflag) { ! 298: getdir(); ! 299: do { ! 300: passtape(); ! 301: if (term) ! 302: done(0); ! 303: getdir(); ! 304: } while (!endtape()); ! 305: backtape(); ! 306: if (tfile != NULL) { ! 307: char buf[200]; ! 308: ! 309: sprintf(buf, ! 310: "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s", ! 311: tname, tname, tname, tname, tname, tname); ! 312: fflush(tfile); ! 313: system(buf); ! 314: freopen(tname, "r", tfile); ! 315: fstat(fileno(tfile), &stbuf); ! 316: high = stbuf.st_size; ! 317: } ! 318: } ! 319: ! 320: (void) getcwd(wdir); ! 321: while (*argv && !term) { ! 322: cp2 = *argv; ! 323: if (!strcmp(cp2, "-C") && argv[1]) { ! 324: argv++; ! 325: if (chdir(*argv) < 0) ! 326: perror(*argv); ! 327: else ! 328: (void) getcwd(wdir); ! 329: argv++; ! 330: continue; ! 331: } ! 332: parent = wdir; ! 333: for (cp = *argv; *cp; cp++) ! 334: if (*cp == '/') ! 335: cp2 = cp; ! 336: /************ ! 337: if (cp2 != *argv) { ! 338: *************/ ! 339: if(*cp2 == '/') { ! 340: if (cp2 != *argv) { ! 341: *cp2 = '\0'; ! 342: if (chdir(*argv) < 0) { ! 343: perror(*argv); ! 344: continue; ! 345: } ! 346: } else ! 347: if (chdir("/") < 0) { ! 348: perror("/"); ! 349: continue; ! 350: } ! 351: parent = getcwd(tempdir); ! 352: *cp2 = '/'; ! 353: cp2++; ! 354: } ! 355: putfile(*argv++, cp2, parent); ! 356: if (chdir(wdir) < 0) { ! 357: fprintf(stderr, "cannot change back?: "); ! 358: perror(wdir); ! 359: } ! 360: } ! 361: putempty(); ! 362: putempty(); ! 363: flushtape(); ! 364: if (linkerrok == 0) ! 365: return; ! 366: for (; ihead != NULL; ihead = ihead->nextp) { ! 367: if (ihead->count == 0) ! 368: continue; ! 369: fprintf(stderr, "tar: missing links to %s\n", ihead->pathname); ! 370: } ! 371: } ! 372: ! 373: endtape() ! 374: { ! 375: return (dblock.dbuf.name[0] == '\0'); ! 376: } ! 377: ! 378: getdir() ! 379: { ! 380: register struct stat *sp; ! 381: int i; ! 382: ! 383: top: ! 384: readtape(dblock.dummy); ! 385: if (dblock.dbuf.name[0] == '\0') ! 386: return; ! 387: sp = &stbuf; ! 388: sscanf(dblock.dbuf.mode, "%o", &i); ! 389: sp->st_mode = i; ! 390: sscanf(dblock.dbuf.uid, "%o", &i); ! 391: sp->st_uid = i; ! 392: sscanf(dblock.dbuf.gid, "%o", &i); ! 393: sp->st_gid = i; ! 394: sscanf(dblock.dbuf.size, "%lo", &sp->st_size); ! 395: sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); ! 396: sscanf(dblock.dbuf.chksum, "%o", &chksum); ! 397: if (chksum != (i = checksum())) { ! 398: fprintf(stderr, "tar: directory checksum error (%d != %d)\n", ! 399: chksum, i); ! 400: if (iflag) ! 401: goto top; ! 402: done(2); ! 403: } ! 404: if (tfile != NULL) ! 405: fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); ! 406: } ! 407: ! 408: passtape() ! 409: { ! 410: long blocks; ! 411: char buf[TBLOCK]; ! 412: ! 413: if (dblock.dbuf.linkflag == '1') ! 414: return; ! 415: blocks = stbuf.st_size; ! 416: blocks += TBLOCK-1; ! 417: blocks /= TBLOCK; ! 418: ! 419: while (blocks-- > 0) ! 420: readtape(buf); ! 421: } ! 422: ! 423: putfile(longname, shortname, parent) ! 424: char *longname; ! 425: char *shortname; ! 426: char *parent; ! 427: { ! 428: int infile = 0; ! 429: long blocks; ! 430: char buf[TBLOCK]; ! 431: register char *cp, *cp2; ! 432: struct direct *dp; ! 433: DIR *dirp; ! 434: int i, j; ! 435: char newparent[NAMSIZ+64]; ! 436: extern int errno; ! 437: ! 438: if (!hflag) ! 439: i = lstat(shortname, &stbuf); ! 440: else ! 441: i = stat(shortname, &stbuf); ! 442: if (i < 0) { ! 443: switch (errno) { ! 444: case EACCES: ! 445: fprintf(stderr, "tar: %s: cannot open file\n", longname); ! 446: break; ! 447: case ENOENT: ! 448: fprintf(stderr, "tar: %s: no such file or directory\n", ! 449: longname); ! 450: break; ! 451: default: ! 452: fprintf(stderr, "tar: %s: cannot stat file\n", longname); ! 453: break; ! 454: } ! 455: return; ! 456: } ! 457: if (tfile != NULL && checkupdate(longname) == 0) ! 458: return; ! 459: if (checkw('r', longname) == 0) ! 460: return; ! 461: if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) ! 462: return; ! 463: ! 464: switch (stbuf.st_mode & S_IFMT) { ! 465: case S_IFDIR: ! 466: for (i = 0, cp = buf; *cp++ = longname[i++];) ! 467: ; ! 468: *--cp = '/'; ! 469: *++cp = 0 ; ! 470: if (!oflag) { ! 471: if ((cp - buf) >= NAMSIZ) { ! 472: fprintf(stderr, "tar: %s: file name too long\n", ! 473: longname); ! 474: return; ! 475: } ! 476: stbuf.st_size = 0; ! 477: tomodes(&stbuf); ! 478: strcpy(dblock.dbuf.name,buf); ! 479: sprintf(dblock.dbuf.chksum, "%6o", checksum()); ! 480: writetape(dblock.dummy); ! 481: } ! 482: sprintf(newparent, "%s/%s", parent, shortname); ! 483: if (chdir(shortname) < 0) { ! 484: perror(shortname); ! 485: return; ! 486: } ! 487: if ((dirp = opendir(".")) == NULL) { ! 488: fprintf(stderr, "tar: %s: directory read error\n", ! 489: longname); ! 490: if (chdir(parent) < 0) { ! 491: fprintf(stderr, "cannot change back?: "); ! 492: perror(parent); ! 493: } ! 494: return; ! 495: } ! 496: while ((dp = readdir(dirp)) != NULL && !term) { ! 497: if (dp->d_ino == 0) ! 498: continue; ! 499: if (!strcmp(".", dp->d_name) || ! 500: !strcmp("..", dp->d_name)) ! 501: continue; ! 502: strcpy(cp, dp->d_name); ! 503: i = telldir(dirp); ! 504: closedir(dirp); ! 505: putfile(buf, cp, newparent); ! 506: dirp = opendir("."); ! 507: seekdir(dirp, i); ! 508: } ! 509: closedir(dirp); ! 510: if (chdir(parent) < 0) { ! 511: fprintf(stderr, "cannot change back?: "); ! 512: perror(parent); ! 513: } ! 514: break; ! 515: ! 516: case S_IFLNK: ! 517: tomodes(&stbuf); ! 518: if (strlen(longname) >= NAMSIZ) { ! 519: fprintf(stderr, "tar: %s: file name too long\n", ! 520: longname); ! 521: return; ! 522: } ! 523: strcpy(dblock.dbuf.name, longname); ! 524: if (stbuf.st_size + 1 >= NAMSIZ) { ! 525: fprintf(stderr, "tar: %s: symbolic link too long\n", ! 526: longname); ! 527: return; ! 528: } ! 529: i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1); ! 530: if (i < 0) { ! 531: perror(longname); ! 532: return; ! 533: } ! 534: dblock.dbuf.linkname[i] = '\0'; ! 535: dblock.dbuf.linkflag = '2'; ! 536: if (vflag) { ! 537: fprintf(stderr, "a %s ", longname); ! 538: fprintf(stderr, "symbolic link to %s\n", ! 539: dblock.dbuf.linkname); ! 540: } ! 541: sprintf(dblock.dbuf.size, "%11lo", 0); ! 542: sprintf(dblock.dbuf.chksum, "%6o", checksum()); ! 543: writetape(dblock.dummy); ! 544: break; ! 545: ! 546: case S_IFREG: ! 547: if ((infile = open(shortname, 0)) < 0) { ! 548: fprintf(stderr, "tar: %s: cannot open file\n", longname); ! 549: return; ! 550: } ! 551: tomodes(&stbuf); ! 552: if (strlen(longname) >= NAMSIZ) { ! 553: fprintf(stderr, "tar: %s: file name too long\n", ! 554: longname); ! 555: return; ! 556: } ! 557: strcpy(dblock.dbuf.name, longname); ! 558: if (stbuf.st_nlink > 1) { ! 559: struct linkbuf *lp; ! 560: int found = 0; ! 561: ! 562: for (lp = ihead; lp != NULL; lp = lp->nextp) ! 563: if (lp->inum == stbuf.st_ino && ! 564: lp->devnum == stbuf.st_dev) { ! 565: found++; ! 566: break; ! 567: } ! 568: if (found) { ! 569: strcpy(dblock.dbuf.linkname, lp->pathname); ! 570: dblock.dbuf.linkflag = '1'; ! 571: sprintf(dblock.dbuf.chksum, "%6o", checksum()); ! 572: writetape( dblock.dummy); ! 573: if (vflag) { ! 574: fprintf(stderr, "a %s ", longname); ! 575: fprintf(stderr, "link to %s\n", ! 576: lp->pathname); ! 577: } ! 578: lp->count--; ! 579: close(infile); ! 580: return; ! 581: } ! 582: lp = (struct linkbuf *) malloc(sizeof(*lp)); ! 583: if (lp == NULL) { ! 584: if (freemem) { ! 585: fprintf(stderr, ! 586: "tar: out of memory, link information lost\n"); ! 587: freemem = 0; ! 588: } ! 589: } else { ! 590: lp->nextp = ihead; ! 591: ihead = lp; ! 592: lp->inum = stbuf.st_ino; ! 593: lp->devnum = stbuf.st_dev; ! 594: lp->count = stbuf.st_nlink - 1; ! 595: strcpy(lp->pathname, longname); ! 596: } ! 597: } ! 598: blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; ! 599: if (vflag) { ! 600: fprintf(stderr, "a %s ", longname); ! 601: fprintf(stderr, "%ld blocks\n", blocks); ! 602: } ! 603: sprintf(dblock.dbuf.chksum, "%6o", checksum()); ! 604: writetape(dblock.dummy); ! 605: ! 606: while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { ! 607: writetape(buf); ! 608: blocks--; ! 609: } ! 610: close(infile); ! 611: if (blocks != 0 || i != 0) ! 612: fprintf(stderr, "tar: %s: file changed size\n", ! 613: longname); ! 614: while (--blocks >= 0) ! 615: putempty(); ! 616: break; ! 617: ! 618: default: ! 619: fprintf(stderr, "tar: %s is not a file. Not dumped\n", ! 620: longname); ! 621: break; ! 622: } ! 623: } ! 624: ! 625: doxtract(argv) ! 626: char *argv[]; ! 627: { ! 628: long blocks, bytes; ! 629: char buf[TBLOCK]; ! 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)) ! 663: continue; ! 664: if (dblock.dbuf.linkflag == '2') { ! 665: unlink(dblock.dbuf.name); ! 666: if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) { ! 667: fprintf(stderr, "tar: %s: symbolic link failed\n", ! 668: dblock.dbuf.name); ! 669: continue; ! 670: } ! 671: if (vflag) ! 672: fprintf(stderr, "x %s symbolic link to %s\n", ! 673: dblock.dbuf.name, dblock.dbuf.linkname); ! 674: #ifdef notdef ! 675: /* ignore alien orders */ ! 676: chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); ! 677: if (mflag == 0) { ! 678: struct timeval tv[2]; ! 679: ! 680: tv[0].tv_sec = time(0); ! 681: tv[0].tv_usec = 0; ! 682: tv[1].tv_sec = stbuf.st_mtime; ! 683: tv[1].tv_usec = 0; ! 684: utimes(dblock.dbuf.name, tv); ! 685: } ! 686: if (pflag) ! 687: chmod(dblock.dbuf.name, stbuf.st_mode & 07777); ! 688: #endif ! 689: continue; ! 690: } ! 691: if (dblock.dbuf.linkflag == '1') { ! 692: unlink(dblock.dbuf.name); ! 693: if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { ! 694: fprintf(stderr, "tar: %s: cannot link\n", ! 695: dblock.dbuf.name); ! 696: continue; ! 697: } ! 698: if (vflag) ! 699: fprintf(stderr, "%s linked to %s\n", ! 700: dblock.dbuf.name, dblock.dbuf.linkname); ! 701: continue; ! 702: } ! 703: if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) { ! 704: fprintf(stderr, "tar: %s - cannot create\n", ! 705: dblock.dbuf.name); ! 706: passtape(); ! 707: continue; ! 708: } ! 709: chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); ! 710: blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; ! 711: if (vflag) ! 712: fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", ! 713: dblock.dbuf.name, bytes, blocks); ! 714: for (; blocks-- > 0; bytes -= TBLOCK) { ! 715: readtape(buf); ! 716: if (bytes > TBLOCK) { ! 717: if (write(ofile, buf, TBLOCK) < 0) { ! 718: fprintf(stderr, ! 719: "tar: %s: HELP - extract write error\n", ! 720: dblock.dbuf.name); ! 721: done(2); ! 722: } ! 723: continue; ! 724: } ! 725: if (write(ofile, buf, (int) bytes) < 0) { ! 726: fprintf(stderr, ! 727: "tar: %s: HELP - extract write error\n", ! 728: dblock.dbuf.name); ! 729: done(2); ! 730: } ! 731: } ! 732: close(ofile); ! 733: if (mflag == 0) { ! 734: struct timeval tv[2]; ! 735: ! 736: tv[0].tv_sec = time(0); ! 737: tv[0].tv_usec = 0; ! 738: tv[1].tv_sec = stbuf.st_mtime; ! 739: tv[1].tv_usec = 0; ! 740: utimes(dblock.dbuf.name, tv); ! 741: } ! 742: if (pflag) ! 743: chmod(dblock.dbuf.name, stbuf.st_mode & 07777); ! 744: } ! 745: } ! 746: ! 747: dotable() ! 748: { ! 749: for (;;) { ! 750: getdir(); ! 751: if (endtape()) ! 752: break; ! 753: if (vflag) ! 754: longt(&stbuf); ! 755: printf("%s", dblock.dbuf.name); ! 756: if (dblock.dbuf.linkflag == '1') ! 757: printf(" linked to %s", dblock.dbuf.linkname); ! 758: if (dblock.dbuf.linkflag == '2') ! 759: printf(" symbolic link to %s", dblock.dbuf.linkname); ! 760: printf("\n"); ! 761: passtape(); ! 762: } ! 763: } ! 764: ! 765: putempty() ! 766: { ! 767: char buf[TBLOCK]; ! 768: ! 769: bzero(buf, sizeof (buf)); ! 770: writetape(buf); ! 771: } ! 772: ! 773: longt(st) ! 774: register struct stat *st; ! 775: { ! 776: register char *cp; ! 777: char *ctime(); ! 778: ! 779: pmode(st); ! 780: printf("%3d/%1d", st->st_uid, st->st_gid); ! 781: printf("%7D", st->st_size); ! 782: cp = ctime(&st->st_mtime); ! 783: printf(" %-12.12s %-4.4s ", cp+4, cp+20); ! 784: } ! 785: ! 786: #define SUID 04000 ! 787: #define SGID 02000 ! 788: #define ROWN 0400 ! 789: #define WOWN 0200 ! 790: #define XOWN 0100 ! 791: #define RGRP 040 ! 792: #define WGRP 020 ! 793: #define XGRP 010 ! 794: #define ROTH 04 ! 795: #define WOTH 02 ! 796: #define XOTH 01 ! 797: #define STXT 01000 ! 798: int m1[] = { 1, ROWN, 'r', '-' }; ! 799: int m2[] = { 1, WOWN, 'w', '-' }; ! 800: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; ! 801: int m4[] = { 1, RGRP, 'r', '-' }; ! 802: int m5[] = { 1, WGRP, 'w', '-' }; ! 803: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; ! 804: int m7[] = { 1, ROTH, 'r', '-' }; ! 805: int m8[] = { 1, WOTH, 'w', '-' }; ! 806: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; ! 807: ! 808: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; ! 809: ! 810: pmode(st) ! 811: register struct stat *st; ! 812: { ! 813: register int **mp; ! 814: ! 815: for (mp = &m[0]; mp < &m[9];) ! 816: select(*mp++, st); ! 817: } ! 818: ! 819: select(pairp, st) ! 820: int *pairp; ! 821: struct stat *st; ! 822: { ! 823: register int n, *ap; ! 824: ! 825: ap = pairp; ! 826: n = *ap++; ! 827: while (--n>=0 && (st->st_mode&*ap++)==0) ! 828: ap++; ! 829: printf("%c", *ap); ! 830: } ! 831: ! 832: checkdir(name) ! 833: register char *name; ! 834: { ! 835: register char *cp; ! 836: ! 837: /* ! 838: * Quick check for existance of directory. ! 839: */ ! 840: if ((cp = rindex(name, '/')) == 0) ! 841: return (0); ! 842: *cp = '\0'; ! 843: if (access(name, 0) >= 0) { ! 844: *cp = '/'; ! 845: return (cp[1] == '\0'); ! 846: } ! 847: *cp = '/'; ! 848: ! 849: /* ! 850: * No luck, try to make all directories in path. ! 851: */ ! 852: for (cp = name; *cp; cp++) { ! 853: if (*cp != '/') ! 854: continue; ! 855: *cp = '\0'; ! 856: if (access(name, 0) < 0) { ! 857: if (mkdir(name, 0777) < 0) { ! 858: perror(name); ! 859: *cp = '/'; ! 860: return (0); ! 861: } ! 862: chown(name, stbuf.st_uid, stbuf.st_gid); ! 863: if (pflag && cp[1] == '\0') ! 864: chmod(name, stbuf.st_mode & 0777); ! 865: } ! 866: *cp = '/'; ! 867: } ! 868: return (cp[-1]=='/'); ! 869: } ! 870: ! 871: onintr() ! 872: { ! 873: signal(SIGINT, SIG_IGN); ! 874: term++; ! 875: } ! 876: ! 877: onquit() ! 878: { ! 879: signal(SIGQUIT, SIG_IGN); ! 880: term++; ! 881: } ! 882: ! 883: onhup() ! 884: { ! 885: signal(SIGHUP, SIG_IGN); ! 886: term++; ! 887: } ! 888: ! 889: onterm() ! 890: { ! 891: signal(SIGTERM, SIG_IGN); ! 892: term++; ! 893: } ! 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 int 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: return (strcmp(name, "SCCS") != 0); ! 956: if ((l = strlen(name)) < 3) ! 957: return (1); ! 958: if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') ! 959: return (0); ! 960: if (strcmp(name, "core") == 0 || ! 961: strcmp(name, "errs") == 0 || ! 962: (howmuch > 1 && strcmp(name, "a.out") == 0)) ! 963: return (0); ! 964: /* SHOULD CHECK IF IT IS EXECUTABLE */ ! 965: return (1); ! 966: } ! 967: ! 968: checkupdate(arg) ! 969: char *arg; ! 970: { ! 971: char name[100]; ! 972: long mtime; ! 973: daddr_t seekp; ! 974: daddr_t lookup(); ! 975: ! 976: rewind(tfile); ! 977: for (;;) { ! 978: if ((seekp = lookup(arg)) < 0) ! 979: return (1); ! 980: fseek(tfile, seekp, 0); ! 981: fscanf(tfile, "%s %lo", name, &mtime); ! 982: return (stbuf.st_mtime > mtime); ! 983: } ! 984: } ! 985: ! 986: done(n) ! 987: { ! 988: unlink(tname); ! 989: exit(n); ! 990: } ! 991: ! 992: prefix(s1, s2) ! 993: register char *s1, *s2; ! 994: { ! 995: while (*s1) ! 996: if (*s1++ != *s2++) ! 997: return (0); ! 998: if (*s2) ! 999: return (*s2 == '/'); ! 1000: return (1); ! 1001: } ! 1002: ! 1003: #define N 200 ! 1004: int njab; ! 1005: ! 1006: daddr_t ! 1007: lookup(s) ! 1008: char *s; ! 1009: { ! 1010: register int i; ! 1011: daddr_t a; ! 1012: ! 1013: for(i=0; s[i]; i++) ! 1014: if (s[i] == ' ') ! 1015: break; ! 1016: a = bsrch(s, i, low, high); ! 1017: return (a); ! 1018: } ! 1019: ! 1020: daddr_t ! 1021: bsrch(s, n, l, h) ! 1022: daddr_t l, h; ! 1023: char *s; ! 1024: { ! 1025: register int i, j; ! 1026: char b[N]; ! 1027: daddr_t m, m1; ! 1028: ! 1029: njab = 0; ! 1030: ! 1031: loop: ! 1032: if (l >= h) ! 1033: return (-1L); ! 1034: m = l + (h-l)/2 - N/2; ! 1035: if (m < l) ! 1036: m = l; ! 1037: fseek(tfile, m, 0); ! 1038: fread(b, 1, N, tfile); ! 1039: njab++; ! 1040: for(i=0; i<N; i++) { ! 1041: if (b[i] == '\n') ! 1042: break; ! 1043: m++; ! 1044: } ! 1045: if (m >= h) ! 1046: return (-1L); ! 1047: m1 = m; ! 1048: j = i; ! 1049: for(i++; i<N; i++) { ! 1050: m1++; ! 1051: if (b[i] == '\n') ! 1052: break; ! 1053: } ! 1054: i = cmp(b+j, s, n); ! 1055: if (i < 0) { ! 1056: h = m; ! 1057: goto loop; ! 1058: } ! 1059: if (i > 0) { ! 1060: l = m1; ! 1061: goto loop; ! 1062: } ! 1063: return (m); ! 1064: } ! 1065: ! 1066: cmp(b, s, n) ! 1067: char *b, *s; ! 1068: { ! 1069: register int i; ! 1070: ! 1071: if (b[0] != '\n') ! 1072: exit(2); ! 1073: for(i=0; i<n; i++) { ! 1074: if (b[i+1] > s[i]) ! 1075: return (-1); ! 1076: if (b[i+1] < s[i]) ! 1077: return (1); ! 1078: } ! 1079: return (b[i+1] == ' '? 0 : -1); ! 1080: } ! 1081: ! 1082: readtape(buffer) ! 1083: char *buffer; ! 1084: { ! 1085: register int i; ! 1086: int old_nblock, retry = 0; ! 1087: ! 1088: if (recno >= nblock || first == 0) { ! 1089: tryagain: ! 1090: if ((i = bread(tbuf, TBLOCK*nblock)) < 0) { ! 1091: fprintf(stderr, "tar: tape read error\n"); ! 1092: done(3); ! 1093: } ! 1094: ! 1095: /* printf("nblk: %d, i: %d\n", nblock, i); for debugging */ ! 1096: ! 1097: if (first == 0) { ! 1098: old_nblock = nblock; ! 1099: if ((i % TBLOCK) != 0) { ! 1100: nblock = i / TBLOCK; ! 1101: if ((nblock <= 0) || retry) { ! 1102: fprintf(stderr, "tar: tape blocksize error\n"); ! 1103: done(3); ! 1104: } else { ! 1105: rewindtape(); ! 1106: retry = 1; ! 1107: goto tryagain; ! 1108: } ! 1109: } ! 1110: i /= TBLOCK; ! 1111: if (i != old_nblock) { ! 1112: fprintf(stderr, "tar: blocksize = %d\n", i); ! 1113: nblock = i; ! 1114: } ! 1115: } ! 1116: recno = 0; ! 1117: } ! 1118: first = 1; ! 1119: bcopy(tbuf[recno++].dummy, buffer, TBLOCK); ! 1120: return (TBLOCK); ! 1121: } ! 1122: ! 1123: writetape(buffer) ! 1124: char *buffer; ! 1125: { ! 1126: first = 1; ! 1127: if (recno >= nblock) { ! 1128: if (rmtwrite(tbuf[0].dummy, TBLOCK*nblock) < 0) { ! 1129: fprintf(stderr, "tar: tape write error\n"); ! 1130: done(2); ! 1131: } ! 1132: recno = 0; ! 1133: } ! 1134: bcopy(buffer, tbuf[recno++].dummy, TBLOCK); ! 1135: if (recno >= nblock) { ! 1136: if (rmtwrite(tbuf[0].dummy, TBLOCK*nblock) < 0) { ! 1137: fprintf(stderr, "tar: tape write error\n"); ! 1138: done(2); ! 1139: } ! 1140: recno = 0; ! 1141: } ! 1142: return (TBLOCK); ! 1143: } ! 1144: ! 1145: backtape() ! 1146: { ! 1147: static int mtdev = 1; ! 1148: static struct mtget *mtget; ! 1149: ! 1150: if (mtdev == 1) { ! 1151: mtget = (struct mtget *)rmtstatus(); ! 1152: mtdev = 0; ! 1153: } ! 1154: if (mtget != (struct mtget *)0) { /* if never been an error */ ! 1155: if (rmtioctl(MTBSR, 1) < 0) { ! 1156: fprintf(stderr, "tar: tape backspace error\n"); ! 1157: done(4); ! 1158: } ! 1159: } else ! 1160: rmtseek((long) -TBLOCK*nblock, 1); ! 1161: recno--; ! 1162: } ! 1163: ! 1164: /* ! 1165: Add for RTAR - needed for automatically figuring out tape block size ! 1166: */ ! 1167: ! 1168: rewindtape() ! 1169: { ! 1170: if (rmtioctl(MTREW, 1) < 0) { ! 1171: fprintf(stderr, "tar: tape rewind error\n"); ! 1172: done(4); ! 1173: } ! 1174: } ! 1175: ! 1176: flushtape() ! 1177: { ! 1178: if (rmtwrite(tbuf[0].dummy, TBLOCK*nblock) < 0) { ! 1179: fprintf(stderr, "tar: tape write error\n"); ! 1180: done(2); ! 1181: } ! 1182: } ! 1183: ! 1184: bread(buf, size) ! 1185: char *buf; ! 1186: int size; ! 1187: { ! 1188: int count; ! 1189: static int lastread = 0; ! 1190: ! 1191: if (!Bflag) ! 1192: return (rmtread(buf, size)); ! 1193: for (count = 0; count < size; count += lastread) { ! 1194: if (lastread < 0) { ! 1195: if (count > 0) ! 1196: return (count); ! 1197: return (lastread); ! 1198: } ! 1199: lastread = rmtread(buf, size - count); ! 1200: buf += lastread; ! 1201: } ! 1202: return (count); ! 1203: } ! 1204: ! 1205: char * ! 1206: getcwd(buf) ! 1207: char *buf; ! 1208: { ! 1209: ! 1210: if (getwd(buf) == NULL) { ! 1211: fprintf(stderr, "tar: %s\n", buf); ! 1212: exit(1); ! 1213: } ! 1214: return (buf); ! 1215: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.