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