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