Annotation of coherent/d/etc/mkfs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * mkfs.c
                      3:  * 7/14/92
                      4:  * Make a filesystem.
                      5:  * Efficiently, rec 84.08.31
                      6:  */
                      7: 
                      8: #define        VERSION "1.2"
                      9: #define NDEBUG         1       /* No assertions turned on */
                     10: #define ES_SUCCESS     0       /* No problems at all */
                     11: #define ES_IGNORED     1       /* Some problems ignored */
                     12: #define ES_FORMAT      2       /* Proto file format error */
                     13: #define ES_FATAL       4       /* Process aborted */
                     14: 
                     15: #include <stdio.h>
                     16: #include <ctype.h>
                     17: #include <errno.h>
                     18: #define syserror       (sys_errlist[errno])
                     19: #include <sys/filsys.h>
                     20: #include <sys/ino.h>
                     21: #include <sys/fblk.h>
                     22: #include <sys/dir.h>
                     23: #include <l.out.h>
                     24: #include <sys/timeb.h>
                     25: #include <canon.h>
                     26: #include <sys/stat.h>
                     27: #include <access.h>
                     28: #include <assert.h>
                     29: #include <string.h>
                     30: #include <sys/mdata.h>
                     31: 
                     32: #define inodeb(i)      (INODEI + ((i)-1)/8)
                     33: #define inodei(i)      (((i)-1)%8)
                     34: #define        NDLEV   25                      /* Maximum directory nesting */
                     35: 
                     36: char s755[20];
                     37: char sB[20];
                     38: 
                     39: struct protoargs {     /* Parameter management */
                     40:        char    *p_bname, *p_fname, *p_fpack;
                     41:        char    *p_fsize, *p_nino, *p_intn, *p_intm;
                     42: };
                     43: 
                     44: struct entre {         /* Directory management */
                     45:        ino_t   e_ino;
                     46:        char    *e_name;
                     47: };
                     48: 
                     49: struct xnode {         /* Minimal inode management */
                     50:        ino_t   x_ino;
                     51:        int     x_mode;
                     52:        int     x_uid;
                     53:        int     x_gid;
                     54:        dev_t   x_dev;
                     55:        char    *x_name;
                     56:        int     x_nlink;
                     57:        fsize_t x_size;
                     58:        time_t  x_atime;
                     59:        time_t  x_mtime;
                     60:        time_t  x_ctime;
                     61:        daddr_t x_start;
                     62:        struct ynode *x_y;
                     63:        struct entre    x_ents[];
                     64: };
                     65: 
                     66: struct ynode {         /* Medial inode management */
                     67:        ino_t   y_ino;
                     68:        fsize_t y_seek;
                     69:        daddr_t y_nb;           /* Number of blocks total */
                     70:        daddr_t y_ni;           /* Number of indirect blocks total */
                     71:        int     y_niiib;        /* Number of triple indirect blocks */
                     72:        int     y_niib;         /* Number of double indirect blocks */
                     73:        daddr_t y_nib;          /* Number of single indirect blocks */
                     74:        daddr_t y_ndb;          /* Number of data blocks */
                     75:        daddr_t *y_db;          /* Data block base */
                     76:        daddr_t *y_ib;          /* Single indirect block base */
                     77:        daddr_t *y_iib;         /* Double indirect block base */
                     78:        daddr_t *y_iiib;        /* Triple indirect block base */
                     79:        daddr_t y_b[];          /* Actual block addresses, indirect first */
                     80: };
                     81: 
                     82: struct pfp {           /* Input parsing */
                     83:        char    *p_fn;          /* File name if any */
                     84:        int     p_ln;           /* Line number if any */
                     85:        int     p_dln;          /* Line number increment if any */
                     86:        char    *p_ip;          /* Initial stream pointer */
                     87:        char    *p_cp;          /* Current stream pointer */
                     88:        struct pfp      *p_fp;  /* Previous stream record */
                     89: };
                     90: 
                     91: extern char    devnull[];
                     92: extern char    ascii0[];
                     93: extern char    ascii1[];
                     94: extern int             nino;
                     95: extern char            *special;
                     96: extern char            *proto;
                     97: extern struct filsys   S;
                     98: extern int             FS;
                     99: extern struct protoargs P;
                    100: extern struct protoargs N;
                    101: extern ino_t           E[NDLEV];
                    102: extern int             Elevel;
                    103: extern struct xnode **X;
                    104: extern char pnil[];
                    105: extern struct pfp pfp;
                    106: extern char    *argv0;
                    107: extern int     estatus;
                    108: extern char    miscbuf[BSIZE];
                    109: 
                    110: extern struct entre *getentre();
                    111: extern ino_t getxnode();
                    112: extern ino_t getlink();
                    113: extern char *gettoken();
                    114: extern char *getline();
                    115: extern int getopen();
                    116: extern int getclose();
                    117: #define getch()                ((*pfp.p_cp != 0) ? *pfp.p_cp++ : -1)
                    118: #define ungetch(c)     ((c>=0 && pfp.p_cp>pfp.p_ip) ? (*--pfp.p_cp = c) : -1)
                    119: extern daddr_t balloc();
                    120: extern ino_t ialloc();
                    121: extern char *bcache();
                    122: extern char *realloc();
                    123: 
                    124: time_t time();
                    125: char   *xmalloc();
                    126: char   *xrealloc();
                    127: char   *strncpy();
                    128: char   *strcat();
                    129: fsize_t        ftell();
                    130: long   atol();
                    131: int    atoi();
                    132: 
                    133: /* FILE data.c */
                    134: char   devnull[] = "/dev/null";
                    135: char   ascii0[] = "0";
                    136: char   ascii1[] = "1";
                    137: 
                    138: int            nino;   /* Number of inodes on new file system */
                    139: char           *special;       /* Special file specified */
                    140: char           *proto;         /* Proto file specified */
                    141: struct filsys  S;      /* Super block for new file system */
                    142: int            FS;     /* File descriptor of file system */
                    143: struct protoargs P;    /* File system prototype parameters */
                    144: struct protoargs N = { /* Some names */
                    145:        "bootstrap file", "file system name", "file pack name",
                    146:        "file system size", "number of inodes", "interleave n", "interleave m"
                    147: };
                    148: ino_t          E[NDLEV];       /* Current nesting of directory inodes */
                    149: int            Elevel = -1;    /* Current nesting level of directory inodes */
                    150: struct xnode **X;      /* I-list pointers for new file system */
                    151: char pnil[] = "";
                    152: struct pfp pfp = { pnil, 0, 0, pnil, pnil, NULL };     /* Initial stream */
                    153: char   *argv0 = "mkfs";        /* Command name */
                    154: int    estatus = ES_SUCCESS;   /* Exit status */
                    155: char   miscbuf[BSIZE];
                    156: 
                    157: int    dflag = 0;              /* Preserve dates if on; set w/ -d opt. */
                    158: 
                    159: /* FILE main.c */
                    160: /*
                    161:  * Magic number of i-nodes as a function of
                    162:  * filesystem size in blocks.
                    163:  */
                    164: magic()
                    165: {
                    166:        register char *p;
                    167:        daddr_t fsize;
                    168:        unsigned long nino;
                    169:        static char b[8];
                    170: 
                    171:        fsize = atol(P.p_fsize);
                    172:        if (fsize > 1000)
                    173:                nino = fsize / 7;
                    174:        else
                    175:                nino = fsize / 5;
                    176:        if (nino > 65000U)              /* must fit into a short! */
                    177:                nino = 65000U;
                    178:        p = b+8;
                    179:        while (nino != 0) {
                    180:                *--p = nino % 10 + '0';
                    181:                nino /= 10;
                    182:        }
                    183:        P.p_nino = p;
                    184: }
                    185: 
                    186: main(argc, argv)
                    187: char *argv[];
                    188: {
                    189:        int anyopts = 0;
                    190:        if (argc < 1)
                    191:                return eusage();
                    192: 
                    193:        strcpy(s755, "\nd--755 0 0\n$\n");
                    194:        strcpy(sB, "B----- 0 0\n");
                    195: 
                    196:        argv0 = argv[0];
                    197:        /*
                    198:         * Collect options.
                    199:         */
                    200:        while (argc > 1 && argv[1][0] == '-') {
                    201:                switch (argv[1][1]) {
                    202:                case 'b':       P.p_bname = argv[2];            break;
                    203:                case 'f':       P.p_fname = argv[2];            break;
                    204:                case 'i':       P.p_nino = argv[2];             break;
                    205:                case 'm':       P.p_intm = argv[2];             break;
                    206:                case 'n':       P.p_intn = argv[2];             break;
                    207:                case 'p':       P.p_fpack = argv[2];            break;
                    208:                case 'd':       dflag = 1; --argc; ++argv;      continue;
                    209:                case 'V':       fprintf(stderr, "%s: V%s\n", argv0, VERSION);
                    210:                                --argc; ++argv;                 continue;
                    211:                default:        return eusage();
                    212:                }
                    213:                anyopts += 1;
                    214:                argc -= 2;
                    215:                argv += 2;
                    216:        }
                    217:        /*
                    218:         * Parse primary arguments and read or construct
                    219:         * prototype description.
                    220:         */
                    221:        if (argc != 3)
                    222:                return eusage();
                    223:        special = argv[1];
                    224:        if ( ! unnatural(argv[2])) {
                    225:                P.p_fsize = argv[2];
                    226:                if (mkproto() < 0)
                    227:                        return estatus;
                    228:        } else {
                    229:                proto = argv[2];
                    230:                if (rdproto() < 0)
                    231:                        return estatus;
                    232:                else if (anyopts)
                    233:                        eignore("superfluous command line options");
                    234:        }
                    235:        /*
                    236:         * Scan real or imaginary proto file.
                    237:         */
                    238:        getboot();
                    239:        if (getsuper() < 0
                    240:         || getdir() < 0
                    241:         || (estatus&ES_FORMAT))
                    242:                return estatus;
                    243:        /*
                    244:         * Scan in core i list and allocate blocks.
                    245:         */
                    246:        scanilist();
                    247:        if (estatus&ES_FATAL)
                    248:                return (estatus);
                    249:        /*
                    250:         * Write the new file system.
                    251:         */
                    252:        if (putboot() < 0
                    253:         || putsuper() < 0
                    254:         || putilist() < 0
                    255:         || putdata() < 0
                    256:         || putfree() < 0)
                    257:                return (estatus);
                    258:        return (estatus);
                    259: }
                    260: 
                    261: /*
                    262:  * Prepare proto file for input.
                    263:  *  rdproto copies file into memory,
                    264:  *  mkproto constructs proto file in memory,
                    265:  *  each sets up gettoken() to read tokens.
                    266:  */
                    267: rdproto()
                    268: {
                    269:        register char *p;
                    270:        register int n;
                    271:        register int fd;
                    272:        register int nb;
                    273: 
                    274:        if ((fd = open(proto, 0)) < 0)
                    275:                return badopen("descriptor file", proto);
                    276:        nb = 0;
                    277:        n = BSIZE;
                    278:        p = xmalloc(n);
                    279:        while ((n = read(fd, p+nb, BSIZE)) == BSIZE) {
                    280:                nb += BSIZE;
                    281:                p = xrealloc(p, nb+BSIZE);
                    282:        }
                    283:        p[nb+n] = 0;
                    284:        getopen(p, proto, 1);
                    285:        return (0);
                    286: }
                    287: 
                    288: mkproto()
                    289: {
                    290:        register char *p, *p1, *p0;
                    291: 
                    292:        p0 = p = xmalloc(BSIZE);
                    293: 
                    294:        if ((p1 = P.p_bname) == NULL && (P.p_fname!=NULL || P.p_fpack != NULL))
                    295:                P.p_bname = devnull;
                    296:        if (P.p_fpack != NULL && P.p_fname == NULL)
                    297:                P.p_fname = "noname";
                    298: 
                    299:        if ((p1 = P.p_bname) != NULL) {
                    300:                while (*p = *p1++) ++p;
                    301:                if ((p1 = P.p_fname) != NULL) {
                    302:                        *p++ = ' ';
                    303:                        while (*p = *p1++) ++p;
                    304:                        if ((p1 = P.p_fpack) != NULL) {
                    305:                                *p++ = ' ';
                    306:                                while (*p = *p1++) ++p;
                    307:                        }
                    308:                }
                    309:        }
                    310:        *p++ = '\n';
                    311:        if (unnatural((p1 = P.p_fsize)))
                    312:                return badvalue(N.p_fsize, p1), -1;
                    313:        while (*p = *p1++) ++p;
                    314:        if (P.p_nino == NULL)
                    315:                magic();
                    316:        if (unnatural((p1 = P.p_nino)))
                    317:                return badvalue(N.p_nino, p1), -1;
                    318:        *p++ = ' ';
                    319:        while (*p = *p1++) ++p;
                    320:        if ((p1 = P.p_intn) != NULL) {
                    321:                if (unnatural(p1))
                    322:                        return badvalue(N.p_intn, p1), -1;
                    323:                *p++ = ' ';
                    324:                while (*p = *p1++) ++p;
                    325:                if ((p1 = P.p_intm) != NULL) {
                    326:                        if (unnatural(p1))
                    327:                                return badvalue(N.p_intm, p1), -1;
                    328:                        *p++ = ' ';
                    329:                        while (*p = *p1++) ++p;
                    330:                }
                    331:        }
                    332:        p1 = s755;
                    333:        while (*p = *p1++) ++p;
                    334:        getopen(p0, NULL, 0);
                    335:        return (0);
                    336: }
                    337: 
                    338: /* FILE get.c */
                    339: /*
                    340:  * First pass activity -- scan proto file
                    341:  *  getboot() reads the boot file name.
                    342:  *  getsuper() reads the super block parameters and initializes
                    343:  *     the in memory file system structure.
                    344:  *  getbad() reads and actuates the bad block specification.
                    345:  *  getdir() reads the remainder of the proto file and constructs
                    346:  *     a directory tree and xnode list for the file system.
                    347:  */
                    348: getboot()
                    349: {
                    350:        P.p_bname = gettoken();
                    351:        if (P.p_bname == NULL)
                    352:                P.p_bname = devnull;
                    353: }
                    354: 
                    355: getsuper()
                    356: {
                    357:        register char   *ch;
                    358:        register int    i;
                    359: 
                    360:        if ((FS = open(special, 2)) < 0)
                    361:                return badopen("special file", special);
                    362: 
                    363:        if ((P.p_fname = gettoken()) == NULL) {
                    364:                P.p_fname = "noname";
                    365:                strncpy(S.s_fname, P.p_fname, 6);
                    366:        } else 
                    367:                for (ch = P.p_fname, i = 0; *ch != ' ' && *ch != '\t' && 
                    368:                                *ch != '\n' && *ch != '\r' && i < 6; i++, ch++)
                    369:                        S.s_fname[i] = *ch;
                    370: 
                    371:        if ((P.p_fpack = gettoken()) == NULL) {
                    372:                P.p_fpack = "nopack";
                    373:                strncpy(S.s_fpack, P.p_fpack, 6);
                    374:        } else
                    375:                for (ch = P.p_fpack, i = 0; *ch != ' ' && *ch != '\t' && 
                    376:                                *ch != '\n' && *ch != '\r' && i < 6; i++, ch++)
                    377:                        S.s_fpack[i] = *ch;
                    378: 
                    379:        if (getline() == NULL)
                    380:                return earlyeof();
                    381:        if ((P.p_fsize = gettoken()) == NULL)
                    382:                return efatal("no value for %s", N.p_fsize);
                    383:        else if (unnatural(P.p_fsize))
                    384:                return badvalue(N.p_fsize, P.p_fsize), -1;
                    385:        S.s_fsize = atol(P.p_fsize);
                    386:        if ((P.p_nino = gettoken()) == NULL)
                    387:                magic();
                    388:        else if (unnatural(P.p_nino))
                    389:                return badvalue(N.p_nino, P.p_nino), -1;
                    390:        S.s_isize = (atoi(P.p_nino)+INOPB-1)/INOPB + INODEI;
                    391:        if ((P.p_intn = gettoken()) == NULL)
                    392:                P.p_intn = ascii1;
                    393:        else if (unnatural(P.p_intn))
                    394:                return badvalue(N.p_intn, P.p_intn), -1;
                    395:        S.s_n = atoi(P.p_intn);
                    396:        if ((P.p_intm = gettoken()) == NULL)
                    397:                P.p_intm = ascii1;
                    398:        else if (unnatural(P.p_intm))
                    399:                return badvalue(N.p_intm, P.p_intm), -1;
                    400:        S.s_m = atoi(P.p_intm);
                    401:        if (getline() == NULL)
                    402:                return earlyeof();
                    403: 
                    404:        /* Set the initial ifree list so that bad file can be initialized */
                    405:        S.s_ninode = 0;
                    406:        S.s_tinode = (S.s_isize - INODEI) * INOPB;
                    407:        S.s_inode[S.s_ninode++] = BADFIN+1;
                    408:        S.s_inode[S.s_ninode++] = BADFIN;
                    409:        nino = S.s_tinode;
                    410:        /* Allocate memory i list */
                    411:        X = xmalloc(S.s_tinode * sizeof(*X));
                    412:        clear(X, S.s_tinode * sizeof(*X));
                    413:        /* Read the bad block list */
                    414:        if (getbad() < 0)
                    415:                return (-1);
                    416:        /* Initialize the free block list */
                    417:        bbegin();
                    418:        /* Fixup the bad block file, ie allocate indirects */
                    419:        xfixup(X[BADFIN-1]);
                    420:        /* Set the time of construction */
                    421:        time(&S.s_time);
                    422:        return (0);
                    423: }
                    424: 
                    425: getbad()
                    426: {
                    427:        register int c;
                    428:        register daddr_t b;
                    429:        register char *tp;
                    430:        static char mymsg1[] = "illegal bad block number '%s'";
                    431:        static char mymsg2[] = "out of bounds bad block number '%s'";
                    432: 
                    433:        if (getxnode(sB) != BADFIN)
                    434:                return efatal("bad block file != inode %d", BADFIN);
                    435:        xexpand(X[BADFIN-1]);
                    436:        for (;;) {
                    437:                if ((c = getch()) != '%') {
                    438:                        ungetch(c);
                    439:                        break;
                    440:                }
                    441:                if ((c = getch()) != 'b') {
                    442:                        ungetch(c);
                    443:                        c = '%';
                    444:                        ungetch(c);
                    445:                        break;
                    446:                }
                    447:                while ((tp = gettoken()) != NULL) {
                    448:                        if (unnatural(tp)) {
                    449:                                eformat(mymsg1, tp);
                    450:                                continue;
                    451:                        }
                    452:                        b = atol(tp);
                    453:                        if (b >= S.s_fsize) {
                    454:                                eformat(mymsg2, tp);
                    455:                                continue;
                    456:                        }
                    457:                        xextend(X[BADFIN-1], b);
                    458:                }
                    459:                getline();
                    460:        }
                    461:        return (0);
                    462: }
                    463: 
                    464: getdir()
                    465: {
                    466:        char *cp1, *cp2;
                    467:        struct entre *ep;
                    468:        struct xnode *xp;
                    469:        int inum;
                    470: 
                    471:        for (;;) {
                    472:                if (Elevel < 0) {
                    473:                        cp1 = getline();
                    474:                } else {
                    475:                        cp1 = gettoken();
                    476:                        cp2 = getline();
                    477:                }
                    478:                if (cp1 == NULL)
                    479:                        return earlyeof();
                    480:                if (*cp1 == '$') {
                    481:                        if (Elevel-- < 0) {
                    482:                                assert(proto != NULL);
                    483:                                efatal("misplaced '$' in '%s'", proto);
                    484:                        }
                    485:                        if (Elevel < 0)
                    486:                                break;
                    487:                        continue;
                    488:                }
                    489:                if (Elevel >= 0) {
                    490:                        ep = getentre(cp1);
                    491:                } else
                    492:                        cp2 = cp1;
                    493:                inum = getxnode(cp2);
                    494:                if (Elevel >= 0)
                    495:                        ep->e_ino = inum;
                    496:                if (inum == 0)
                    497:                        continue;
                    498:                assert(inum > BADFIN);
                    499:                assert(inum <= nino);
                    500:                xp = X[inum-1];
                    501:                xp->x_nlink += 1;
                    502:                assert(xp != NULL);
                    503:                if ((xp->x_mode&IFMT) == IFDIR) {
                    504:                        if (++Elevel >= NDLEV)
                    505:                                return efatal("directories too deep");
                    506:                        E[Elevel] = inum;
                    507:                        ep = getentre(".");
                    508:                        ep->e_ino = inum;
                    509:                        xp = X[inum-1];
                    510:                        xp->x_nlink += 1;
                    511:                        ep = getentre("..");
                    512:                        if (Elevel != 0)
                    513:                                inum = E[Elevel-1];
                    514:                        ep->e_ino = inum;
                    515:                        xp = X[inum-1];
                    516:                        xp->x_nlink += 1;
                    517:                }
                    518:        }
                    519:        return (0);
                    520: }
                    521: 
                    522: struct entre *
                    523: getentre(cp)
                    524: char *cp;
                    525: {
                    526:        register struct xnode *xp;
                    527:        register struct entre *ep;
                    528:        register int inum;
                    529:        int nent;
                    530: 
                    531:        assert(Elevel >= 0);
                    532:        inum = E[Elevel];
                    533:        assert(inum > BADFIN);
                    534:        assert(inum <= nino);
                    535:        xp = X[inum-1];
                    536:        assert(xp != NULL);
                    537:        assert((xp->x_mode&IFMT) == IFDIR);
                    538:        xp->x_size += sizeof(struct direct);
                    539:        nent = xp->x_size / sizeof(struct direct);
                    540:        xp = xrealloc(xp, sizeof(*xp) + nent*sizeof(*ep));
                    541:        X[inum-1] = xp;
                    542:        ep = &xp->x_ents[nent-1];
                    543:        ep->e_ino = 0;
                    544:        ep->e_name = cp;
                    545:        return (ep);
                    546: }
                    547: 
                    548: ino_t
                    549: getxnode(cp)
                    550: char *cp;
                    551: {
                    552:        register struct xnode *xp;
                    553:        register ino_t inum;
                    554:        char *type, *uid, *gid, *name;
                    555:        int mode;
                    556:        dev_t dev;
                    557:        struct stat sbuf;
                    558: 
                    559:        if (cp == NULL)
                    560: missing_spec:
                    561:                return eformat("missing file specification");
                    562:        getopen(cp, NULL, 0);
                    563:        type = gettoken();
                    564:        uid = gettoken();
                    565:        gid = gettoken();
                    566:        name = gettoken();
                    567:        getclose();
                    568:        if (type == NULL)
                    569:                goto missing_spec;
                    570:        inum = 0;
                    571:        sbuf.st_size = 0;
                    572:        sbuf.st_mtime = sbuf.st_atime = sbuf.st_ctime = S.s_time;
                    573:        dev = 0;
                    574:        if (*type == 'l') {     /* Link to previously defined file */
                    575:                if (name == NULL)
                    576:                        return eformat("missing link name '%s'", cp);
                    577:                inum = getlink((*name=='/' ? E[0] : E[Elevel]), name);
                    578:                if (inum == 0)
                    579:                        return eformat("unknown link name '%s'", name);
                    580:                return (inum);
                    581:        }
                    582:        switch (type[0]) {
                    583:        case 'b':
                    584:        case 'c':
                    585:                if (name == NULL)
                    586:                        return eformat("missing device specification");
                    587:                else
                    588:                        dev = getdev(name);
                    589:                goto common;
                    590:        case 'd':
                    591:        case 'p':
                    592:                goto common;
                    593:        case 'B':
                    594:                goto common;
                    595:        case '-':
                    596:                if (name == NULL)
                    597:                   return eformat("missing source for regular file");
                    598:                else if (access(name, AREAD) < 0)
                    599:                   return eignore("access to '%s' failed: %s", name, syserror);
                    600:                else if (stat(name, &sbuf) < 0)
                    601:                   return eignore("stat of '%s' failed: %s", name, syserror);
                    602:                else if ((sbuf.st_mode&IFMT) != IFREG)
                    603:                   return eformat("'%s' is not a regular file", name);
                    604:        common:
                    605:                if ((mode = getmode(type)) == 0)
                    606:                        return (0);
                    607:                if (uid == NULL || unnatural(uid))
                    608:                        return eformat("bad user id '%s'", uid);
                    609:                if (gid == NULL || unnatural(gid))
                    610:                        return eformat("bad or missing group id '%s'", gid);
                    611:                break;
                    612:        default:
                    613:                return eformat("bad file specification '%s'", cp);
                    614:        }
                    615:        xp = xmalloc(sizeof(*xp));
                    616:        xp->x_size = sbuf.st_size;
                    617:        xp->x_atime = sbuf.st_atime;
                    618:        xp->x_mtime = sbuf.st_mtime;
                    619:        xp->x_ctime = sbuf.st_ctime;
                    620:        xp->x_nlink = 0;
                    621:        xp->x_y = NULL;
                    622:        xp->x_start = 0;
                    623:        xp->x_ino = inum = ialloc();
                    624:        xp->x_mode = mode;
                    625:        xp->x_dev = dev;
                    626:        xp->x_uid = atoi(uid);
                    627:        xp->x_gid = atoi(gid);
                    628:        xp->x_name = name;
                    629:        X[inum-1] = xp;
                    630:        return (inum);
                    631: }
                    632: 
                    633: /* Translate proto mode specification into mode word */
                    634: getmode(cp)
                    635: char *cp;
                    636: {
                    637:        register char *p;
                    638:        register int mode;
                    639:        register int i;
                    640:        static char mymessage[] = "mode format: %s char should be one of %s";
                    641: 
                    642:        p = cp;
                    643:        assert(p != NULL);
                    644:        mode = 0;
                    645:        switch (*p++) {
                    646:        case 'b': mode |= IFBLK; break;
                    647:        case 'c': mode |= IFCHR; break;
                    648:        case 'd': mode |= IFDIR; break;
                    649:        case 'p': mode |= IFPIPE; break;
                    650:        case '-': mode |= IFREG; break;
                    651:        case 'B': mode |= IFREG; return (mode);
                    652:        case 'l': assert(p[-1] != 'l'); break;
                    653:        default: return eformat(mymessage, "1st", "[bcdlp-]");
                    654:        }
                    655:        switch (*p++) {
                    656:        case 'u': mode |= ISUID; break;
                    657:        case '-': break;
                    658:        default: return eformat(mymessage, "2nd", "[u-]");
                    659:        }
                    660:        switch (*p++) {
                    661:        case 'g': mode |= ISGID; break;
                    662:        case '-': break;
                    663:        default: return eformat(mymessage, "3rd", "[g-]");
                    664:        }
                    665:        for (i = 1<<6; i > 0; i >>= 3) switch (*p++) {
                    666:        case '7': mode += i;
                    667:        case '6': mode += i;
                    668:        case '5': mode += i;
                    669:        case '4': mode += i;
                    670:        case '3': mode += i;
                    671:        case '2': mode += i;
                    672:        case '1': mode += i;
                    673:        case '0':
                    674:        case '-': break;
                    675:        default: return eformat(mymessage, "4th, 5th, or 6th", "[01234567-]");
                    676:        }
                    677:        return (mode);
                    678: }
                    679: 
                    680: getdev(cp)
                    681: char *cp;
                    682: {
                    683:        char *majp, *minp;
                    684: 
                    685:        getopen(cp, NULL, 0);
                    686:        majp = gettoken();
                    687:        minp = gettoken();
                    688:        getclose();
                    689:        if (majp == NULL || unnatural(majp))
                    690:                return badvalue("major number", cp);
                    691:        if (minp == NULL || unnatural(minp))
                    692:                return badvalue("minor number", cp);
                    693:        return makedev(atoi(majp), atoi(minp));
                    694: }
                    695: 
                    696: /*
                    697:  * Lookup a name in our directory tree.
                    698:  */
                    699: ino_t
                    700: getlink(inum, name)
                    701: ino_t inum;
                    702: char *name;
                    703: {
                    704:        int i, nent;
                    705:        struct entre *ep;
                    706:        struct xnode *xp;
                    707: 
                    708:        assert(inum > BADFIN);
                    709:        assert(inum <= nino);
                    710:        xp = X[inum-1];
                    711: nextname:
                    712:        assert(xp != NULL);
                    713:        ep = xp->x_ents;
                    714:        nent = xp->x_size / sizeof(struct direct);
                    715:        while (*name == '/')
                    716:                name += 1;
                    717:        if (*name == 0)
                    718:                return (inum);
                    719:        while (--nent >= 0) {
                    720:                if (ep->e_ino == 0) {
                    721:                        ep += 1;
                    722:                        continue;
                    723:                }
                    724:                for (i = 0; ; i += 1) {
                    725:                        if (name[i] != '\0' && name[i] != '/'
                    726:                          && name[i] != ep->e_name[i])
                    727:                                break;
                    728:                        if (i == DIRSIZ
                    729:                         || ep->e_name[i] == 0) {
                    730:                                inum = ep->e_ino;
                    731:                                assert(inum > BADFIN);
                    732:                                assert(inum <= nino);
                    733:                                if (name[i] == 0)
                    734:                                        return (inum);
                    735:                                if (name[i] == '/') {
                    736:                                        name += i;
                    737:                                        xp = X[inum-1];
                    738:                                        assert(xp != NULL);
                    739:                                        if ((xp->x_mode&IFMT) != IFDIR)
                    740:                                                return (0);
                    741:                                        goto nextname;
                    742:                                }
                    743:                                return (0);
                    744:                        }
                    745:                }
                    746:                ep += 1;
                    747:        }
                    748:        return (0);
                    749: }
                    750: 
                    751: /*
                    752:  * Intermediate pass, prepare for writing.
                    753:  *  scanilist() scans the xnode list and allocates data blocks
                    754:  *     and indirect mapping blocks.
                    755:  */
                    756: scanilist()
                    757: {
                    758:        register int i;
                    759:        register struct xnode *xp;
                    760: 
                    761:        for (i = BADFIN+1; i <= nino; i += 1) {
                    762:                if ((xp = X[i-1]) == NULL)
                    763:                        continue;
                    764:                xexpand(xp);
                    765:                xcontract(xp);
                    766:        }
                    767: }
                    768: 
                    769: /* FILE put.c */
                    770: /*
                    771:  * Second pass --
                    772:  *  we write everything in the order it appears
                    773:  *  without intervening reads.
                    774:  *  putboot() writes the boot block.
                    775:  *  putsuper() writes the super block.
                    776:  *  putilist() writes the ilist.
                    777:  *  putdata() writes the files.
                    778:  *  putfree() fills in the free block list.
                    779:  */
                    780: putboot()
                    781: {
                    782:        register int fd;
                    783:        register struct ldheader *ldp;
                    784:        char *bp;
                    785:        fsize_t fsize;
                    786: 
                    787:        if ((fd = open(P.p_bname, 0)) < 0) {
                    788:                eignore("open %s '%s': %s\n", N.p_bname, P.p_bname, syserror);
                    789:                return (0);
                    790:        }
                    791:        bp = bcache((daddr_t)BOOTBI);
                    792:        if (read(fd, bp, BSIZE) == BSIZE) {
                    793:                ldp = (struct ldheader *)bp;
                    794:                canint(ldp->l_magic);
                    795:                if (ldp->l_magic == L_MAGIC) {
                    796:                        cansize(ldp->l_ssize[L_PRVD]);
                    797:                        cansize(ldp->l_ssize[L_SHRD]);
                    798:                        cansize(ldp->l_ssize[L_PRVI]);
                    799:                        cansize(ldp->l_ssize[L_SHRI]);
                    800:                        fsize = ldp->l_ssize[L_PRVD] + ldp->l_ssize[L_SHRD]
                    801:                              + ldp->l_ssize[L_PRVI] + ldp->l_ssize[L_SHRI];
                    802:                        if (fsize > BSIZE)
                    803:                                eignore("%s '%s' truncated to %d",
                    804:                                        N.p_bname, P.p_bname, BSIZE);
                    805:                        lseek(fd, 44L, 0);
                    806:                        read(fd, bp, BSIZE);
                    807:                } else
                    808:                        canint(ldp->l_magic);
                    809:        }
                    810:        close(fd);
                    811:        return (0);
                    812: }
                    813: 
                    814: putsuper()
                    815: {
                    816:        register char *bp;
                    817: 
                    818:        bp = bcache((daddr_t)SUPERI);
                    819:        copy(bp, &S, BSIZE);
                    820:        cansuper(bp);
                    821:        return (0);
                    822: }
                    823: 
                    824: /*
                    825:  * Canonicalize the super block.
                    826:  */
                    827: cansuper(sbp)
                    828: register struct filsys *sbp;
                    829: {
                    830:        canshort(sbp->s_isize);
                    831:        candaddr(sbp->s_fsize);
                    832:        canshort(sbp->s_nfree);
                    833:        {
                    834:                register daddr_t *dp;
                    835:                register int i;
                    836: 
                    837:                i = NICFREE;
                    838:                dp = &sbp->s_free[NICFREE];
                    839:                while (--i >= 0) {
                    840:                        dp -= 1;        /* Watch for side effects */
                    841:                        candaddr(*dp);
                    842:                }
                    843:        }
                    844:        canshort(sbp->s_ninode);
                    845:        {
                    846:                register ino_t *ip;
                    847:                register int i;
                    848: 
                    849:                i = NICINOD;
                    850:                ip = &sbp->s_inode[NICINOD];
                    851:                while (--i >= 0) {
                    852:                        ip -= 1;
                    853:                        canino(*ip);
                    854:                }
                    855:        }
                    856:        cantime(sbp->s_time);
                    857:        candaddr(sbp->s_tfree);
                    858:        canino(sbp->s_tinode);
                    859:        canshort(sbp->s_m);
                    860:        canshort(sbp->s_n);
                    861:        canlong(sbp->s_unique);
                    862: }
                    863: 
                    864: putilist()
                    865: {
                    866:        register struct xnode *xp;
                    867:        struct dinode din;
                    868:        ino_t inum;
                    869: 
                    870:        clear(&din, sizeof(din));
                    871:        for (inum = BADFIN; inum <= nino; inum += 1) {
                    872:                if (bad((daddr_t)inodeb(inum))) {
                    873:                        inum += INOPB;
                    874:                        continue;
                    875:                }
                    876:                xp = X[inum-1];
                    877:                if (xp == NULL) {
                    878:                        iput(inum, &din);
                    879:                        continue;
                    880:                }
                    881:                din.di_mode = xp->x_mode;
                    882:                if (dflag)  {
                    883:                        din.di_mtime = xp->x_mtime;
                    884:                        din.di_atime = xp->x_atime;
                    885:                        din.di_ctime = xp->x_ctime;
                    886:                } else {
                    887:                        din.di_mtime = S.s_time;
                    888:                        din.di_ctime = S.s_time;
                    889:                        din.di_atime = S.s_time;
                    890:                }
                    891:                din.di_size = xp->x_size;
                    892:                din.di_nlink = xp->x_nlink;
                    893:                din.di_uid = xp->x_uid;
                    894:                din.di_gid = xp->x_gid;
                    895:                switch (xp->x_mode&IFMT) {
                    896:                case IFBLK:
                    897:                case IFCHR:
                    898:                        din.di_a.di_rdev = xp->x_dev;
                    899:                        break;
                    900:                case IFDIR:
                    901:                case IFREG:
                    902:                        if (inum != BADFIN)
                    903:                                xexpand(xp);
                    904:                        xymerge(xp, &din);
                    905:                        if (inum != BADFIN)
                    906:                                xcontract(xp);
                    907:                        break;
                    908:                }
                    909:                iput(inum, &din);
                    910:                clear(&din, sizeof(din));
                    911:        }
                    912:        return (0);
                    913: }
                    914: 
                    915: putdata()
                    916: {
                    917:        register int i;
                    918:        register struct xnode *xp;
                    919: 
                    920:        putbad();
                    921:        for (i = BADFIN+1; i <= nino; i += 1) {
                    922:                if ((xp = X[i-1]) == NULL)
                    923:                        continue;
                    924:                if ((xp->x_mode&IFMT) == IFDIR)
                    925:                        putdir(xp);
                    926:                else if ((xp->x_mode&IFMT) == IFREG)
                    927:                        putreg(xp);
                    928:        }
                    929:        return (0);
                    930: }
                    931: 
                    932: putbad()
                    933: {
                    934:        register struct ynode *yp;
                    935: 
                    936:        assert(X[BADFIN-1] != NULL);
                    937:        yp = X[BADFIN-1]->x_y;
                    938:        assert(yp != NULL);
                    939:        if (yp->y_ni)
                    940:                xindir(yp);
                    941: }
                    942: 
                    943: putdir(xp)
                    944: struct xnode *xp;
                    945: {
                    946:        struct direct dir;
                    947:        register struct entre *ep;
                    948:        int i, nent;
                    949: 
                    950:        xexpand(xp);
                    951:        nent = xp->x_size / sizeof(struct direct);
                    952:        for (i = 0; i < nent; i += 1) {
                    953:                ep = xp->x_ents + i;
                    954:                dir.d_ino = ep->e_ino;
                    955:                strncpy(dir.d_name, ep->e_name, DIRSIZ);
                    956:                if (strlen(ep->e_name) > DIRSIZ)
                    957:                        eignore("directory name '%s' truncated to %d chars",
                    958:                                ep->e_name, DIRSIZ);
                    959:                canino(dir.d_ino);
                    960:                xwrite(xp, &dir, sizeof(struct direct));
                    961:        }
                    962:        xcontract(xp);
                    963: }
                    964: 
                    965: putreg(xp)
                    966: struct xnode *xp;
                    967: {
                    968:        int fd, nb;
                    969:        fsize_t size;
                    970:        struct stat sbuf;
                    971: 
                    972:        if (stat(xp->x_name, &sbuf) < 0)
                    973:                return eignore("stat of %s failed: %s", xp->x_name, syserror);
                    974:        if (sbuf.st_size != xp->x_size)
                    975:                return eignore("size of %s has changed", xp->x_name);
                    976:        if ((fd = open(xp->x_name, 0)) < 0)
                    977:                return eignore("open %s failed: %s", xp->x_name, syserror);
                    978:        xexpand(xp);
                    979:        size = xp->x_size;
                    980:        while (size > 0) {
                    981:                nb = read(fd, miscbuf, BSIZE);
                    982:                if (nb < 0) {
                    983:                        eignore("read %s failed: %s", xp->x_name, syserror);
                    984:                        break;
                    985:                }
                    986:                xwrite(xp, miscbuf, BSIZE);
                    987:                size -= nb;
                    988:        }
                    989:        xcontract(xp);
                    990:        close(fd);
                    991: }
                    992: 
                    993: putfree()
                    994: {
                    995:        daddr_t b;
                    996:        register daddr_t *dp;
                    997:        register int n;
                    998: 
                    999:        while (S.s_nfree > 0) {
                   1000:                while (S.s_nfree > 1)
                   1001:                        b = balloc();
                   1002:                b = balloc();   /* Forces load of next free block */
                   1003:                dp = bcache(b);
                   1004:                ((struct fblk *)dp)->df_nfree = n = S.s_nfree;
                   1005:                canint(((struct flbk *)dp)->df_nfree);
                   1006:                dp = &((struct fblk *)dp)->df_free[0];
                   1007:                copy(dp, S.s_free, n * sizeof(daddr_t));
                   1008:                while (--n >= 0) {
                   1009:                        candaddr(*dp);
                   1010:                        dp += 1;
                   1011:                }
                   1012:        }
                   1013:        bcache((daddr_t)-1);    /* Flush */
                   1014:        return (0);
                   1015: }
                   1016: 
                   1017: /* FILE misc.c */
                   1018: /*
                   1019:  * Allocation with fatal errors.
                   1020:  */
                   1021: char *
                   1022: xmalloc(nb)
                   1023: {
                   1024:        char *p;
                   1025: 
                   1026:        p = malloc(nb);
                   1027:        if (p != NULL)
                   1028:                return (p);
                   1029:        efatal("memory allocation failed");
                   1030: }
                   1031: 
                   1032: char *
                   1033: xrealloc(p, nb)
                   1034: char *p;
                   1035: {
                   1036:        p = realloc(p, nb);
                   1037:        if (p != NULL)
                   1038:                return (p);
                   1039:        efatal("memory reallocation failed");
                   1040: }
                   1041: 
                   1042: /*
                   1043:  * Errors.
                   1044:  */
                   1045: char usage[] = "Usage: %s [ option ... ] special proto\n"
                   1046:                "Options:\n"
                   1047:                "\t-b boot\n"
                   1048:                "\t-d\n"
                   1049:                "\t-f name\n"
                   1050:                "\t-i inodes\n"
                   1051:                "\t-m arg\n"
                   1052:                "\t-n arg\n"
                   1053:                "\t-p pack\n";
                   1054: 
                   1055: eusage()
                   1056: {
                   1057:        fprintf(stderr, usage, argv0, argv0);
                   1058:        estatus |= ES_FATAL;
                   1059:        exit(estatus);
                   1060: }
                   1061: 
                   1062: eerror(es, fs, ap)
                   1063: int es;
                   1064: char *fs;
                   1065: char **ap;
                   1066: {
                   1067:        fprintf(stderr, "%s: ", argv0);
                   1068:        if (pfp.p_fn) fprintf(stderr, "in %s: ", pfp.p_fn);
                   1069:        if (pfp.p_ln) fprintf(stderr, "at %d: ", pfp.p_ln);
                   1070:        fprintf(stderr, fs, ap);
                   1071:        estatus |= es;
                   1072:        if (estatus & ES_FATAL)
                   1073:                exit(estatus);
                   1074:        return (0);
                   1075: }
                   1076: 
                   1077: efatal(a1)
                   1078: char *a1;
                   1079: {
                   1080:        return eerror(ES_FATAL, "%r\n", &a1);
                   1081: }
                   1082: 
                   1083: eignore(a1)
                   1084: char *a1;
                   1085: {
                   1086:        return eerror(ES_IGNORED, "%r (ignored)\n", &a1);
                   1087: }
                   1088: 
                   1089: eformat(a1)
                   1090: char *a1;
                   1091: {
                   1092:        return eerror(ES_FORMAT, "%r\n", &a1);
                   1093: }
                   1094: 
                   1095: badvalue(np, vp)
                   1096: char *np, *vp;
                   1097: {
                   1098:        return eformat("bad value for %s: %s", np, vp);
                   1099: }
                   1100: 
                   1101: badopen(np, cp)
                   1102: char *cp, *np;
                   1103: {
                   1104:        return efatal("open '%s' as %s failed: %s", cp, np, syserror);
                   1105: }
                   1106: 
                   1107: earlyeof()
                   1108: {
                   1109:        assert(proto != NULL);
                   1110:        return efatal("unexpected end of descriptor file: %s", proto);
                   1111: }
                   1112: 
                   1113: /*
                   1114:  * Token and line input.
                   1115:  *  getopen() pushes the current input string,
                   1116:  *  getclose() pops the previous input string,
                   1117:  *  gettoken() returns a pointer to the beginning of the next token,
                   1118:  *  getline() returns pointer to the same and advances to next line.
                   1119:  *  both return NULL on unexpected end of file.
                   1120:  */
                   1121: getopen(cp, fn, dln)
                   1122: char *cp;
                   1123: char *fn;
                   1124: int dln;
                   1125: {
                   1126:        struct pfp *tp;
                   1127: 
                   1128:        tp = xmalloc(sizeof(*tp));
                   1129:        *tp = pfp;
                   1130:        pfp.p_fn = fn;
                   1131:        pfp.p_ln = 0;
                   1132:        pfp.p_dln = dln;
                   1133:        pfp.p_ip = pfp.p_cp = cp;
                   1134:        pfp.p_fp = tp;
                   1135: }
                   1136: 
                   1137: getclose()
                   1138: {
                   1139:        struct pfp *tp;
                   1140: 
                   1141:        assert(pfp.p_fp != NULL);
                   1142:        tp = pfp.p_fp;
                   1143:        pfp = *tp;
                   1144:        free(tp);
                   1145: }
                   1146: 
                   1147: char *
                   1148: gettoken()
                   1149: {
                   1150:        register int c;
                   1151:        register char *p, *tp;
                   1152: 
                   1153:        pfp.p_ln += pfp.p_dln;
                   1154:        pfp.p_dln = 0;
                   1155:        p = pfp.p_cp;
                   1156: 
                   1157:        /* DEBUG - this code is writing into string literals! */
                   1158: #if _I386 && !NDEBUG
                   1159:        if ((int)pfp.p_cp < 0x400000) {
                   1160:                fprintf(stderr, "pfp.p_cp=%x:%s\n",
                   1161:                  pfp.p_cp, pfp.p_cp);
                   1162:                fflush(stderr);
                   1163:                exit(1);
                   1164:        }
                   1165: #endif
                   1166: 
                   1167:        while ((c = *p) == ' ' || c == '\t')
                   1168:                *p++ = 0;
                   1169:        pfp.p_cp = tp = p;
                   1170:        if (c == 0 || c == '\n')
                   1171:                return (NULL);
                   1172:        do
                   1173:                c = *p++;
                   1174:        while (c != 0 && c != ' ' && c != '\t' && c != '\n');
                   1175:        pfp.p_cp = p - 1;
                   1176:        return (tp);
                   1177: }
                   1178: 
                   1179: char *
                   1180: getline()
                   1181: {
                   1182:        register int c;
                   1183:        register char *p, *tp;
                   1184: 
                   1185:        pfp.p_ln += pfp.p_dln;
                   1186:        pfp.p_dln = 0;
                   1187:        p = pfp.p_cp;
                   1188:        while ((c = *p) == ' ' || c == '\t')
                   1189:                *p++ = 0;
                   1190:        pfp.p_cp = tp = p;
                   1191:        if (c == 0)
                   1192:                return earlyeof();
                   1193:        if (c == '\n') {
                   1194:                *p++ = 0;
                   1195:                pfp.p_cp += 1;
                   1196:                if (pfp.p_ln) pfp.p_dln = 1;
                   1197:                return (tp);
                   1198:        }
                   1199:        do
                   1200:                c = *p++;
                   1201:        while (c != 0 && c != '\n');
                   1202:        if (c == 0)
                   1203:                return earlyeof();
                   1204:        pfp.p_cp = p;
                   1205:        p[-1] = 0;
                   1206:        return (tp);
                   1207: }
                   1208: 
                   1209: /*
                   1210:  * Miscellaneous.
                   1211:  */
                   1212: unnatural(cp)
                   1213: char *cp;
                   1214: {
                   1215:        register char *p;
                   1216: 
                   1217:        p = cp;
                   1218:        while (isdigit(*p)) p += 1;
                   1219:        switch (*p) {
                   1220:        case 0:
                   1221:        case ' ':
                   1222:        case '\t':
                   1223:        case '\n':
                   1224:                return (0);
                   1225:        default: 
                   1226:                return (-1);
                   1227:        }
                   1228: }
                   1229: 
                   1230: clear(bp, n)
                   1231: register char *bp;
                   1232: register unsigned n;
                   1233: {
                   1234:        if (n) do {
                   1235:                *bp++ = 0;
                   1236:        } while (--n);
                   1237: }
                   1238: 
                   1239: copy(bp1, bp2, n)
                   1240: register char *bp1;
                   1241: register char *bp2;
                   1242: register unsigned n;
                   1243: {
                   1244:        if (n) do {
                   1245:                *bp1++ = *bp2++;
                   1246:        } while (--n);
                   1247: }
                   1248: 
                   1249: iszero(bp, n)
                   1250: register char *bp;
                   1251: register unsigned n;
                   1252: {
                   1253:        if (n) do
                   1254:                if (*bp++ != 0) return (0);
                   1255:        while (--n);
                   1256:        return (1);
                   1257: }
                   1258: 
                   1259: /* FILE xmisc.c */
                   1260: /*
                   1261:  *  xexpand() - creates a block map for the inode.
                   1262:  *     indirect blocks are allocated sequentially, followed by data blocks
                   1263:  *     also sequentially.
                   1264:  *  xcontract() - discards the block map.
                   1265:  *  xextend() - appends a specified data block to the bad inode.
                   1266:  *  xymerge() - merges block addresses into disk inode structure.
                   1267:  *  xwrite() - writes data and necessary indirect blocks into filesystem.
                   1268:  */
                   1269: int xwatch = 0;
                   1270: 
                   1271: xexpand(xp)
                   1272: struct xnode *xp;
                   1273: {
                   1274:        register struct ynode *yp;
                   1275:        register daddr_t *dp;
                   1276:        register daddr_t nb;
                   1277:        daddr_t b;
                   1278: 
                   1279:        assert(xp != NULL);
                   1280:        assert(xp->x_ino >= BADFIN);
                   1281:        assert(xp->x_ino <= nino);
                   1282:        yp = xp->x_y;
                   1283:        assert(yp == NULL);
                   1284:        xp->x_y = yp = xmalloc(sizeof(*yp) + NADDR * sizeof(daddr_t));
                   1285:        clear(yp, sizeof(*yp) + NADDR * sizeof(daddr_t));
                   1286:        yp->y_ino = xp->x_ino;
                   1287:        yp->y_seek = 0;
                   1288:        xblkuse(xp);
                   1289:        nb = yp->y_nb;
                   1290:        if (nb > NADDR) {
                   1291:            xp->x_y = yp = xrealloc(yp, sizeof(*yp)
                   1292:                + ((unsigned)nb) * sizeof(daddr_t));
                   1293:            clear(yp->y_b, ((unsigned)nb) * sizeof(daddr_t));
                   1294:        }
                   1295:        /* Set up pointers */
                   1296:        yp->y_iiib = yp->y_b;
                   1297:        yp->y_iib = yp->y_iiib + yp->y_niiib;
                   1298:        yp->y_ib = yp->y_iib + yp->y_niib;
                   1299:        yp->y_db = yp->y_ib + yp->y_nib;
                   1300:        /* Resynchronize the allocator */
                   1301:        if (b = xp->x_start)
                   1302:                bstart(xp->x_start);
                   1303:        /* Allocate blocks */
                   1304:        dp = yp->y_b;
                   1305:        nb = yp->y_nb;
                   1306:        while (--nb >= 0)
                   1307:                *dp++ = balloc();
                   1308:        if (xp->x_start == 0)
                   1309:                xp->x_start = yp->y_b[0];
                   1310: }
                   1311: 
                   1312: xblkuse(xp)
                   1313: struct xnode *xp;
                   1314: {
                   1315:        register struct ynode *yp;
                   1316:        register daddr_t nb;
                   1317: 
                   1318:        yp = xp->x_y;
                   1319:        nb = xp->x_size + BSIZE - 1;
                   1320:        nb /= BSIZE;
                   1321:        yp->y_niiib = 0;
                   1322:        yp->y_niib = 0;
                   1323:        yp->y_nib = 0;
                   1324:        yp->y_ndb = 0;
                   1325:        yp->y_ni = 0;
                   1326:        if (nb > ND) {
                   1327:                if (nb > ND+NBN) {
                   1328:                        if (nb > ND+NBN+NBN*NBN) {
                   1329:                                nb -= ND+NBN+NBN*NBN;
                   1330:                                assert(nb > 0 && nb < NBN*NBN*(long)NBN);
                   1331:                                yp->y_ndb += nb;
                   1332:                                nb += NBN-1;
                   1333:                                nb /= NBN;
                   1334:                                yp->y_nib += nb;
                   1335:                                nb += NBN-1;
                   1336:                                nb /= NBN;
                   1337:                                yp->y_niib += nb;
                   1338:                                assert(((nb+NBN-1)/NBN) == 1);
                   1339:                                yp->y_niiib += 1;
                   1340:                                nb = ND+NBN+NBN*NBN;
                   1341:                        }
                   1342:                        nb -= ND+NBN;
                   1343:                        assert(nb > 0 && nb < NBN*NBN);
                   1344:                        yp->y_ndb += nb;
                   1345:                        nb += NBN-1;
                   1346:                        nb /= NBN;
                   1347:                        yp->y_nib += nb;
                   1348:                        assert(((nb+NBN-1)/NBN) == 1);
                   1349:                        yp->y_niib += 1;
                   1350:                        nb = ND+NBN;
                   1351:                }
                   1352:                nb -= ND;
                   1353:                assert(nb > 0 && nb < NBN);
                   1354:                yp->y_ndb += nb;
                   1355:                assert(((nb+NBN-1)/NBN) == 1);
                   1356:                yp->y_nib += 1;
                   1357:                nb = ND;
                   1358:        }
                   1359:        assert(nb >= 0 && nb <= ND);
                   1360:        yp->y_ndb += nb;
                   1361:        yp->y_ni = yp->y_nib + yp->y_niib + yp->y_niiib;
                   1362:        yp->y_nb = yp->y_ndb + yp->y_ni;
                   1363: }
                   1364: 
                   1365: xcontract(xp)
                   1366: register struct xnode *xp;
                   1367: {
                   1368:        register struct ynode *yp;
                   1369: 
                   1370:        assert(xp != NULL);
                   1371:        assert(xp->x_ino >= BADFIN);
                   1372:        assert(xp->x_ino <= nino);
                   1373:        yp = xp->x_y;
                   1374:        assert(yp != NULL);
                   1375:        assert(yp->y_ino == xp->x_ino);
                   1376:        xp->x_y = NULL;
                   1377:        free(yp);
                   1378: }
                   1379: 
                   1380: xymerge(xp, dip)
                   1381: struct xnode *xp;
                   1382: struct dinode *dip;
                   1383: {
                   1384:        register struct ynode *yp;
                   1385:        char *l3p;
                   1386: 
                   1387:        assert(xp != NULL);
                   1388:        assert(xp->x_ino >= BADFIN);
                   1389:        assert(xp->x_ino <= nino);
                   1390:        yp = xp->x_y;
                   1391:        assert(yp != NULL);
                   1392:        assert(yp->y_ino == xp->x_ino);
                   1393:        l3p = dip->di_addr;
                   1394:        ltol3(l3p, yp->y_db, ND);
                   1395:        l3p += 3*ND;
                   1396:        if (yp->y_nib)
                   1397:                ltol3(l3p, yp->y_ib, 1);
                   1398:        l3p += 3;
                   1399:        if (yp->y_niib) 
                   1400:                ltol3(l3p, yp->y_iib, 1);
                   1401:        l3p += 3;
                   1402:        if (yp->y_niiib)
                   1403:                ltol3(l3p, yp->y_iiib, 1);
                   1404: }
                   1405: 
                   1406: xwrite(xp, cp, nb)
                   1407: struct xnode *xp;
                   1408: char *cp;
                   1409: int nb;
                   1410: {
                   1411:        register struct ynode *yp;
                   1412:        daddr_t bn;
                   1413:        int bo;
                   1414:        char *bp;
                   1415: 
                   1416:        assert(xp != NULL);
                   1417:        assert(xp->x_ino > BADFIN);
                   1418:        assert(xp->x_ino <= nino);
                   1419:        yp = xp->x_y;
                   1420:        assert(yp != NULL);
                   1421:        assert(yp->y_ino == xp->x_ino);
                   1422:        if (yp->y_seek == 0 && yp->y_ni != 0)
                   1423:                xindir(yp);     /* Write indirect blocks */
                   1424:        bn = yp->y_seek / BSIZE;
                   1425:        assert(bn < yp->y_ndb);
                   1426:        bo = yp->y_seek % BSIZE;
                   1427:        assert(bo+nb <= BSIZE);
                   1428:        bp = bcache(yp->y_db[(int)bn]);
                   1429:        copy(bp+bo, cp, nb);
                   1430:        yp->y_seek += nb;
                   1431: }
                   1432: 
                   1433: xindir(yp)
                   1434: register struct ynode *yp;
                   1435: {
                   1436:        /* Triple indirect block */
                   1437:        if (yp->y_niiib)
                   1438:                xindblks(yp->y_iiib, yp->y_iib+1, (daddr_t)yp->y_niib-1);
                   1439:        /* Double indirect blocks */
                   1440:        if (yp->y_niib)
                   1441:                xindblks(yp->y_iib, yp->y_ib+1, (daddr_t)yp->y_nib-1);
                   1442:        /* Single indirect blocks */
                   1443:        if (yp->y_nib)
                   1444:                xindblks(yp->y_ib, yp->y_db+ND, (daddr_t)yp->y_ndb-ND);
                   1445: }
                   1446: 
                   1447: xindblks(dp, sp, nb)
                   1448: register daddr_t *dp, *sp, nb;
                   1449: {
                   1450:        register int n;
                   1451: 
                   1452:        while (nb > 0) {
                   1453:                if (nb >= NBN)
                   1454:                        n = NBN;
                   1455:                else
                   1456:                        n = nb;
                   1457:                xindblk(*dp, sp, n);
                   1458:                dp += 1;
                   1459:                sp += n;
                   1460:                nb -= n;
                   1461:        }
                   1462: }
                   1463: 
                   1464: 
                   1465: xindblk(b, bp, nd)
                   1466: daddr_t b, *bp;
                   1467: register int nd;
                   1468: {
                   1469:        register daddr_t *dp;
                   1470:        dp = bcache(b);
                   1471:        copy(dp, bp, nd * sizeof(daddr_t));
                   1472:        while (--nd >= 0) {
                   1473:                candaddr(*dp);
                   1474:                dp += 1;
                   1475:        }
                   1476: }
                   1477: 
                   1478: /*
                   1479:  * Extend the bad block file.
                   1480:  */
                   1481: xextend(xp, b)
                   1482: struct xnode *xp;
                   1483: daddr_t b;
                   1484: {
                   1485:        register struct ynode *yp;
                   1486:        int nd;
                   1487: 
                   1488:        assert(xp != NULL);
                   1489:        assert(xp->x_ino == BADFIN);
                   1490:        yp = xp->x_y;
                   1491:        assert(yp != NULL);
                   1492:        assert(yp->y_ino == BADFIN);
                   1493:        assert(b < S.s_fsize);
                   1494:        if (bad(b))
                   1495:                return eignore("duplicated bad block %ld", b);
                   1496:        else if (b == BOOTBI)
                   1497:                return eignore("boot block (%ld) is bad", b);
                   1498:        else if (b == SUPERI)
                   1499:                return efatal("super block (%ld) is bad", b);
                   1500:        else if (b == inodeb(BADFIN))
                   1501:                return efatal("first inode block (%ld) is bad", b);
                   1502:        else if (b < S.s_isize)
                   1503:                S.s_tinode -= INOPB;
                   1504:        else
                   1505:                S.s_tfree -= 1;
                   1506:        xp->x_size += BSIZE;
                   1507:        nd = yp->y_ndb += 1;
                   1508:        if (nd > NADDR)
                   1509:            xp->x_y = yp = xrealloc(yp, sizeof(*yp) + nd * sizeof(daddr_t));
                   1510:        yp->y_b[nd-1] = b;
                   1511: }
                   1512: 
                   1513: bad(b)
                   1514: daddr_t b;
                   1515: {
                   1516:        struct ynode *yp;
                   1517:        register daddr_t *dp;
                   1518:        register int i;
                   1519: 
                   1520:        assert(X[BADFIN-1] != NULL);
                   1521:        yp = X[BADFIN-1]->x_y;
                   1522:        assert(yp != NULL);
                   1523:        assert(yp->y_ino == BADFIN);
                   1524:        i = yp->y_ndb;
                   1525:        dp = yp->y_db;
                   1526:        while (--i >= 0)
                   1527:                if (b == *dp)
                   1528:                        return (1);
                   1529:                else
                   1530:                        dp += 1;
                   1531:        return (0);
                   1532: }
                   1533: 
                   1534: xfixup(xp)
                   1535: struct xnode *xp;
                   1536: {
                   1537:        struct ynode *yp;
                   1538:        register daddr_t *dp1, *dp2;
                   1539:        register int i;
                   1540: 
                   1541: 
                   1542:        assert(xp != NULL);
                   1543:        assert(xp->x_ino == BADFIN);
                   1544:        yp = xp->x_y;
                   1545:        assert(yp != NULL);
                   1546:        xblkuse(xp);
                   1547:        if (yp->y_ni) {
                   1548:                yp = xrealloc(yp, sizeof(*yp) + yp->y_nb * sizeof(daddr_t));
                   1549:                xp->x_y = yp;
                   1550:                yp->y_iiib = yp->y_b;
                   1551:                yp->y_iib = yp->y_iiib + yp->y_niiib;
                   1552:                yp->y_ib = yp->y_iib + yp->y_niib;
                   1553:                yp->y_db = yp->y_ib + yp->y_nib;
                   1554:                dp1 = yp->y_db + yp->y_ndb;
                   1555:                dp2 = yp->y_b + yp->y_ndb;
                   1556:                i = yp->y_ndb;
                   1557:                while (--i >= 0)
                   1558:                        *--dp1 = *--dp2;
                   1559:                dp1 = yp->y_b;
                   1560:                i = yp->y_ni;
                   1561:                while (--i >= 0)
                   1562:                        *dp1++ = balloc();
                   1563:        }
                   1564: }
                   1565: 
                   1566: xdump(xp)
                   1567: register struct xnode *xp;
                   1568: {
                   1569:        register struct ynode *yp;
                   1570: 
                   1571:        yp = xp->x_y;
                   1572:        fprintf(stderr, "%d %x %ld\n", xp->x_ino, xp->x_mode, xp->x_size);
                   1573:        if (yp->y_niiib)
                   1574:                xlist("indir^3", yp->y_iiib, (daddr_t)yp->y_niiib);
                   1575:        if (yp->y_niib)
                   1576:                xlist("indir^2", yp->y_iib, (daddr_t)yp->y_niib);
                   1577:        if (yp->y_nib)
                   1578:                xlist("indir^1", yp->y_ib, (daddr_t)yp->y_nib);
                   1579:        if (yp->y_ndb)
                   1580:                xlist("data", yp->y_db, (daddr_t)yp->y_ndb);
                   1581: }
                   1582: xlist(cp, dp, n)
                   1583: char *cp;
                   1584: daddr_t *dp;
                   1585: daddr_t n;
                   1586: {
                   1587:        fprintf(stderr, "       %d %s: ", n, cp);
                   1588:        for (;;) {
                   1589:                fprintf(stderr, "%ld", dp[0]);
                   1590:                dp += 1;
                   1591:                n -= 1;
                   1592:                if (n == 0)
                   1593:                        break;
                   1594:                if (dp[0] == dp[-1]+1) {
                   1595:                        fprintf(stderr, "..");
                   1596:                        while (dp[0] == dp[-1]+1) {
                   1597:                                dp += 1;
                   1598:                                n -= 1;
                   1599:                                if (n == 0)
                   1600:                                        break;
                   1601:                        }
                   1602:                        fprintf(stderr, "%ld", dp[-1]);
                   1603:                        if (n == 0)
                   1604:                                break;
                   1605:                }
                   1606:                fprintf(stderr, ", ");
                   1607:        }
                   1608:        fprintf(stderr, "\n");
                   1609: }
                   1610: 
                   1611: /* FILE imisc.c */
                   1612: /*
                   1613:  * Inode cache management.
                   1614:  *  iput() - writes an inode to disk.
                   1615:  */
                   1616: /*
                   1617:  * Write the inode `ip' containing the inode `i' onto the
                   1618:  * filesystem in canonical form.
                   1619:  */
                   1620: iput(i, dip1)
                   1621: ino_t i;
                   1622: register struct dinode *dip1;
                   1623: {
                   1624:        register struct dinode *dip2;
                   1625: 
                   1626:        dip2 = bcache((daddr_t)inodeb(i));
                   1627:        dip2 += inodei(i);
                   1628:        *dip2 = *dip1;
                   1629:        canshort(dip2->di_mode);
                   1630:        canshort(dip2->di_nlink);
                   1631:        canshort(dip2->di_uid);
                   1632:        canshort(dip2->di_gid);
                   1633:        cansize(dip2->di_size);
                   1634:        cantime(dip2->di_atime);
                   1635:        cantime(dip2->di_mtime);
                   1636:        cantime(dip2->di_ctime);
                   1637:        switch (dip1->di_mode&IFMT) {
                   1638:        case IFCHR:
                   1639:        case IFBLK:
                   1640:                candev(dip2->di_a.di_rdev);
                   1641:                break;
                   1642:        }
                   1643: }
                   1644: 
                   1645: /*
                   1646:  * Return a free inode number.
                   1647:  */
                   1648: ino_t
                   1649: ialloc()
                   1650: {
                   1651:        ino_t inum;
                   1652:        ino_t in;
                   1653:        ino_t *ip;
                   1654:        daddr_t b;
                   1655: 
                   1656:        if (S.s_ninode == 0)
                   1657:                return efatal("out of inodes");
                   1658:        inum = S.s_inode[--S.s_ninode];
                   1659:        if (S.s_ninode == 0) {
                   1660:                ip = &S.s_inode[NICINOD];
                   1661:                in = inum + 1;
                   1662:                while ((b = inodeb(in)) < S.s_isize && ip >S.s_inode) {
                   1663:                        if (bad(b)) {
                   1664:                                in += INOPB;
                   1665:                                continue;
                   1666:                        }
                   1667:                        *--ip = in++;
                   1668:                }
                   1669:                S.s_ninode = NICINOD;
                   1670:                if (ip != S.s_inode) {
                   1671:                        S.s_ninode -= ip - S.s_inode;
                   1672:                        copy(S.s_inode, ip, S.s_ninode * sizeof(ino_t));
                   1673:                }
                   1674:        }
                   1675:        --S.s_tinode;
                   1676:        return (inum);
                   1677: }
                   1678: 
                   1679: /* FILE bmisc.c */
                   1680: /*
                   1681:  * Block management.
                   1682:  *  bbegin() - set the seed of the block allocator.
                   1683:  *  balloc() - allocate a block.
                   1684:  *  bstart() - resynchronize the allocation.
                   1685:  *  bmap() - implement interleave mapping.
                   1686:  *  bcache() - single block buffer cache.
                   1687:  */
                   1688: int bwatch = 0;
                   1689: 
                   1690: static daddr_t bseed;
                   1691: static daddr_t bmap();
                   1692: 
                   1693: bbegin()
                   1694: {
                   1695:        /* Must be called after the bad block list is initialized */
                   1696:        assert(X != NULL);
                   1697:        assert(X[BADFIN-1] != NULL);
                   1698:        assert(X[BADFIN-1]->x_y != NULL);
                   1699:        bseed = S.s_isize;
                   1700:        S.s_tfree += S.s_fsize - S.s_isize;
                   1701:        clear(S.s_free, NICFREE*sizeof(daddr_t));
                   1702:        S.s_nfree = 1;
                   1703:        while (bad(S.s_free[0] = bmap(bseed)))
                   1704:                ++bseed;
                   1705: }
                   1706: 
                   1707: daddr_t
                   1708: balloc()
                   1709: {
                   1710:        register daddr_t *dp;
                   1711:        register daddr_t b, b1;
                   1712: 
                   1713:        if (S.s_nfree == 0)
                   1714:                return 0;
                   1715:        b = S.s_free[--S.s_nfree];
                   1716:        if (S.s_nfree == 0) {
                   1717:                clear(S.s_free, sizeof S.s_free);
                   1718:                dp = &S.s_free[NICFREE];
                   1719:                while (dp > S.s_free && ++bseed < S.s_fsize) {
                   1720:                        b1 = bmap(bseed);
                   1721:                        if (bad(b1))
                   1722:                                continue;
                   1723:                        *--dp = b1;
                   1724:                }
                   1725:                S.s_nfree = NICFREE - (dp - S.s_free);
                   1726:                if (dp != S.s_free)
                   1727:                        copy(S.s_free, dp, S.s_nfree * sizeof(daddr_t));
                   1728:        }
                   1729:        --S.s_tfree;
                   1730:        return (b);
                   1731: }
                   1732: 
                   1733: bstart(b)
                   1734: daddr_t b;
                   1735: {
                   1736:        if (S.s_nfree && S.s_free[S.s_nfree-1] == b)
                   1737:                return;
                   1738:        bbegin();
                   1739:        while (S.s_nfree && S.s_free[S.s_nfree-1] != b)
                   1740:                balloc();
                   1741:        assert(S.s_nfree != 0);
                   1742: }
                   1743: 
                   1744: #define        MAXINTN 255                     /* maptab must be int * if > 255 */
                   1745: static unsigned        char    *maptab;        /* Interleave table */
                   1746: static daddr_t mapbot;
                   1747: static daddr_t maptop;
                   1748: /*
                   1749:  * Return a mapped block number with interleaving.
                   1750:  */
                   1751: static daddr_t
                   1752: bmap(b)
                   1753: daddr_t b;
                   1754: {
                   1755:        register short i;
                   1756:        register int ints;
                   1757: 
                   1758:        if (maptab == NULL) {
                   1759:                if (S.s_n > MAXINTN
                   1760:                 || S.s_m > S.s_n
                   1761:                 || S.s_n%S.s_m != 0)
                   1762:                        efatal("%d/%d: bad interleave factor", S.s_m, S.s_n);
                   1763:                maptab = xmalloc(S.s_n);
                   1764:                mapbot = ((S.s_isize + S.s_n - 1) / S.s_n) * S.s_n;
                   1765:                maptop = (S.s_fsize / S.s_n) * S.s_n;
                   1766:                ints = S.s_n / S.s_m;
                   1767:                for (i=0; i < S.s_n; i++)
                   1768:                        maptab[i] = (i / ints) + (i % ints) * S.s_m;
                   1769:        }
                   1770:        if (b >= mapbot && b < maptop) {
                   1771:                i = b % S.s_n;
                   1772:                b -= i;
                   1773:                b += maptab[i];
                   1774:        }
                   1775:        return (b);
                   1776: }
                   1777: 
                   1778: char *
                   1779: bcache(b)
                   1780: daddr_t b;
                   1781: {
                   1782:        static daddr_t bcacheb = -1;
                   1783:        static char buffer[BSIZE];
                   1784:        if (bcacheb != b) {
                   1785:                if (bcacheb >= 0) {
                   1786:                        lseek(FS, (long)bcacheb*BSIZE, 0);
                   1787: if (bwatch) bdump(b, bcacheb, buffer);
                   1788:                        if (write(FS, buffer, BSIZE) != BSIZE)
                   1789:                            eignore("filesystem write error at block %ld", b);
                   1790:                }
                   1791:                clear(buffer, BSIZE);
                   1792:        }
                   1793:        bcacheb = b;
                   1794:        return (buffer);
                   1795: }
                   1796: 
                   1797: bdump(b1, b2, bp)
                   1798: daddr_t b1, b2;
                   1799: char *bp;
                   1800: {
                   1801:        int i, j;
                   1802:        fprintf(stderr, "bcache(%ld) writes(%ld) = {", b1, b2);
                   1803:        if (iszero(bp, BSIZE))
                   1804:                fprintf(stderr, " 0 ");
                   1805:        else {
                   1806:                fprintf(stderr, "\n");
                   1807:                for (i = 0; i < 32; i += 1) {
                   1808:                        for (j = 0; j < 16; j += 1)
                   1809:                                fprintf(stderr, " %02x", *bp++ & 0377);
                   1810:                        fprintf(stderr, "\n");
                   1811:                }
                   1812:        }
                   1813:        fprintf(stderr, "}\n");
                   1814: }
                   1815: 
                   1816: /* end of mkfs.c */

unix.superglobalmegacorp.com

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