Annotation of cci/usr/src/bin/tar.c, revision 1.1.1.2

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;
1.1.1.2 ! root      102:        usefile = magtape;
1.1       root      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:                        }
1.1.1.2 ! root      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
1.1       root      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:                }
1.1.1.2 ! root      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
1.1       root      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
1.1.1.2 ! root      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
1.1       root      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:        }
1.1.1.2 ! root      304: #endif RTAR
1.1       root      305:        if (xflag)
                    306:                doxtract(argv);
                    307:        else
                    308:                dotable();
1.1.1.2 ! root      309:        bread(mt, tbuf, TBLOCK*nblock); 
1.1       root      310:        done(0);
                    311: }
                    312: 
                    313: usage()
                    314: {
                    315:        fprintf(stderr,
1.1.1.2 ! root      316: #ifdef RTAR
        !           317: "rtar: usage: rtar -f{txru}[cvblmhopwBi] remotehost:[tapefile] [blocksize] file1 file2...\n");
        !           318: #else
1.1       root      319: "tar: usage: tar -{txru}[cvfblmhopwBi] [tapefile] [blocksize] file1 file2...\n");
1.1.1.2 ! root      320: #endif RTAR
1.1       root      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());
1.1.1.2 ! root      338:                backtape(); 
1.1       root      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);
1.1.1.2 ! root      354:        while (*argv && !term) {
1.1       root      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) {
1.1.1.2 ! root      639:                        while (i < TBLOCK)
        !           640:                                buf[i++] = '\0';
1.1       root      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:                }
1.1.1.2 ! root     1126: 
1.1       root     1127:                if (first == 0) {
1.1.1.2 ! root     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);
1.1       root     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) {
1.1.1.2 ! root     1151: #ifdef RTAR
        !          1152:                if (rmtwrite(tbuf[0].dummy, TBLOCK*nblock) < 0) {
        !          1153: #else
1.1       root     1154:                if (write(mt, tbuf[0].dummy, TBLOCK*nblock) < 0) {
1.1.1.2 ! root     1155: #endif RTAR
1.1       root     1156:                        fprintf(stderr, "tar: tape write error\n");
                   1157:                        done(2);
                   1158:                }
                   1159:                recno = 0;
                   1160:        }
                   1161:        return (TBLOCK);
                   1162: }
1.1.1.2 ! root     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
1.1       root     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: 
1.1.1.2 ! root     1201: #endif RTAR
        !          1202: 
1.1       root     1203: flushtape()
                   1204: {
1.1.1.2 ! root     1205:        register int record = recno;
        !          1206: 
        !          1207:        while ((record != 0) && (record++ < nblock))
        !          1208:                putempty();
1.1       root     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)
1.1.1.2 ! root     1220: #ifdef RTAR
        !          1221:                return (rmtread(buf, size));
        !          1222: #else
1.1       root     1223:                return (read(fd, buf, size));
1.1.1.2 ! root     1224: #endif RTAR
1.1       root     1225:        for (count = 0; count < size; count += lastread) {
                   1226:                if (lastread < 0) {
                   1227:                        if (count > 0)
                   1228:                                return (count);
                   1229:                        return (lastread);
                   1230:                }
1.1.1.2 ! root     1231: #ifdef RTAR
        !          1232:                lastread = rmtread(buf, size - count);
        !          1233: #else
1.1       root     1234:                lastread = read(fd, buf, size - count);
1.1.1.2 ! root     1235:                printf("lastread: %d ", lastread);      
        !          1236: #endif RTAR
1.1       root     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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.