Annotation of coherent/d/bin/dump/restor.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Restore.
                      3:  * restor key [args]
                      4:  * f [dump]    Use this dump, not the default.
                      5:  * v           Verbose.
                      6:  * t           Print dates of the dump.
                      7:  * x,X         Extract. X asks for reel numbers and does
                      8:  *             a rewind between reels.
                      9:  * r,R         Mass restore. R asks for reel numbers and does
                     10:  *             a rewind between reels.
                     11:  *
                     12:  * Multiple dumps can be put on a single spool of
                     13:  * tape by dumping to the no rewind device. The restore is
                     14:  * done by positioning the tape using the `skip' command and
                     15:  * restoring using the `x' option.
                     16:  */
                     17: #include <stdio.h>
                     18: #include <dumptape.h>
                     19: #include <canon.h>
                     20: #include <sys/filsys.h>
                     21: #include <sys/fblk.h>
                     22: #include <discbuf.h>
                     23: #include <signal.h>
                     24: 
                     25: #define        NRBUF   10                      /* # of restore cache buffers */
                     26: 
                     27: /*
                     28:  * This structure is used
                     29:  * to remember the names and i numbers
                     30:  * of the files being extracted.
                     31:  */
                     32: struct xf
                     33: {
                     34:        char    *xf_path;               /* Path name */
                     35:        ino_t   xf_ino;                 /* The associated inumber */
                     36: };
                     37: 
                     38: /*
                     39:  * Structure used to remember
                     40:  * things about the directories that
                     41:  * were on the tape.
                     42:  */
                     43: struct dlist
                     44: {
                     45:        struct  dlist   *dl_dlp;        /* Link */
                     46:        ino_t   dl_ino;                 /* Inumber of the directory */
                     47:        long    dl_seek;                /* Temp file seek address */
                     48:        long    dl_size;                /* Size in bytes */
                     49: };
                     50: 
                     51: int    is_open;                        /* dump device open? */
                     52: int    key;                            /* Operation */
                     53: int    vflag;                          /* A verbose flag */
                     54: char   *dtn    = DTAPE;                /* Dump file name */
                     55: FILE   *dtp;                           /* Its file pointer */
                     56: struct dumpheader dh;                  /* Header buffer */
                     57: int    reel    = 1;                    /* Reel # */
                     58: fsize_t        length = 512;                   /* Length of volume */
                     59: fsize_t        nread;                          /* Bytes read from volume */
                     60: char   tfn[30] = "/tmp/ddxxxxxx";      /* Temp file name */
                     61: FILE   *tfp;                           /* Its file pointer */
                     62: struct dlist   *dlist;                 /* List of directory nodes */
                     63: struct dlist   *droot;                 /* Root (first) directory node */
                     64: char   *ddbuf;                         /* Big buffer */
                     65: char   *ddend;                         /* End of the big buffer */
                     66: int    ddnbuf;                         /* Size of the big buffer */
                     67: union  dumpdata *ddptr;                /* Current buffer pointer */
                     68: char   *map;                           /* Directory map */
                     69: int    nxf;                            /* # of `x' files */
                     70: ino_t  nindisc;                        /* # of inodes on the disc */
                     71: ino_t  ningrab;                        /* # of inodes to grab */
                     72: struct xf      *xfp;                   /* Pointer for x names */
                     73: 
                     74: /*
                     75:  * Block mapping tables.
                     76:  */
                     77: #define        LNBN    ((daddr_t) NBN)
                     78: 
                     79: char   offs[]          = {
                     80:        0,
                     81:        ND,
                     82:        ND+1,
                     83:        ND+1+1,
                     84:        ND+1+1+1
                     85: };
                     86: 
                     87: daddr_t        ranges[]        = {
                     88:        ND,
                     89:        ND + 1*LNBN,
                     90:        ND + 1*LNBN + 1*LNBN*LNBN,
                     91:        ND + 1*LNBN + 1*LNBN*LNBN + 1*LNBN*LNBN*LNBN
                     92: };
                     93: 
                     94: char   shifts[]        = {
                     95:        0,
                     96:        L2NBN,
                     97:        2*L2NBN,
                     98:        3*L2NBN
                     99: };
                    100: 
                    101: daddr_t        masks[]         = {
                    102:        0,
                    103:        LNBN-1,
                    104:        LNBN*LNBN-1,
                    105:        LNBN*LNBN*LNBN-1
                    106: };
                    107: 
                    108: /*
                    109:  * Forward references for the
                    110:  * one pass compiler.
                    111:  */
                    112: ino_t  lookup();
                    113: ino_t  numfile();
                    114: daddr_t                balloc();
                    115: char   *ctime();
                    116: int    cleanup();
                    117: struct dlist *findnode();
                    118: union  dumpdata *readdump();
                    119: char   *calloc();
                    120: DISCBUF        *dbimap();
                    121: 
                    122: main(argc, argv)
                    123: char *argv[];
                    124: {
                    125:        register char *p;
                    126:        register c, i;
                    127:        register struct xf *rxfp;
                    128:        char *name, *path;
                    129:        ino_t ino;
                    130: 
                    131:        if (argc < 2)
                    132:                usage();
                    133:        p = argv[1];
                    134:        i = 1;
                    135:        while ((c = *p++) != '\0') {
                    136:                switch (c) {
                    137: 
                    138:                case 'f':
                    139:                        if (++i >= argc)
                    140:                                usage();
                    141:                        dtn = argv[i];
                    142:                        break;
                    143: 
                    144:                case 'r':
                    145:                case 'R':
                    146:                case 'x':
                    147:                case 'X':
                    148:                case 't':
                    149:                        if (key != 0)
                    150:                                usage();
                    151:                        key = c;
                    152:                        break;
                    153: 
                    154:                case 'v':
                    155:                        vflag = 1;
                    156:                        break;
                    157: 
                    158:                case '-':
                    159:                {
                    160:                        /* Cf. nextvol() */
                    161:                        extern long RESTMIN, RESTMAX;
                    162: 
                    163:                        if (++i >= argc)
                    164:                                usage();
                    165:                        RESTMIN = atoi(argv[i]);
                    166:                        if (++i >= argc)
                    167:                                usage();
                    168:                        RESTMAX = atoi(argv[i]);
                    169:                        break;
                    170:                }
                    171: 
                    172:                default:
                    173:                        usage();
                    174:                }
                    175:        }
                    176:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                    177:                signal(SIGINT, cleanup);
                    178:        switch (key) {
                    179: 
                    180:        case 'r':
                    181:        case 'R':
                    182:                if (++i >= argc)
                    183:                        usage();
                    184:                if ((dbfp = fopen(argv[i], "r+w")) == NULL)
                    185:                        message(1, "%s: cannot open filesystem", argv[i]);
                    186:                dbclaim(NRBUF);
                    187:                if (key == 'r')
                    188:                        nextvol(1);
                    189:                else {
                    190:                        for (;;) {
                    191:                                reel = getreel();
                    192:                                opendump();
                    193:                                if (readhead(0) != 0)
                    194:                                        break;
                    195:                                fclose(dtp);
                    196:                        }
                    197:                }
                    198:                restore();
                    199:                dbflush(1);
                    200:                break;
                    201: 
                    202:        case 'x':
                    203:        case 'X':
                    204:                nextvol(1);
                    205:                mktemp(tfn);
                    206:                if ((tfp = fopen(tfn, "w")) == NULL
                    207:                ||  (tfp = freopen(tfn, "r+w", tfp)) == NULL)
                    208:                        message(1, "cannot create temporary file");
                    209:                readdirs();
                    210:                xfp = (struct xf *)malloc((argc-i)*sizeof(struct xf));
                    211:                if (xfp == NULL)
                    212:                        message(1, "too many restore names");
                    213:                rxfp = xfp;
                    214:                while (++i < argc) {
                    215:                        name = argv[i];
                    216:                        if ((ino = numfile(name)) != 0) {
                    217:                                if (ino<ROOTIN || ino>dh.dh_nino) {
                    218:                                        message(0, "%s: bad inumber", name);
                    219:                                        continue;
                    220:                                }
                    221:                                path = "(by ino)";
                    222:                        } else  if ((ino = lookup(name)) != 0)
                    223:                                path = name;
                    224:                        else {
                    225:                                message(0, "%s: not found", name);
                    226:                                continue;
                    227:                        }
                    228:                        if (getmap(ino) == 0) {
                    229:                                message(0, "%s: not dumped", name);
                    230:                                continue;
                    231:                        }
                    232:                        rxfp->xf_path = path;
                    233:                        rxfp->xf_ino = ino;
                    234:                        rxfp++;
                    235:                        ++nxf;
                    236:                }
                    237:                if (nxf == 0)
                    238:                        break;
                    239:                for (i=0; i<nxf; ++i)
                    240:                        printf("%u\t%s\n", xfp[i].xf_ino, xfp[i].xf_path);
                    241:                if (key == 'x')
                    242:                        readfile(0);
                    243:                else {
                    244:                        for (;;) {
                    245:                                fclose(dtp);
                    246:                                reel = getreel();
                    247:                                opendump();
                    248:                                readfile(1);
                    249:                                for (i=0; i<nxf && xfp[i].xf_ino==0; ++i)
                    250:                                        ;
                    251:                                if (i == nxf)
                    252:                                        break;
                    253:                        }
                    254:                }
                    255:                fclose(dtp);
                    256:                for (i=0; i<nxf; ++i)
                    257:                        if (xfp[i].xf_ino != 0)
                    258:                                message(0, "%s: not restored", xfp[i].xf_path);
                    259:                break;
                    260: 
                    261:        case 't':
                    262:                opendump();
                    263:                readhead(1);
                    264:                fprintf(stderr, "Dump since %s", ctime(&dh.dh_ddate));
                    265:                fprintf(stderr, "Dumped  on %s", ctime(&dh.dh_bdate));
                    266:                break;
                    267: 
                    268:        default:
                    269:                usage();
                    270:        }
                    271:        delexit(0);
                    272: }
                    273: 
                    274: /*
                    275:  * If the supplied character string
                    276:  * is all number convert it to binary and
                    277:  * return it. Otherwise return 0. A
                    278:  * file name that is all numeric is taken
                    279:  * to be an inumber.
                    280:  */
                    281: ino_t
                    282: numfile(s)
                    283: register char *s;
                    284: {
                    285:        register ino_t ino;
                    286:        register c;
                    287: 
                    288:        ino = 0;
                    289:        while ((c = *s++)>='0' && c<='9')
                    290:                ino = 10*ino + c - '0';
                    291:        if (c != '\0')
                    292:                return (0);
                    293:        return (ino);
                    294: }
                    295: 
                    296: /*
                    297:  * Open the dump tape.
                    298:  * Die if the tape cannot be opened
                    299:  * for any reason.
                    300:  */
                    301: opendump()
                    302: {
                    303:        if ((dtp = fopen(dtn, "r")) == NULL)
                    304:                message(1, "%s: cannot open dump file", dtn);
                    305:        ++is_open;
                    306: }
                    307: 
                    308: /*
                    309:  * Read reel number.
                    310:  */
                    311: getreel()
                    312: {
                    313:        register c, flag, reel;
                    314: 
                    315:        for (;;) {
                    316:                fprintf(stderr, "restor: desired volume? ");
                    317:                reel = 0;
                    318:                flag = 0;
                    319:                while ((c = getchar())>='0' && c<='9') {
                    320:                        flag = 1;
                    321:                        reel = 10*reel + c - '0';
                    322:                }
                    323:                if (c == EOF)
                    324:                        delexit(1);
                    325:                if (c=='\n' && flag!=0)
                    326:                        return (reel);
                    327:                message(0, "bad reel number");
                    328:                while (c!=EOF && c!='\n')
                    329:                        c = getchar();
                    330:                if (c == EOF)
                    331:                        delexit(1);
                    332:        }
                    333: }
                    334: 
                    335: /*
                    336:  * Do the hard work of a
                    337:  * restore.
                    338:  * (NOTE: I think that the flag is now a fossil).
                    339:  */
                    340: readfile(flag)
                    341: {
                    342:        register union dumpdata *ddp;
                    343:        register ino_t ino;
                    344:        register FILE *rfp;
                    345:        register i;
                    346:        int bwerror, outsync;
                    347:        char rfn[20];
                    348: 
                    349:        if (flag) {
                    350:                while ((ddp = readdump()) != NULL)
                    351:                        if (ddp->dd_type != DD_DATA)
                    352:                                break;
                    353: #if 0
                    354:                if (readhead(0) == 0)
                    355:                        return;
                    356:                while ((ddp = readdump()) != NULL) {
                    357:                        if (ddp->dd_type != DD_MAP)
                    358:                                break;
                    359:                        canino(ddp->dd_ino);
                    360:                        canint(ddp->dd_nmap);
                    361:                        setmap(ddp);
                    362:                }
                    363: #endif
                    364:        } else
                    365:                ddp = readdump();
                    366:        if (ddp==NULL || anyfiles()==0)
                    367:                return;
                    368:        outsync = 0;
                    369:        do {
                    370:                switch (ddp->dd_type) {
                    371: 
                    372:                case DD_EOT:
                    373:                        return;
                    374: 
                    375:                case DD_INO:
                    376:                        canino(ddp->dd_ino);
                    377:                        ino = ddp->dd_ino;
                    378:                        rfp = NULL;
                    379:                        bwerror = 0;
                    380:                        if (outsync == 1)
                    381:                                message(0, "skipped 1 item");
                    382:                        else if (outsync != 0)
                    383:                                message(0, "skipped %d items", outsync);
                    384:                        outsync = 0;
                    385:                        for (i=0; i<nxf && xfp[i].xf_ino!=ino; ++i)
                    386:                                ;
                    387:                        if (i != nxf) {
                    388:                                sprintf(rfn, "%u", ino);
                    389:                                if ((rfp = fopen(rfn, "w")) == NULL)
                    390:                                        message(0, "%s: cannot create", rfn);
                    391:                                else
                    392:                                        xfp[i].xf_ino = 0;
                    393:                        }
                    394:                        while ((ddp = readdump()) != NULL) {
                    395:                                if (ddp->dd_type != DD_DATA)
                    396:                                        break;
                    397:                                canino(ddp->dd_ino);
                    398:                                if (ddp->dd_ino != ino) {
                    399:                                        if (outsync == 0)
                    400:                                                message(0, "data sync");
                    401:                                        ++outsync;
                    402:                                        continue;
                    403:                                }
                    404:                                if (rfp != NULL) {
                    405:                                        candaddr(ddp->dd_block);
                    406:                                        canint(ddp->dd_size);
                    407:                                        if (bwrite(rfp, ddp) == 0)
                    408:                                                bwerror = 1;
                    409:                                }
                    410:                        }
                    411:                        if (bwerror)
                    412:                                message("%s: write error", rfn);
                    413:                        if (rfp != NULL)
                    414:                                fclose(rfp);
                    415:                        if (anyfiles() == 0)
                    416:                                return;
                    417:                        break;
                    418: 
                    419:                default:
                    420:                        if (outsync == 0)
                    421:                                message(0, "inode sync");
                    422:                        ++outsync;
                    423:                }
                    424:        } while (ddp != NULL);
                    425: }
                    426: 
                    427: /*
                    428:  * Do a restore.
                    429:  * The tape is open and the header
                    430:  * has been checked.
                    431:  */
                    432: restore()
                    433: {
                    434:        register union dumpdata *ddp;
                    435:        register DISCBUF *dbp;
                    436:        struct filsys *fsp;
                    437:        register ino_t ino;
                    438:        struct dinode *dip;
                    439:        struct dinode dinode;
                    440:        int me, outsync;
                    441:        int ifmt, ndeleted;
                    442: 
                    443:        /*
                    444:         * If the target file system is not
                    445:         * large enough, complain about it and pretend
                    446:         * that all of the inodes that are beyond the
                    447:         * end are not there. This may, of course, leave
                    448:         * the file system addled.
                    449:         */
                    450:        dbp = dbread((long) SUPERI);
                    451:        fsp = (struct filsys *) dbp->db_data;
                    452:        nindisc = fsp->s_isize;
                    453:        canino(nindisc);
                    454:        nindisc = INOPB * (nindisc-INODEI);
                    455:        ningrab = dh.dh_nino;
                    456:        if (ningrab > nindisc) {
                    457:                message(0, "I-list too small, some I-nodes may be deleted");
                    458:                ningrab = nindisc;
                    459:        }
                    460:        /*
                    461:         * Read in the map.
                    462:         */
                    463:        while ((ddp=readdump()) != NULL) {
                    464:                if (ddp->dd_type != DD_MAP)
                    465:                        break;
                    466:                canino(ddp->dd_ino);
                    467:                canint(ddp->dd_nmap);
                    468:                setmap(ddp);
                    469:        }
                    470:        /*
                    471:         * Do required inode clears.
                    472:         * Never clear the badblock inode.
                    473:         * Clear only as far as we are restoring;
                    474:         * that is, ningrab inodes.
                    475:         */
                    476:        for (ino=ROOTIN; ino<=ningrab; ++ino) {
                    477:                me = getmap(ino);
                    478:                if ((me&DD_BUSY)==0 || (me&DD_HERE)==DD_HERE) {
                    479:                        if (vflag)
                    480:                                message(0, "clri I#%u", ino);
                    481:                        clri(ino);
                    482:                }
                    483:        }
                    484:        /*
                    485:         * Read through the tape.
                    486:         * Look for files that we are going to
                    487:         * restore and do so.
                    488:         */
                    489:        outsync  = 0;
                    490:        ndeleted = 0;
                    491:        while (ddp!=NULL && ddp->dd_type!=DD_EOT) {
                    492:                if (ddp->dd_type != DD_INO) {
                    493:                        if (outsync++ == 0)
                    494:                                message(0, "inode sync");
                    495:                        ddp = readdump();
                    496:                        continue;
                    497:                }
                    498:                /*
                    499:                 * Restore the file.
                    500:                 * Block by block.
                    501:                 * Don't move anything.
                    502:                 */
                    503:                canino(ddp->dd_ino);
                    504:                if ((ino=ddp->dd_ino) > ningrab) {
                    505:                        if (vflag != 0)
                    506:                                message(0, "deleted I#%u", (unsigned)ino);
                    507:                        ++ndeleted;
                    508:                        printskip(outsync);
                    509:                        outsync = 0;
                    510:                        while ((ddp=readdump()) != NULL) {
                    511:                                if (ddp->dd_type != DD_DATA)
                    512:                                        break;
                    513:                                canino(ddp->dd_ino);
                    514:                                if (ddp->dd_ino!=ino && outsync++==0)
                    515:                                        message(0, "skip sync");
                    516:                        }
                    517:                        continue;
                    518:                }
                    519:                if (vflag != 0)
                    520:                        message(0, "restoring I#%u", (unsigned)ino);
                    521:                copyb(&dinode, &ddp->dd_dinode, sizeof(dinode));
                    522:                canshort(ddp->dd_dinode.di_mode);
                    523:                ifmt = ddp->dd_dinode.di_mode&IFMT;
                    524:                if (ifmt==IFREG || ifmt==IFDIR)
                    525:                        zerob(dinode.di_addr, sizeof(dinode.di_addr));
                    526:                printskip(outsync);
                    527:                outsync = 0;
                    528:                while ((ddp=readdump()) != NULL) {
                    529:                        if (ddp->dd_type != DD_DATA)
                    530:                                break;
                    531:                        canino(ddp->dd_ino);
                    532:                        if (ddp->dd_ino != ino) {
                    533:                                if (outsync++ == 0)
                    534:                                        message(0, "data sync");
                    535:                                continue;
                    536:                        }
                    537:                        candaddr(ddp->dd_block);
                    538:                        canint(ddp->dd_size);
                    539:                        dbp = dbimap(&dinode, ddp->dd_block);
                    540:                        copyb(dbp->db_data,ddp->dd_data,ddp->dd_size);
                    541:                        dbfree(dbp, DB_DIRT);
                    542:                }
                    543:                dbp = dbread((long) (--ino/INOPB + INODEI));
                    544:                dip = (struct dinode *)(dbp->db_data) + ino%INOPB;
                    545:                if (dip->di_mode != 0) {
                    546:                        message(0, "I#%u busy", (unsigned)ino+1);
                    547:                        clri(ino+1);
                    548:                }
                    549:                copyb((char *)dip, (char *)&dinode, sizeof(dinode));
                    550:                dbfree(dbp, DB_DIRT);
                    551:        }
                    552:        if (ndeleted != 0)
                    553:                message(0, "%d I-nodes deleted", ndeleted);
                    554:        fixilist();
                    555: }
                    556: 
                    557: /*
                    558:  * Print out a message that
                    559:  * tells the number of data items that were
                    560:  * skipped on the tape. Special stuff for
                    561:  * handling 0 and 1 items.
                    562:  */
                    563: printskip(n)
                    564: {
                    565:        if (n == 1)
                    566:                message(0, "skipped 1 item");
                    567:        else if (n != 0)
                    568:                message(0, "skipped %d items", n);
                    569: }
                    570: 
                    571: /*
                    572:  * Fix the ifree list in
                    573:  * the super block. It is safer to
                    574:  * always reconstruct it.
                    575:  */
                    576: fixilist()
                    577: {
                    578:        DISCBUF *ibp, *sbp;
                    579:        register struct filsys *fsp;
                    580:        register struct dinode *dip;
                    581:        register ino_t  ino;
                    582:        short ninode, tinode, minode;
                    583:        ino_t tmpino;
                    584: 
                    585:        if (vflag)
                    586:                message(0, "building I-free list");
                    587:        sbp = dbread((long) SUPERI);
                    588:        fsp = (struct filsys *)(sbp->db_data);
                    589:        tinode = 0;
                    590:        ninode = 0;
                    591:        minode = fsp->s_isize;
                    592:        canshort(minode);
                    593:        minode = INOPB * (minode-INODEI);
                    594:        ibp = NULL;
                    595:        for (ino=1; ino<=minode; ++ino) {
                    596:                if ((ino-1)%INOPB == 0) {
                    597:                        if (ibp != NULL)
                    598:                                dbfree(ibp, 0);
                    599:                        ibp = dbread((long) ((ino-1)/INOPB + INODEI));
                    600:                        dip = (struct dinode *)(ibp->db_data);
                    601:                }
                    602:                if (dip->di_mode == 0) {
                    603:                        ++tinode;
                    604:                        if (ninode < NICINOD) {
                    605:                                tmpino = ino;
                    606:                                canino(tmpino);
                    607:                                fsp->s_inode[ninode++] = tmpino;
                    608:                        }
                    609:                }
                    610:                ++dip;
                    611:        }
                    612:        dbfree(ibp, 0);
                    613:        canshort(tinode);
                    614:        fsp->s_tinode = tinode;
                    615:        canshort(ninode);
                    616:        fsp->s_ninode = ninode;
                    617:        strncpy(fsp->s_fname, dh.dh_fname, sizeof(dh.dh_fname));
                    618:        strncpy(fsp->s_fpack, dh.dh_fpack, sizeof(dh.dh_fpack));
                    619:        dbfree(sbp, DB_DIRT);
                    620: }
                    621: 
                    622: /*
                    623:  * Clear an inode.
                    624:  * Free all of its blocks and
                    625:  * zero the on disc inode. Don't worry about
                    626:  * the super block as it is always rebuilt
                    627:  * at the end.
                    628:  */
                    629: clri(ino)
                    630: ino_t ino;
                    631: {
                    632:        register DISCBUF *dbp;
                    633:        register struct dinode *dip;
                    634:        register i;
                    635:        short dimode;
                    636:        daddr_t addr[NADDR];
                    637: 
                    638:        dbp = dbread((long) ((ino-1)/INOPB + INODEI));
                    639:        dip = (struct dinode *)(dbp->db_data) + (ino-1)%INOPB;
                    640:        dimode = dip->di_mode;
                    641:        canshort(dimode);
                    642:        if ((dimode&IFMT)==IFDIR || (dimode&IFMT)==IFREG) {
                    643:                l3tol(addr, dip->di_addr, NADDR);
                    644:                for (i=0; i<NADDR-3; ++i)
                    645:                        bfree(addr[i], 0);
                    646:                bfree(addr[NADDR-3], 1);
                    647:                bfree(addr[NADDR-2], 2);
                    648:                bfree(addr[NADDR-1], 3);
                    649:        }
                    650:        zerob((char *) dip, sizeof(struct dinode));
                    651:        dbfree(dbp, DB_DIRT);
                    652: }
                    653: 
                    654: /*
                    655:  * Free a block.
                    656:  * The first argument is the block
                    657:  * number. 0 here means no block is allocated
                    658:  * and the call is a nop. The second argument
                    659:  * is the number of levels of indirect blocks
                    660:  * to read through.
                    661:  */
                    662: bfree(bn, nil)
                    663: daddr_t bn;
                    664: {
                    665:        register DISCBUF *dbp, *dbp1;
                    666:        struct filsys *fsp;
                    667:        struct fblk *fbp;
                    668:        int dbp1flag;
                    669:        int i;
                    670:        daddr_t ibn;
                    671: 
                    672:        if (bn == 0)
                    673:                return;
                    674:        dbp1 = NULL;
                    675:        if (nil != 0) {
                    676:                dbp1flag = 0;
                    677:                dbp1 = dbread((long) bn);
                    678:                for (i=0; i<NBN; ++i) {
                    679:                        ibn = ((daddr_t *) dbp1->db_data)[i];
                    680:                        if (ibn != 0) {
                    681:                                candaddr(ibn);  /* Added by Mike */
                    682:                                bfree(ibn, nil-1);
                    683:                        }
                    684:                }
                    685:        }
                    686:        dbp = dbread((long) SUPERI);
                    687:        fsp = (struct filsys *) dbp->db_data;
                    688:        canshort(fsp->s_nfree);
                    689:        if (fsp->s_nfree == NICFREE) {
                    690:                if (dbp1 == NULL)
                    691:                        dbp1 = dbread((long) bn);
                    692:                dbp1flag = DB_DIRT;
                    693:                fbp = (struct fblk *) dbp1->db_data;
                    694:                fbp->df_nfree = fsp->s_nfree;
                    695:                canshort(fbp->df_nfree);
                    696:                copyb(fbp->df_free, fsp->s_free, sizeof(fsp->s_free));
                    697:                fsp->s_nfree = 0;
                    698:        }
                    699:        candaddr(bn);
                    700:        fsp->s_free[fsp->s_nfree++] = bn;
                    701:        canshort(fsp->s_nfree);
                    702:        candaddr(fsp->s_tfree);
                    703:        ++fsp->s_tfree;
                    704:        candaddr(fsp->s_tfree);
                    705:        if (dbp1 != NULL)
                    706:                dbfree(dbp1, dbp1flag);
                    707:        dbfree(dbp, DB_DIRT);
                    708: }
                    709: 
                    710: /*
                    711:  * Allocate a block.
                    712:  * Return 0 if there are no blocks
                    713:  * remaining.
                    714:  */
                    715: daddr_t
                    716: balloc()
                    717: {
                    718:        register struct filsys *fsp;
                    719:        register DISCBUF *dbp;
                    720:        register DISCBUF *dbp1;
                    721:        register struct fblk *fbp;
                    722:        short nfree;
                    723:        daddr_t tfree, bn;
                    724: 
                    725:        dbp = dbread((long) SUPERI);
                    726:        fsp = (struct filsys *) dbp->db_data;
                    727:        if ((tfree = fsp->s_tfree) == 0)
                    728:                message(1, "out of space");
                    729:        candaddr(tfree);
                    730:        nfree = fsp->s_nfree;
                    731:        canshort(nfree);
                    732:        if ((bn = fsp->s_free[--nfree]) == 0)
                    733:                message(1, "out of space and tfree lied");
                    734:        candaddr(bn);
                    735:        if (nfree == 0) {
                    736:                dbp1 = dbread((long) bn);
                    737:                fbp = (struct fblk *) dbp1->db_data;
                    738:                nfree = fbp->df_nfree;
                    739:                canshort(nfree);
                    740:                copyb(fsp->s_free, fbp->df_free, sizeof(fsp->s_free));
                    741:                dbfree(dbp1, 0);
                    742:        }
                    743:        --tfree;
                    744:        canshort(nfree);
                    745:        fsp->s_nfree = nfree;
                    746:        candaddr(tfree);
                    747:        fsp->s_tfree = tfree;
                    748:        dbfree(dbp, DB_DIRT);
                    749:        return (bn);
                    750: }
                    751: 
                    752: /*
                    753:  * Quickly zero out a block of
                    754:  * memory. Used to clear out disc inodes
                    755:  * and other similar things.
                    756:  */
                    757: zerob(ap, an)
                    758: char *ap;
                    759: {
                    760:        register char *p;
                    761:        register n;
                    762: 
                    763:        if ((n = an) != 0) {
                    764:                p = ap;
                    765:                do {
                    766:                        *p++ = 0;
                    767:                } while (--n);
                    768:        }
                    769: }
                    770: 
                    771: /*
                    772:  * Quickly move a block of
                    773:  * memory from one place to another
                    774:  * place.
                    775:  */
                    776: copyb(atp, afp, an)
                    777: char *atp;
                    778: char *afp;
                    779: {
                    780:        register char *tp, *fp;
                    781:        register n;
                    782: 
                    783:        if ((n = an) != 0) {
                    784:                tp = atp;
                    785:                fp = afp;
                    786:                do {
                    787:                        *tp++ = *fp++;
                    788:                } while (--n);
                    789:        }
                    790: }
                    791: 
                    792: /*
                    793:  * Yet another version of
                    794:  * the inode mapping code. This version
                    795:  * allocates blocks if they are not present
                    796:  * in the file. It makes good use of the
                    797:  * buffer cache.
                    798:  * A pointer to a DISCBUF holding the
                    799:  * block is returned. Usually this will be
                    800:  * a buffer created by `dbzero'.
                    801:  */
                    802: DISCBUF *
                    803: dbimap(dip, lb)
                    804: struct dinode *dip;
                    805: daddr_t lb;
                    806: {
                    807:        register DISCBUF *dbp;
                    808:        register il, newblock;
                    809:        daddr_t addr[NADDR];
                    810:        daddr_t pb, bpos, *bkp;
                    811: 
                    812:        l3tol(addr, dip->di_addr, NADDR);
                    813:        for (il=0; il<4; ++il) {
                    814:                if (lb < ranges[il]) {
                    815:                        if (il > 0)
                    816:                                lb -= ranges[il-1];
                    817:                        bpos = lb >> shifts[il];
                    818:                        lb &= masks[il];
                    819:                        bkp = &addr[(int)bpos + offs[il]];
                    820:                        newblock = 0;
                    821:                        if ((pb = *bkp) == 0) {
                    822:                                newblock = 1;
                    823:                                *bkp = pb = balloc();
                    824:                                ltol3(dip->di_addr, addr, NADDR);
                    825:                        }
                    826:                        if (pb != 0) {
                    827:                                while (il-- > 0) {
                    828:                                        if (newblock)
                    829:                                                dbp = dbzero(pb); else
                    830:                                                dbp = dbread(pb);
                    831:                                        bpos = lb >> shifts[il];
                    832:                                        lb &= masks[il];
                    833:                                        bkp = (long *)dbp->db_data + bpos;
                    834:                                        pb = *bkp;
                    835:                                        candaddr(pb);
                    836:                                        if (pb == 0) {
                    837:                                                newblock = 1;
                    838:                                                pb = balloc();
                    839:                                                *bkp = pb;
                    840:                                                candaddr(*bkp);
                    841:                                                dbfree(dbp, DB_DIRT);
                    842:                                        } else {
                    843:                                                newblock = 0;
                    844:                                                dbfree(dbp, 0);
                    845:                                        }
                    846:                                        if (pb == 0)
                    847:                                                break;
                    848:                                }
                    849:                        }
                    850:                        if (pb != 0) {
                    851:                                if (newblock)
                    852:                                        dbp = dbzero(pb); else
                    853:                                        dbp = dbread(pb);
                    854:                                return (dbp);
                    855:                        }
                    856:                        return (NULL);
                    857:                }
                    858:        }
                    859:        message(0, "file too large to map");
                    860:        return (NULL);
                    861: }
                    862: 
                    863: /*
                    864:  * Write a block.
                    865:  */
                    866: bwrite(fp, ddp)
                    867: register FILE *fp;
                    868: register union dumpdata *ddp;
                    869: {
                    870:        lseek(fileno(fp), BUFSIZ*ddp->dd_block, 0);
                    871:        if (write(fileno(fp), ddp->dd_data, ddp->dd_size) != ddp->dd_size)
                    872:                return (0);
                    873:        return (1);
                    874: }
                    875: 
                    876: /*
                    877:  * Check if any files in the
                    878:  * `x' file list remain on this
                    879:  * tape (as indicated by the
                    880:  * map).
                    881:  */
                    882: anyfiles()
                    883: {
                    884:        register ino_t ino;
                    885:        register i;
                    886: 
                    887:        for (i=0; i<nxf; ++i) {
                    888:                if ((ino = xfp[i].xf_ino)!=0 && getmap(ino)!=0)
                    889:                        return (1);
                    890:        }
                    891:        return (0);
                    892: }
                    893: 
                    894: /*
                    895:  * Read and validate tape header.
                    896:  * The `quit' flag is true if errors
                    897:  * are fatal.
                    898:  * Only allocate the map first time.
                    899:  */
                    900: readhead(quit)
                    901: {
                    902:        register char *p;
                    903:        register checksum;
                    904: 
                    905:        if (read(fileno(dtp), &dh, sizeof dh) != sizeof dh) {
                    906:                message(quit, "header read error");
                    907:                return (0);
                    908:        }
                    909:        nread = sizeof dh;
                    910:        canint(dh.dh_magic);
                    911:        canino(dh.dh_nino);
                    912:        cantime(dh.dh_bdate);
                    913:        cantime(dh.dh_ddate);
                    914:        canint(dh.dh_level);
                    915:        canint(dh.dh_reel);
                    916:        canint(dh.dh_blocking);
                    917:        cansize(dh.dh_nbyte);
                    918:        canint(dh.dh_checksum);
                    919:        if (dh.dh_magic != DH_MAG) {
                    920:                message(quit, "not a dump");
                    921:                return (0);
                    922:        }
                    923:        p = (char *) &dh;
                    924:        checksum = 0;
                    925:        while (p < (char *) &dh.dh_checksum)
                    926:                checksum += (*p++) & 0377;
                    927:        if (checksum != dh.dh_checksum) {
                    928:                message(quit, "checksum error");
                    929:                return (0);
                    930:        }
                    931:        if (dh.dh_reel != reel) {
                    932:                message(quit, "wrong reel (is %d, not %d)", dh.dh_reel, reel);
                    933:                return (0);
                    934:        }
                    935:        ++reel;
                    936:        length = dh.dh_nbyte;
                    937:        if (map == NULL) {
                    938:                if ((map = calloc(sizeof(char), dh.dh_nino)) == NULL)
                    939:                        message(1, "out of memory (map)");
                    940:        }
                    941:        if (ddbuf != NULL)
                    942:                free(ddbuf);
                    943:        ddnbuf = dh.dh_blocking * sizeof(union dumpdata);
                    944:        if ((ddbuf = malloc(ddnbuf)) == NULL)
                    945:                message(1, "out of memory (big buffer)");
                    946:        ddend = &ddbuf[ddnbuf];
                    947:        ddptr = (union dumpdata *) ddend;
                    948:        return (1);
                    949: }
                    950: 
                    951: /*
                    952:  * Read in directories and set up
                    953:  * the map. The last tape record is ungotten
                    954:  * so that the extract code can be made a
                    955:  * little simpler.
                    956:  */
                    957: readdirs()
                    958: {
                    959:        register union dumpdata *ddp;
                    960:        register struct dlist *dlp;
                    961:        unsigned short mode;
                    962: 
                    963:        while ((ddp = readdump()) != NULL) {
                    964:                switch (ddp->dd_type) {
                    965: 
                    966:                case DD_EOT:
                    967:                        --ddptr;
                    968:                        return;
                    969: 
                    970:                case DD_MAP:
                    971:                        canino(ddp->dd_ino);
                    972:                        canint(ddp->dd_nmap);
                    973:                        setmap(ddp);
                    974:                        break;
                    975: 
                    976:                case DD_INO:
                    977:                        mode = ddp->dd_dinode.di_mode;
                    978:                        canshort(mode);
                    979:                        if ((mode&IFMT) != IFDIR) {
                    980:                                --ddptr;
                    981:                                return;
                    982:                        }
                    983:                        canino(ddp->dd_ino);
                    984:                        cansize(ddp->dd_dinode.di_size);
                    985:                        dlp = (struct dlist *) malloc(sizeof(struct dlist));
                    986:                        if (dlp == NULL)
                    987:                                message(1, "out of memory (dlist)");
                    988:                        dlp->dl_dlp = dlist;
                    989:                        dlist = dlp;
                    990:                        if (droot == NULL)
                    991:                                droot = dlp;
                    992:                        dlp->dl_ino = ddp->dd_ino;
                    993:                        dlp->dl_seek = ftell(tfp);
                    994:                        dlp->dl_size = ddp->dd_dinode.di_size;
                    995:                        break;
                    996: 
                    997:                case DD_DATA:
                    998:                        canino(ddp->dd_ino);
                    999:                        candaddr(ddp->dd_block);
                   1000:                        canint(ddp->dd_size);
                   1001:                        if (dlist==NULL || dlist->dl_ino!=ddp->dd_ino)
                   1002:                                message(1, "directory out of sync");
                   1003:                        fseek(tfp, dlp->dl_seek+(BUFSIZ*ddp->dd_block), 0);
                   1004:                        fwrite(ddp->dd_data, sizeof(char), ddp->dd_size, tfp);
                   1005:                        if (ferror(tfp))
                   1006:                                message(1, "directory write error");
                   1007:                        break;
                   1008: 
                   1009:                default:
                   1010:                        message(1, "bad type %d", ddp->dd_type);
                   1011:                }
                   1012:        }
                   1013: }
                   1014: 
                   1015: /*
                   1016:  * Fill in map.
                   1017:  */
                   1018: setmap(ddp)
                   1019: union dumpdata *ddp;
                   1020: {
                   1021:        register char *p1, *p2;
                   1022:        register nb;
                   1023: 
                   1024:        if ((nb = ddp->dd_nmap) != 0) {
                   1025:                p1 = &map[ddp->dd_ino-1];
                   1026:                p2 = ddp->dd_map;
                   1027:                do {
                   1028:                        *p1++ = *p2++;
                   1029:                } while (--nb);
                   1030:        }
                   1031: }
                   1032: 
                   1033: /*
                   1034:  * Get map item.
                   1035:  */
                   1036: getmap(ino)
                   1037: ino_t ino;
                   1038: {
                   1039:        return (map[ino-1]);
                   1040: }
                   1041: 
                   1042: /*
                   1043:  * Read dump file.
                   1044:  * Canonize the type and look after
                   1045:  * multi-volume (reel) dumps.
                   1046:  */
                   1047: union  dumpdata *
                   1048: readdump()
                   1049: {
                   1050:        register nb;
                   1051: 
                   1052:        while ((char *) ddptr == ddend) {
                   1053:                if (length != 0 && (nread+ddnbuf) > length) {
                   1054:                        nextvol(0);
                   1055:                        continue;
                   1056:                }
                   1057:                if ((nb = read(fileno(dtp), ddbuf, ddnbuf)) != ddnbuf) {
                   1058:                        if (nb != 0)
                   1059:                                message(1, "dump read error");
                   1060:                        nextvol(0);
                   1061:                        continue;
                   1062:                }
                   1063:                ddptr = (union dumpdata *) ddbuf;
                   1064:                nread += nb;
                   1065:                break;
                   1066:        }
                   1067:        canint(ddptr->dd_type);
                   1068:        return (ddptr++);
                   1069: }
                   1070: 
                   1071: /*
                   1072:  * Read the next volume (reel or diskette)
                   1073:  * from the dump.
                   1074:  * The flag is passed onto readhead for quiting.
                   1075:  *
                   1076:  * RESTMIN, RESTMAX, and restime are used to bound the time taken
                   1077:  * to restor a volume in hopes of preventing unbounded copies of
                   1078:  * Coherent dump distributions.  The values are passed with an
                   1079:  * undocumented '-' option which specifies RESTMIN and RESTMAX.
                   1080:  */
                   1081: long RESTMIN, RESTMAX, restime, time();
                   1082: 
                   1083: nextvol(flag)
                   1084: int flag;
                   1085: {
                   1086:        register int c;
                   1087:        register char *vtype = "reel";
                   1088: 
                   1089:        restime += time(NULL);
                   1090:        /* Spurious error to detect copies of dump volumes
                   1091:         * made with ms-dos formatter/copier.  Activated by
                   1092:         * '-' key modifier in command list.
                   1093:         * Not documented in manual.
                   1094:         */
                   1095:        if (RESTMIN && reel > 1 && (restime < RESTMIN || restime > RESTMAX))
                   1096:                message(1, "volume sync: %ld", restime);
                   1097:        for (;;) {
                   1098:                if (is_open) {
                   1099:                        fclose(dtp);
                   1100:                        is_open = 0;
                   1101:                }
                   1102:                if (length != 0)
                   1103:                        vtype = "volume";
                   1104:                fprintf(stderr, "restor: mount %s %d, type return key...",
                   1105:                        vtype, reel);
                   1106:                while ((c = getchar())!=EOF && c!='\n')
                   1107:                        ;
                   1108:                if (c == EOF)
                   1109:                        delexit(1);
                   1110:                restime = -time(NULL);
                   1111:                opendump();
                   1112:                if (readhead(flag) != 0)
                   1113:                        break;
                   1114:        }
                   1115: }
                   1116: 
                   1117: /*
                   1118:  * Lookup a file, by name.
                   1119:  * Return the inumber.
                   1120:  * This routine only looks in
                   1121:  * directories. The file may
                   1122:  * not actually be on the tape.
                   1123:  */
                   1124: ino_t
                   1125: lookup(cp)
                   1126: register char *cp;
                   1127: {
                   1128:        char db[DIRSIZ];
                   1129:        struct direct dirbuf;
                   1130:        ino_t ino;
                   1131:        long seek;
                   1132:        struct dlist *dlp;
                   1133: 
                   1134:        ino = ROOTIN;
                   1135:        for (;;) {
                   1136:                {
                   1137:                        register char *dp;
                   1138:                        register c;
                   1139: 
                   1140:                        while ((c = *cp++) == '/')
                   1141:                                ;
                   1142:                        if (c == '\0')
                   1143:                                return (ino);
                   1144:                        dp = db;
                   1145:                        for (;;) {
                   1146:                                if (dp < &db[DIRSIZ])
                   1147:                                        *dp++ = c;
                   1148:                                if ((c = *cp)=='\0' || c=='/')
                   1149:                                        break;
                   1150:                                ++cp;
                   1151:                        }
                   1152:                        while (dp < &db[DIRSIZ])
                   1153:                                *dp++ = 0;
                   1154:                }
                   1155:                if ((dlp = findnode(ino)) == NULL)
                   1156:                        return (0);
                   1157:                seek = dlp->dl_seek;
                   1158:                for (;;) {
                   1159:                        if (seek-dlp->dl_seek >= dlp->dl_size)
                   1160:                                return (0);
                   1161:                        fseek(tfp, seek, 0);
                   1162:                        fread(&dirbuf, sizeof(dirbuf), 1, tfp);
                   1163:                        if (ferror(tfp))
                   1164:                                message(1, "temporary file read error");
                   1165:                        canino(dirbuf.d_ino);
                   1166:                        ino = dirbuf.d_ino;
                   1167:                        if (ino!=0 && strncmp(db, dirbuf.d_name, DIRSIZ)==0)
                   1168:                                break;
                   1169:                        seek += sizeof(struct direct);
                   1170:                }
                   1171:        }
                   1172: }
                   1173: 
                   1174: /*
                   1175:  * Look for a directory inode
                   1176:  * in the dlist.
                   1177:  */
                   1178: struct dlist *
                   1179: findnode(ino)
                   1180: register ino_t ino;
                   1181: {
                   1182:        register struct dlist *dlp;
                   1183: 
                   1184:        dlp = dlist;
                   1185:        while (dlp != NULL) {
                   1186:                if (dlp->dl_ino == ino)
                   1187:                        break;
                   1188:                dlp = dlp->dl_dlp;
                   1189:        }
                   1190:        return (dlp);
                   1191: }
                   1192: 
                   1193: /*
                   1194:  * Usage message.
                   1195:  */
                   1196: usage()
                   1197: {
                   1198:        fprintf(stderr, "Usage: restor key [args]\n");
                   1199:        delexit(1);
                   1200: }
                   1201: 
                   1202: /*
                   1203:  * Message output.
                   1204:  */
                   1205: message(quit, a)
                   1206: {
                   1207:        fprintf(stderr, "restor: %r\n", &a);
                   1208:        if (quit)
                   1209:                delexit(1);
                   1210: }
                   1211: 
                   1212: /*
                   1213:  * Cleanup function.
                   1214:  * Called from the interrupt signal.
                   1215:  */
                   1216: cleanup()
                   1217: {
                   1218:        delexit(1);
                   1219: }
                   1220: 
                   1221: /*
                   1222:  * Exit.
                   1223:  * Delete the temp file, if there.
                   1224:  */
                   1225: delexit(s)
                   1226: {
                   1227:        if (tfp != NULL)
                   1228:                unlink(tfn);
                   1229:        exit(s);
                   1230: }

unix.superglobalmegacorp.com

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