Annotation of 42BSD/etc/fsck/fsck.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: char version[] = "@(#)fsck.c   2.30 (Berkeley) 9/19/83";
                      3: #endif
                      4: 
                      5: #include <stdio.h>
                      6: #include <ctype.h>
                      7: #include <sys/param.h>
                      8: #include <sys/fs.h>
                      9: #include <sys/inode.h>
                     10: #include <sys/stat.h>
                     11: #include <sys/wait.h>
                     12: #include <fstab.h>
                     13: #define KERNEL
                     14: #include <sys/dir.h>
                     15: #undef KERNEL
                     16: 
                     17: /* RECONSTRUCT ONLY BAD CG IN PASS 6 */
                     18: 
                     19: typedef        int     (*SIG_TYP)();
                     20: 
                     21: #define        MAXNINDIR       (MAXBSIZE / sizeof (daddr_t))
                     22: #define        MAXINOPB        (MAXBSIZE / sizeof (struct dinode))
                     23: #define        SPERB           (MAXBSIZE / sizeof(short))
                     24: #define MINDIRSIZE     (sizeof (struct dirtemplate))
                     25: 
                     26: #define        MAXDUP  10              /* limit on dup blks (per inode) */
                     27: #define        MAXBAD  10              /* limit on bad blks (per inode) */
                     28: 
                     29: #define        USTATE  0               /* inode not allocated */
                     30: #define        FSTATE  01              /* inode is file */
                     31: #define        DSTATE  02              /* inode is directory */
                     32: #define        CLEAR   03              /* inode is to be cleared */
                     33: 
                     34: typedef struct dinode  DINODE;
                     35: typedef struct direct  DIRECT;
                     36: 
                     37: #define        ALLOC   ((dp->di_mode & IFMT) != 0)
                     38: #define        DIRCT   ((dp->di_mode & IFMT) == IFDIR)
                     39: #define        REG     ((dp->di_mode & IFMT) == IFREG)
                     40: #define        BLK     ((dp->di_mode & IFMT) == IFBLK)
                     41: #define        CHR     ((dp->di_mode & IFMT) == IFCHR)
                     42: #define        LNK     ((dp->di_mode & IFMT) == IFLNK)
                     43: #define        SOCK    ((dp->di_mode & IFMT) == IFSOCK)
                     44: #define        BADBLK  ((dp->di_mode & IFMT) == IFMT)
                     45: #define        SPECIAL (BLK || CHR)
                     46: 
                     47: struct bufarea {
                     48:        struct bufarea  *b_next;                /* must be first */
                     49:        daddr_t b_bno;
                     50:        int     b_size;
                     51:        union {
                     52:                char    b_buf[MAXBSIZE];        /* buffer space */
                     53:                short   b_lnks[SPERB];          /* link counts */
                     54:                daddr_t b_indir[MAXNINDIR];     /* indirect block */
                     55:                struct  fs b_fs;                /* super block */
                     56:                struct  cg b_cg;                /* cylinder group */
                     57:                struct dinode b_dinode[MAXINOPB]; /* inode block */
                     58:        } b_un;
                     59:        char    b_dirty;
                     60: };
                     61: 
                     62: typedef struct bufarea BUFAREA;
                     63: 
                     64: BUFAREA        inoblk;                 /* inode blocks */
                     65: BUFAREA        fileblk;                /* other blks in filesys */
                     66: BUFAREA        sblk;                   /* file system superblock */
                     67: BUFAREA        cgblk;                  /* cylinder group blocks */
                     68: 
                     69: #define        initbarea(x)    (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1
                     70: #define        dirty(x)        (x)->b_dirty = 1
                     71: #define        inodirty()      inoblk.b_dirty = 1
                     72: #define        sbdirty()       sblk.b_dirty = 1
                     73: #define        cgdirty()       cgblk.b_dirty = 1
                     74: 
                     75: #define        dirblk          fileblk.b_un
                     76: #define        sblock          sblk.b_un.b_fs
                     77: #define        cgrp            cgblk.b_un.b_cg
                     78: 
                     79: struct filecntl {
                     80:        int     rfdes;
                     81:        int     wfdes;
                     82:        int     mod;
                     83: } dfile;                       /* file descriptors for filesys */
                     84: 
                     85: struct inodesc {
                     86:        char id_type;           /* type of descriptor, DATA or ADDR */
                     87:        int (*id_func)();       /* function to be applied to blocks of inode */
                     88:        ino_t id_number;        /* inode number described */
                     89:        ino_t id_parent;        /* for DATA nodes, their parent */
                     90:        daddr_t id_blkno;       /* current block number being examined */
                     91:        int id_numfrags;        /* number of frags contained in block */
                     92:        long id_filesize;       /* for DATA nodes, the size of the directory */
                     93:        int id_loc;             /* for DATA nodes, current location in dir */
                     94:        int id_entryno;         /* for DATA nodes, current entry number */
                     95:        DIRECT *id_dirp;        /* for data nodes, ptr to current entry */
                     96:        enum {DONTKNOW, NOFIX, FIX} id_fix; /* policy on fixing errors */
                     97: };
                     98: /* file types */
                     99: #define        DATA    1
                    100: #define        ADDR    2
                    101: 
                    102: 
                    103: #define        DUPTBLSIZE      100     /* num of dup blocks to remember */
                    104: daddr_t        duplist[DUPTBLSIZE];    /* dup block table */
                    105: daddr_t        *enddup;                /* next entry in dup table */
                    106: daddr_t        *muldup;                /* multiple dups part of table */
                    107: 
                    108: #define        MAXLNCNT        500     /* num zero link cnts to remember */
                    109: ino_t  badlncnt[MAXLNCNT];     /* table of inos with zero link cnts */
                    110: ino_t  *badlnp;                /* next entry in table */
                    111: 
                    112: char   rawflg;
                    113: char   nflag;                  /* assume a no response */
                    114: char   yflag;                  /* assume a yes response */
                    115: int    bflag;                  /* location of alternate super block */
                    116: int    debug;                  /* output debugging info */
                    117: char   preen;                  /* just fix normal inconsistencies */
                    118: char   rplyflag;               /* any questions asked? */
                    119: char   hotroot;                /* checking root device */
                    120: char   fixcg;                  /* corrupted free list bit maps */
                    121: 
                    122: char   *blockmap;              /* ptr to primary blk allocation map */
                    123: char   *freemap;               /* ptr to secondary blk allocation map */
                    124: char   *statemap;              /* ptr to inode state table */
                    125: short  *lncntp;                /* ptr to link count table */
                    126: 
                    127: char   *srchname;              /* name being searched for in dir */
                    128: char   pathname[BUFSIZ];       /* current pathname */
                    129: char   *pathp;                 /* pointer to pathname position */
                    130: char   *endpathname = &pathname[BUFSIZ - 2];
                    131: 
                    132: char   *lfname = "lost+found";
                    133: 
                    134: ino_t  imax;                   /* number of inodes */
                    135: ino_t  lastino;                /* hiwater mark of inodes */
                    136: ino_t  lfdir;                  /* lost & found directory */
                    137: 
                    138: off_t  maxblk;                 /* largest logical blk in file */
                    139: off_t  bmapsz;                 /* num chars in blockmap */
                    140: 
                    141: daddr_t        n_ffree;                /* number of small free blocks */
                    142: daddr_t        n_bfree;                /* number of large free blocks */
                    143: daddr_t        n_blks;                 /* number of blocks used */
                    144: daddr_t        n_files;                /* number of files seen */
                    145: daddr_t        n_index;
                    146: daddr_t        n_bad;
                    147: daddr_t        fmax;                   /* number of blocks in the volume */
                    148: 
                    149: daddr_t        badblk;
                    150: daddr_t        dupblk;
                    151: 
                    152: int    inosumbad;
                    153: int    offsumbad;
                    154: int    frsumbad;
                    155: int    sbsumbad;
                    156: 
                    157: #define        zapino(x)       (*(x) = zino)
                    158: struct dinode zino;
                    159: 
                    160: #define        setbmap(x)      setbit(blockmap, x)
                    161: #define        getbmap(x)      isset(blockmap, x)
                    162: #define        clrbmap(x)      clrbit(blockmap, x)
                    163: 
                    164: #define        setfmap(x)      setbit(freemap, x)
                    165: #define        getfmap(x)      isset(freemap, x)
                    166: #define        clrfmap(x)      clrbit(freemap, x)
                    167: 
                    168: #define        ALTERED 010
                    169: #define        KEEPON  04
                    170: #define        SKIP    02
                    171: #define        STOP    01
                    172: 
                    173: int    (*signal())();
                    174: long   lseek();
                    175: time_t time();
                    176: DINODE *ginode();
                    177: DIRECT *fsck_readdir();
                    178: BUFAREA        *getblk();
                    179: int    catch();
                    180: int    findino(), mkentry(), chgdd();
                    181: int    pass1check(), pass1bcheck(), pass2check(), pass4check();
                    182: char   *rawname(), *unrawname();
                    183: char   *calloc(), *strcpy(), *strcat(), *rindex();
                    184: extern int inside[], around[];
                    185: extern unsigned char *fragtbl[];
                    186: 
                    187: char   *devname;
                    188: 
                    189: main(argc, argv)
                    190:        int     argc;
                    191:        char    *argv[];
                    192: {
                    193:        struct fstab *fsp;
                    194:        int pid, passno, anygtr, sumstatus;
                    195: 
                    196:        sync();
                    197:        while (--argc > 0 && **++argv == '-') {
                    198:                switch (*++*argv) {
                    199: 
                    200:                case 'p':
                    201:                        preen++;
                    202:                        break;
                    203: 
                    204:                case 'b':
                    205:                        if (argv[0][1] != '\0') {
                    206:                                bflag = atoi(argv[0]+1);
                    207:                        } else {
                    208:                                bflag = atoi(*++argv);
                    209:                                argc--;
                    210:                        }
                    211:                        printf("Alternate super block location: %d\n", bflag);
                    212:                        break;
                    213: 
                    214:                case 'd':
                    215:                        debug++;
                    216:                        break;
                    217: 
                    218:                case 'n':       /* default no answer flag */
                    219:                case 'N':
                    220:                        nflag++;
                    221:                        yflag = 0;
                    222:                        break;
                    223: 
                    224:                case 'y':       /* default yes answer flag */
                    225:                case 'Y':
                    226:                        yflag++;
                    227:                        nflag = 0;
                    228:                        break;
                    229: 
                    230:                default:
                    231:                        errexit("%c option?\n", **argv);
                    232:                }
                    233:        }
                    234:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                    235:                (void)signal(SIGINT, catch);
                    236:        if (argc) {
                    237:                while (argc-- > 0) {
                    238:                        hotroot = 0;
                    239:                        checkfilesys(*argv++);
                    240:                }
                    241:                exit(0);
                    242:        }
                    243:        sumstatus = 0;
                    244:        passno = 1;
                    245:        do {
                    246:                anygtr = 0;
                    247:                if (setfsent() == 0)
                    248:                        errexit("Can't open checklist file: %s\n", FSTAB);
                    249:                while ((fsp = getfsent()) != 0) {
                    250:                        if (strcmp(fsp->fs_type, FSTAB_RW) &&
                    251:                            strcmp(fsp->fs_type, FSTAB_RO) &&
                    252:                            strcmp(fsp->fs_type, FSTAB_RQ))
                    253:                                continue;
                    254:                        if (preen == 0 ||
                    255:                            passno == 1 && fsp->fs_passno == passno) {
                    256:                                if (blockcheck(fsp->fs_spec) == 0 && preen)
                    257:                                        exit(8);
                    258:                        } else if (fsp->fs_passno > passno)
                    259:                                anygtr = 1;
                    260:                        else if (fsp->fs_passno == passno) {
                    261:                                pid = fork();
                    262:                                if (pid < 0) {
                    263:                                        perror("fork");
                    264:                                        exit(8);
                    265:                                }
                    266:                                if (pid == 0)
                    267:                                        if (blockcheck(fsp->fs_spec)==0)
                    268:                                                exit(8);
                    269:                                        else
                    270:                                                exit(0);
                    271:                        }
                    272:                }
                    273:                if (preen) {
                    274:                        union wait status;
                    275:                        while (wait(&status) != -1)
                    276:                                sumstatus |= status.w_retcode;
                    277:                }
                    278:                passno++;
                    279:        } while (anygtr);
                    280:        if (sumstatus)
                    281:                exit(8);
                    282:        (void)endfsent();
                    283:        exit(0);
                    284: }
                    285: 
                    286: blockcheck(name)
                    287:        char *name;
                    288: {
                    289:        struct stat stslash, stblock, stchar;
                    290:        char *raw;
                    291:        int looped = 0;
                    292: 
                    293:        hotroot = 0;
                    294:        if (stat("/", &stslash) < 0){
                    295:                error("Can't stat root\n");
                    296:                return (0);
                    297:        }
                    298: retry:
                    299:        if (stat(name, &stblock) < 0){
                    300:                error("Can't stat %s\n", name);
                    301:                return (0);
                    302:        }
                    303:        if (stblock.st_mode & S_IFBLK) {
                    304:                raw = rawname(name);
                    305:                if (stat(raw, &stchar) < 0){
                    306:                        error("Can't stat %s\n", raw);
                    307:                        return (0);
                    308:                }
                    309:                if (stchar.st_mode & S_IFCHR) {
                    310:                        if (stslash.st_dev == stblock.st_rdev) {
                    311:                                hotroot++;
                    312:                                raw = unrawname(name);
                    313:                        }
                    314:                        checkfilesys(raw);
                    315:                        return (1);
                    316:                } else {
                    317:                        error("%s is not a character device\n", raw);
                    318:                        return (0);
                    319:                }
                    320:        } else if (stblock.st_mode & S_IFCHR) {
                    321:                if (looped) {
                    322:                        error("Can't make sense out of name %s\n", name);
                    323:                        return (0);
                    324:                }
                    325:                name = unrawname(name);
                    326:                looped++;
                    327:                goto retry;
                    328:        }
                    329:        error("Can't make sense out of name %s\n", name);
                    330:        return (0);
                    331: }
                    332: 
                    333: checkfilesys(filesys)
                    334:        char *filesys;
                    335: {
                    336: 
                    337:        devname = filesys;
                    338:        if (setup(filesys) == 0) {
                    339:                if (preen)
                    340:                        pfatal("CAN'T CHECK FILE SYSTEM.");
                    341:                return;
                    342:        }
                    343: /* 1: scan inodes tallying blocks used */
                    344:        if (preen == 0) {
                    345:                printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
                    346:                if (hotroot)
                    347:                        printf("** Root file system\n");
                    348:                printf("** Phase 1 - Check Blocks and Sizes\n");
                    349:        }
                    350:        pass1();
                    351: 
                    352: /* 1b: locate first references to duplicates, if any */
                    353:        if (enddup != &duplist[0]) {
                    354:                if (preen)
                    355:                        pfatal("INTERNAL ERROR: dups with -p");
                    356:                printf("** Phase 1b - Rescan For More DUPS\n");
                    357:                pass1b();
                    358:        }
                    359: 
                    360: /* 2: traverse directories from root to mark all connected directories */
                    361:        if (preen == 0)
                    362:                printf("** Phase 2 - Check Pathnames\n");
                    363:        pass2();
                    364: 
                    365: /* 3: scan inodes looking for disconnected directories */
                    366:        if (preen == 0)
                    367:                printf("** Phase 3 - Check Connectivity\n");
                    368:        pass3();
                    369: 
                    370: /* 4: scan inodes looking for disconnected files; check reference counts */
                    371:        if (preen == 0)
                    372:                printf("** Phase 4 - Check Reference Counts\n");
                    373:        pass4();
                    374: 
                    375: /* 5: check resource counts in cylinder groups */
                    376:        if (preen == 0)
                    377:                printf("** Phase 5 - Check Cyl groups\n");
                    378:        pass5();
                    379: 
                    380:        if (fixcg) {
                    381:                if (preen == 0)
                    382:                        printf("** Phase 6 - Salvage Cylinder Groups\n");
                    383:                makecg();
                    384:                n_ffree = sblock.fs_cstotal.cs_nffree;
                    385:                n_bfree = sblock.fs_cstotal.cs_nbfree;
                    386:        }
                    387: 
                    388:        pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n",
                    389:            n_files, n_blks - howmany(sblock.fs_cssize, sblock.fs_fsize),
                    390:            n_ffree + sblock.fs_frag * n_bfree, n_ffree, n_bfree);
                    391:        if (dfile.mod) {
                    392:                (void)time(&sblock.fs_time);
                    393:                sbdirty();
                    394:        }
                    395:        ckfini();
                    396:        free(blockmap);
                    397:        free(freemap);
                    398:        free(statemap);
                    399:        free((char *)lncntp);
                    400:        if (!dfile.mod)
                    401:                return;
                    402:        if (!preen) {
                    403:                printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
                    404:                if (hotroot)
                    405:                        printf("\n***** REBOOT UNIX *****\n");
                    406:        }
                    407:        if (hotroot) {
                    408:                sync();
                    409:                exit(4);
                    410:        }
                    411: }
                    412: 
                    413: setup(dev)
                    414:        char *dev;
                    415: {
                    416:        dev_t rootdev;
                    417:        struct stat statb;
                    418:        daddr_t super = bflag ? bflag : SBLOCK;
                    419:        int i, j, c, d, cgd;
                    420:        long size;
                    421:        BUFAREA asblk;
                    422: #      define altsblock asblk.b_un.b_fs
                    423: 
                    424:        if (stat("/", &statb) < 0)
                    425:                errexit("Can't stat root\n");
                    426:        rootdev = statb.st_dev;
                    427:        if (stat(dev, &statb) < 0) {
                    428:                error("Can't stat %s\n", dev);
                    429:                return (0);
                    430:        }
                    431:        rawflg = 0;
                    432:        if ((statb.st_mode & S_IFMT) == S_IFBLK)
                    433:                ;
                    434:        else if ((statb.st_mode & S_IFMT) == S_IFCHR)
                    435:                rawflg++;
                    436:        else {
                    437:                if (reply("file is not a block or character device; OK") == 0)
                    438:                        return (0);
                    439:        }
                    440:        if (rootdev == statb.st_rdev)
                    441:                hotroot++;
                    442:        if ((dfile.rfdes = open(dev, 0)) < 0) {
                    443:                error("Can't open %s\n", dev);
                    444:                return (0);
                    445:        }
                    446:        if (preen == 0)
                    447:                printf("** %s", dev);
                    448:        if (nflag || (dfile.wfdes = open(dev, 1)) < 0) {
                    449:                dfile.wfdes = -1;
                    450:                if (preen)
                    451:                        pfatal("NO WRITE ACCESS");
                    452:                printf(" (NO WRITE)");
                    453:        }
                    454:        if (preen == 0)
                    455:                printf("\n");
                    456:        fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; sbsumbad = 0;
                    457:        dfile.mod = 0;
                    458:        n_files = n_blks = n_ffree = n_bfree = 0;
                    459:        muldup = enddup = &duplist[0];
                    460:        badlnp = &badlncnt[0];
                    461:        lfdir = 0;
                    462:        rplyflag = 0;
                    463:        initbarea(&sblk);
                    464:        initbarea(&fileblk);
                    465:        initbarea(&inoblk);
                    466:        initbarea(&cgblk);
                    467:        initbarea(&asblk);
                    468:        /*
                    469:         * Read in the super block and its summary info.
                    470:         */
                    471:        if (bread(&dfile, (char *)&sblock, super, (long)SBSIZE) == 0)
                    472:                return (0);
                    473:        sblk.b_bno = super;
                    474:        sblk.b_size = SBSIZE;
                    475:        /*
                    476:         * run a few consistency checks of the super block
                    477:         */
                    478:        if (sblock.fs_magic != FS_MAGIC)
                    479:                { badsb("MAGIC NUMBER WRONG"); return (0); }
                    480:        if (sblock.fs_ncg < 1)
                    481:                { badsb("NCG OUT OF RANGE"); return (0); }
                    482:        if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG)
                    483:                { badsb("CPG OUT OF RANGE"); return (0); }
                    484:        if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
                    485:            (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl)
                    486:                { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); }
                    487:        if (sblock.fs_sbsize > SBSIZE)
                    488:                { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); }
                    489:        /*
                    490:         * Set all possible fields that could differ, then do check
                    491:         * of whole super block against an alternate super block.
                    492:         * When an alternate super-block is specified this check is skipped.
                    493:         */
                    494:        if (bflag)
                    495:                goto sbok;
                    496:        if (getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1),
                    497:            sblock.fs_sbsize) == 0)
                    498:                return (0);
                    499:        altsblock.fs_link = sblock.fs_link;
                    500:        altsblock.fs_rlink = sblock.fs_rlink;
                    501:        altsblock.fs_time = sblock.fs_time;
                    502:        altsblock.fs_cstotal = sblock.fs_cstotal;
                    503:        altsblock.fs_cgrotor = sblock.fs_cgrotor;
                    504:        altsblock.fs_fmod = sblock.fs_fmod;
                    505:        altsblock.fs_clean = sblock.fs_clean;
                    506:        altsblock.fs_ronly = sblock.fs_ronly;
                    507:        altsblock.fs_flags = sblock.fs_flags;
                    508:        altsblock.fs_maxcontig = sblock.fs_maxcontig;
                    509:        altsblock.fs_minfree = sblock.fs_minfree;
                    510:        altsblock.fs_rotdelay = sblock.fs_rotdelay;
                    511:        altsblock.fs_maxbpg = sblock.fs_maxbpg;
                    512:        bcopy((char *)sblock.fs_csp, (char *)altsblock.fs_csp,
                    513:                sizeof sblock.fs_csp);
                    514:        bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt,
                    515:                sizeof sblock.fs_fsmnt);
                    516:        if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize))
                    517:                { badsb("TRASHED VALUES IN SUPER BLOCK"); return (0); }
                    518: sbok:
                    519:        fmax = sblock.fs_size;
                    520:        imax = sblock.fs_ncg * sblock.fs_ipg;
                    521:        n_bad = cgsblock(&sblock, 0); /* boot block plus dedicated sblock */
                    522:        /*
                    523:         * read in the summary info.
                    524:         */
                    525:        for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
                    526:                size = sblock.fs_cssize - i < sblock.fs_bsize ?
                    527:                    sblock.fs_cssize - i : sblock.fs_bsize;
                    528:                sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size);
                    529:                if (bread(&dfile, (char *)sblock.fs_csp[j],
                    530:                    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
                    531:                    size) == 0)
                    532:                        return (0);
                    533:        }
                    534:        /*
                    535:         * allocate and initialize the necessary maps
                    536:         */
                    537:        bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
                    538:        blockmap = calloc((unsigned)bmapsz, sizeof (char));
                    539:        if (blockmap == NULL) {
                    540:                printf("cannot alloc %d bytes for blockmap\n", bmapsz);
                    541:                goto badsb;
                    542:        }
                    543:        freemap = calloc((unsigned)bmapsz, sizeof (char));
                    544:        if (freemap == NULL) {
                    545:                printf("cannot alloc %d bytes for freemap\n", bmapsz);
                    546:                goto badsb;
                    547:        }
                    548:        statemap = calloc((unsigned)(imax + 1), sizeof(char));
                    549:        if (statemap == NULL) {
                    550:                printf("cannot alloc %d bytes for statemap\n", imax + 1);
                    551:                goto badsb;
                    552:        }
                    553:        lncntp = (short *)calloc((unsigned)(imax + 1), sizeof(short));
                    554:        if (lncntp == NULL) {
                    555:                printf("cannot alloc %d bytes for lncntp\n", 
                    556:                    (imax + 1) * sizeof(short));
                    557:                goto badsb;
                    558:        }
                    559:        for (c = 0; c < sblock.fs_ncg; c++) {
                    560:                cgd = cgdmin(&sblock, c);
                    561:                if (c == 0) {
                    562:                        d = cgbase(&sblock, c);
                    563:                        cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
                    564:                } else
                    565:                        d = cgsblock(&sblock, c);
                    566:                for (; d < cgd; d++)
                    567:                        setbmap(d);
                    568:        }
                    569: 
                    570:        return (1);
                    571: 
                    572: badsb:
                    573:        ckfini();
                    574:        return (0);
                    575: #      undef altsblock
                    576: }
                    577: 
                    578: pass1()
                    579: {
                    580:        register int c, i, n, j;
                    581:        register DINODE *dp;
                    582:        int ndb, partial;
                    583:        struct inodesc idesc;
                    584:        ino_t inumber;
                    585: 
                    586:        bzero((char *)&idesc, sizeof(struct inodesc));
                    587:        idesc.id_type = ADDR;
                    588:        idesc.id_func = pass1check;
                    589:        inumber = 0;
                    590:        n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
                    591:        for (c = 0; c < sblock.fs_ncg; c++) {
                    592:                if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
                    593:                        continue;
                    594:                if (cgrp.cg_magic != CG_MAGIC) {
                    595:                        pfatal("CG %d: BAD MAGIC NUMBER\n", c);
                    596:                        bzero((char *)&cgrp, (int)sblock.fs_cgsize);
                    597:                }
                    598:                n = 0;
                    599:                for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
                    600:                        dp = ginode(inumber);
                    601:                        if (dp == NULL)
                    602:                                continue;
                    603:                        n++;
                    604:                        if (ALLOC) {
                    605:                                if (!isset(cgrp.cg_iused, i)) {
                    606:                                        if (debug)
                    607:                                                printf("%d bad, not used\n",
                    608:                                                    inumber);
                    609:                                        inosumbad++;
                    610:                                }
                    611:                                n--;
                    612:                                lastino = inumber;
                    613:                                if (!preen && BADBLK &&
                    614:                                    reply("HOLD BAD BLOCK") == 1) {
                    615:                                        dp->di_size = sblock.fs_fsize;
                    616:                                        dp->di_mode = IFREG|0600;
                    617:                                        inodirty();
                    618:                                } else if (ftypeok(dp) == 0)
                    619:                                        goto unknown;
                    620:                                if (dp->di_size < 0) {
                    621:                                        if (debug)
                    622:                                                printf("bad size %d:",
                    623:                                                        dp->di_size);
                    624:                                        goto unknown;
                    625:                                }
                    626:                                ndb = howmany(dp->di_size, sblock.fs_bsize);
                    627:                                if (SPECIAL)
                    628:                                        ndb++;
                    629:                                for (j = ndb; j < NDADDR; j++)
                    630:                                        if (dp->di_db[j] != 0) {
                    631:                                                if (debug)
                    632:                                                        printf("bad direct addr: %d\n",
                    633:                                                                dp->di_db[j]);
                    634:                                                goto unknown;
                    635:                                        }
                    636:                                for (j = 0, ndb -= NDADDR; ndb > 0; j++)
                    637:                                        ndb /= NINDIR(&sblock);
                    638:                                for (; j < NIADDR; j++)
                    639:                                        if (dp->di_ib[j] != 0) {
                    640:                                                if (debug)
                    641:                                                        printf("bad indirect addr: %d\n",
                    642:                                                                dp->di_ib[j]);
                    643:                                                goto unknown;
                    644:                                        }
                    645:                                n_files++;
                    646:                                lncntp[inumber] = dp->di_nlink;
                    647:                                if (dp->di_nlink <= 0) {
                    648:                                        if (badlnp < &badlncnt[MAXLNCNT])
                    649:                                                *badlnp++ = inumber;
                    650:                                        else {
                    651:                                                pfatal("LINK COUNT TABLE OVERFLOW");
                    652:                                                if (reply("CONTINUE") == 0)
                    653:                                                        errexit("");
                    654:                                        }
                    655:                                }
                    656:                                statemap[inumber] = DIRCT ? DSTATE : FSTATE;
                    657:                                badblk = dupblk = 0; maxblk = 0;
                    658:                                idesc.id_number = inumber;
                    659:                                idesc.id_filesize = 0;
                    660:                                (void)ckinode(dp, &idesc);
                    661:                                idesc.id_filesize *= btodb(sblock.fs_fsize);
                    662:                                if (dp->di_blocks != idesc.id_filesize) {
                    663:                                        pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
                    664:                                            inumber, dp->di_blocks,
                    665:                                            idesc.id_filesize);
                    666:                                        if (preen)
                    667:                                                printf(" (CORRECTED)\n");
                    668:                                        else if (reply("CORRECT") == 0)
                    669:                                                continue;
                    670:                                        dp->di_blocks = idesc.id_filesize;
                    671:                                        inodirty();
                    672:                                }
                    673:                                continue;
                    674:                unknown:
                    675:                                pfatal("UNKNOWN FILE TYPE I=%u", inumber);
                    676:                                if (reply("CLEAR") == 1) {
                    677:                                        zapino(dp);
                    678:                                        inodirty();
                    679:                                        inosumbad++;
                    680:                                }
                    681:                        } else {
                    682:                                if (isset(cgrp.cg_iused, i)) {
                    683:                                        if (debug)
                    684:                                                printf("%d bad, marked used\n",
                    685:                                                    inumber);
                    686:                                        inosumbad++;
                    687:                                        n--;
                    688:                                }
                    689:                                partial = 0;
                    690:                                for (j = 0; j < NDADDR; j++)
                    691:                                        if (dp->di_db[j] != 0)
                    692:                                                partial++;
                    693:                                for (j = 0; j < NIADDR; j++)
                    694:                                        if (dp->di_ib[j] != 0)
                    695:                                                partial++;
                    696:                                if (partial || dp->di_mode != 0 ||
                    697:                                    dp->di_size != 0) {
                    698:                                        pfatal("PARTIALLY ALLOCATED INODE I=%u",
                    699:                                                inumber);
                    700:                                        if (reply("CLEAR") == 1) {
                    701:                                                zapino(dp);
                    702:                                                inodirty();
                    703:                                                inosumbad++;
                    704:                                        }
                    705:                                }
                    706:                        }
                    707:                }
                    708:                if (n != cgrp.cg_cs.cs_nifree) {
                    709:                        if (debug)
                    710:                                printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n",
                    711:                                    c, cgrp.cg_cs.cs_nifree, n);
                    712:                        inosumbad++;
                    713:                }
                    714:                if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree
                    715:                  || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree
                    716:                  || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree
                    717:                  || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir)
                    718:                        sbsumbad++;
                    719:        }
                    720: }
                    721: 
                    722: pass1check(idesc)
                    723:        register struct inodesc *idesc;
                    724: {
                    725:        register daddr_t *dlp;
                    726:        int res = KEEPON;
                    727:        int anyout, nfrags;
                    728:        daddr_t blkno = idesc->id_blkno;
                    729: 
                    730:        anyout = outrange(blkno, idesc->id_numfrags);
                    731:        for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
                    732:                if (anyout && outrange(blkno, 1)) {
                    733:                        blkerr(idesc->id_number, "BAD", blkno);
                    734:                        if (++badblk >= MAXBAD) {
                    735:                                pwarn("EXCESSIVE BAD BLKS I=%u",
                    736:                                        idesc->id_number);
                    737:                                if (preen)
                    738:                                        printf(" (SKIPPING)\n");
                    739:                                else if (reply("CONTINUE") == 0)
                    740:                                        errexit("");
                    741:                                return (STOP);
                    742:                        }
                    743:                        res = SKIP;
                    744:                } else if (getbmap(blkno)) {
                    745:                        blkerr(idesc->id_number, "DUP", blkno);
                    746:                        if (++dupblk >= MAXDUP) {
                    747:                                pwarn("EXCESSIVE DUP BLKS I=%u",
                    748:                                        idesc->id_number);
                    749:                                if (preen)
                    750:                                        printf(" (SKIPPING)\n");
                    751:                                else if (reply("CONTINUE") == 0)
                    752:                                        errexit("");
                    753:                                return (STOP);
                    754:                        }
                    755:                        if (enddup >= &duplist[DUPTBLSIZE]) {
                    756:                                pfatal("DUP TABLE OVERFLOW.");
                    757:                                if (reply("CONTINUE") == 0)
                    758:                                        errexit("");
                    759:                                return (STOP);
                    760:                        }
                    761:                        for (dlp = duplist; dlp < muldup; dlp++)
                    762:                                if (*dlp == blkno) {
                    763:                                        *enddup++ = blkno;
                    764:                                        break;
                    765:                                }
                    766:                        if (dlp >= muldup) {
                    767:                                *enddup++ = *muldup;
                    768:                                *muldup++ = blkno;
                    769:                        }
                    770:                } else {
                    771:                        n_blks++;
                    772:                        setbmap(blkno);
                    773:                }
                    774:                idesc->id_filesize++;
                    775:        }
                    776:        return (res);
                    777: }
                    778: 
                    779: pass1b()
                    780: {
                    781:        register int c, i;
                    782:        register DINODE *dp;
                    783:        struct inodesc idesc;
                    784:        ino_t inumber;
                    785: 
                    786:        bzero((char *)&idesc, sizeof(struct inodesc));
                    787:        idesc.id_type = ADDR;
                    788:        idesc.id_func = pass1bcheck;
                    789:        inumber = 0;
                    790:        for (c = 0; c < sblock.fs_ncg; c++) {
                    791:                for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
                    792:                        dp = ginode(inumber);
                    793:                        if (dp == NULL)
                    794:                                continue;
                    795:                        idesc.id_number = inumber;
                    796:                        if (statemap[inumber] != USTATE &&
                    797:                            (ckinode(dp, &idesc) & STOP))
                    798:                                goto out1b;
                    799:                }
                    800:        }
                    801: out1b:
                    802:        flush(&dfile, &inoblk);
                    803: }
                    804: 
                    805: pass1bcheck(idesc)
                    806:        register struct inodesc *idesc;
                    807: {
                    808:        register daddr_t *dlp;
                    809:        int nfrags, res = KEEPON;
                    810:        daddr_t blkno = idesc->id_blkno;
                    811: 
                    812:        for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
                    813:                if (outrange(blkno, 1))
                    814:                        res = SKIP;
                    815:                for (dlp = duplist; dlp < muldup; dlp++)
                    816:                        if (*dlp == blkno) {
                    817:                                blkerr(idesc->id_number, "DUP", blkno);
                    818:                                *dlp = *--muldup;
                    819:                                *muldup = blkno;
                    820:                                if (muldup == duplist)
                    821:                                        return (STOP);
                    822:                        }
                    823:        }
                    824:        return (res);
                    825: }
                    826: 
                    827: pass2()
                    828: {
                    829:        register DINODE *dp;
                    830:        struct inodesc rootdesc;
                    831: 
                    832:        bzero((char *)&rootdesc, sizeof(struct inodesc));
                    833:        rootdesc.id_type = ADDR;
                    834:        rootdesc.id_func = pass2check;
                    835:        rootdesc.id_number = ROOTINO;
                    836:        pathp = pathname;
                    837:        switch (statemap[ROOTINO]) {
                    838: 
                    839:        case USTATE:
                    840:                errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
                    841: 
                    842:        case FSTATE:
                    843:                pfatal("ROOT INODE NOT DIRECTORY");
                    844:                if (reply("FIX") == 0 || (dp = ginode(ROOTINO)) == NULL)
                    845:                        errexit("");
                    846:                dp->di_mode &= ~IFMT;
                    847:                dp->di_mode |= IFDIR;
                    848:                inodirty();
                    849:                inosumbad++;
                    850:                statemap[ROOTINO] = DSTATE;
                    851:                /* fall into ... */
                    852: 
                    853:        case DSTATE:
                    854:                descend(&rootdesc, ROOTINO);
                    855:                break;
                    856: 
                    857:        case CLEAR:
                    858:                pfatal("DUPS/BAD IN ROOT INODE");
                    859:                printf("\n");
                    860:                if (reply("CONTINUE") == 0)
                    861:                        errexit("");
                    862:                statemap[ROOTINO] = DSTATE;
                    863:                descend(&rootdesc, ROOTINO);
                    864:        }
                    865: }
                    866: 
                    867: pass2check(idesc)
                    868:        struct inodesc *idesc;
                    869: {
                    870:        register DIRECT *dirp = idesc->id_dirp;
                    871:        char *curpathloc;
                    872:        int n, entrysize, ret = 0;
                    873:        DINODE *dp;
                    874:        DIRECT proto;
                    875: 
                    876:        /* 
                    877:         * check for "."
                    878:         */
                    879:        if (idesc->id_entryno != 0)
                    880:                goto chk1;
                    881:        if (dirp->d_ino != 0 && dirp->d_namlen == 1 && dirp->d_name[0] == '.') {
                    882:                if (dirp->d_ino != idesc->id_number) {
                    883:                        direrr(idesc->id_number, "BAD INODE NUMBER FOR '.'");
                    884:                        dirp->d_ino = idesc->id_number;
                    885:                        if (reply("FIX") == 1)
                    886:                                ret |= ALTERED;
                    887:                }
                    888:                goto chk1;
                    889:        }
                    890:        direrr(idesc->id_number, "MISSING '.'");
                    891:        proto.d_ino = idesc->id_number;
                    892:        proto.d_namlen = 1;
                    893:        (void)strcpy(proto.d_name, ".");
                    894:        entrysize = DIRSIZ(&proto);
                    895:        if (dirp->d_ino != 0) {
                    896:                pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
                    897:                        dirp->d_name);
                    898:        } else if (dirp->d_reclen < entrysize) {
                    899:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
                    900:        } else if (dirp->d_reclen < 2 * entrysize) {
                    901:                proto.d_reclen = dirp->d_reclen;
                    902:                bcopy((char *)&proto, (char *)dirp, entrysize);
                    903:                if (reply("FIX") == 1)
                    904:                        ret |= ALTERED;
                    905:        } else {
                    906:                n = dirp->d_reclen - entrysize;
                    907:                proto.d_reclen = entrysize;
                    908:                bcopy((char *)&proto, (char *)dirp, entrysize);
                    909:                idesc->id_entryno++;
                    910:                lncntp[dirp->d_ino]--;
                    911:                dirp = (DIRECT *)((char *)(dirp) + entrysize);
                    912:                bzero((char *)dirp, n);
                    913:                dirp->d_reclen = n;
                    914:                if (reply("FIX") == 1)
                    915:                        ret |= ALTERED;
                    916:        }
                    917: chk1:
                    918:        if (idesc->id_entryno > 1)
                    919:                goto chk2;
                    920:        proto.d_ino = idesc->id_parent;
                    921:        proto.d_namlen = 2;
                    922:        (void)strcpy(proto.d_name, "..");
                    923:        entrysize = DIRSIZ(&proto);
                    924:        if (idesc->id_entryno == 0) {
                    925:                n = DIRSIZ(dirp);
                    926:                if (dirp->d_reclen < n + entrysize)
                    927:                        goto chk2;
                    928:                proto.d_reclen = dirp->d_reclen - n;
                    929:                dirp->d_reclen = n;
                    930:                idesc->id_entryno++;
                    931:                lncntp[dirp->d_ino]--;
                    932:                dirp = (DIRECT *)((char *)(dirp) + n);
                    933:                bzero((char *)dirp, n);
                    934:                dirp->d_reclen = n;
                    935:        }
                    936:        if (dirp->d_ino != 0 && dirp->d_namlen == 2 &&
                    937:            strcmp(dirp->d_name, "..") == 0) {
                    938:                if (dirp->d_ino != idesc->id_parent) {
                    939:                        direrr(idesc->id_number, "BAD INODE NUMBER FOR '..'");
                    940:                        dirp->d_ino = idesc->id_parent;
                    941:                        if (reply("FIX") == 1)
                    942:                                ret |= ALTERED;
                    943:                }
                    944:                goto chk2;
                    945:        }
                    946:        direrr(idesc->id_number, "MISSING '..'");
                    947:        if (dirp->d_ino != 0) {
                    948:                pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
                    949:                        dirp->d_name);
                    950:        } else if (dirp->d_reclen < entrysize) {
                    951:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
                    952:        } else {
                    953:                proto.d_reclen = dirp->d_reclen;
                    954:                bcopy((char *)&proto, (char *)dirp, entrysize);
                    955:                if (reply("FIX") == 1)
                    956:                        ret |= ALTERED;
                    957:        }
                    958: chk2:
                    959:        if (dirp->d_ino == 0)
                    960:                return (ret|KEEPON);
                    961:        if (idesc->id_entryno >= 2 &&
                    962:            dirp->d_namlen <= 2 &&
                    963:            dirp->d_name[0] == '.') {
                    964:                if (dirp->d_namlen == 1) {
                    965:                        direrr(idesc->id_number, "EXTRA '.' ENTRY");
                    966:                        dirp->d_ino = 0;
                    967:                        if (reply("FIX") == 1)
                    968:                                ret |= ALTERED;
                    969:                        return (KEEPON | ret);
                    970:                }
                    971:                if (dirp->d_name[1] == '.') {
                    972:                        direrr(idesc->id_number, "EXTRA '..' ENTRY");
                    973:                        dirp->d_ino = 0;
                    974:                        if (reply("FIX") == 1)
                    975:                                ret |= ALTERED;
                    976:                        return (KEEPON | ret);
                    977:                }
                    978:        }
                    979:        curpathloc = pathp;
                    980:        *pathp++ = '/';
                    981:        if (pathp + dirp->d_namlen >= endpathname) {
                    982:                *pathp = '\0';
                    983:                errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
                    984:        }
                    985:        bcopy(dirp->d_name, pathp, dirp->d_namlen + 1);
                    986:        pathp += dirp->d_namlen;
                    987:        idesc->id_entryno++;
                    988:        n = 0;
                    989:        if (dirp->d_ino > imax || dirp->d_ino <= 0) {
                    990:                direrr(dirp->d_ino, "I OUT OF RANGE");
                    991:                n = reply("REMOVE");
                    992:        } else {
                    993: again:
                    994:                switch (statemap[dirp->d_ino]) {
                    995:                case USTATE:
                    996:                        direrr(dirp->d_ino, "UNALLOCATED");
                    997:                        n = reply("REMOVE");
                    998:                        break;
                    999: 
                   1000:                case CLEAR:
                   1001:                        direrr(dirp->d_ino, "DUP/BAD");
                   1002:                        if ((n = reply("REMOVE")) == 1)
                   1003:                                break;
                   1004:                        if ((dp = ginode(dirp->d_ino)) == NULL)
                   1005:                                break;
                   1006:                        statemap[dirp->d_ino] = DIRCT ? DSTATE : FSTATE;
                   1007:                        goto again;
                   1008: 
                   1009:                case FSTATE:
                   1010:                        lncntp[dirp->d_ino]--;
                   1011:                        break;
                   1012: 
                   1013:                case DSTATE:
                   1014:                        descend(idesc, dirp->d_ino);
                   1015:                        if (statemap[dirp->d_ino] != CLEAR) {
                   1016:                                lncntp[dirp->d_ino]--;
                   1017:                        } else {
                   1018:                                dirp->d_ino = 0;
                   1019:                                ret |= ALTERED;
                   1020:                        }
                   1021:                        break;
                   1022:                }
                   1023:        }
                   1024:        pathp = curpathloc;
                   1025:        *pathp = '\0';
                   1026:        if (n == 0)
                   1027:                return (ret|KEEPON);
                   1028:        dirp->d_ino = 0;
                   1029:        return (ret|KEEPON|ALTERED);
                   1030: }
                   1031: 
                   1032: pass3()
                   1033: {
                   1034:        register DINODE *dp;
                   1035:        struct inodesc idesc;
                   1036:        ino_t inumber, orphan;
                   1037:        int loopcnt;
                   1038: 
                   1039:        bzero((char *)&idesc, sizeof(struct inodesc));
                   1040:        idesc.id_type = DATA;
                   1041:        for (inumber = ROOTINO; inumber <= lastino; inumber++) {
                   1042:                if (statemap[inumber] == DSTATE) {
                   1043:                        pathp = pathname;
                   1044:                        *pathp++ = '?';
                   1045:                        *pathp = '\0';
                   1046:                        idesc.id_func = findino;
                   1047:                        srchname = "..";
                   1048:                        idesc.id_parent = inumber;
                   1049:                        loopcnt = 0;
                   1050:                        do {
                   1051:                                orphan = idesc.id_parent;
                   1052:                                if ((dp = ginode(orphan)) == NULL)
                   1053:                                        break;
                   1054:                                idesc.id_parent = 0;
                   1055:                                idesc.id_filesize = dp->di_size;
                   1056:                                idesc.id_number = orphan;
                   1057:                                (void)ckinode(dp, &idesc);
                   1058:                                if (idesc.id_parent == 0)
                   1059:                                        break;
                   1060:                                if (loopcnt >= sblock.fs_cstotal.cs_ndir)
                   1061:                                        break;
                   1062:                                loopcnt++;
                   1063:                        } while (statemap[idesc.id_parent] == DSTATE);
                   1064:                        if (linkup(orphan, idesc.id_parent) == 1) {
                   1065:                                idesc.id_func = pass2check;
                   1066:                                idesc.id_number = lfdir;
                   1067:                                descend(&idesc, orphan);
                   1068:                        }
                   1069:                }
                   1070:        }
                   1071: }
                   1072: 
                   1073: pass4()
                   1074: {
                   1075:        register ino_t inumber, *blp;
                   1076:        int n;
                   1077:        struct inodesc idesc;
                   1078: 
                   1079:        bzero((char *)&idesc, sizeof(struct inodesc));
                   1080:        idesc.id_type = ADDR;
                   1081:        idesc.id_func = pass4check;
                   1082:        for (inumber = ROOTINO; inumber <= lastino; inumber++) {
                   1083:                idesc.id_number = inumber;
                   1084:                switch (statemap[inumber]) {
                   1085: 
                   1086:                case FSTATE:
                   1087:                        n = lncntp[inumber];
                   1088:                        if (n)
                   1089:                                adjust(&idesc, (short)n);
                   1090:                        else {
                   1091:                                for (blp = badlncnt;blp < badlnp; blp++)
                   1092:                                        if (*blp == inumber) {
                   1093:                                                clri(&idesc, "UNREF", 1);
                   1094:                                                break;
                   1095:                                        }
                   1096:                        }
                   1097:                        break;
                   1098: 
                   1099:                case DSTATE:
                   1100:                        clri(&idesc, "UNREF", 1);
                   1101:                        break;
                   1102: 
                   1103:                case CLEAR:
                   1104:                        clri(&idesc, "BAD/DUP", 1);
                   1105:                        break;
                   1106:                }
                   1107:        }
                   1108:        if (imax - ROOTINO - n_files != sblock.fs_cstotal.cs_nifree) {
                   1109:                pwarn("FREE INODE COUNT WRONG IN SUPERBLK");
                   1110:                if (preen)
                   1111:                        printf(" (FIXED)\n");
                   1112:                if (preen || reply("FIX") == 1) {
                   1113:                        sblock.fs_cstotal.cs_nifree = imax - ROOTINO - n_files;
                   1114:                        sbdirty();
                   1115:                }
                   1116:        }
                   1117:        flush(&dfile, &fileblk);
                   1118: }
                   1119: 
                   1120: pass4check(idesc)
                   1121:        register struct inodesc *idesc;
                   1122: {
                   1123:        register daddr_t *dlp;
                   1124:        int nfrags, res = KEEPON;
                   1125:        daddr_t blkno = idesc->id_blkno;
                   1126: 
                   1127:        for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
                   1128:                if (outrange(blkno, 1))
                   1129:                        res = SKIP;
                   1130:                else if (getbmap(blkno)) {
                   1131:                        for (dlp = duplist; dlp < enddup; dlp++)
                   1132:                                if (*dlp == blkno) {
                   1133:                                        *dlp = *--enddup;
                   1134:                                        return (KEEPON);
                   1135:                                }
                   1136:                        clrbmap(blkno);
                   1137:                        n_blks--;
                   1138:                }
                   1139:        }
                   1140:        return (res);
                   1141: }
                   1142: 
                   1143: pass5()
                   1144: {
                   1145:        register int c, n, i, b, d;
                   1146:        short bo[MAXCPG][NRPOS];
                   1147:        long botot[MAXCPG];
                   1148:        long frsum[MAXFRAG];
                   1149:        int blk;
                   1150:        daddr_t cbase;
                   1151:        int blockbits = (1<<sblock.fs_frag)-1;
                   1152: 
                   1153:        bcopy(blockmap, freemap, (unsigned)bmapsz);
                   1154:        dupblk = 0;
                   1155:        n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0));
                   1156:        for (c = 0; c < sblock.fs_ncg; c++) {
                   1157:                cbase = cgbase(&sblock, c);
                   1158:                bzero((char *)botot, sizeof (botot));
                   1159:                bzero((char *)bo, sizeof (bo));
                   1160:                bzero((char *)frsum, sizeof (frsum));
                   1161:                /*
                   1162:                 * need to account for the super blocks
                   1163:                 * which appear (inaccurately) bad
                   1164:                 */
                   1165:                n_bad += cgtod(&sblock, c) - cgsblock(&sblock, c);
                   1166:                if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
                   1167:                        continue;
                   1168:                if (cgrp.cg_magic != CG_MAGIC) {
                   1169:                        pfatal("CG %d: BAD MAGIC NUMBER\n", c);
                   1170:                        bzero((char *)&cgrp, (int)sblock.fs_cgsize);
                   1171:                }
                   1172:                for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
                   1173:                        blk = blkmap(&sblock, cgrp.cg_free, b);
                   1174:                        if (blk == 0)
                   1175:                                continue;
                   1176:                        if (blk == blockbits) {
                   1177:                                if (pass5check(cbase+b, sblock.fs_frag) == STOP)
                   1178:                                        goto out5;
                   1179:                                /* this is clumsy ... */
                   1180:                                n_ffree -= sblock.fs_frag;
                   1181:                                n_bfree++;
                   1182:                                botot[cbtocylno(&sblock, b)]++;
                   1183:                                bo[cbtocylno(&sblock, b)]
                   1184:                                    [cbtorpos(&sblock, b)]++;
                   1185:                                continue;
                   1186:                        }
                   1187:                        for (d = 0; d < sblock.fs_frag; d++)
                   1188:                                if ((blk & (1<<d)) &&
                   1189:                                    pass5check(cbase + b + d, (long)1) == STOP)
                   1190:                                        goto out5;
                   1191:                        fragacct(&sblock, blk, frsum, 1);
                   1192:                }
                   1193:                if (bcmp((char *)cgrp.cg_frsum, (char *)frsum, sizeof(frsum))) {
                   1194:                        if (debug)
                   1195:                        for (i = 0; i < sblock.fs_frag; i++)
                   1196:                                if (cgrp.cg_frsum[i] != frsum[i])
                   1197:                                printf("cg[%d].cg_frsum[%d] have %d calc %d\n",
                   1198:                                    c, i, cgrp.cg_frsum[i], frsum[i]);
                   1199:                        frsumbad++;
                   1200:                }
                   1201:                if (bcmp((char *)cgrp.cg_btot, (char *)botot, sizeof (botot))) {
                   1202:                        if (debug)
                   1203:                        for (n = 0; n < sblock.fs_cpg; n++)
                   1204:                                if (botot[n] != cgrp.cg_btot[n])
                   1205:                                printf("cg[%d].cg_btot[%d] have %d calc %d\n",
                   1206:                                    c, n, cgrp.cg_btot[n], botot[n]);
                   1207:                        offsumbad++;
                   1208:                }
                   1209:                if (bcmp((char *)cgrp.cg_b, (char *)bo, sizeof (bo))) {
                   1210:                        if (debug)
                   1211:                        for (i = 0; i < NRPOS; i++)
                   1212:                                if (bo[n][i] != cgrp.cg_b[n][i])
                   1213:                                printf("cg[%d].cg_b[%d][%d] have %d calc %d\n",
                   1214:                                    c, n, i, cgrp.cg_b[n][i], bo[n][i]);
                   1215:                        offsumbad++;
                   1216:                }
                   1217:        }
                   1218: out5:
                   1219:        if (dupblk)
                   1220:                pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk);
                   1221:        if (fixcg == 0) {
                   1222:                if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) {
                   1223:                        pwarn("%ld BLK(S) MISSING\n", fmax - b);
                   1224:                        fixcg = 1;
                   1225:                } else if (inosumbad + offsumbad + frsumbad + sbsumbad) {
                   1226:                        pwarn("SUMMARY INFORMATION %s%s%s%sBAD\n",
                   1227:                            inosumbad ? "(INODE FREE) " : "",
                   1228:                            offsumbad ? "(BLOCK OFFSETS) " : "",
                   1229:                            frsumbad ? "(FRAG SUMMARIES) " : "",
                   1230:                            sbsumbad ? "(SUPER BLOCK SUMMARIES) " : "");
                   1231:                        fixcg = 1;
                   1232:                } else if (n_ffree != sblock.fs_cstotal.cs_nffree ||
                   1233:                    n_bfree != sblock.fs_cstotal.cs_nbfree) {
                   1234:                        pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK");
                   1235:                        if (preen)
                   1236:                                printf(" (FIXED)\n");
                   1237:                        if (preen || reply("FIX") == 1) {
                   1238:                                sblock.fs_cstotal.cs_nffree = n_ffree;
                   1239:                                sblock.fs_cstotal.cs_nbfree = n_bfree;
                   1240:                                sbdirty();
                   1241:                        }
                   1242:                }
                   1243:        }
                   1244:        if (fixcg) {
                   1245:                pwarn("BAD CYLINDER GROUPS");
                   1246:                if (preen)
                   1247:                        printf(" (SALVAGED)\n");
                   1248:                else if (reply("SALVAGE") == 0)
                   1249:                        fixcg = 0;
                   1250:        }
                   1251: }
                   1252: 
                   1253: pass5check(blk, size)
                   1254:        daddr_t blk;
                   1255:        long size;
                   1256: {
                   1257: 
                   1258:        if (outrange(blk, (int)size)) {
                   1259:                fixcg = 1;
                   1260:                if (preen)
                   1261:                        pfatal("BAD BLOCKS IN BIT MAPS.");
                   1262:                if (++badblk >= MAXBAD) {
                   1263:                        printf("EXCESSIVE BAD BLKS IN BIT MAPS.");
                   1264:                        if (reply("CONTINUE") == 0)
                   1265:                                errexit("");
                   1266:                        return (STOP);
                   1267:                }
                   1268:        }
                   1269:        for (; size > 0; blk++, size--)
                   1270:                if (getfmap(blk)) {
                   1271:                        fixcg = 1;
                   1272:                        ++dupblk;
                   1273:                } else {
                   1274:                        n_ffree++;
                   1275:                        setfmap(blk);
                   1276:                }
                   1277:        return (KEEPON);
                   1278: }
                   1279: 
                   1280: ckinode(dp, idesc)
                   1281:        DINODE *dp;
                   1282:        register struct inodesc *idesc;
                   1283: {
                   1284:        register daddr_t *ap;
                   1285:        int ret, n, ndb, offset;
                   1286:        DINODE dino;
                   1287: 
                   1288:        if (SPECIAL)
                   1289:                return (KEEPON);
                   1290:        dino = *dp;
                   1291:        idesc->id_fix = DONTKNOW;
                   1292:        idesc->id_entryno = 0;
                   1293:        ndb = howmany(dino.di_size, sblock.fs_bsize);
                   1294:        for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
                   1295:                if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
                   1296:                        idesc->id_numfrags =
                   1297:                                numfrags(&sblock, fragroundup(&sblock, offset));
                   1298:                else
                   1299:                        idesc->id_numfrags = sblock.fs_frag;
                   1300:                if (*ap == 0)
                   1301:                        continue;
                   1302:                idesc->id_blkno = *ap;
                   1303:                if (idesc->id_type == ADDR)
                   1304:                        ret = (*idesc->id_func)(idesc);
                   1305:                else
                   1306:                        ret = dirscan(idesc);
                   1307:                if (ret & STOP)
                   1308:                        return (ret);
                   1309:        }
                   1310:        idesc->id_numfrags = sblock.fs_frag;
                   1311:        for (ap = &dino.di_ib[0], n = 1; n <= 2; ap++, n++) {
                   1312:                if (*ap) {
                   1313:                        idesc->id_blkno = *ap;
                   1314:                        ret = iblock(idesc, n,
                   1315:                                dino.di_size - sblock.fs_bsize * NDADDR);
                   1316:                        if (ret & STOP)
                   1317:                                return (ret);
                   1318:                }
                   1319:        }
                   1320:        return (KEEPON);
                   1321: }
                   1322: 
                   1323: iblock(idesc, ilevel, isize)
                   1324:        struct inodesc *idesc;
                   1325:        register ilevel;
                   1326:        long isize;
                   1327: {
                   1328:        register daddr_t *ap;
                   1329:        register daddr_t *aplim;
                   1330:        int i, n, (*func)(), nif;
                   1331:        BUFAREA ib;
                   1332: 
                   1333:        if (idesc->id_type == ADDR) {
                   1334:                func = idesc->id_func;
                   1335:                if (((n = (*func)(idesc)) & KEEPON) == 0)
                   1336:                        return (n);
                   1337:        } else
                   1338:                func = dirscan;
                   1339:        if (outrange(idesc->id_blkno, idesc->id_numfrags)) /* protect thyself */
                   1340:                return (SKIP);
                   1341:        initbarea(&ib);
                   1342:        if (getblk(&ib, idesc->id_blkno, sblock.fs_bsize) == NULL)
                   1343:                return (SKIP);
                   1344:        ilevel--;
                   1345:        if (ilevel == 0) {
                   1346:                nif = lblkno(&sblock, isize) + 1;
                   1347:        } else /* ilevel == 1 */ {
                   1348:                nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1;
                   1349:        }
                   1350:        if (nif > NINDIR(&sblock))
                   1351:                nif = NINDIR(&sblock);
                   1352:        aplim = &ib.b_un.b_indir[nif];
                   1353:        for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
                   1354:                if (*ap) {
                   1355:                        idesc->id_blkno = *ap;
                   1356:                        if (ilevel > 0)
                   1357:                                n = iblock(idesc, ilevel,
                   1358:                                    isize - i*NINDIR(&sblock)*sblock.fs_bsize);
                   1359:                        else
                   1360:                                n = (*func)(idesc);
                   1361:                        if (n & STOP)
                   1362:                                return (n);
                   1363:                }
                   1364:        return (KEEPON);
                   1365: }
                   1366: 
                   1367: outrange(blk, cnt)
                   1368:        daddr_t blk;
                   1369:        int cnt;
                   1370: {
                   1371:        register int c;
                   1372: 
                   1373:        if ((unsigned)(blk+cnt) > fmax)
                   1374:                return (1);
                   1375:        c = dtog(&sblock, blk);
                   1376:        if (blk < cgdmin(&sblock, c)) {
                   1377:                if ((blk+cnt) > cgsblock(&sblock, c)) {
                   1378:                        if (debug) {
                   1379:                                printf("blk %d < cgdmin %d;",
                   1380:                                    blk, cgdmin(&sblock, c));
                   1381:                                printf(" blk+cnt %d > cgsbase %d\n",
                   1382:                                    blk+cnt, cgsblock(&sblock, c));
                   1383:                        }
                   1384:                        return (1);
                   1385:                }
                   1386:        } else {
                   1387:                if ((blk+cnt) > cgbase(&sblock, c+1)) {
                   1388:                        if (debug)  {
                   1389:                                printf("blk %d >= cgdmin %d;",
                   1390:                                    blk, cgdmin(&sblock, c));
                   1391:                                printf(" blk+cnt %d > sblock.fs_fpg %d\n",
                   1392:                                    blk+cnt, sblock.fs_fpg);
                   1393:                        }
                   1394:                        return (1);
                   1395:                }
                   1396:        }
                   1397:        return (0);
                   1398: }
                   1399: 
                   1400: blkerr(ino, s, blk)
                   1401:        ino_t ino;
                   1402:        char *s;
                   1403:        daddr_t blk;
                   1404: {
                   1405: 
                   1406:        pfatal("%ld %s I=%u", blk, s, ino);
                   1407:        printf("\n");
                   1408:        statemap[ino] = CLEAR;
                   1409: }
                   1410: 
                   1411: descend(parentino, inumber)
                   1412:        struct inodesc *parentino;
                   1413:        ino_t inumber;
                   1414: {
                   1415:        register DINODE *dp;
                   1416:        struct inodesc curino;
                   1417: 
                   1418:        bzero((char *)&curino, sizeof(struct inodesc));
                   1419:        statemap[inumber] = FSTATE;
                   1420:        if ((dp = ginode(inumber)) == NULL)
                   1421:                return;
                   1422:        if (dp->di_size == 0) {
                   1423:                direrr(inumber, "ZERO LENGTH DIRECTORY");
                   1424:                if (reply("REMOVE") == 1)
                   1425:                        statemap[inumber] = CLEAR;
                   1426:                return;
                   1427:        }
                   1428:        if (dp->di_size < MINDIRSIZE) {
                   1429:                direrr(inumber, "DIRECTORY TOO SHORT");
                   1430:                dp->di_size = MINDIRSIZE;
                   1431:                if (reply("FIX") == 1)
                   1432:                        inodirty();
                   1433:        }
                   1434:        curino.id_type = DATA;
                   1435:        curino.id_func = parentino->id_func;
                   1436:        curino.id_parent = parentino->id_number;
                   1437:        curino.id_number = inumber;
                   1438:        curino.id_filesize = dp->di_size;
                   1439:        (void)ckinode(dp, &curino);
                   1440: }
                   1441: 
                   1442: dirscan(idesc)
                   1443:        register struct inodesc *idesc;
                   1444: {
                   1445:        register DIRECT *dp;
                   1446:        int dsize, n;
                   1447:        long blksiz;
                   1448:        char dbuf[DIRBLKSIZ];
                   1449: 
                   1450:        if (idesc->id_type != DATA)
                   1451:                errexit("wrong type to dirscan %d\n", idesc->id_type);
                   1452:        blksiz = idesc->id_numfrags * sblock.fs_fsize;
                   1453:        if (outrange(idesc->id_blkno, idesc->id_numfrags)) {
                   1454:                idesc->id_filesize -= blksiz;
                   1455:                return (SKIP);
                   1456:        }
                   1457:        idesc->id_loc = 0;
                   1458:        for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
                   1459:                dsize = dp->d_reclen;
                   1460:                bcopy((char *)dp, dbuf, dsize);
                   1461:                idesc->id_dirp = (DIRECT *)dbuf;
                   1462:                if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
                   1463:                        if (getblk(&fileblk, idesc->id_blkno, blksiz) != NULL) {
                   1464:                                bcopy(dbuf, (char *)dp, dsize);
                   1465:                                dirty(&fileblk);
                   1466:                                sbdirty();
                   1467:                        } else
                   1468:                                n &= ~ALTERED;
                   1469:                }
                   1470:                if (n & STOP) 
                   1471:                        return (n);
                   1472:        }
                   1473:        return (idesc->id_filesize > 0 ? KEEPON : STOP);
                   1474: }
                   1475: 
                   1476: /*
                   1477:  * get next entry in a directory.
                   1478:  */
                   1479: DIRECT *
                   1480: fsck_readdir(idesc)
                   1481:        register struct inodesc *idesc;
                   1482: {
                   1483:        register DIRECT *dp, *ndp;
                   1484:        long size, blksiz;
                   1485: 
                   1486:        blksiz = idesc->id_numfrags * sblock.fs_fsize;
                   1487:        if (getblk(&fileblk, idesc->id_blkno, blksiz) == NULL) {
                   1488:                idesc->id_filesize -= blksiz - idesc->id_loc;
                   1489:                return NULL;
                   1490:        }
                   1491:        if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
                   1492:            idesc->id_loc < blksiz) {
                   1493:                dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
                   1494:                if (dircheck(idesc, dp))
                   1495:                        goto dpok;
                   1496:                idesc->id_loc += DIRBLKSIZ;
                   1497:                idesc->id_filesize -= DIRBLKSIZ;
                   1498:                dp->d_reclen = DIRBLKSIZ;
                   1499:                dp->d_ino = 0;
                   1500:                dp->d_namlen = 0;
                   1501:                dp->d_name[0] = '\0';
                   1502:                if (dofix(idesc))
                   1503:                        dirty(&fileblk);
                   1504:                return (dp);
                   1505:        }
                   1506: dpok:
                   1507:        if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
                   1508:                return NULL;
                   1509:        dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
                   1510:        idesc->id_loc += dp->d_reclen;
                   1511:        idesc->id_filesize -= dp->d_reclen;
                   1512:        ndp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
                   1513:        if ((idesc->id_filesize <= 0 && idesc->id_loc % DIRBLKSIZ != 0) ||
                   1514:            (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
                   1515:             dircheck(idesc, ndp) == 0)) {
                   1516:                size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
                   1517:                dp->d_reclen += size;
                   1518:                idesc->id_loc += size;
                   1519:                idesc->id_filesize -= size;
                   1520:                if (dofix(idesc))
                   1521:                        dirty(&fileblk);
                   1522:        }
                   1523:        return (dp);
                   1524: }
                   1525: 
                   1526: /*
                   1527:  * Verify that a directory entry is valid.
                   1528:  * This is a superset of the checks made in the kernel.
                   1529:  */
                   1530: dircheck(idesc, dp)
                   1531:        struct inodesc *idesc;
                   1532:        register DIRECT *dp;
                   1533: {
                   1534:        register int size;
                   1535:        register char *cp;
                   1536:        int spaceleft;
                   1537: 
                   1538:        size = DIRSIZ(dp);
                   1539:        spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
                   1540:        if (dp->d_ino < imax &&
                   1541:            dp->d_reclen != 0 &&
                   1542:            dp->d_reclen <= spaceleft &&
                   1543:            (dp->d_reclen & 0x3) == 0 &&
                   1544:            dp->d_reclen >= size &&
                   1545:            idesc->id_filesize >= size &&
                   1546:            dp->d_namlen <= MAXNAMLEN) {
                   1547:                if (dp->d_ino == 0)
                   1548:                        return (1);
                   1549:                for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++)
                   1550:                        if (*cp == 0 || (*cp++ & 0200))
                   1551:                                return (0);
                   1552:                if (*cp == 0)
                   1553:                        return (1);
                   1554:        }
                   1555:        return (0);
                   1556: }
                   1557: 
                   1558: direrr(ino, s)
                   1559:        ino_t ino;
                   1560:        char *s;
                   1561: {
                   1562:        register DINODE *dp;
                   1563: 
                   1564:        pwarn("%s ", s);
                   1565:        pinode(ino);
                   1566:        printf("\n");
                   1567:        if ((dp = ginode(ino)) != NULL && ftypeok(dp))
                   1568:                pfatal("%s=%s\n", DIRCT?"DIR":"FILE", pathname);
                   1569:        else
                   1570:                pfatal("NAME=%s\n", pathname);
                   1571: }
                   1572: 
                   1573: adjust(idesc, lcnt)
                   1574:        register struct inodesc *idesc;
                   1575:        short lcnt;
                   1576: {
                   1577:        register DINODE *dp;
                   1578: 
                   1579:        if ((dp = ginode(idesc->id_number)) == NULL)
                   1580:                return;
                   1581:        if (dp->di_nlink == lcnt) {
                   1582:                if (linkup(idesc->id_number, (ino_t)0) == 0)
                   1583:                        clri(idesc, "UNREF", 0);
                   1584:        }
                   1585:        else {
                   1586:                pwarn("LINK COUNT %s",
                   1587:                        (lfdir==idesc->id_number)?lfname:(DIRCT?"DIR":"FILE"));
                   1588:                pinode(idesc->id_number);
                   1589:                printf(" COUNT %d SHOULD BE %d",
                   1590:                        dp->di_nlink, dp->di_nlink-lcnt);
                   1591:                if (preen) {
                   1592:                        if (lcnt < 0) {
                   1593:                                printf("\n");
                   1594:                                preendie();
                   1595:                        }
                   1596:                        printf(" (ADJUSTED)\n");
                   1597:                }
                   1598:                if (preen || reply("ADJUST") == 1) {
                   1599:                        dp->di_nlink -= lcnt;
                   1600:                        inodirty();
                   1601:                }
                   1602:        }
                   1603: }
                   1604: 
                   1605: clri(idesc, s, flg)
                   1606:        register struct inodesc *idesc;
                   1607:        char *s;
                   1608:        int flg;
                   1609: {
                   1610:        register DINODE *dp;
                   1611: 
                   1612:        if ((dp = ginode(idesc->id_number)) == NULL)
                   1613:                return;
                   1614:        if (flg == 1) {
                   1615:                pwarn("%s %s", s, DIRCT?"DIR":"FILE");
                   1616:                pinode(idesc->id_number);
                   1617:        }
                   1618:        if (preen || reply("CLEAR") == 1) {
                   1619:                if (preen)
                   1620:                        printf(" (CLEARED)\n");
                   1621:                n_files--;
                   1622:                (void)ckinode(dp, idesc);
                   1623:                zapino(dp);
                   1624:                statemap[idesc->id_number] = USTATE;
                   1625:                inodirty();
                   1626:                inosumbad++;
                   1627:        }
                   1628: }
                   1629: 
                   1630: badsb(s)
                   1631:        char *s;
                   1632: {
                   1633: 
                   1634:        if (preen)
                   1635:                printf("%s: ", devname);
                   1636:        printf("BAD SUPER BLOCK: %s\n", s);
                   1637:        pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n");
                   1638:        pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n");
                   1639: }
                   1640: 
                   1641: DINODE *
                   1642: ginode(inumber)
                   1643:        ino_t inumber;
                   1644: {
                   1645:        daddr_t iblk;
                   1646:        static ino_t startinum = 0;     /* blk num of first in raw area */
                   1647: 
                   1648: 
                   1649:        if (inumber < ROOTINO || inumber > imax) {
                   1650:                if (debug && inumber > imax)
                   1651:                        printf("inumber out of range (%d)\n", inumber);
                   1652:                return (NULL);
                   1653:        }
                   1654:        if (startinum == 0 ||
                   1655:            inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
                   1656:                iblk = itod(&sblock, inumber);
                   1657:                if (getblk(&inoblk, iblk, sblock.fs_bsize) == NULL) {
                   1658:                        return (NULL);
                   1659:                }
                   1660:                startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
                   1661:        }
                   1662:        return (&inoblk.b_un.b_dinode[inumber % INOPB(&sblock)]);
                   1663: }
                   1664: 
                   1665: ftypeok(dp)
                   1666:        DINODE *dp;
                   1667: {
                   1668:        switch (dp->di_mode & IFMT) {
                   1669: 
                   1670:        case IFDIR:
                   1671:        case IFREG:
                   1672:        case IFBLK:
                   1673:        case IFCHR:
                   1674:        case IFLNK:
                   1675:        case IFSOCK:
                   1676:                return (1);
                   1677: 
                   1678:        default:
                   1679:                if (debug)
                   1680:                        printf("bad file type 0%o\n", dp->di_mode);
                   1681:                return (0);
                   1682:        }
                   1683: }
                   1684: 
                   1685: reply(s)
                   1686:        char *s;
                   1687: {
                   1688:        char line[80];
                   1689: 
                   1690:        if (preen)
                   1691:                pfatal("INTERNAL ERROR: GOT TO reply()");
                   1692:        rplyflag = 1;
                   1693:        printf("\n%s? ", s);
                   1694:        if (nflag || dfile.wfdes < 0) {
                   1695:                printf(" no\n\n");
                   1696:                return (0);
                   1697:        }
                   1698:        if (yflag) {
                   1699:                printf(" yes\n\n");
                   1700:                return (1);
                   1701:        }
                   1702:        if (getline(stdin, line, sizeof(line)) == EOF)
                   1703:                errexit("\n");
                   1704:        printf("\n");
                   1705:        if (line[0] == 'y' || line[0] == 'Y')
                   1706:                return (1);
                   1707:        else
                   1708:                return (0);
                   1709: }
                   1710: 
                   1711: getline(fp, loc, maxlen)
                   1712:        FILE *fp;
                   1713:        char *loc;
                   1714: {
                   1715:        register n;
                   1716:        register char *p, *lastloc;
                   1717: 
                   1718:        p = loc;
                   1719:        lastloc = &p[maxlen-1];
                   1720:        while ((n = getc(fp)) != '\n') {
                   1721:                if (n == EOF)
                   1722:                        return (EOF);
                   1723:                if (!isspace(n) && p < lastloc)
                   1724:                        *p++ = n;
                   1725:        }
                   1726:        *p = 0;
                   1727:        return (p - loc);
                   1728: }
                   1729: 
                   1730: BUFAREA *
                   1731: getblk(bp, blk, size)
                   1732:        register BUFAREA *bp;
                   1733:        daddr_t blk;
                   1734:        long size;
                   1735: {
                   1736:        register struct filecntl *fcp;
                   1737:        daddr_t dblk;
                   1738: 
                   1739:        fcp = &dfile;
                   1740:        dblk = fsbtodb(&sblock, blk);
                   1741:        if (bp->b_bno == dblk)
                   1742:                return (bp);
                   1743:        flush(fcp, bp);
                   1744:        if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) {
                   1745:                bp->b_bno = dblk;
                   1746:                bp->b_size = size;
                   1747:                return (bp);
                   1748:        }
                   1749:        bp->b_bno = (daddr_t)-1;
                   1750:        return (NULL);
                   1751: }
                   1752: 
                   1753: flush(fcp, bp)
                   1754:        struct filecntl *fcp;
                   1755:        register BUFAREA *bp;
                   1756: {
                   1757: 
                   1758:        if (bp->b_dirty)
                   1759:                (void)bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
                   1760:        bp->b_dirty = 0;
                   1761: }
                   1762: 
                   1763: rwerr(s, blk)
                   1764:        char *s;
                   1765:        daddr_t blk;
                   1766: {
                   1767: 
                   1768:        if (preen == 0)
                   1769:                printf("\n");
                   1770:        pfatal("CANNOT %s: BLK %ld", s, blk);
                   1771:        if (reply("CONTINUE") == 0)
                   1772:                errexit("Program terminated\n");
                   1773: }
                   1774: 
                   1775: ckfini()
                   1776: {
                   1777: 
                   1778:        flush(&dfile, &fileblk);
                   1779:        flush(&dfile, &sblk);
                   1780:        if (sblk.b_bno != SBLOCK) {
                   1781:                sblk.b_bno = SBLOCK;
                   1782:                sbdirty();
                   1783:                flush(&dfile, &sblk);
                   1784:        }
                   1785:        flush(&dfile, &inoblk);
                   1786:        (void)close(dfile.rfdes);
                   1787:        (void)close(dfile.wfdes);
                   1788: }
                   1789: 
                   1790: pinode(ino)
                   1791:        ino_t ino;
                   1792: {
                   1793:        register DINODE *dp;
                   1794:        register char *p;
                   1795:        char uidbuf[BUFSIZ];
                   1796:        char *ctime();
                   1797: 
                   1798:        printf(" I=%u ", ino);
                   1799:        if ((dp = ginode(ino)) == NULL)
                   1800:                return;
                   1801:        printf(" OWNER=");
                   1802:        if (getpw((int)dp->di_uid, uidbuf) == 0) {
                   1803:                for (p = uidbuf; *p != ':'; p++);
                   1804:                *p = 0;
                   1805:                printf("%s ", uidbuf);
                   1806:        }
                   1807:        else {
                   1808:                printf("%d ", dp->di_uid);
                   1809:        }
                   1810:        printf("MODE=%o\n", dp->di_mode);
                   1811:        if (preen)
                   1812:                printf("%s: ", devname);
                   1813:        printf("SIZE=%ld ", dp->di_size);
                   1814:        p = ctime(&dp->di_mtime);
                   1815:        printf("MTIME=%12.12s %4.4s ", p+4, p+20);
                   1816: }
                   1817: 
                   1818: makecg()
                   1819: {
                   1820:        int c, blk;
                   1821:        daddr_t dbase, d, dlower, dupper, dmax;
                   1822:        long i, j, s;
                   1823:        ino_t inumber;
                   1824:        register struct csum *cs;
                   1825:        register DINODE *dp;
                   1826: 
                   1827:        sblock.fs_cstotal.cs_nbfree = 0;
                   1828:        sblock.fs_cstotal.cs_nffree = 0;
                   1829:        sblock.fs_cstotal.cs_nifree = 0;
                   1830:        sblock.fs_cstotal.cs_ndir = 0;
                   1831:        for (c = 0; c < sblock.fs_ncg; c++) {
                   1832:                dbase = cgbase(&sblock, c);
                   1833:                dmax = dbase + sblock.fs_fpg;
                   1834:                if (dmax > sblock.fs_size) {
                   1835:                        for ( ; dmax >= sblock.fs_size; dmax--)
                   1836:                                clrbit(cgrp.cg_free, dmax - dbase);
                   1837:                        dmax++;
                   1838:                }
                   1839:                dlower = cgsblock(&sblock, c) - dbase;
                   1840:                dupper = cgdmin(&sblock, c) - dbase;
                   1841:                cs = &sblock.fs_cs(&sblock, c);
                   1842:                (void)time(&cgrp.cg_time);
                   1843:                cgrp.cg_magic = CG_MAGIC;
                   1844:                cgrp.cg_cgx = c;
                   1845:                if (c == sblock.fs_ncg - 1)
                   1846:                        cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
                   1847:                else
                   1848:                        cgrp.cg_ncyl = sblock.fs_cpg;
                   1849:                cgrp.cg_niblk = sblock.fs_ipg;
                   1850:                cgrp.cg_ndblk = dmax - dbase;
                   1851:                cgrp.cg_cs.cs_ndir = 0;
                   1852:                cgrp.cg_cs.cs_nffree = 0;
                   1853:                cgrp.cg_cs.cs_nbfree = 0;
                   1854:                cgrp.cg_cs.cs_nifree = 0;
                   1855:                cgrp.cg_rotor = 0;
                   1856:                cgrp.cg_frotor = 0;
                   1857:                cgrp.cg_irotor = 0;
                   1858:                for (i = 0; i < sblock.fs_frag; i++)
                   1859:                        cgrp.cg_frsum[i] = 0;
                   1860:                inumber = sblock.fs_ipg * c;
                   1861:                for (i = 0; i < sblock.fs_ipg; inumber++, i++) {
                   1862:                        cgrp.cg_cs.cs_nifree++;
                   1863:                        clrbit(cgrp.cg_iused, i);
                   1864:                        dp = ginode(inumber);
                   1865:                        if (dp == NULL)
                   1866:                                continue;
                   1867:                        if (ALLOC) {
                   1868:                                if (DIRCT)
                   1869:                                        cgrp.cg_cs.cs_ndir++;
                   1870:                                cgrp.cg_cs.cs_nifree--;
                   1871:                                setbit(cgrp.cg_iused, i);
                   1872:                                continue;
                   1873:                        }
                   1874:                }
                   1875:                while (i < MAXIPG) {
                   1876:                        clrbit(cgrp.cg_iused, i);
                   1877:                        i++;
                   1878:                }
                   1879:                if (c == 0)
                   1880:                        for (i = 0; i < ROOTINO; i++) {
                   1881:                                setbit(cgrp.cg_iused, i);
                   1882:                                cgrp.cg_cs.cs_nifree--;
                   1883:                        }
                   1884:                for (s = 0; s < MAXCPG; s++) {
                   1885:                        cgrp.cg_btot[s] = 0;
                   1886:                        for (i = 0; i < NRPOS; i++)
                   1887:                                cgrp.cg_b[s][i] = 0;
                   1888:                }
                   1889:                if (c == 0) {
                   1890:                        dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
                   1891:                }
                   1892:                for (d = dlower; d < dupper; d++)
                   1893:                        clrbit(cgrp.cg_free, d);
                   1894:                for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
                   1895:                    d += sblock.fs_frag) {
                   1896:                        j = 0;
                   1897:                        for (i = 0; i < sblock.fs_frag; i++) {
                   1898:                                if (!getbmap(dbase + d + i)) {
                   1899:                                        setbit(cgrp.cg_free, d + i);
                   1900:                                        j++;
                   1901:                                } else
                   1902:                                        clrbit(cgrp.cg_free, d+i);
                   1903:                        }
                   1904:                        if (j == sblock.fs_frag) {
                   1905:                                cgrp.cg_cs.cs_nbfree++;
                   1906:                                cgrp.cg_btot[cbtocylno(&sblock, d)]++;
                   1907:                                cgrp.cg_b[cbtocylno(&sblock, d)]
                   1908:                                    [cbtorpos(&sblock, d)]++;
                   1909:                        } else if (j > 0) {
                   1910:                                cgrp.cg_cs.cs_nffree += j;
                   1911:                                blk = blkmap(&sblock, cgrp.cg_free, d);
                   1912:                                fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                   1913:                        }
                   1914:                }
                   1915:                for (j = d; d < dmax - dbase; d++) {
                   1916:                        if (!getbmap(dbase + d)) {
                   1917:                                setbit(cgrp.cg_free, d);
                   1918:                                cgrp.cg_cs.cs_nffree++;
                   1919:                        } else
                   1920:                                clrbit(cgrp.cg_free, d);
                   1921:                }
                   1922:                for (; d % sblock.fs_frag != 0; d++)
                   1923:                        clrbit(cgrp.cg_free, d);
                   1924:                if (j != d) {
                   1925:                        blk = blkmap(&sblock, cgrp.cg_free, j);
                   1926:                        fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                   1927:                }
                   1928:                for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
                   1929:                        clrblock(&sblock, cgrp.cg_free, d);
                   1930:                sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
                   1931:                sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
                   1932:                sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
                   1933:                sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
                   1934:                *cs = cgrp.cg_cs;
                   1935:                (void)bwrite(&dfile, (char *)&cgrp,
                   1936:                        fsbtodb(&sblock, cgtod(&sblock, c)), sblock.fs_cgsize);
                   1937:        }
                   1938:        for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
                   1939:                (void)bwrite(&dfile, (char *)sblock.fs_csp[j],
                   1940:                    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
                   1941:                    sblock.fs_cssize - i < sblock.fs_bsize ?
                   1942:                    sblock.fs_cssize - i : sblock.fs_bsize);
                   1943:        }
                   1944:        sblock.fs_ronly = 0;
                   1945:        sblock.fs_fmod = 0;
                   1946:        sbdirty();
                   1947: }
                   1948: 
                   1949: findino(idesc)
                   1950:        struct inodesc *idesc;
                   1951: {
                   1952:        register DIRECT *dirp = idesc->id_dirp;
                   1953: 
                   1954:        if (dirp->d_ino == 0)
                   1955:                return (KEEPON);
                   1956:        if (!strcmp(dirp->d_name, srchname)) {
                   1957:                if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax)
                   1958:                        idesc->id_parent = dirp->d_ino;
                   1959:                return (STOP);
                   1960:        }
                   1961:        return (KEEPON);
                   1962: }
                   1963: 
                   1964: mkentry(idesc)
                   1965:        struct inodesc *idesc;
                   1966: {
                   1967:        register DIRECT *dirp = idesc->id_dirp;
                   1968:        DIRECT newent;
                   1969:        int newlen, oldlen;
                   1970: 
                   1971:        newent.d_namlen = 11;
                   1972:        newlen = DIRSIZ(&newent);
                   1973:        if (dirp->d_ino != 0)
                   1974:                oldlen = DIRSIZ(dirp);
                   1975:        else
                   1976:                oldlen = 0;
                   1977:        if (dirp->d_reclen - oldlen < newlen)
                   1978:                return (KEEPON);
                   1979:        newent.d_reclen = dirp->d_reclen - oldlen;
                   1980:        dirp->d_reclen = oldlen;
                   1981:        dirp = (struct direct *)(((char *)dirp) + oldlen);
                   1982:        dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
                   1983:        dirp->d_reclen = newent.d_reclen;
                   1984:        dirp->d_namlen = lftempname(dirp->d_name, idesc->id_parent);
                   1985:        return (ALTERED|STOP);
                   1986: }
                   1987: 
                   1988: chgdd(idesc)
                   1989:        struct inodesc *idesc;
                   1990: {
                   1991:        register DIRECT *dirp = idesc->id_dirp;
                   1992: 
                   1993:        if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' &&
                   1994:        dirp->d_name[2] == 0) {
                   1995:                dirp->d_ino = lfdir;
                   1996:                return (ALTERED|STOP);
                   1997:        }
                   1998:        return (KEEPON);
                   1999: }
                   2000: 
                   2001: linkup(orphan, pdir)
                   2002:        ino_t orphan;
                   2003:        ino_t pdir;
                   2004: {
                   2005:        register DINODE *dp;
                   2006:        int lostdir, len;
                   2007:        struct inodesc idesc;
                   2008: 
                   2009:        bzero((char *)&idesc, sizeof(struct inodesc));
                   2010:        if ((dp = ginode(orphan)) == NULL)
                   2011:                return (0);
                   2012:        lostdir = DIRCT;
                   2013:        pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
                   2014:        pinode(orphan);
                   2015:        if (preen && dp->di_size == 0)
                   2016:                return (0);
                   2017:        if (preen)
                   2018:                printf(" (RECONNECTED)\n");
                   2019:        else
                   2020:                if (reply("RECONNECT") == 0)
                   2021:                        return (0);
                   2022:        pathp = pathname;
                   2023:        *pathp++ = '/';
                   2024:        *pathp = '\0';
                   2025:        if (lfdir == 0) {
                   2026:                if ((dp = ginode(ROOTINO)) == NULL)
                   2027:                        return (0);
                   2028:                srchname = lfname;
                   2029:                idesc.id_type = DATA;
                   2030:                idesc.id_func = findino;
                   2031:                idesc.id_number = ROOTINO;
                   2032:                idesc.id_filesize = dp->di_size;
                   2033:                (void)ckinode(dp, &idesc);
                   2034:                if ((lfdir = idesc.id_parent) == 0) {
                   2035:                        pfatal("SORRY. NO lost+found DIRECTORY");
                   2036:                        printf("\n\n");
                   2037:                        return (0);
                   2038:                }
                   2039:        }
                   2040:        if ((dp = ginode(lfdir)) == NULL ||
                   2041:             !DIRCT || statemap[lfdir] != FSTATE) {
                   2042:                pfatal("SORRY. NO lost+found DIRECTORY");
                   2043:                printf("\n\n");
                   2044:                return (0);
                   2045:        }
                   2046:        if (fragoff(&sblock, dp->di_size)) {
                   2047:                dp->di_size = fragroundup(&sblock, dp->di_size);
                   2048:                inodirty();
                   2049:        }
                   2050:        len = strlen(lfname);
                   2051:        bcopy(lfname, pathp, len + 1);
                   2052:        pathp += len;
                   2053:        idesc.id_type = DATA;
                   2054:        idesc.id_func = mkentry;
                   2055:        idesc.id_number = lfdir;
                   2056:        idesc.id_filesize = dp->di_size;
                   2057:        idesc.id_parent = orphan;       /* this is the inode to enter */
                   2058:        idesc.id_fix = DONTKNOW;
                   2059:        if ((ckinode(dp, &idesc) & ALTERED) == 0) {
                   2060:                pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
                   2061:                printf("\n\n");
                   2062:                return (0);
                   2063:        }
                   2064:        lncntp[orphan]--;
                   2065:        *pathp++ = '/';
                   2066:        pathp += lftempname(pathp, orphan);
                   2067:        if (lostdir) {
                   2068:                dp = ginode(orphan);
                   2069:                idesc.id_type = DATA;
                   2070:                idesc.id_func = chgdd;
                   2071:                idesc.id_number = orphan;
                   2072:                idesc.id_filesize = dp->di_size;
                   2073:                idesc.id_fix = DONTKNOW;
                   2074:                (void)ckinode(dp, &idesc);
                   2075:                if ((dp = ginode(lfdir)) != NULL) {
                   2076:                        dp->di_nlink++;
                   2077:                        inodirty();
                   2078:                        lncntp[lfdir]++;
                   2079:                }
                   2080:                pwarn("DIR I=%u CONNECTED. ", orphan);
                   2081:                printf("PARENT WAS I=%u\n", pdir);
                   2082:                if (preen == 0)
                   2083:                        printf("\n");
                   2084:        }
                   2085:        return (1);
                   2086: }
                   2087: 
                   2088: /*
                   2089:  * generate a temporary name for the lost+found directory.
                   2090:  */
                   2091: lftempname(bufp, ino)
                   2092:        char *bufp;
                   2093:        ino_t ino;
                   2094: {
                   2095:        register ino_t in;
                   2096:        register char *cp;
                   2097:        int namlen;
                   2098: 
                   2099:        cp = bufp + 2;
                   2100:        for (in = imax; in > 0; in /= 10)
                   2101:                cp++;
                   2102:        *--cp = 0;
                   2103:        namlen = cp - bufp;
                   2104:        in = ino;
                   2105:        while (cp > bufp) {
                   2106:                *--cp = (in % 10) + '0';
                   2107:                in /= 10;
                   2108:        }
                   2109:        *cp = '#';
                   2110:        return (namlen);
                   2111: }
                   2112: 
                   2113: bread(fcp, buf, blk, size)
                   2114:        register struct filecntl *fcp;
                   2115:        char *buf;
                   2116:        daddr_t blk;
                   2117:        long size;
                   2118: {
                   2119:        if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
                   2120:                rwerr("SEEK", blk);
                   2121:        else if (read(fcp->rfdes, buf, (int)size) == size)
                   2122:                return (1);
                   2123:        rwerr("READ", blk);
                   2124:        return (0);
                   2125: }
                   2126: 
                   2127: bwrite(fcp, buf, blk, size)
                   2128:        register struct filecntl *fcp;
                   2129:        char *buf;
                   2130:        daddr_t blk;
                   2131:        long size;
                   2132: {
                   2133: 
                   2134:        if (fcp->wfdes < 0)
                   2135:                return (0);
                   2136:        if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
                   2137:                rwerr("SEEK", blk);
                   2138:        else if (write(fcp->wfdes, buf, (int)size) == size) {
                   2139:                fcp->mod = 1;
                   2140:                return (1);
                   2141:        }
                   2142:        rwerr("WRITE", blk);
                   2143:        return (0);
                   2144: }
                   2145: 
                   2146: catch()
                   2147: {
                   2148: 
                   2149:        ckfini();
                   2150:        exit(12);
                   2151: }
                   2152: 
                   2153: char *
                   2154: unrawname(cp)
                   2155:        char *cp;
                   2156: {
                   2157:        char *dp = rindex(cp, '/');
                   2158:        struct stat stb;
                   2159: 
                   2160:        if (dp == 0)
                   2161:                return (cp);
                   2162:        if (stat(cp, &stb) < 0)
                   2163:                return (cp);
                   2164:        if ((stb.st_mode&S_IFMT) != S_IFCHR)
                   2165:                return (cp);
                   2166:        if (*(dp+1) != 'r')
                   2167:                return (cp);
                   2168:        (void)strcpy(dp+1, dp+2);
                   2169:        return (cp);
                   2170: }
                   2171: 
                   2172: char *
                   2173: rawname(cp)
                   2174:        char *cp;
                   2175: {
                   2176:        static char rawbuf[32];
                   2177:        char *dp = rindex(cp, '/');
                   2178: 
                   2179:        if (dp == 0)
                   2180:                return (0);
                   2181:        *dp = 0;
                   2182:        (void)strcpy(rawbuf, cp);
                   2183:        *dp = '/';
                   2184:        (void)strcat(rawbuf, "/r");
                   2185:        (void)strcat(rawbuf, dp+1);
                   2186:        return (rawbuf);
                   2187: }
                   2188: 
                   2189: /*
                   2190:  * determine whether an inode should be fixed.
                   2191:  */
                   2192: dofix(idesc)
                   2193:        register struct inodesc *idesc;
                   2194: {
                   2195: 
                   2196:        switch (idesc->id_fix) {
                   2197: 
                   2198:        case DONTKNOW:
                   2199:                direrr(idesc->id_number, "DIRECTORY CORRUPTED");
                   2200:                if (reply("SALVAGE") == 0) {
                   2201:                        idesc->id_fix = NOFIX;
                   2202:                        return (0);
                   2203:                }
                   2204:                idesc->id_fix = FIX;
                   2205:                return (ALTERED);
                   2206: 
                   2207:        case FIX:
                   2208:                return (ALTERED);
                   2209: 
                   2210:        case NOFIX:
                   2211:                return (0);
                   2212: 
                   2213:        default:
                   2214:                errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
                   2215:        }
                   2216:        /* NOTREACHED */
                   2217: }
                   2218: 
                   2219: /* VARARGS1 */
                   2220: error(s1, s2, s3, s4)
                   2221:        char *s1;
                   2222: {
                   2223: 
                   2224:        printf(s1, s2, s3, s4);
                   2225: }
                   2226: 
                   2227: /* VARARGS1 */
                   2228: errexit(s1, s2, s3, s4)
                   2229:        char *s1;
                   2230: {
                   2231:        error(s1, s2, s3, s4);
                   2232:        exit(8);
                   2233: }
                   2234: 
                   2235: /*
                   2236:  * An inconsistency occured which shouldn't during normal operations.
                   2237:  * Die if preening, otherwise just printf.
                   2238:  */
                   2239: /* VARARGS1 */
                   2240: pfatal(s, a1, a2, a3)
                   2241:        char *s;
                   2242: {
                   2243: 
                   2244:        if (preen) {
                   2245:                printf("%s: ", devname);
                   2246:                printf(s, a1, a2, a3);
                   2247:                printf("\n");
                   2248:                preendie();
                   2249:        }
                   2250:        printf(s, a1, a2, a3);
                   2251: }
                   2252: 
                   2253: preendie()
                   2254: {
                   2255: 
                   2256:        printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname);
                   2257:        exit(8);
                   2258: }
                   2259: 
                   2260: /*
                   2261:  * Pwarn is like printf when not preening,
                   2262:  * or a warning (preceded by filename) when preening.
                   2263:  */
                   2264: /* VARARGS1 */
                   2265: pwarn(s, a1, a2, a3, a4, a5, a6)
                   2266:        char *s;
                   2267: {
                   2268: 
                   2269:        if (preen)
                   2270:                printf("%s: ", devname);
                   2271:        printf(s, a1, a2, a3, a4, a5, a6);
                   2272: }
                   2273: 
                   2274: #ifndef lint
                   2275: /*
                   2276:  * Stub for routines from kernel.
                   2277:  */
                   2278: panic(s)
                   2279:        char *s;
                   2280: {
                   2281: 
                   2282:        pfatal("INTERNAL INCONSISTENCY: %s\n", s);
                   2283:        exit(12);
                   2284: }
                   2285: #endif

unix.superglobalmegacorp.com

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