Annotation of 42BSD/etc/fsck/fsck.c, revision 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.