Annotation of coherent/d/etc/mkfs.c, revision 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.