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

unix.superglobalmegacorp.com

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