Annotation of cci/usr/src/etc/restore/tape.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)tape.c     3.21    (Berkeley)      83/08/11";
                      3: #endif
                      4: 
                      5: /* Copyright (c) 1983 Regents of the University of California */
                      6: 
                      7: #include "restore.h"
                      8: #include <dumprestor.h>
                      9: #include <sys/ioctl.h>
                     10: #include <sys/mtio.h>
                     11: #include <sys/file.h>
                     12: #include <setjmp.h>
                     13: #include <sys/stat.h>
                     14: 
                     15: static long    fssize = MAXBSIZE;
                     16: static int     mt = -1;
                     17: static int     pipein = 0;
                     18: static char    *magtape;
                     19: static int     bct = NTREC+1;
                     20: static char    tbf[NTREC*TP_BSIZE];
                     21: static union   u_spcl endoftapemark;
                     22: static long    blksread;
                     23: static long    tapesread;
                     24: static jmp_buf restart;
                     25: static int     gettingfile = 0;        /* restart has a valid frame */
                     26: 
                     27: static int     ofile;
                     28: static char    *map;
                     29: static char    lnkbuf[MAXPATHLEN + 1];
                     30: static int     pathlen;
                     31: 
                     32: /*
                     33:  * Set up an input source
                     34:  */
                     35: setinput(source)
                     36:        char *source;
                     37: {
                     38: #ifdef RRESTORE
                     39:        char *host;
                     40: #endif RRESTORE
                     41: 
                     42:        terminal = stdin;
                     43: #ifdef RRESTORE
                     44:        host = source;
                     45:        magtape = index(host, ':');
                     46:        if (magtape == 0) {
                     47: nohost:
                     48:                msg("need keyletter ``f'' and device ``host:tape''\n");
                     49:                done(1);
                     50:        }
                     51:        *magtape++ = '\0';
                     52:        if (rmthost(host) == 0)
                     53:                done(1);
                     54:        setuid(getuid());       /* no longer need or want root privileges */
                     55: #else
                     56:        if (strcmp(source, "-") == 0) {
                     57:                /*
                     58:                 * Since input is coming from a pipe we must establish
                     59:                 * our own connection to the terminal.
                     60:                 */
                     61:                terminal = fopen("/dev/tty", "r");
                     62:                if (terminal == NULL) {
                     63:                        perror("open(\"/dev/tty\")");
                     64:                        done(1);
                     65:                }
                     66:                pipein++;
                     67:        }
                     68:        magtape = source;
                     69: #endif RRESTORE
                     70: }
                     71: 
                     72: /*
                     73:  * Verify that the tape drive can be accessed and
                     74:  * that it actually is a dump tape.
                     75:  */
                     76: setup()
                     77: {
                     78:        int i, j, *ip;
                     79:        struct stat stbuf;
                     80:        extern char *ctime();
                     81:        extern int xtrmap(), xtrmapskip();
                     82: 
                     83:        vprintf(stdout, "Verify tape and initialize maps\n");
                     84: #ifdef RRESTORE
                     85:        if ((mt = rmtopen(magtape, 0)) < 0)
                     86: #else
                     87:        if (pipein)
                     88:                mt = 0;
                     89:        else if ((mt = open(magtape, 0)) < 0)
                     90: #endif
                     91:        {
                     92:                perror(magtape);
                     93:                done(1);
                     94:        }
                     95:        volno = 1;
                     96:        setdumpnum();
                     97:        flsht();
                     98:        if (gethead(&spcl) == FAIL) {
                     99:                bct--; /* push back this block */
                    100:                cvtflag++;
                    101:                if (gethead(&spcl) == FAIL) {
                    102:                        fprintf(stderr, "Tape is not a dump tape\n");
                    103:                        done(1);
                    104:                }
                    105:                fprintf(stderr, "Converting to new file system format.\n");
                    106:        }
                    107:        if (pipein) {
                    108:                endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
                    109:                endoftapemark.s_spcl.c_type = TS_END;
                    110:                ip = (int *)&endoftapemark;
                    111:                j = sizeof(union u_spcl) / sizeof(int);
                    112:                i = 0;
                    113:                do
                    114:                        i += *ip++;
                    115:                while (--j);
                    116:                endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
                    117:        }
                    118:        if (vflag || command == 't' || command == 'T') {
                    119:                fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
                    120:                if (spcl.c_ddate == 0)
                    121:                        fprintf(stdout, "Dumped from: the epoch\n");
                    122:                else
                    123:                        fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
                    124:        }
                    125:        if (command == 'T')
                    126:                return;
                    127:        dumptime = spcl.c_ddate;
                    128:        dumpdate = spcl.c_date;
                    129:        if (stat(".", &stbuf) < 0) {
                    130:                perror("cannot stat .");
                    131:                done(1);
                    132:        }
                    133:        fssize = stbuf.st_blksize;
                    134:        if (fssize <= 0 || ((fssize - 1) & fssize) != 0) {
                    135:                fprintf(stderr, "bad block size %d\n", fssize);
                    136:                done(1);
                    137:        }
                    138:        if (checkvol(&spcl, (long)1) == FAIL) {
                    139:                fprintf(stderr, "Tape is not volume 1 of the dump\n");
                    140:                done(1);
                    141:        }
                    142:        if (readhdr(&spcl) == FAIL)
                    143:                panic("no header after volume mark!\n");
                    144:        findinode(&spcl, 1);
                    145:        if (checktype(&spcl, TS_CLRI) == FAIL) {
                    146:                fprintf(stderr, "Cannot find file removal list\n");
                    147:                done(1);
                    148:        }
                    149:        maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
                    150:        dprintf(stdout, "maxino = %d\n", maxino);
                    151:        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
                    152:        if (map == (char *)NIL)
                    153:                panic("no memory for file removal list\n");
                    154:        clrimap = map;
                    155:        curfile.action = USING;
                    156:        getfile(xtrmap, xtrmapskip);
                    157:        if (checktype(&spcl, TS_BITS) == FAIL) {
                    158:                fprintf(stderr, "Cannot find file dump list\n");
                    159:                done(1);
                    160:        }
                    161:        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
                    162:        if (map == (char *)NULL)
                    163:                panic("no memory for file dump list\n");
                    164:        dumpmap = map;
                    165:        curfile.action = USING;
                    166:        getfile(xtrmap, xtrmapskip);
                    167: }
                    168: 
                    169: /*
                    170:  * Prompt user to load a new dump volume.
                    171:  * "Nextvol" is the next suggested volume to use.
                    172:  * This suggested volume is enforced when doing full
                    173:  * or incremental restores, but can be overrridden by
                    174:  * the user when only extracting a subset of the files.
                    175:  */
                    176: getvol(nextvol)
                    177:        long nextvol;
                    178: {
                    179:        long newvol;
                    180:        long savecnt, i;
                    181:        union u_spcl tmpspcl;
                    182: #      define tmpbuf tmpspcl.s_spcl
                    183: 
                    184:        if (nextvol == 1)
                    185:                tapesread = 0;
                    186:        if (pipein) {
                    187:                if (nextvol != 1)
                    188:                        panic("Changing volumes on pipe input?\n");
                    189:                if (volno == 1)
                    190:                        return;
                    191:                goto gethdr;
                    192:        }
                    193:        savecnt = blksread;
                    194: again:
                    195:        if (pipein)
                    196:                done(1); /* pipes do not get a second chance */
                    197:        if (command == 'R' || command == 'r' || curfile.action != SKIP)
                    198:                newvol = nextvol;
                    199:        else 
                    200:                newvol = 0;
                    201:        while (newvol <= 0) {
                    202:                if (tapesread == 0) {
                    203:                        fprintf(stderr, "%s%s%s%s%s",
                    204:                            "You have not read any tapes yet.\n",
                    205:                            "Unless you know which volume your",
                    206:                            " file(s) are on you should start\n",
                    207:                            "with the last volume and work",
                    208:                            " towards towards the first.\n");
                    209:                } else {
                    210:                        fprintf(stderr, "You have read volumes");
                    211:                        strcpy(tbf, ": ");
                    212:                        for (i = 1; i < 32; i++)
                    213:                                if (tapesread & (1 << i)) {
                    214:                                        fprintf(stderr, "%s%d", tbf, i);
                    215:                                        strcpy(tbf, ", ");
                    216:                                }
                    217:                        fprintf(stderr, "\n");
                    218:                }
                    219:                do      {
                    220:                        fprintf(stderr, "Specify next volume #: ");
                    221:                        (void) fflush(stderr);
                    222:                        (void) fgets(tbf, BUFSIZ, terminal);
                    223:                } while (!feof(terminal) && tbf[0] == '\n');
                    224:                if (feof(terminal))
                    225:                        done(1);
                    226:                newvol = atoi(tbf);
                    227:                if (newvol <= 0) {
                    228:                        fprintf(stderr,
                    229:                            "Volume numbers are positive numerics\n");
                    230:                }
                    231:        }
                    232:        if (newvol == volno) {
                    233:                tapesread |= 1 << volno;
                    234:                return;
                    235:        }
                    236:        closemt();
                    237:        fprintf(stderr, "Mount tape volume %d then type return ", newvol);
                    238:        (void) fflush(stderr);
                    239:        while (getc(terminal) != '\n')
                    240:                ;
                    241: #ifdef RRESTORE
                    242:        if ((mt = rmtopen(magtape, 0)) == -1)
                    243: #else
                    244:        if ((mt = open(magtape, 0)) == -1)
                    245: #endif
                    246:        {
                    247:                fprintf(stderr, "Cannot open tape!\n");
                    248:                goto again;
                    249:        }
                    250: gethdr:
                    251:        volno = newvol;
                    252:        setdumpnum();
                    253:        flsht();
                    254:        if (readhdr(&tmpbuf) == FAIL) {
                    255:                fprintf(stderr, "tape is not dump tape\n");
                    256:                volno = 0;
                    257:                goto again;
                    258:        }
                    259:        if (checkvol(&tmpbuf, volno) == FAIL) {
                    260:                fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
                    261:                volno = 0;
                    262:                goto again;
                    263:        }
                    264:        if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
                    265:                fprintf(stderr, "Wrong dump date\n\tgot: %s",
                    266:                        ctime(&tmpbuf.c_date));
                    267:                fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
                    268:                volno = 0;
                    269:                goto again;
                    270:        }
                    271:        tapesread |= 1 << volno;
                    272:        blksread = savecnt;
                    273:        if (curfile.action == USING) {
                    274:                if (volno == 1)
                    275:                        panic("active file into volume 1\n");
                    276:                return;
                    277:        }
                    278:        (void) gethead(&spcl);
                    279:        findinode(&spcl, curfile.action == UNKNOWN ? 1 : 0);
                    280:        if (gettingfile) {
                    281:                gettingfile = 0;
                    282:                longjmp(restart, 1);
                    283:        }
                    284: }
                    285: 
                    286: /*
                    287:  * handle multiple dumps per tape by skipping forward to the
                    288:  * appropriate one.
                    289:  */
                    290: setdumpnum()
                    291: {
                    292:        struct mtop tcom;
                    293: 
                    294:        if (dumpnum == 1 || volno != 1)
                    295:                return;
                    296:        if (pipein) {
                    297:                fprintf(stderr, "Cannot have multiple dumps on pipe input\n");
                    298:                done(1);
                    299:        }
                    300:        tcom.mt_op = MTFSF;
                    301:        tcom.mt_count = dumpnum - 1;
                    302: #ifdef RRESTORE
                    303:        rmtioctl(MTFSF, dumpnum - 1);
                    304: #else
                    305:        if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0)
                    306:                perror("ioctl MTFSF");
                    307: #endif
                    308: }
                    309: 
                    310: extractfile(name)
                    311:        char *name;
                    312: {
                    313:        int mode;
                    314:        time_t timep[2];
                    315:        struct entry *ep;
                    316:        extern int xtrlnkfile(), xtrlnkskip();
                    317:        extern int xtrfile(), xtrskip();
                    318: 
                    319:        curfile.name = name;
                    320:        curfile.action = USING;
                    321:        timep[0] = curfile.dip->di_atime;
                    322:        timep[1] = curfile.dip->di_mtime;
                    323:        mode = curfile.dip->di_mode;
                    324:        switch (mode & IFMT) {
                    325: 
                    326:        default:
                    327:                fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
                    328:                skipfile();
                    329:                return (FAIL);
                    330: 
                    331:        case IFDIR:
                    332:                if (mflag) {
                    333:                        ep = lookupname(name);
                    334:                        if (ep == NIL || ep->e_flags & EXTRACT)
                    335:                                panic("unextracted directory %s\n", name);
                    336:                        skipfile();
                    337:                        return (GOOD);
                    338:                }
                    339:                vprintf(stdout, "extract file %s\n", name);
                    340:                return (genliteraldir(name, curfile.ino));
                    341: 
                    342:        case IFLNK:
                    343:                lnkbuf[0] = '\0';
                    344:                pathlen = 0;
                    345:                getfile(xtrlnkfile, xtrlnkskip);
                    346:                if (pathlen == 0) {
                    347:                        vprintf(stdout,
                    348:                            "%s: zero length symbolic link (ignored)\n", name);
                    349:                } else if (symlink(lnkbuf, name) < 0) {
                    350:                        fprintf(stderr, "%s: ", name);
                    351:                        (void) fflush(stderr);
                    352:                        perror("cannot create symbolic link");
                    353:                        return (FAIL);
                    354:                } else
                    355:                        vprintf(stdout, "extract symbolic link %s\n", name);
                    356:                return (GOOD);
                    357: 
                    358:        case IFCHR:
                    359:        case IFBLK:
                    360:                vprintf(stdout, "extract special file %s\n", name);
                    361:                if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
                    362:                        fprintf(stderr, "%s: ", name);
                    363:                        (void) fflush(stderr);
                    364:                        perror("cannot create special file");
                    365:                        skipfile();
                    366:                        return (FAIL);
                    367:                }
                    368:                (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
                    369:                (void) chmod(name, mode);
                    370:                skipfile();
                    371:                utime(name, timep);
                    372:                return (GOOD);
                    373: 
                    374:        case IFREG:
                    375:                vprintf(stdout, "extract file %s\n", name);
                    376:                if ((ofile = creat(name, 0666)) < 0) {
                    377:                        fprintf(stderr, "%s: ", name);
                    378:                        (void) fflush(stderr);
                    379:                        perror("cannot create file");
                    380:                        skipfile();
                    381:                        return (FAIL);
                    382:                }
                    383:                (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
                    384:                (void) fchmod(ofile, mode);
                    385:                getfile(xtrfile, xtrskip);
                    386:                (void) close(ofile);
                    387:                utime(name, timep);
                    388:                return (GOOD);
                    389:        }
                    390:        /* NOTREACHED */
                    391: }
                    392: 
                    393: /*
                    394:  * skip over bit maps on the tape
                    395:  */
                    396: skipmaps()
                    397: {
                    398: 
                    399:        while (checktype(&spcl, TS_CLRI) == GOOD ||
                    400:               checktype(&spcl, TS_BITS) == GOOD)
                    401:                skipfile();
                    402: }
                    403: 
                    404: /*
                    405:  * skip over a file on the tape
                    406:  */
                    407: skipfile()
                    408: {
                    409:        extern int null();
                    410: 
                    411:        curfile.action = SKIP;
                    412:        getfile(null, null);
                    413: }
                    414: 
                    415: /*
                    416:  * Do the file extraction, calling the supplied functions
                    417:  * with the blocks
                    418:  */
                    419: getfile(f1, f2)
                    420:        int     (*f2)(), (*f1)();
                    421: {
                    422:        register int i;
                    423:        int curblk = 0;
                    424:        off_t size = spcl.c_dinode.di_size;
                    425:        static char clearedbuf[MAXBSIZE];
                    426:        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
                    427: 
                    428:        if (checktype(&spcl, TS_END) == GOOD)
                    429:                panic("ran off end of tape\n");
                    430:        if (ishead(&spcl) == FAIL)
                    431:                panic("not at beginning of a file\n");
                    432:        if (!gettingfile && setjmp(restart) != 0)
                    433:                return;
                    434:        gettingfile++;
                    435: loop:
                    436:        for (i = 0; i < spcl.c_count; i++) {
                    437:                if (spcl.c_addr[i]) {
                    438:                        readtape(&buf[curblk++][0]);
                    439:                        if (curblk == fssize / TP_BSIZE) {
                    440:                                (*f1)(buf, size > TP_BSIZE ?
                    441:                                     (long) (fssize) :
                    442:                                     (curblk - 1) * TP_BSIZE + size);
                    443:                                curblk = 0;
                    444:                        }
                    445:                } else {
                    446:                        if (curblk > 0) {
                    447:                                (*f1)(buf, size > TP_BSIZE ?
                    448:                                     (long) (curblk * TP_BSIZE) :
                    449:                                     (curblk - 1) * TP_BSIZE + size);
                    450:                                curblk = 0;
                    451:                        }
                    452:                        (*f2)(clearedbuf, size > TP_BSIZE ?
                    453:                                (long) TP_BSIZE : size);
                    454:                }
                    455:                if ((size -= TP_BSIZE) <= 0)
                    456:                        break;
                    457:        }
                    458:        if (readhdr(&spcl) == GOOD && size > 0) {
                    459:                if (checktype(&spcl, TS_ADDR) == GOOD)
                    460:                        goto loop;
                    461:                dprintf(stdout, "Missing address (header) block for %s\n",
                    462:                        curfile.name);
                    463:        }
                    464:        if (curblk > 0)
                    465:                (*f1)(buf, (curblk * TP_BSIZE) + size);
                    466:        findinode(&spcl, 1);
                    467:        gettingfile = 0;
                    468: }
                    469: 
                    470: /*
                    471:  * The next routines are called during file extraction to
                    472:  * put the data into the right form and place.
                    473:  */
                    474: xtrfile(buf, size)
                    475:        char    *buf;
                    476:        long    size;
                    477: {
                    478: 
                    479:        if (write(ofile, buf, (int) size) == -1) {
                    480:                fprintf(stderr, "write error extracting inode %d, name %s\n",
                    481:                        curfile.ino, curfile.name);
                    482:                perror("write");
                    483:                done(1);
                    484:        }
                    485: }
                    486: 
                    487: xtrskip(buf, size)
                    488:        char *buf;
                    489:        long size;
                    490: {
                    491: 
                    492: #ifdef lint
                    493:        buf = buf;
                    494: #endif
                    495:        if (lseek(ofile, size, 1) == (long)-1) {
                    496:                fprintf(stderr, "seek error extracting inode %d, name %s\n",
                    497:                        curfile.ino, curfile.name);
                    498:                perror("lseek");
                    499:                done(1);
                    500:        }
                    501: }
                    502: 
                    503: xtrlnkfile(buf, size)
                    504:        char    *buf;
                    505:        long    size;
                    506: {
                    507: 
                    508:        pathlen += size;
                    509:        if (pathlen > MAXPATHLEN) {
                    510:                fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n",
                    511:                    curfile.name, lnkbuf, buf, pathlen);
                    512:                done(1);
                    513:        }
                    514:        (void) strcat(lnkbuf, buf);
                    515: }
                    516: 
                    517: xtrlnkskip(buf, size)
                    518:        char *buf;
                    519:        long size;
                    520: {
                    521: 
                    522: #ifdef lint
                    523:        buf = buf, size = size;
                    524: #endif
                    525:        fprintf(stderr, "unallocated block in symbolic link %s\n",
                    526:                curfile.name);
                    527:        done(1);
                    528: }
                    529: 
                    530: xtrmap(buf, size)
                    531:        char    *buf;
                    532:        long    size;
                    533: {
                    534: 
                    535:        bcopy(buf, map, size);
                    536:        map += size;
                    537: }
                    538: 
                    539: xtrmapskip(buf, size)
                    540:        char *buf;
                    541:        long size;
                    542: {
                    543: 
                    544: #ifdef lint
                    545:        buf = buf;
                    546: #endif
                    547:        panic("hole in map\n");
                    548:        map += size;
                    549: }
                    550: 
                    551: null() {;}
                    552: 
                    553: /*
                    554:  * Do the tape i/o, dealing with volume changes
                    555:  * etc..
                    556:  */
                    557: readtape(b)
                    558:        char *b;
                    559: {
                    560:        register long i;
                    561:        long rd, newvol;
                    562:        int cnt;
                    563: 
                    564:        if (bct >= NTREC) {
                    565:                for (i = 0; i < NTREC; i++)
                    566:                        ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
                    567:                bct = 0;
                    568:                cnt = NTREC*TP_BSIZE;
                    569:                rd = 0;
                    570:        getmore:
                    571: #ifdef RRESTORE
                    572:                i = rmtread(&tbf[rd], cnt);
                    573: #else
                    574:                i = read(mt, &tbf[rd], cnt);
                    575: #endif
                    576:                if (i > 0 && i != NTREC*TP_BSIZE) {
                    577:                        if (!pipein)
                    578:                                panic("partial block read: %d should be %d\n",
                    579:                                        i, NTREC*TP_BSIZE);
                    580:                        rd += i;
                    581:                        cnt -= i;
                    582:                        if (cnt > 0)
                    583:                                goto getmore;
                    584:                        i = rd;
                    585:                }
                    586:                if (i < 0) {
                    587:                        fprintf(stderr, "Tape read error while ");
                    588:                        switch (curfile.action) {
                    589:                        default:
                    590:                                fprintf(stderr, "trying to set up tape\n");
                    591:                                break;
                    592:                        case UNKNOWN:
                    593:                                fprintf(stderr, "trying to resyncronize\n");
                    594:                                break;
                    595:                        case USING:
                    596:                                fprintf(stderr, "restoring %s\n", curfile.name);
                    597:                                break;
                    598:                        case SKIP:
                    599:                                fprintf(stderr, "skipping over inode %d\n",
                    600:                                        curfile.ino);
                    601:                                break;
                    602:                        }
                    603:                        if (!yflag && !reply("continue"))
                    604:                                done(1);
                    605:                        i = NTREC*TP_BSIZE;
                    606:                        bzero(tbf, i);
                    607: #ifdef RRESTORE
                    608:                        if (rmtseek(i, 1) < 0)
                    609: #else
                    610:                        if (lseek(mt, i, 1) == (long)-1)
                    611: #endif
                    612:                        {
                    613:                                perror("continuation failed");
                    614:                                done(1);
                    615:                        }
                    616:                }
                    617:                if (i == 0) {
                    618:                        if (pipein) {
                    619:                                bcopy((char *)&endoftapemark, b,
                    620:                                        (long)TP_BSIZE);
                    621:                                flsht();
                    622:                                return;
                    623:                        }
                    624:                        newvol = volno + 1;
                    625:                        volno = 0;
                    626:                        getvol(newvol);
                    627:                        readtape(b);
                    628:                        return;
                    629:                }
                    630:        }
                    631:        bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
                    632:        blksread++;
                    633: }
                    634: 
                    635: flsht()
                    636: {
                    637: 
                    638:        bct = NTREC+1;
                    639: }
                    640: 
                    641: closemt()
                    642: {
                    643:        if (mt < 0)
                    644:                return;
                    645: #ifdef RRESTORE
                    646:        rmtclose();
                    647: #else
                    648:        (void) close(mt);
                    649: #endif
                    650: }
                    651: 
                    652: checkvol(b, t)
                    653:        struct s_spcl *b;
                    654:        long t;
                    655: {
                    656: 
                    657:        if (b->c_volume != t)
                    658:                return(FAIL);
                    659:        return(GOOD);
                    660: }
                    661: 
                    662: readhdr(b)
                    663:        struct s_spcl *b;
                    664: {
                    665: 
                    666:        if (gethead(b) == FAIL) {
                    667:                dprintf(stdout, "readhdr fails at %d blocks\n", blksread);
                    668:                return(FAIL);
                    669:        }
                    670:        return(GOOD);
                    671: }
                    672: 
                    673: /*
                    674:  * read the tape into buf, then return whether or
                    675:  * or not it is a header block.
                    676:  */
                    677: gethead(buf)
                    678:        struct s_spcl *buf;
                    679: {
                    680:        long i;
                    681:        union u_ospcl {
                    682:                char dummy[TP_BSIZE];
                    683:                struct  s_ospcl {
                    684:                        long    c_type;
                    685:                        long    c_date;
                    686:                        long    c_ddate;
                    687:                        long    c_volume;
                    688:                        long    c_tapea;
                    689:                        u_short c_inumber;
                    690:                        long    c_magic;
                    691:                        long    c_checksum;
                    692:                        struct odinode {
                    693:                                unsigned short odi_mode;
                    694:                                u_short odi_nlink;
                    695:                                u_short odi_uid;
                    696:                                u_short odi_gid;
                    697:                                long    odi_size;
                    698:                                long    odi_rdev;
                    699:                                char    odi_addr[36];
                    700:                                long    odi_atime;
                    701:                                long    odi_mtime;
                    702:                                long    odi_ctime;
                    703:                        } c_dinode;
                    704:                        long    c_count;
                    705:                        char    c_addr[256];
                    706:                } s_ospcl;
                    707:        } u_ospcl;
                    708: 
                    709:        if (!cvtflag) {
                    710:                readtape((char *)buf);
                    711:                if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == FAIL)
                    712:                        return(FAIL);
                    713:                goto good;
                    714:        }
                    715:        readtape((char *)(&u_ospcl.s_ospcl));
                    716:        bzero((char *)buf, (long)TP_BSIZE);
                    717:        buf->c_type = u_ospcl.s_ospcl.c_type;
                    718:        buf->c_date = u_ospcl.s_ospcl.c_date;
                    719:        buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
                    720:        buf->c_volume = u_ospcl.s_ospcl.c_volume;
                    721:        buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
                    722:        buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
                    723:        buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
                    724:        buf->c_magic = u_ospcl.s_ospcl.c_magic;
                    725:        buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
                    726:        buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
                    727:        buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
                    728:        buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
                    729:        buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
                    730:        buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
                    731:        buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
                    732:        buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
                    733:        buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
                    734:        buf->c_count = u_ospcl.s_ospcl.c_count;
                    735:        bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256);
                    736:        if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
                    737:            checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
                    738:                return(FAIL);
                    739:        buf->c_magic = NFS_MAGIC;
                    740: 
                    741: good:
                    742:        switch (buf->c_type) {
                    743: 
                    744:        case TS_CLRI:
                    745:        case TS_BITS:
                    746:                /*
                    747:                 * Have to patch up missing information in bit map headers
                    748:                 */
                    749:                buf->c_inumber = 0;
                    750:                buf->c_dinode.di_size = buf->c_count * TP_BSIZE;
                    751:                for (i = 0; i < buf->c_count; i++)
                    752:                        buf->c_addr[i]++;
                    753:                break;
                    754: 
                    755:        case TS_TAPE:
                    756:        case TS_END:
                    757:                buf->c_inumber = 0;
                    758:                break;
                    759: 
                    760:        case TS_INODE:
                    761:        case TS_ADDR:
                    762:                break;
                    763: 
                    764:        default:
                    765:                panic("gethead: unknown inode type %d\n", buf->c_type);
                    766:                break;
                    767:        }
                    768:        if (dflag)
                    769:                accthdr(buf);
                    770:        return(GOOD);
                    771: }
                    772: 
                    773: /*
                    774:  * Check that a header is where it belongs and predict the next header
                    775:  */
                    776: accthdr(header)
                    777:        struct s_spcl *header;
                    778: {
                    779:        static ino_t previno = 0x7fffffff;
                    780:        static int prevtype;
                    781:        static long predict;
                    782:        long blks, i;
                    783: 
                    784:        if (header->c_type == TS_TAPE) {
                    785:                fprintf(stderr, "Volume header\n");
                    786:                return;
                    787:        }
                    788:        if (previno == 0x7fffffff)
                    789:                goto newcalc;
                    790:        switch (prevtype) {
                    791:        case TS_BITS:
                    792:                fprintf(stderr, "Dump mask header");
                    793:                break;
                    794:        case TS_CLRI:
                    795:                fprintf(stderr, "Remove mask header");
                    796:                break;
                    797:        case TS_INODE:
                    798:                fprintf(stderr, "File header, ino %d", previno);
                    799:                break;
                    800:        case TS_ADDR:
                    801:                fprintf(stderr, "File continuation header, ino %d", previno);
                    802:                break;
                    803:        case TS_END:
                    804:                fprintf(stderr, "End of tape header");
                    805:                break;
                    806:        }
                    807:        if (predict != blksread - 1)
                    808:                fprintf(stderr, "; predicted %d blocks, got %d blocks",
                    809:                        predict, blksread - 1);
                    810:        fprintf(stderr, "\n");
                    811: newcalc:
                    812:        blks = 0;
                    813:        if (header->c_type != TS_END)
                    814:                for (i = 0; i < header->c_count; i++)
                    815:                        if (header->c_addr[i] != 0)
                    816:                                blks++;
                    817:        predict = blks;
                    818:        blksread = 0;
                    819:        prevtype = header->c_type;
                    820:        previno = header->c_inumber;
                    821: }
                    822: 
                    823: /*
                    824:  * Find an inode header.
                    825:  * Complain if had to skip, and complain is set.
                    826:  */
                    827: findinode(header, complain)
                    828:        struct s_spcl *header;
                    829:        int complain;
                    830: {
                    831:        static long skipcnt = 0;
                    832: 
                    833:        curfile.name = "<name unknown>";
                    834:        curfile.action = UNKNOWN;
                    835:        curfile.dip = (struct dinode *)NIL;
                    836:        curfile.ino = 0;
                    837:        if (ishead(header) == FAIL) {
                    838:                skipcnt++;
                    839:                while (gethead(header) == FAIL)
                    840:                        skipcnt++;
                    841:        }
                    842:        for (;;) {
                    843:                if (checktype(header, TS_INODE) == GOOD) {
                    844:                        curfile.dip = &header->c_dinode;
                    845:                        curfile.ino = header->c_inumber;
                    846:                        break;
                    847:                }
                    848:                if (checktype(header, TS_END) == GOOD) {
                    849:                        curfile.ino = maxino;
                    850:                        break;
                    851:                }
                    852:                if (checktype(header, TS_CLRI) == GOOD) {
                    853:                        curfile.name = "<file removal list>";
                    854:                        break;
                    855:                }
                    856:                if (checktype(header, TS_BITS) == GOOD) {
                    857:                        curfile.name = "<file dump list>";
                    858:                        break;
                    859:                }
                    860:                while (gethead(header) == FAIL)
                    861:                        skipcnt++;
                    862:        }
                    863:        if (skipcnt > 0 && complain)
                    864:                fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);
                    865:        skipcnt = 0;
                    866: }
                    867: 
                    868: /*
                    869:  * return whether or not the buffer contains a header block
                    870:  */
                    871: ishead(buf)
                    872:        struct s_spcl *buf;
                    873: {
                    874: 
                    875:        if (buf->c_magic != NFS_MAGIC)
                    876:                return(FAIL);
                    877:        return(GOOD);
                    878: }
                    879: 
                    880: checktype(b, t)
                    881:        struct s_spcl *b;
                    882:        int     t;
                    883: {
                    884: 
                    885:        if (b->c_type != t)
                    886:                return(FAIL);
                    887:        return(GOOD);
                    888: }
                    889: 
                    890: checksum(b)
                    891:        register int *b;
                    892: {
                    893:        register int i, j;
                    894: 
                    895:        j = sizeof(union u_spcl) / sizeof(int);
                    896:        i = 0;
                    897:        do
                    898:                i += *b++;
                    899:        while (--j);
                    900:        if (i != CHECKSUM) {
                    901:                fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
                    902:                        curfile.ino, curfile.name);
                    903:                return(FAIL);
                    904:        }
                    905:        return(GOOD);
                    906: }
                    907: 
                    908: #ifdef RRESTORE
                    909: /* VARARGS1 */
                    910: msg(cp, a1, a2, a3)
                    911:        char *cp;
                    912: {
                    913: 
                    914:        fprintf(stderr, cp, a1, a2, a3);
                    915: }
                    916: #endif RRESTORE

unix.superglobalmegacorp.com

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