Annotation of coherent/d/bin/dump/restor.c, revision 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.