Annotation of researchv10no/cmd/fsck.c, revision 1.1

1.1     ! root        1: #define BITFS(x)       (1)
        !             2: #ifdef notdef
        !             3: #define SMALL  0       /* 1k file systems */
        !             4: #endif
        !             5: /* #include <ansi.h> */
        !             6: /* #include <posix.h> */
        !             7: #include <pwd.h>
        !             8: #include <stdio.h>
        !             9: #include <ctype.h>
        !            10: #include <sys/param.h>
        !            11: #ifdef SMALL
        !            12: #include <sys/fblk.h>
        !            13: #endif
        !            14: #include <sys/filsys.h>
        !            15: #include <sys/dir.h>
        !            16: /* #include <sys/dinode.h> */
        !            17: #include <sys/fblk.h>
        !            18: #include <sys/ino.h>
        !            19: #include <sys/inode.h>
        !            20: /* #include <sys/stat.h> */
        !            21: #include <stat.h>
        !            22: #include <fstab.h>
        !            23: 
        !            24: #define BIG    64      /* 4k file systems */
        !            25: #define BCOUNT         BSIZE(BIG)
        !            26: #define BITSPERBLK     (BCOUNT*NBBY)
        !            27: #define NDIRECT(x)     (BSIZE(x)/sizeof(struct direct))
        !            28: #define SPERB(x)       (BSIZE(x)/sizeof(short))
        !            29: 
        !            30: #define NO     0
        !            31: #define YES    1
        !            32: 
        !            33: #define        MAXDUP  10              /* limit on dup blks (per inode) */
        !            34: #define        MAXBAD  10              /* limit on bad blks (per inode) */
        !            35: 
        !            36: #define STEPSIZE       9       /* default step for freelist spacing */
        !            37: #define CYLSIZE                400     /* default cyl size for spacing */
        !            38: #define MAXCYL         1000    /* maximum cylinder size */
        !            39: 
        !            40: #define BITSPB 8               /* number bits per byte */
        !            41: #define BITSHIFT       3       /* log2(BITSPB) */
        !            42: #define BITMASK        07              /* BITSPB-1 */
        !            43: #define LSTATE 2               /* bits per inode state */
        !            44: #define STATEPB        (BITSPB/LSTATE) /* inode states per byte */
        !            45: #define USTATE 0               /* inode not allocated */
        !            46: #define FSTATE 01              /* inode is file */
        !            47: #define DSTATE 02              /* inode is directory */
        !            48: #define CLEAR  03              /* inode is to be cleared */
        !            49: #define SMASK  03              /* mask for inode state */
        !            50: 
        !            51: typedef struct dinode  DINODE;
        !            52: typedef struct direct  DIRECT;
        !            53: 
        !            54: #define ALLOC  ((dp->di_mode & IFMT) != 0)
        !            55: #define DIR    ((dp->di_mode & IFMT) == IFDIR)
        !            56: #define REG    ((dp->di_mode & IFMT) == IFREG)
        !            57: #define BLK    ((dp->di_mode & IFMT) == IFBLK)
        !            58: #define CHR    ((dp->di_mode & IFMT) == IFCHR)
        !            59: #define MPC    ((dp->di_mode & IFMT) == IFMPC)
        !            60: #define MPB    ((dp->di_mode & IFMT) == IFMPB)
        !            61: #define LNK    ((dp->di_mode & IFMT) == IFLNK)
        !            62: #define SPECIAL        (BLK || CHR /* || MPC || MPB */ )
        !            63: 
        !            64: #define NINOBLK        11              /* num blks for raw reading */
        !            65: #define MAXRAW 110             /* largest raw read (in blks) */
        !            66: daddr_t        startib;                /* blk num of first in raw area */
        !            67: unsigned niblk;                        /* num of blks in raw area */
        !            68: 
        !            69: struct bufarea {
        !            70:        struct bufarea  *b_next;                /* must be first */
        !            71:        daddr_t b_bno;
        !            72:        union {
        !            73:                char    b_buf[BSIZE(BIG)];              /* buffer space */
        !            74:                short   b_lnks[SPERB(BIG)];             /* link counts */
        !            75:                daddr_t b_indir[NINDIR(BIG)];   /* indirect block */
        !            76:                struct filsys b_fs;             /* super block */
        !            77: #ifdef SMALL
        !            78:                struct fblk b_fb;               /* free block */
        !            79: #endif
        !            80:                struct dinode b_dinode[INOPB(BIG)];     /* inode block */
        !            81:                DIRECT b_dir[NDIRECT(BIG)];             /* directory */
        !            82:        } b_un;
        !            83:        char    b_dirty;
        !            84: };
        !            85: 
        !            86: typedef struct bufarea BUFAREA;
        !            87: 
        !            88: BUFAREA        inoblk;                 /* inode blocks */
        !            89: BUFAREA        fileblk;                /* other blks in filesys */
        !            90: BUFAREA        sblk;                   /* file system superblock */
        !            91: BUFAREA        *poolhead;              /* ptr to first buffer in pool */
        !            92: 
        !            93: #define initbarea(x)   (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1
        !            94: #define dirty(x)       (x)->b_dirty = 1
        !            95: #define inodirty()     inoblk.b_dirty = 1
        !            96: #define fbdirty()      fileblk.b_dirty = 1
        !            97: #define sbdirty()      sblk.b_dirty = 1
        !            98: 
        !            99: #define freeblk                fileblk.b_un.b_fb
        !           100: #define dirblk         fileblk.b_un
        !           101: #define superblk       sblk.b_un.b_fs
        !           102: 
        !           103: struct filecntl {
        !           104:        int     rfdes;
        !           105:        int     wfdes;
        !           106:        int     mod;
        !           107: };
        !           108: 
        !           109: struct filecntl        dfile;          /* file descriptors for filesys */
        !           110: struct filecntl        sfile;          /* file descriptors for scratch file */
        !           111: 
        !           112: typedef unsigned MEMSIZE;
        !           113: 
        !           114: MEMSIZE        memsize;                /* amt of memory we got */
        !           115: MEMSIZE        minsize;
        !           116: #ifdef pdp11
        !           117: #define MAXDATA ((MEMSIZE)54*1024)
        !           118: #endif
        !           119: #ifdef vax
        !           120: #define MAXDATA ((MEMSIZE)400*1024)
        !           121: #endif
        !           122: #ifdef interdata
        !           123: #define MAXDATA ((MEMSIZE)400*1024)
        !           124: #endif
        !           125: #ifdef mips
        !           126: #define MAXDATA        (0x10000000+(MEMSIZE)400*1024)  /* hack */
        !           127: #endif
        !           128: #ifndef MAXDATA
        !           129: #define MAXDATA ((MEMSIZE)200*1024)
        !           130: #endif
        !           131: 
        !           132: #define        DUPTBLSIZE      100     /* num of dup blocks to remember */
        !           133: daddr_t        duplist[DUPTBLSIZE];    /* dup block table */
        !           134: daddr_t        *enddup;                /* next entry in dup table */
        !           135: daddr_t        *muldup;                /* multiple dups part of table */
        !           136: 
        !           137: #define MAXLNCNT       500     /* num zero link cnts to remember */
        !           138: ino_t  badlncnt[MAXLNCNT];     /* table of inos with zero link cnts */
        !           139: ino_t  *badlnp;                /* next entry in table */
        !           140: 
        !           141: char   sflag;                  /* salvage free block list */
        !           142: char   csflag;                 /* salvage free block list (conditional) */
        !           143: char   nflag;                  /* assume a no response */
        !           144: char   yflag;                  /* assume a yes response */
        !           145: char   tflag;                  /* scratch file specified */
        !           146: char   preen;                  /* just fix normal inconsistencies */
        !           147: char   rplyflag;               /* any questions asked? */
        !           148: char   hotroot;                /* checking root device */
        !           149: char   rawflg;                 /* read raw device */
        !           150: char   rmscr;                  /* remove scratch file when done */
        !           151: char   fixfree;                /* corrupted free list */
        !           152: char   *membase;               /* base of memory we get */
        !           153: long   *bm_buf;                /* ptr to bit map buffer area */
        !           154: char   *blkmap;                /* ptr to primary blk allocation map */
        !           155: char   *freemap;               /* ptr to secondary blk allocation map */
        !           156: char   *statemap;              /* ptr to inode state table */
        !           157: char   *pathp;                 /* pointer to pathname position */
        !           158: char   *thisname;              /* ptr to current pathname component */
        !           159: char   *srchname;              /* name being searched for in dir */
        !           160: char   pathname[200];
        !           161: char   scrfile[80];
        !           162: char   *lfname =       "lost+found";
        !           163: char   *checklist =    FSTAB;
        !           164: char   big;                    /* it is a 4k file system */
        !           165: 
        !           166: short  *lncntp;                /* ptr to link count table */
        !           167: 
        !           168: int    cylsize;                /* num blocks per cylinder */
        !           169: int    stepsize;               /* num blocks for spacing purposes */
        !           170: int    badblk;                 /* num of bad blks seen (per inode) */
        !           171: int    dupblk;                 /* num of dup blks seen (per inode) */
        !           172: int    (*pfunc)();             /* function to call to chk blk */
        !           173: int    zcleared;               /* num of empty, linkless files cleared */
        !           174: 
        !           175: ino_t  inum;                   /* inode we are currently working on */
        !           176: ino_t  imax;                   /* number of inodes */
        !           177: ino_t  parentdir;              /* i number of parent directory */
        !           178: ino_t  lastino;                /* hiwater mark of inodes */
        !           179: ino_t  lfdir;                  /* lost & found directory */
        !           180: ino_t  orphan;                 /* orphaned inode */
        !           181: 
        !           182: off_t  filsize;                /* num blks seen in file */
        !           183: off_t  maxblk;                 /* largest logical blk in file */
        !           184: off_t  bmapsz;                 /* num chars in blkmap */
        !           185: 
        !           186: daddr_t        smapblk;                /* starting blk of state map */
        !           187: daddr_t        lncntblk;               /* starting blk of link cnt table */
        !           188: daddr_t        fmapblk;                /* starting blk of free map */
        !           189: daddr_t        n_free;                 /* number of free blocks */
        !           190: daddr_t        n_blks;                 /* number of blocks used */
        !           191: daddr_t        n_files;                /* number of files seen */
        !           192: daddr_t        fmin;                   /* block number of the first data block */
        !           193: daddr_t        fmax;                   /* number of blocks in the volume */
        !           194: daddr_t m_blks;                        /* number of bitmap blocks in the file system */
        !           195: 
        !           196: #undef howmany
        !           197: #undef roundup
        !           198: #define howmany(x,y)   (((x)+((y)-1))/(y))
        !           199: #define roundup(x,y)   ((((x)+((y)-1))/(y))*(y))
        !           200: #define outrange(x)    (x < fmin || x >= fmax)
        !           201: #define zapino(x)      clear((char *)(x),sizeof(DINODE))
        !           202: 
        !           203: #define setlncnt(x)    dolncnt(x,0)
        !           204: #define getlncnt()     dolncnt(0,1)
        !           205: #define declncnt()     dolncnt(0,2)
        !           206: 
        !           207: #define setbmap(x)     domap(x,0)
        !           208: #define getbmap(x)     domap(x,1)
        !           209: #define clrbmap(x)     domap(x,2)
        !           210: 
        !           211: #define setfmap(x)     domap(x,0+4)
        !           212: #define getfmap(x)     domap(x,1+4)
        !           213: #define clrfmap(x)     domap(x,2+4)
        !           214: 
        !           215: #define setstate(x)    dostate(x,0)
        !           216: #define getstate()     dostate(0,1)
        !           217: 
        !           218: #define DATA   1
        !           219: #define ADDR   0
        !           220: #define ALTERD 010
        !           221: #define KEEPON 04
        !           222: #define SKIP   02
        !           223: #define STOP   01
        !           224: 
        !           225: DINODE *ginode();
        !           226: BUFAREA        *getblk();
        !           227: BUFAREA        *search();
        !           228: int    dirscan();
        !           229: int    findino();
        !           230: void   catch(int);
        !           231: int    mkentry();
        !           232: int    chgdd();
        !           233: int    pass1();
        !           234: int    pass1b();
        !           235: int    pass2();
        !           236: int    pass3();
        !           237: int    pass4();
        !           238: int    pass5();
        !           239: void ltol3(char *, long *, int);
        !           240: void l3tol(long *, char *, int);
        !           241: 
        !           242: char   *devname;
        !           243: 
        !           244: main(argc,argv)
        !           245: int    argc;
        !           246: char   *argv[];
        !           247: {
        !           248:        register FILE *fp;
        !           249:        register n;
        !           250:        register char *p;
        !           251:        char filename[50];
        !           252:        char *sbrk();
        !           253: 
        !           254:        setbuf(stdout, NULL);
        !           255:        sync();
        !           256:        while(--argc > 0 && **++argv == '-') {
        !           257:                switch(*++*argv) {
        !           258:                        case 'p':
        !           259:                                preen++;
        !           260:                                break;
        !           261:                        case 't':
        !           262:                        case 'T':
        !           263:                                tflag++;
        !           264:                                if(**++argv == '-' || --argc <= 0)
        !           265:                                        errexit("Bad -t option\n");
        !           266:                                p = scrfile;
        !           267:                                while(*p++ = **argv)
        !           268:                                        (*argv)++;
        !           269:                                break;
        !           270:                        case 's':       /* salvage flag */
        !           271:                                stype(++*argv);
        !           272:                                sflag++;
        !           273:                                break;
        !           274:                        case 'S':       /* conditional salvage */
        !           275:                                stype(++*argv);
        !           276:                                csflag++;
        !           277:                                break;
        !           278:                        case 'n':       /* default no answer flag */
        !           279:                        case 'N':
        !           280:                                nflag++;
        !           281:                                yflag = 0;
        !           282:                                break;
        !           283:                        case 'y':       /* default yes answer flag */
        !           284:                        case 'Y':
        !           285:                                yflag++;
        !           286:                                nflag = 0;
        !           287:                                break;
        !           288:                        default:
        !           289:                                errexit("%c option?\n",**argv);
        !           290:                }
        !           291:        }
        !           292:        if(nflag && (sflag || csflag))
        !           293:                errexit("Incompatible options: -n and -%s\n",sflag?"s":"S");
        !           294:        if(sflag && csflag)
        !           295:                sflag = 0;
        !           296:        memsize = (MEMSIZE)sbrk(0);
        !           297:        memsize = MAXDATA - memsize - sizeof(int);
        !           298:        minsize = 2*sizeof(BUFAREA)+BSIZE(BIG);
        !           299:        while(memsize >= minsize &&
        !           300:                (membase = sbrk(memsize)) == (char *)-1)
        !           301:                memsize -= 1024;
        !           302:        if(memsize < minsize)
        !           303:                errexit("Can't get memory\n");
        !           304:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !           305:                signal(SIGINT, catch);
        !           306:        if(argc) {              /* arg list has file names */
        !           307:                while(argc-- > 0){
        !           308:                        hotroot = 0;
        !           309:                        check(*argv++);
        !           310:                }
        !           311:        }
        !           312:        else {                  /* use default checklist */
        !           313:                struct fstab *fsp;
        !           314:                int pid, passno, anygtr, sumstatus = 0;
        !           315:                passno = 1;
        !           316:                do {
        !           317:                        anygtr = 0;
        !           318:                        if (setfsent() == 0)
        !           319:                                errexit("Can't open checklist file: %s\n",
        !           320:                                        FSTAB);
        !           321:                        while ( (fsp = getfsent()) != 0){
        !           322:                                if (fsp->fs_ftype != 0) /* regular fs */
        !           323:                                        continue;
        !           324:                                if (preen == 0 ||
        !           325:                                    passno == 1 && fsp->fs_passno == passno) {
        !           326:                                        if (blockcheck(fsp->fs_spec) == NO &&
        !           327:                                            preen)
        !           328:                                                exit(8);
        !           329:                                } else if (fsp->fs_passno > passno)
        !           330:                                        anygtr = 1;
        !           331:                                else if (fsp->fs_passno == passno) {
        !           332:                                        pid = fork();
        !           333:                                        if (pid < 0) {
        !           334:                                                perror("fork");
        !           335:                                                exit(8);
        !           336:                                        }
        !           337:                                        if (pid == 0)
        !           338:                                                if (blockcheck(fsp->fs_spec)==NO)
        !           339:                                                        exit(8);
        !           340:                                                else
        !           341:                                                        exit(0);
        !           342:                                }
        !           343:                        }
        !           344:                        if (preen) {
        !           345:                                int status;
        !           346:                                while (wait(&status) != -1)
        !           347:                                        sumstatus |= status;
        !           348:                        }
        !           349:                        passno++;
        !           350:                } while (anygtr);
        !           351:                if (sumstatus)
        !           352:                        exit(8);
        !           353:                endfsent();
        !           354:        }
        !           355:        exit(0);
        !           356: }
        !           357: 
        !           358: /* char *rawname(), *unrawname(); */
        !           359: char *rawname(), *strrchr(), *unrawname();
        !           360: 
        !           361: blockcheck(name)
        !           362:        char    *name;
        !           363: {
        !           364:        struct  stat    stat_slash, stat_block, stat_char;
        !           365:        char    *raw;
        !           366:        int     looped = 0;
        !           367: 
        !           368:        hotroot = 0;
        !           369:        if (stat("/", &stat_slash) < 0){
        !           370:                error("Can't stat root\n");
        !           371:                return(NO);
        !           372:        }
        !           373:   retry:
        !           374:        if (stat(name, &stat_block) < 0){
        !           375:                error("Can't stat %s\n", name);
        !           376:                return(NO);
        !           377:        }
        !           378:        big = BIG;              /* 1k blocks by default */
        !           379:        if (S_ISBLK(stat_block.st_mode)){
        !           380:                if(BITFS(stat_block.st_rdev))
        !           381:                        big = BIG;              /* a 4k file system */
        !           382:                raw = rawname(name);
        !           383:                if (stat(raw, &stat_char) < 0){
        !           384:                        error("Can't stat %s\n", raw);
        !           385:                        return(NO);
        !           386:                }
        !           387:                if (S_ISCHR(stat_char.st_mode)){
        !           388:                        if (stat_slash.st_dev == stat_block.st_rdev) {
        !           389:                                hotroot++;
        !           390:                                raw = unrawname(name);
        !           391:                        }
        !           392:                        check(raw);
        !           393:                        return(YES);
        !           394:                } else if(big == BIG) {
        !           395:                        check(name);
        !           396:                        return(YES);
        !           397:                } else {
        !           398:                        error("%s is not a character device\n", raw);
        !           399:                        return(NO);
        !           400:                }
        !           401:        } else
        !           402:        if (S_ISCHR(stat_block.st_mode)){
        !           403:                if (looped) {
        !           404:                        error("Can't make sense out of name %s\n", name);
        !           405:                        return(NO);
        !           406:                }
        !           407:                name = unrawname(name);
        !           408:                looped++;
        !           409:                goto retry;
        !           410:        }
        !           411:        error("Can't make sense out of name %s\n", name);
        !           412:        return(NO);
        !           413: }
        !           414: 
        !           415: char *
        !           416: unrawname(cp)
        !           417:        char    *cp;
        !           418: {
        !           419:        char    *dp = strrchr(cp, '/');
        !           420:        struct stat stb;
        !           421:        if (dp == 0)
        !           422:                return(cp);
        !           423:        if (stat(cp, &stb) < 0)
        !           424:                return(cp);
        !           425:        if (S_ISCHR(stb.st_mode) == 0)
        !           426:                return(cp);
        !           427:        if (*(dp+1) != 'r')
        !           428:                return(cp);
        !           429:        strcpy(dp+1, dp+2);
        !           430:        return(cp);
        !           431: }
        !           432: 
        !           433: char *
        !           434: rawname(cp)
        !           435:        char *cp;
        !           436: {
        !           437:        static char rawbuf[32];
        !           438:        char *dp = strrchr(cp, '/');
        !           439: 
        !           440:        if (dp == 0)
        !           441:                return (0);
        !           442:        if(big == BIG)
        !           443:                return(cp);
        !           444:        *dp = 0;
        !           445:        strcpy(rawbuf, cp);
        !           446:        *dp = '/';
        !           447:        strcat(rawbuf, "/r");
        !           448:        strcat(rawbuf, dp+1);
        !           449:        return (rawbuf);
        !           450: }
        !           451: 
        !           452: check(dev)
        !           453: char *dev;
        !           454: {
        !           455: 
        !           456:        devname = dev;
        !           457:        check1(dev);
        !           458:        devname = 0;
        !           459: }
        !           460: 
        !           461: check1(dev)
        !           462: char *dev;
        !           463: {
        !           464:        register DINODE *dp;
        !           465:        register n;
        !           466:        register ino_t *blp;
        !           467:        ino_t savino;
        !           468:        daddr_t blk;
        !           469:        BUFAREA *bp1, *bp2;
        !           470: 
        !           471:        if(setup(dev) == NO)
        !           472:                return;
        !           473:        if (preen==0) {
        !           474:                printf("** Checking %s\n", dev);
        !           475:                printf("** Phase 1 - Check Blocks and Sizes\n");
        !           476:        }
        !           477:        pfunc = pass1;
        !           478:        for(inum = 1; inum <= imax; inum++) {
        !           479:                if((dp = ginode()) == NULL)
        !           480:                        continue;
        !           481:                if(ALLOC) {
        !           482:                        lastino = inum;
        !           483:                        if(ftypeok(dp) == NO) {
        !           484:                                pfatal("UNKNOWN FILE TYPE I=%u",inum);
        !           485:                                if(reply("CLEAR") == YES) {
        !           486:                                        zapino(dp);
        !           487:                                        inodirty();
        !           488:                                }
        !           489:                                continue;
        !           490:                        }
        !           491:                        n_files++;
        !           492:                        if(setlncnt(dp->di_nlink) <= 0) {
        !           493:                                if(badlnp < &badlncnt[MAXLNCNT])
        !           494:                                        *badlnp++ = inum;
        !           495:                                else {
        !           496:                                        pfatal("LINK COUNT TABLE OVERFLOW");
        !           497:                                        if(reply("CONTINUE") == NO)
        !           498:                                                errexit("");
        !           499:                                }
        !           500:                        }
        !           501:                        setstate(DIR ? DSTATE : FSTATE);
        !           502:                        badblk = dupblk = 0;
        !           503:                        filsize = 0;
        !           504:                        maxblk = 0;
        !           505:                        ckinode(dp,ADDR);
        !           506:                        if((n = getstate()) == DSTATE || n == FSTATE)
        !           507:                                sizechk(dp);
        !           508:                }
        !           509:                else if(dp->di_mode != 0) {
        !           510:                        pfatal("PARTIALLY ALLOCATED INODE I=%u",inum);
        !           511:                        if(reply("CLEAR") == YES) {
        !           512:                                zapino(dp);
        !           513:                                inodirty();
        !           514:                        }
        !           515:                }
        !           516:        }
        !           517: 
        !           518: 
        !           519:        if(enddup != &duplist[0]) {
        !           520:                if (preen)
        !           521:                        pfatal("INTERNAL ERROR: dups with -p");
        !           522:                printf("** Phase 1b - Rescan For More DUPS\n");
        !           523:                pfunc = pass1b;
        !           524:                for(inum = 1; inum <= lastino; inum++) {
        !           525:                        if(getstate() != USTATE && (dp = ginode()) != NULL)
        !           526:                                if(ckinode(dp,ADDR) & STOP)
        !           527:                                        break;
        !           528:                }
        !           529:        }
        !           530:        if(rawflg) {    /* shouldn't be set for 4k system */
        !           531:                if(inoblk.b_dirty)
        !           532:                        bwrite(&dfile,membase,startib,(int)niblk*BSIZE(big));
        !           533:                inoblk.b_dirty = 0;
        !           534:                if(poolhead) {
        !           535:                        clear(membase,niblk*BSIZE(BIG));
        !           536:                        for(bp1 = poolhead;bp1->b_next;bp1 = bp1->b_next);
        !           537:                        bp2 = &((BUFAREA *)membase)[(niblk*BSIZE(BIG))/sizeof(BUFAREA)];
        !           538:                        while(--bp2 >= (BUFAREA *)membase) {
        !           539:                                initbarea(bp2);
        !           540:                                bp2->b_next = bp1->b_next;
        !           541:                                bp1->b_next = bp2;
        !           542:                        }
        !           543:                }
        !           544:                rawflg = 0;
        !           545: 
        !           546:        }
        !           547: 
        !           548: 
        !           549:        if (preen == 0)
        !           550:                printf("** Phase 2 - Check Pathnames\n");
        !           551:        inum = ROOTINO;
        !           552:        thisname = pathp = pathname;
        !           553:        pfunc = pass2;
        !           554:        switch(getstate()) {
        !           555:                case USTATE:
        !           556:                        errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
        !           557:                case FSTATE:
        !           558:                        pfatal("ROOT INODE NOT DIRECTORY");
        !           559:                        if(reply("FIX") == NO || (dp = ginode()) == NULL)
        !           560:                                errexit("");
        !           561:                        dp->di_mode &= ~IFMT;
        !           562:                        dp->di_mode |= IFDIR;
        !           563:                        inodirty();
        !           564:                        setstate(DSTATE);
        !           565:                case DSTATE:
        !           566:                        descend();
        !           567:                        break;
        !           568:                case CLEAR:
        !           569:                        pfatal("DUPS/BAD IN ROOT INODE");
        !           570:                        printf("\n");
        !           571:                        if(reply("CONTINUE") == NO)
        !           572:                                errexit("");
        !           573:                        setstate(DSTATE);
        !           574:                        descend();
        !           575:        }
        !           576: 
        !           577: 
        !           578:        if (preen == 0)
        !           579:                printf("** Phase 3 - Check Connectivity\n");
        !           580:        for(inum = 1; inum <= lastino; inum++) {
        !           581:                if(getstate() == DSTATE) {
        !           582:                        pfunc = findino;
        !           583:                        srchname = "..";
        !           584:                        savino = inum;
        !           585:                        do {
        !           586:                                orphan = inum;
        !           587:                                if((dp = ginode()) == NULL)
        !           588:                                        break;
        !           589:                                filsize = dp->di_size;
        !           590:                                parentdir = 0;
        !           591:                                ckinode(dp,DATA);
        !           592:                                if((inum = parentdir) == 0)
        !           593:                                        break;
        !           594:                        } while(getstate() == DSTATE);
        !           595:                        inum = orphan;
        !           596:                        if(linkup() == YES) {
        !           597:                                thisname = pathp = pathname;
        !           598:                                *pathp++ = '?';
        !           599:                                pfunc = pass2;
        !           600:                                descend();
        !           601:                        }
        !           602:                        inum = savino;
        !           603:                }
        !           604:        }
        !           605: 
        !           606: 
        !           607:        if (preen == 0)
        !           608:                printf("** Phase 4 - Check Reference Counts\n");
        !           609:        pfunc = pass4;
        !           610:        zcleared = 0;
        !           611:        for(inum = 1; inum <= lastino; inum++) {
        !           612:                switch(getstate()) {
        !           613:                        case FSTATE:
        !           614:                                if(n = getlncnt())
        !           615:                                        adjust((short)n);
        !           616:                                else {
        !           617:                                        for(blp = badlncnt;blp < badlnp; blp++)
        !           618:                                                if(*blp == inum) {
        !           619:                                                        clri("UNREF",preen?NO:YES,YES);
        !           620:                                                        break;
        !           621:                                                }
        !           622:                                }
        !           623:                                break;
        !           624:                        case DSTATE:
        !           625:                                clri("UNREF",YES,NO);
        !           626:                                break;
        !           627:                        case CLEAR:
        !           628:                                clri("BAD/DUP",YES,NO);
        !           629:                }
        !           630:        }
        !           631:        if (zcleared)
        !           632:                pwarn("%u LINKLESS FILES CLEARED\n", zcleared);
        !           633:        if(imax - n_files != superblk.s_tinode) {
        !           634:                pwarn("FREE INODE COUNT %u SHOULD BE %u IN SUPERBLK",
        !           635:                        superblk.s_tinode, imax - n_files);
        !           636:                if (preen)
        !           637:                        printf(" (FIXED)\n");
        !           638:                if (preen || reply("FIX") == YES) {
        !           639:                        superblk.s_tinode = imax - n_files;
        !           640:                        sbdirty();
        !           641:                }
        !           642:        }
        !           643:        flush(&dfile,&fileblk);
        !           644: 
        !           645:        if (preen == 0)
        !           646:                printf("** Phase 5 - Check Free List ");
        !           647:        if(sflag || (csflag && rplyflag == 0)) {
        !           648:                if (preen == 0)
        !           649:                        printf("(Ignored)\n");
        !           650:                fixfree = 1;
        !           651:        }
        !           652:        else {
        !           653:                if (preen == 0)
        !           654:                        printf("\n");
        !           655:                if(freemap)
        !           656:                        copy(blkmap,freemap,(MEMSIZE)bmapsz);
        !           657:                else {
        !           658:                        for(blk = 0; blk < fmapblk; blk++) {
        !           659:                                bp1 = getblk((BUFAREA *)NULL,blk);
        !           660:                                bp2 = getblk((BUFAREA *)NULL,blk+fmapblk);
        !           661:                                copy(bp1->b_un.b_buf,bp2->b_un.b_buf,BSIZE(big));
        !           662:                                dirty(bp2);
        !           663:                        }
        !           664:                }
        !           665:                badblk = dupblk = 0;
        !           666: #ifdef SMALL
        !           667:                if(big == SMALL) {
        !           668:                        freeblk.df_nfree = superblk.s_nfree;
        !           669:                        for(n = 0; n < NICFREE; n++)
        !           670:                                freeblk.df_free[n] = superblk.s_free[n];
        !           671:                }
        !           672: #endif
        !           673:                freechk();
        !           674:                if(badblk) {
        !           675:                        pfatal("%d BAD BLKS IN FREE LIST",badblk);
        !           676:                        printf("\n");
        !           677:                }
        !           678:                if(dupblk)
        !           679:                        pwarn("%d DUP BLKS IN FREE LIST\n",dupblk);
        !           680:                if(fixfree == 0) {
        !           681:                        if((n_blks+n_free) != (fmax-fmin)) {
        !           682:                                pwarn("%ld BLK(S) MISSING\n",
        !           683:                                        fmax-fmin-n_blks-n_free);
        !           684:                                fixfree = 1;
        !           685:                        }
        !           686: #ifdef SMALL
        !           687:                        else if(big == SMALL && n_free != superblk.s_tfree) {
        !           688:                                pwarn("FREE BLK COUNT WRONG IN SUPERBLK");
        !           689:                                if (preen)
        !           690:                                        printf(" (FIXED)\n");
        !           691:                                if(preen || reply("FIX") == YES) {
        !           692:                                        superblk.s_tfree = n_free;
        !           693:                                        sbdirty();
        !           694:                                }
        !           695:                        }
        !           696: #endif
        !           697:                }
        !           698:                if(fixfree) {
        !           699:                        pwarn("BAD FREE LIST");
        !           700:                        if (preen)
        !           701:                                printf(" (SALVAGED)\n");
        !           702:                        else if(reply("SALVAGE") == NO)
        !           703:                                fixfree = 0;
        !           704:                }
        !           705:        }
        !           706: 
        !           707:        if(fixfree) {
        !           708:                if (preen == 0)
        !           709:                        printf("** Phase 6 - Salvage Free List\n");
        !           710:                makefree();
        !           711:                n_free = superblk.s_tfree;
        !           712:        }
        !           713: 
        !           714:        pwarn("%ld files %ld blocks %ld free\n", n_files,n_blks,n_free);
        !           715:        if(dfile.mod) {
        !           716:                time(&superblk.s_time);
        !           717:                sbdirty();
        !           718:        }
        !           719:        ckfini();
        !           720:        sync();
        !           721:        if(dfile.mod && hotroot) {
        !           722:                printf("ROOT MODIFIED\n");
        !           723:        }
        !           724:        if(dfile.mod && preen == 0)
        !           725:                printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
        !           726: }
        !           727: 
        !           728: /* VARARGS1 */
        !           729: error(s1,s2,s3,s4)
        !           730: char *s1;
        !           731: {
        !           732:        printf(s1,s2,s3,s4);
        !           733: }
        !           734: 
        !           735: /* VARARGS1 */
        !           736: errexit(s1,s2,s3,s4)
        !           737: char *s1;
        !           738: {
        !           739:        error(s1,s2,s3,s4);
        !           740:        exit(8);
        !           741: }
        !           742: 
        !           743: /*
        !           744:  * Pfatal is called when an inconsistency occurs
        !           745:  * which should not happen during normal operations.
        !           746:  * It printfs a message and then dies.
        !           747:  * When not preening, this is just a printf.
        !           748:  */
        !           749: pfatal(s,a1,a2,a3)
        !           750: char *s;
        !           751: {
        !           752: 
        !           753:        if (preen) {
        !           754:                printf("%s: ", devname);
        !           755:                printf(s, a1, a2, a3);
        !           756:                printf("\n");
        !           757:                preendie();
        !           758:        }
        !           759:        printf(s, a1, a2, a3);
        !           760: }
        !           761: 
        !           762: /*
        !           763:  * Fatal is called to terminate preening
        !           764:  * due to unexplainable inconsistency.
        !           765:  */
        !           766: preendie()
        !           767: {
        !           768: 
        !           769:        printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname);
        !           770:        exit(8);
        !           771: }
        !           772: 
        !           773: /*
        !           774:  * Pwarn is like printf when not preening,
        !           775:  * or a warning (preceded by filename) when preening.
        !           776:  */
        !           777: pwarn(s,a1,a2,a3,a4,a5,a6)
        !           778: char *s;
        !           779: {
        !           780: 
        !           781:        if (preen)
        !           782:                printf("%s: ", devname);
        !           783:        printf(s, a1, a2, a3, a4, a5, a6);
        !           784: }
        !           785: 
        !           786: ckinode(dp,flg)
        !           787: DINODE *dp;
        !           788: register flg;
        !           789: {
        !           790:        register daddr_t *ap;
        !           791:        register ret;
        !           792:        int (*func)(), n;
        !           793:        daddr_t iaddrs[NADDR];
        !           794: 
        !           795:        if(SPECIAL)
        !           796:                return(KEEPON);
        !           797:        l3tol(iaddrs,dp->di_addr,NADDR);
        !           798:        func = (flg == ADDR) ? pfunc : dirscan;
        !           799:        for(ap = iaddrs; ap < &iaddrs[NADDR-3]; ap++) {
        !           800:                if(*ap && (ret = (*func)(*ap)) & STOP)
        !           801:                        return(ret);
        !           802:        }
        !           803:        for(n = 1; n < 4; n++) {
        !           804:                if(*ap && (ret = iblock(*ap,n,flg)) & STOP)
        !           805:                        return(ret);
        !           806:                ap++;
        !           807:        }
        !           808:        return(KEEPON);
        !           809: }
        !           810: 
        !           811: 
        !           812: iblock(blk,ilevel,flg)
        !           813: daddr_t blk;
        !           814: register ilevel;
        !           815: {
        !           816:        register daddr_t *ap;
        !           817:        register n;
        !           818:        int (*func)();
        !           819:        BUFAREA ib;
        !           820: 
        !           821:        if(flg == ADDR) {
        !           822:                func = pfunc;
        !           823:                if(((n = (*func)(blk)) & KEEPON) == 0)
        !           824:                        return(n);
        !           825:        }
        !           826:        else
        !           827:                func = dirscan;
        !           828:        if(outrange(blk))               /* protect thyself */
        !           829:                return(SKIP);
        !           830:        initbarea(&ib);
        !           831:        if(getblk(&ib,blk) == NULL)
        !           832:                return(SKIP);
        !           833:        ilevel--;
        !           834:        for(ap = ib.b_un.b_indir; ap < &ib.b_un.b_indir[NINDIR(big)]; ap++) {
        !           835:                if(*ap) {
        !           836:                        if(ilevel > 0) {
        !           837:                                n = iblock(*ap,ilevel,flg);
        !           838:                        }
        !           839:                        else
        !           840:                                n = (*func)(*ap);
        !           841:                        if(n & STOP)
        !           842:                                return(n);
        !           843:                }
        !           844:        }
        !           845:        return(KEEPON);
        !           846: }
        !           847: 
        !           848: 
        !           849: pass1(blk)
        !           850: daddr_t blk;
        !           851: {
        !           852:        register daddr_t *dlp;
        !           853: 
        !           854:        if(outrange(blk)) {
        !           855:                blkerr("BAD",blk);
        !           856:                if(++badblk >= MAXBAD) {
        !           857:                        printf("EXCESSIVE BAD BLKS I=%u",inum);
        !           858:                        if(reply("CONTINUE") == NO)
        !           859:                                errexit("");
        !           860:                        return(STOP);
        !           861:                }
        !           862:                return(SKIP);
        !           863:        }
        !           864:        if(getbmap(blk)) {
        !           865:                blkerr("DUP",blk);
        !           866:                if(++dupblk >= MAXDUP) {
        !           867:                        printf("EXCESSIVE DUP BLKS I=%u",inum);
        !           868:                        if(reply("CONTINUE") == NO)
        !           869:                                errexit("");
        !           870:                        return(STOP);
        !           871:                }
        !           872:                if(enddup >= &duplist[DUPTBLSIZE]) {
        !           873:                        printf("DUP TABLE OVERFLOW.");
        !           874:                        if(reply("CONTINUE") == NO)
        !           875:                                errexit("");
        !           876:                        return(STOP);
        !           877:                }
        !           878:                for(dlp = duplist; dlp < muldup; dlp++) {
        !           879:                        if(*dlp == blk) {
        !           880:                                *enddup++ = blk;
        !           881:                                break;
        !           882:                        }
        !           883:                }
        !           884:                if(dlp >= muldup) {
        !           885:                        *enddup++ = *muldup;
        !           886:                        *muldup++ = blk;
        !           887:                }
        !           888:        }
        !           889:        else {
        !           890:                n_blks++;
        !           891:                setbmap(blk);
        !           892:        }
        !           893:        filsize++;
        !           894:        return(KEEPON);
        !           895: }
        !           896: 
        !           897: 
        !           898: pass1b(blk)
        !           899: daddr_t blk;
        !           900: {
        !           901:        register daddr_t *dlp;
        !           902: 
        !           903:        if(outrange(blk))
        !           904:                return(SKIP);
        !           905:        for(dlp = duplist; dlp < muldup; dlp++) {
        !           906:                if(*dlp == blk) {
        !           907:                        blkerr("DUP",blk);
        !           908:                        *dlp = *--muldup;
        !           909:                        *muldup = blk;
        !           910:                        return(muldup == duplist ? STOP : KEEPON);
        !           911:                }
        !           912:        }
        !           913:        return(KEEPON);
        !           914: }
        !           915: 
        !           916: 
        !           917: pass2(dirp)
        !           918: register DIRECT *dirp;
        !           919: {
        !           920:        register char *p;
        !           921:        register n;
        !           922:        DINODE *dp;
        !           923: 
        !           924:        if((inum = dirp->d_ino) == 0)
        !           925:                return(KEEPON);
        !           926:        thisname = pathp;
        !           927:        for(p = dirp->d_name; p < &dirp->d_name[DIRSIZ]; )
        !           928:                if((*pathp++ = *p++) == 0) {
        !           929:                        --pathp;
        !           930:                        break;
        !           931:                }
        !           932:        *pathp = 0;
        !           933:        n = NO;
        !           934:        if(inum > imax || inum <= 0)
        !           935:                n = direrr("I OUT OF RANGE");
        !           936:        else {
        !           937:        again:
        !           938:                switch(getstate()) {
        !           939:                        case USTATE:
        !           940:                                n = direrr("UNALLOCATED");
        !           941:                                break;
        !           942:                        case CLEAR:
        !           943:                                if((n = direrr("DUP/BAD")) == YES)
        !           944:                                        break;
        !           945:                                if((dp = ginode()) == NULL)
        !           946:                                        break;
        !           947:                                setstate(DIR ? DSTATE : FSTATE);
        !           948:                                goto again;
        !           949:                        case FSTATE:
        !           950:                                declncnt();
        !           951:                                break;
        !           952:                        case DSTATE:
        !           953:                                declncnt();
        !           954:                                descend();
        !           955:                }
        !           956:        }
        !           957:        pathp = thisname;
        !           958:        if(n == NO)
        !           959:                return(KEEPON);
        !           960:        dirp->d_ino = 0;
        !           961:        return(KEEPON|ALTERD);
        !           962: }
        !           963: 
        !           964: 
        !           965: pass4(blk)
        !           966: daddr_t blk;
        !           967: {
        !           968:        register daddr_t *dlp;
        !           969: 
        !           970:        if(outrange(blk))
        !           971:                return(SKIP);
        !           972:        if(getbmap(blk)) {
        !           973:                for(dlp = duplist; dlp < enddup; dlp++)
        !           974:                        if(*dlp == blk) {
        !           975:                                *dlp = *--enddup;
        !           976:                                return(KEEPON);
        !           977:                        }
        !           978:                clrbmap(blk);
        !           979:                n_blks--;
        !           980:        }
        !           981:        return(KEEPON);
        !           982: }
        !           983: 
        !           984: 
        !           985: pass5(blk)
        !           986: daddr_t blk;
        !           987: {
        !           988:        if(outrange(blk)) {
        !           989:                fixfree = 1;
        !           990:                if (preen)
        !           991:                        pfatal("BAD BLOCKS IN FREE LIST.");
        !           992:                if(++badblk >= MAXBAD) {
        !           993:                        printf("EXCESSIVE BAD BLKS IN FREE LIST.");
        !           994:                        if(reply("CONTINUE") == NO)
        !           995:                                errexit("");
        !           996:                        return(STOP);
        !           997:                }
        !           998:                return(SKIP);
        !           999:        }
        !          1000:        if(getfmap(blk)) {
        !          1001:                fixfree = 1;
        !          1002:                if(++dupblk >= DUPTBLSIZE) {
        !          1003:                        printf("EXCESSIVE DUP BLKS IN FREE LIST.");
        !          1004:                        if(reply("CONTINUE") == NO)
        !          1005:                                errexit("");
        !          1006:                        return(STOP);
        !          1007:                }
        !          1008:        }
        !          1009:        else {
        !          1010:                n_free++;
        !          1011:                setfmap(blk);
        !          1012:        }
        !          1013:        return(KEEPON);
        !          1014: }
        !          1015: 
        !          1016: 
        !          1017: blkerr(s,blk)
        !          1018: daddr_t blk;
        !          1019: char *s;
        !          1020: {
        !          1021:        pfatal("%ld %s I=%u",blk,s,inum);
        !          1022:        printf("\n");
        !          1023:        setstate(CLEAR);        /* mark for possible clearing */
        !          1024: }
        !          1025: 
        !          1026: 
        !          1027: descend()
        !          1028: {
        !          1029:        register DINODE *dp;
        !          1030:        register char *savname;
        !          1031:        off_t savsize;
        !          1032: 
        !          1033:        setstate(FSTATE);
        !          1034:        if((dp = ginode()) == NULL)
        !          1035:                return;
        !          1036:        savname = thisname;
        !          1037:        *pathp++ = '/';
        !          1038:        savsize = filsize;
        !          1039:        filsize = dp->di_size;
        !          1040:        ckinode(dp,DATA);
        !          1041:        thisname = savname;
        !          1042:        *--pathp = 0;
        !          1043:        filsize = savsize;
        !          1044: }
        !          1045: 
        !          1046: 
        !          1047: dirscan(blk)
        !          1048: daddr_t blk;
        !          1049: {
        !          1050:        register DIRECT *dirp;
        !          1051:        register char *p1, *p2;
        !          1052:        register n;
        !          1053:        DIRECT direntry;
        !          1054: 
        !          1055:        if(outrange(blk)) {
        !          1056:                filsize -= BSIZE(big);
        !          1057:                return(SKIP);
        !          1058:        }
        !          1059:        for(dirp = dirblk.b_dir; dirp < &dirblk.b_dir[NDIRECT(big)] &&
        !          1060:                filsize > 0; dirp++, filsize -= sizeof(DIRECT)) {
        !          1061:                if(getblk(&fileblk,blk) == NULL) {
        !          1062:                        filsize -= (&dirblk.b_dir[NDIRECT(big)]-dirp)*
        !          1063:                                sizeof(DIRECT);
        !          1064:                        return(SKIP);
        !          1065:                }
        !          1066:                p1 = &dirp->d_name[DIRSIZ];
        !          1067:                p2 = &direntry.d_name[DIRSIZ];
        !          1068:                while(p1 > (char *)dirp)
        !          1069:                        *--p2 = *--p1;
        !          1070:                if((n = (*pfunc)(&direntry)) & ALTERD) {
        !          1071:                        if(getblk(&fileblk,blk) != NULL) {
        !          1072:                                p1 = &dirp->d_name[DIRSIZ];
        !          1073:                                p2 = &direntry.d_name[DIRSIZ];
        !          1074:                                while(p1 > (char *)dirp)
        !          1075:                                        *--p1 = *--p2;
        !          1076:                                fbdirty();
        !          1077:                        }
        !          1078:                        else
        !          1079:                                n &= ~ALTERD;
        !          1080:                }
        !          1081:                if(n & STOP)
        !          1082:                        return(n);
        !          1083:        }
        !          1084:        return(filsize > 0 ? KEEPON : STOP);
        !          1085: }
        !          1086: 
        !          1087: 
        !          1088: direrr(s)
        !          1089: char *s;
        !          1090: {
        !          1091:        register DINODE *dp;
        !          1092: 
        !          1093:        pwarn("%s ",s);
        !          1094:        pinode();
        !          1095:        printf("\n");
        !          1096:        if((dp = ginode()) != NULL && ftypeok(dp))
        !          1097:                pfatal("%s=%s",DIR?"DIR":"FILE",pathname);
        !          1098:        else
        !          1099:                pfatal("NAME=%s",pathname);
        !          1100:        return(reply("REMOVE"));
        !          1101: }
        !          1102: 
        !          1103: 
        !          1104: adjust(lcnt)
        !          1105: register short lcnt;
        !          1106: {
        !          1107:        register DINODE *dp;
        !          1108: 
        !          1109:        if((dp = ginode()) == NULL)
        !          1110:                return;
        !          1111:        if(dp->di_nlink == lcnt) {
        !          1112:                if(linkup() == NO)
        !          1113:                        clri("UNREF",NO,NO);
        !          1114:        }
        !          1115:        else {
        !          1116:                pwarn("LINK COUNT %s",
        !          1117:                        (lfdir==inum)?lfname:(DIR?"DIR":"FILE"));
        !          1118:                pinode();
        !          1119:                printf(" COUNT %d SHOULD BE %d",
        !          1120:                        dp->di_nlink,dp->di_nlink-lcnt);
        !          1121:                if (preen) {
        !          1122:                        if (lcnt < 0) {
        !          1123:                                printf("\n");
        !          1124:                                preendie();
        !          1125:                        }
        !          1126:                        printf(" (ADJUSTED)\n");
        !          1127:                }
        !          1128:                if(preen || reply("ADJUST") == YES) {
        !          1129:                        dp->di_nlink -= lcnt;
        !          1130:                        inodirty();
        !          1131:                }
        !          1132:        }
        !          1133: }
        !          1134: 
        !          1135: 
        !          1136: clri(s,flg,jclr)
        !          1137: char *s;
        !          1138: {
        !          1139:        register DINODE *dp;
        !          1140: 
        !          1141:        if((dp = ginode()) == NULL)
        !          1142:                return;
        !          1143:        if(flg == YES) {
        !          1144:                pwarn("%s %s",s,DIR?"DIR":"FILE");
        !          1145:                pinode();
        !          1146:        }
        !          1147:        if(preen || reply("CLEAR") == YES) {
        !          1148:                if (preen)
        !          1149:                        if (jclr == YES)
        !          1150:                                zcleared++;
        !          1151:                        else
        !          1152:                                printf(" (CLEARED)\n");
        !          1153:                n_files--;
        !          1154:                pfunc = pass4;
        !          1155:                ckinode(dp,ADDR);
        !          1156:                zapino(dp);
        !          1157:                inodirty();
        !          1158:        }
        !          1159: }
        !          1160: 
        !          1161: 
        !          1162: setup(dev)
        !          1163: char *dev;
        !          1164: {
        !          1165:        register n;
        !          1166:        register BUFAREA *bp;
        !          1167:        register MEMSIZE msize;
        !          1168:        char *mbase;
        !          1169:        daddr_t bcnt, nscrblk;
        !          1170:        dev_t rootdev;
        !          1171:        off_t smapsz, lncntsz, totsz;
        !          1172:        struct stat statarea;
        !          1173: 
        !          1174:        if(stat("/",&statarea) < 0)
        !          1175:                errexit("Can't stat root\n");
        !          1176:        rootdev = statarea.st_dev;
        !          1177:        if(stat(dev,&statarea) < 0) {
        !          1178:                error("Can't stat %s\n",dev);
        !          1179:                return(NO);
        !          1180:        }
        !          1181:        rawflg = 0;
        !          1182:        big = BIG;      /* does this undo the work in blockcheck? */
        !          1183:        if(S_ISBLK(statarea.st_mode)) {
        !          1184:                if(BITFS(statarea.st_rdev))
        !          1185:                        big = BIG;
        !          1186:        }
        !          1187:        else if(S_ISCHR(statarea.st_mode))
        !          1188:                rawflg++;
        !          1189:        else {
        !          1190:                if (reply("file is not a block or character device; OK") == NO)
        !          1191:                        return(NO);
        !          1192:                big = BIG;
        !          1193:        }
        !          1194:        if(rootdev == statarea.st_rdev)
        !          1195:                hotroot++;
        !          1196:        if((dfile.rfdes = open(dev,0)) < 0) {
        !          1197:                error("Can't open %s\n",dev);
        !          1198:                return(NO);
        !          1199:        }
        !          1200:        if (preen == 0)
        !          1201:                printf("\n%s",dev);
        !          1202:        if(nflag || (dfile.wfdes = open(dev,1)) < 0) {
        !          1203:                dfile.wfdes = -1;
        !          1204:                if (preen)
        !          1205:                        pfatal("NO WRITE ACCESS");
        !          1206:                printf(" (NO WRITE)");
        !          1207:        }
        !          1208:        if (preen == 0)
        !          1209:                printf("\n");
        !          1210:        fixfree = 0;
        !          1211:        dfile.mod = 0;
        !          1212:        n_files = n_blks = n_free = 0;
        !          1213:        muldup = enddup = &duplist[0];
        !          1214:        badlnp = &badlncnt[0];
        !          1215:        lfdir = 0;
        !          1216:        rplyflag = 0;
        !          1217:        initbarea(&sblk);
        !          1218:        initbarea(&fileblk);
        !          1219:        initbarea(&inoblk);
        !          1220:        sfile.wfdes = sfile.rfdes = -1;
        !          1221:        rmscr = 0;
        !          1222:        if(getblk(&sblk,SUPERB) == NULL) {
        !          1223:                ckfini();
        !          1224:                return(NO);
        !          1225:        }
        !          1226:        imax = ((ino_t)superblk.s_isize - (SUPERB+1)) * INOPB(big);
        !          1227:        fmin = (daddr_t)superblk.s_isize;       /* first data blk num */
        !          1228:        fmax = superblk.s_fsize;                /* first invalid blk num */
        !          1229:        m_blks = 0;
        !          1230:        /*
        !          1231:          * if this is a big bit mapped file system,
        !          1232:         *      back off fmax by m_blks the number of bitmap blocks.
        !          1233:         */
        !          1234:        if ((big == BIG) && superblk.U.N.S_flag) {
        !          1235:                m_blks = (superblk.s_fsize+superblk.U.N.S_bsize-1)/superblk.U.N.S_bsize;
        !          1236:                fmax -= m_blks;
        !          1237:        }
        !          1238:        if(fmin >= fmax || 
        !          1239:                (imax/INOPB(big)) != ((ino_t)superblk.s_isize-(SUPERB+1))) {
        !          1240:                pfatal("Size check: fsize %ld isize %d",
        !          1241:                        superblk.s_fsize,superblk.s_isize);
        !          1242:                printf("\n");
        !          1243:                ckfini();
        !          1244:                return(NO);
        !          1245:        }
        !          1246:        if (preen == 0)
        !          1247:                printf("File System: %.12s\n\n", superblk.s_fsmnt);
        !          1248:        bmapsz = roundup(howmany(fmax,BITSPB),sizeof(*lncntp));
        !          1249:        smapsz = roundup(howmany((long)(imax+1),STATEPB),sizeof(*lncntp));
        !          1250:        lncntsz = (long)(imax+1) * sizeof(*lncntp);
        !          1251:        if(bmapsz > smapsz+lncntsz)
        !          1252:                smapsz = bmapsz-lncntsz;
        !          1253:        totsz = bmapsz+smapsz+lncntsz;
        !          1254: 
        !          1255:        bm_buf = (long *)membase;
        !          1256:        memsize = memsize-BSIZE(BIG);
        !          1257:        membase = membase+BSIZE(BIG);
        !          1258: 
        !          1259:        msize = memsize;
        !          1260:        mbase = membase;
        !          1261:        if(rawflg) {
        !          1262:                if(msize < (MEMSIZE)(NINOBLK*BSIZE(big)) + 2*sizeof(BUFAREA))
        !          1263:                        rawflg = 0;
        !          1264:                else {
        !          1265:                        msize -= (MEMSIZE)NINOBLK*BSIZE(big);
        !          1266:                        mbase += (MEMSIZE)NINOBLK*BSIZE(big);
        !          1267:                        niblk = NINOBLK;
        !          1268:                        startib = fmax;
        !          1269:                }
        !          1270:        }
        !          1271:        clear(mbase,msize);
        !          1272:        if((off_t)msize < totsz) {
        !          1273:                bmapsz = roundup(bmapsz,BSIZE(big));
        !          1274:                smapsz = roundup(smapsz,BSIZE(big));
        !          1275:                lncntsz = roundup(lncntsz,BSIZE(big));
        !          1276:                nscrblk = (bmapsz+smapsz+lncntsz)>>BSHIFT(big);
        !          1277:                if(tflag == 0) {
        !          1278:                        printf("\nNEED SCRATCH FILE (%ld BLKS)\n",nscrblk);
        !          1279:                        do {
        !          1280:                                printf("ENTER FILENAME:  ");
        !          1281:                                if((n = getline(stdin,scrfile,sizeof(scrfile))) == EOF)
        !          1282:                                        errexit("\n");
        !          1283:                        } while(n == 0);
        !          1284:                }
        !          1285:                if(stat(scrfile,&statarea) < 0 || S_ISREG(statarea.st_mode))
        !          1286:                        rmscr++;
        !          1287:                if((sfile.wfdes = creat(scrfile,0666)) < 0 ||
        !          1288:                        (sfile.rfdes = open(scrfile,0)) < 0) {
        !          1289:                        error("Can't create %s\n",scrfile);
        !          1290:                        ckfini();
        !          1291:                        return(NO);
        !          1292:                }
        !          1293:                bp = &((BUFAREA *)mbase)[(msize/sizeof(BUFAREA))];
        !          1294:                poolhead = NULL;
        !          1295:                while(--bp >= (BUFAREA *)mbase) {
        !          1296:                        initbarea(bp);
        !          1297:                        bp->b_next = poolhead;
        !          1298:                        poolhead = bp;
        !          1299:                }
        !          1300:                bp = poolhead;
        !          1301:                for(bcnt = 0; bcnt < nscrblk; bcnt++) {
        !          1302:                        bp->b_bno = bcnt;
        !          1303:                        dirty(bp);
        !          1304:                        flush(&sfile,bp);
        !          1305:                }
        !          1306:                blkmap = freemap = statemap = (char *) NULL;
        !          1307:                lncntp = (short *) NULL;
        !          1308:                smapblk = bmapsz / BSIZE(big);
        !          1309:                lncntblk = smapblk + smapsz / BSIZE(big);
        !          1310:                fmapblk = smapblk;
        !          1311:        }
        !          1312:        else {
        !          1313:                if(rawflg && (off_t)msize > totsz+BSIZE(big)) {
        !          1314:                        niblk += (unsigned)((off_t)msize-totsz)>>BSHIFT(big);
        !          1315:                        if(niblk > MAXRAW)
        !          1316:                                niblk = MAXRAW;
        !          1317:                        msize = memsize - (niblk*BSIZE(big));
        !          1318:                        mbase = membase + (niblk*BSIZE(big));
        !          1319:                }
        !          1320:                poolhead = NULL;
        !          1321:                blkmap = mbase;
        !          1322:                statemap = &mbase[(MEMSIZE)bmapsz];
        !          1323:                freemap = statemap;
        !          1324:                lncntp = (short *)&statemap[(MEMSIZE)smapsz];
        !          1325:        }
        !          1326:        return(YES);
        !          1327: }
        !          1328: 
        !          1329: 
        !          1330: DINODE *
        !          1331: ginode()
        !          1332: {
        !          1333:        register DINODE *dp;
        !          1334:        register char *mbase;
        !          1335:        daddr_t iblk;
        !          1336: 
        !          1337:        if(inum > imax)
        !          1338:                return(NULL);
        !          1339:        iblk = itod(big, inum);
        !          1340:        if(rawflg) {
        !          1341:                mbase = membase;
        !          1342:                if(iblk < startib || iblk >= startib+niblk) {
        !          1343:                        if(inoblk.b_dirty)
        !          1344:                                bwrite(&dfile,mbase,startib,(int)niblk*BSIZE(big));
        !          1345:                        inoblk.b_dirty = 0;
        !          1346:                        if(bread(&dfile,mbase,iblk,(int)niblk*BSIZE(big)) == NO) {
        !          1347:                                startib = fmax;
        !          1348:                                return(NULL);
        !          1349:                        }
        !          1350:                        startib = iblk;
        !          1351:                }
        !          1352:                dp = (DINODE *)&mbase[(unsigned)((iblk-startib)<<BSHIFT(big))];
        !          1353:        }
        !          1354:        else if(getblk(&inoblk,iblk) != NULL)
        !          1355:                dp = inoblk.b_un.b_dinode;
        !          1356:        else
        !          1357:                return(NULL);
        !          1358:        return(dp + itoo(big, inum));
        !          1359: }
        !          1360: 
        !          1361: 
        !          1362: ftypeok(dp)
        !          1363: DINODE *dp;
        !          1364: {
        !          1365:        switch(dp->di_mode & IFMT) {
        !          1366:                case IFDIR:
        !          1367:                case IFREG:
        !          1368:                case IFBLK:
        !          1369:                case IFCHR:
        !          1370:        /*      case IFMPC:     */
        !          1371:                case IFLNK:
        !          1372:        /*      case IFMPB:     */
        !          1373:                        return(YES);
        !          1374:                default:
        !          1375:                        return(NO);
        !          1376:        }
        !          1377: }
        !          1378: 
        !          1379: 
        !          1380: reply(s)
        !          1381: char *s;
        !          1382: {
        !          1383:        char line[80];
        !          1384: 
        !          1385:        if (preen)
        !          1386:                pfatal("INTERNAL ERROR: GOT TO reply()");
        !          1387:        rplyflag = 1;
        !          1388:        printf("\n%s? ",s);
        !          1389:        if(nflag || csflag || dfile.wfdes < 0) {
        !          1390:                printf(" no\n\n");
        !          1391:                return(NO);
        !          1392:        }
        !          1393:        if(yflag) {
        !          1394:                printf(" yes\n\n");
        !          1395:                return(YES);
        !          1396:        }
        !          1397:        if(getline(stdin,line,sizeof(line)) == EOF)
        !          1398:                errexit("\n");
        !          1399:        printf("\n");
        !          1400:        if(line[0] == 'y' || line[0] == 'Y')
        !          1401:                return(YES);
        !          1402:        else
        !          1403:                return(NO);
        !          1404: }
        !          1405: 
        !          1406: 
        !          1407: getline(fp,loc,maxlen)
        !          1408: FILE *fp;
        !          1409: char *loc;
        !          1410: {
        !          1411:        register n;
        !          1412:        register char *p, *lastloc;
        !          1413: 
        !          1414:        p = loc;
        !          1415:        lastloc = &p[maxlen-1];
        !          1416:        while((n = getc(fp)) != '\n') {
        !          1417:                if(n == EOF)
        !          1418:                        return(EOF);
        !          1419:                if(!isspace(n) && p < lastloc)
        !          1420:                        *p++ = n;
        !          1421:        }
        !          1422:        *p = 0;
        !          1423:        return(p - loc);
        !          1424: }
        !          1425: 
        !          1426: 
        !          1427: stype(p)
        !          1428: register char *p;
        !          1429: {
        !          1430:        if(*p == 0)
        !          1431:                return;
        !          1432:        cylsize = atoi(p);
        !          1433:        while(*p && *p != ':')
        !          1434:                p++;
        !          1435:        if(*p)
        !          1436:                p++;
        !          1437:        stepsize = atoi(p);
        !          1438:        if(stepsize <= 0 || stepsize > cylsize ||
        !          1439:        cylsize <= 0 || cylsize > MAXCYL) {
        !          1440:                error("Invalid -s argument, defaults assumed\n");
        !          1441:                cylsize = stepsize = 0;
        !          1442:        }
        !          1443: }
        !          1444: 
        !          1445: 
        !          1446: dostate(s,flg)
        !          1447: {
        !          1448:        register char *p;
        !          1449:        register unsigned byte, shift;
        !          1450:        BUFAREA *bp;
        !          1451: 
        !          1452:        byte = (inum)/STATEPB;
        !          1453:        shift = LSTATE * ((inum)%STATEPB);
        !          1454:        if(statemap != NULL) {
        !          1455:                bp = NULL;
        !          1456:                p = &statemap[byte];
        !          1457:        }
        !          1458:        else if((bp = getblk((BUFAREA *)NULL,
        !          1459:                        (daddr_t)(smapblk+(byte/BSIZE(big))))) == NULL)
        !          1460:                errexit("Fatal I/O error\n");
        !          1461:        else
        !          1462:                p = &bp->b_un.b_buf[byte%BSIZE(big)];
        !          1463:        switch(flg) {
        !          1464:                case 0:
        !          1465:                        *p &= ~(SMASK<<(shift));
        !          1466:                        *p |= s<<(shift);
        !          1467:                        if(bp != NULL)
        !          1468:                                dirty(bp);
        !          1469:                        return(s);
        !          1470:                case 1:
        !          1471:                        return((*p>>(shift)) & SMASK);
        !          1472:        }
        !          1473:        return(USTATE);
        !          1474: }
        !          1475: 
        !          1476: 
        !          1477: domap(blk,flg)
        !          1478: daddr_t blk;
        !          1479: {
        !          1480:        register char *p;
        !          1481:        register unsigned n;
        !          1482:        register BUFAREA *bp;
        !          1483:        off_t byte;
        !          1484: 
        !          1485:        byte = blk >> BITSHIFT;
        !          1486:        n = 1<<((unsigned)(blk & BITMASK));
        !          1487:        if(flg & 04) {
        !          1488:                p = freemap;
        !          1489:                blk = fmapblk;
        !          1490:        }
        !          1491:        else {
        !          1492:                p = blkmap;
        !          1493:                blk = 0;
        !          1494:        }
        !          1495:        if(p != NULL) {
        !          1496:                bp = NULL;
        !          1497:                p += (unsigned)byte;
        !          1498:        }
        !          1499:        else if((bp = getblk((BUFAREA *)NULL,blk+(byte>>BSHIFT(big)))) == NULL)
        !          1500:                errexit("Fatal I/O error\n");
        !          1501:        else
        !          1502:                p = &bp->b_un.b_buf[(unsigned)(byte&BMASK(big))];
        !          1503:        switch(flg&03) {
        !          1504:                case 0:
        !          1505:                        *p |= n;
        !          1506:                        break;
        !          1507:                case 1:
        !          1508:                        n &= *p;
        !          1509:                        bp = NULL;
        !          1510:                        break;
        !          1511:                case 2:
        !          1512:                        *p &= ~n;
        !          1513:        }
        !          1514:        if(bp != NULL)
        !          1515:                dirty(bp);
        !          1516:        return(n);
        !          1517: }
        !          1518: 
        !          1519: 
        !          1520: dobfree(blk,flg)
        !          1521: {
        !          1522: }
        !          1523: 
        !          1524: 
        !          1525: dolncnt(val,flg)
        !          1526: short val;
        !          1527: {
        !          1528:        register short *sp;
        !          1529:        register BUFAREA *bp;
        !          1530: 
        !          1531:        if(lncntp != NULL) {
        !          1532:                bp = NULL;
        !          1533:                sp = &lncntp[inum];
        !          1534:        }
        !          1535:        else if((bp = getblk((BUFAREA *)NULL,(daddr_t)(lncntblk+(inum/SPERB(big))))) == NULL)
        !          1536:                errexit("Fatal I/O error\n");
        !          1537:        else
        !          1538:                sp = &bp->b_un.b_lnks[inum%SPERB(big)];
        !          1539:        switch(flg) {
        !          1540:                case 0:
        !          1541:                        *sp = val;
        !          1542:                        break;
        !          1543:                case 1:
        !          1544:                        bp = NULL;
        !          1545:                        break;
        !          1546:                case 2:
        !          1547:                        (*sp)--;
        !          1548:        }
        !          1549:        if(bp != NULL)
        !          1550:                dirty(bp);
        !          1551:        return(*sp);
        !          1552: }
        !          1553: 
        !          1554: 
        !          1555: BUFAREA *
        !          1556: getblk(bp,blk)
        !          1557: daddr_t blk;
        !          1558: register BUFAREA *bp;
        !          1559: {
        !          1560:        register struct filecntl *fcp;
        !          1561: 
        !          1562:        if(bp == NULL) {
        !          1563:                bp = search(blk);
        !          1564:                fcp = &sfile;
        !          1565:        }
        !          1566:        else
        !          1567:                fcp = &dfile;
        !          1568:        if(bp->b_bno == blk)
        !          1569:                return(bp);
        !          1570:        flush(fcp,bp);
        !          1571:        if(bread(fcp,bp->b_un.b_buf,blk,BSIZE(big)) != NO) {
        !          1572:                bp->b_bno = blk;
        !          1573:                return(bp);
        !          1574:        }
        !          1575:        bp->b_bno = (daddr_t)-1;
        !          1576:        return(NULL);
        !          1577: }
        !          1578: 
        !          1579: 
        !          1580: flush(fcp,bp)
        !          1581: struct filecntl *fcp;
        !          1582: register BUFAREA *bp;
        !          1583: {
        !          1584:        if(bp->b_dirty) {
        !          1585:                bwrite(fcp,bp->b_un.b_buf,bp->b_bno,BSIZE(big));
        !          1586:        }
        !          1587:        bp->b_dirty = 0;
        !          1588: }
        !          1589: 
        !          1590: 
        !          1591: rwerr(s,blk)
        !          1592: char *s;
        !          1593: daddr_t blk;
        !          1594: {
        !          1595:        if (preen == 0)
        !          1596:                printf("\n");
        !          1597:        pfatal("CAN NOT %s: BLK %ld",s,blk);
        !          1598:        if(reply("CONTINUE") == NO)
        !          1599:                errexit("Program terminated\n");
        !          1600: }
        !          1601: 
        !          1602: 
        !          1603: sizechk(dp)
        !          1604: register DINODE *dp;
        !          1605: {
        !          1606: /*
        !          1607:        if (maxblk != howmany(dp->di_size, BSIZE))
        !          1608:                printf("POSSIBLE FILE SIZE ERROR I=%u (%ld,%ld)\n\n",
        !          1609:                    inum, maxblk, howmany(dp->di_size,BSIZE));
        !          1610: */
        !          1611:        if(DIR && (dp->di_size % sizeof(DIRECT)) != 0) {
        !          1612:                pwarn("DIRECTORY MISALIGNED I=%u\n",inum);
        !          1613:                if (preen == 0)
        !          1614:                        printf("\n");
        !          1615:        }
        !          1616: }
        !          1617: 
        !          1618: 
        !          1619: ckfini()
        !          1620: {
        !          1621:        flush(&dfile,&fileblk);
        !          1622:        flush(&dfile,&sblk);
        !          1623:        flush(&dfile,&inoblk);
        !          1624:        close(dfile.rfdes);
        !          1625:        close(dfile.wfdes);
        !          1626:        close(sfile.rfdes);
        !          1627:        close(sfile.wfdes);
        !          1628:        if(rmscr) {
        !          1629:                unlink(scrfile);
        !          1630:        }
        !          1631: }
        !          1632: 
        !          1633: 
        !          1634: pinode()
        !          1635: {
        !          1636:        register DINODE *dp;
        !          1637:        register char *p;
        !          1638:        struct passwd *passwd;
        !          1639:        struct passwd *getpwuid();
        !          1640:        char *ctime();
        !          1641: 
        !          1642:        printf(" I=%u ",inum);
        !          1643:        if((dp = ginode()) == NULL)
        !          1644:                return;
        !          1645:        printf(" OWNER=");
        !          1646:        if((passwd = getpwuid((int)dp->di_uid)) != 0) {
        !          1647:                printf("%s ", passwd->pw_name);
        !          1648:        }
        !          1649:        else {
        !          1650:                printf("%d ",dp->di_uid);
        !          1651:        }
        !          1652:        printf("MODE=%o\n",dp->di_mode);
        !          1653:        if (preen)
        !          1654:                printf("%s: ", devname);
        !          1655:        printf("SIZE=%ld ",dp->di_size);
        !          1656:        p = ctime(&dp->di_mtime);
        !          1657:        printf("MTIME=%12.12s %4.4s ",p+4,p+20);
        !          1658: }
        !          1659: 
        !          1660: 
        !          1661: copy(fp,tp,size)
        !          1662: register char *tp, *fp;
        !          1663: MEMSIZE size;
        !          1664: {
        !          1665:        while(size--)
        !          1666:                *tp++ = *fp++;
        !          1667: }
        !          1668: 
        !          1669: 
        !          1670: freechk()
        !          1671: {
        !          1672:        register daddr_t *ap;
        !          1673:        daddr_t blkno;
        !          1674:        daddr_t bm_blk;
        !          1675:        daddr_t bitno;
        !          1676: 
        !          1677:        n_free = 0;
        !          1678:        if(big == BIG) {
        !          1679:                if (m_blks) {
        !          1680:                        blkno = bitno = superblk.s_isize;
        !          1681:                         bm_blk = fmax;
        !          1682:                         memset((char *)bm_buf, 0, BSIZE(BIG));
        !          1683:                         while(blkno < fmax) {
        !          1684:                                if(!getfmap(blkno++)) {
        !          1685:                                         BITFREE(bm_buf, bitno);
        !          1686:                                         n_free++;
        !          1687:                                 }
        !          1688:                                 if(++bitno == BITSPERBLK) {
        !          1689:                                         bwrite(&dfile, (char *)bm_buf, bm_blk, BSIZE(BIG));
        !          1690:                                         bm_blk++;
        !          1691:                                        memset((char *)bm_buf, 0, BSIZE(BIG));
        !          1692:                                         bitno = 0;
        !          1693:                                 }
        !          1694: 
        !          1695:                        }
        !          1696:                         if(bitno) {
        !          1697:                                bwrite(&dfile, (char *)bm_buf, bm_blk, BSIZE(BIG));
        !          1698:                         }
        !          1699:                }
        !          1700:                else {
        !          1701:                        memset((char *)superblk.s_bfree, 0, BITMAP);
        !          1702:                        for(blkno = superblk.s_isize; blkno < fmax; blkno++) {
        !          1703:                                 if(!getfmap(blkno)) {
        !          1704:                                         BITFREE(superblk.s_bfree, blkno-superblk.s_isize);
        !          1705:                                         n_free++;
        !          1706:                                 }
        !          1707:                        }
        !          1708:                }
        !          1709:                superblk.s_valid = 1;
        !          1710:                superblk.s_tfree = n_free;
        !          1711:                sbdirty();
        !          1712:                return;
        !          1713:        }
        !          1714: #ifdef SMALL
        !          1715:        if(freeblk.df_nfree == 0)
        !          1716:                return;
        !          1717:        do {
        !          1718:                if(freeblk.df_nfree <= 0 || freeblk.df_nfree > NICFREE) {
        !          1719:                        pwarn("BAD FREEBLK COUNT");
        !          1720:                        printf("\n");
        !          1721:                        fixfree = 1;
        !          1722:                        return;
        !          1723:                }
        !          1724:                ap = &freeblk.df_free[freeblk.df_nfree];
        !          1725:                while(--ap > &freeblk.df_free[0]) {
        !          1726:                        if(pass5(*ap) == STOP)
        !          1727:                                return;
        !          1728:                }
        !          1729:                if(*ap == (daddr_t)0 || pass5(*ap) != KEEPON)
        !          1730:                        return;
        !          1731:        } while(getblk(&fileblk,*ap) != NULL);
        !          1732: #endif
        !          1733: }
        !          1734: 
        !          1735: 
        !          1736: makefree()
        !          1737: {
        !          1738:        register i, cyl, step;
        !          1739:        int j;
        !          1740:        char flg[MAXCYL];
        !          1741:        short addr[MAXCYL];
        !          1742:        daddr_t blk, baseblk;
        !          1743: 
        !          1744:        if(big == BIG)
        !          1745:                return;
        !          1746: #ifdef SMALL
        !          1747:        superblk.s_nfree = 0;
        !          1748:        superblk.s_flock = 0;
        !          1749:        superblk.s_fmod = 0;
        !          1750:        superblk.s_tfree = 0;
        !          1751:        superblk.s_ninode = 0;
        !          1752:        superblk.s_ilock = 0;
        !          1753:        superblk.s_ronly = 0;
        !          1754:        if(cylsize == 0 || stepsize == 0) {
        !          1755:                step = superblk.s_dinfo[0];
        !          1756:                cyl = superblk.s_dinfo[1];
        !          1757:        }
        !          1758:        else {
        !          1759:                step = stepsize;
        !          1760:                cyl = cylsize;
        !          1761:        }
        !          1762:        if(step > cyl || step <= 0 || cyl <= 0 || cyl > MAXCYL) {
        !          1763:                error("Default free list spacing assumed\n");
        !          1764:                step = STEPSIZE;
        !          1765:                cyl = CYLSIZE;
        !          1766:        }
        !          1767:        superblk.s_dinfo[0] = step;
        !          1768:        superblk.s_dinfo[1] = cyl;
        !          1769:        clear(flg,sizeof(flg));
        !          1770:        i = 0;
        !          1771:        for(j = 0; j < cyl; j++) {
        !          1772:                while(flg[i])
        !          1773:                        i = (i + 1) % cyl;
        !          1774:                addr[j] = i + 1;
        !          1775:                flg[i]++;
        !          1776:                i = (i + step) % cyl;
        !          1777:        }
        !          1778:        baseblk = (daddr_t)roundup(fmax,cyl);
        !          1779:        clear((char *)&freeblk,BSIZE(big));
        !          1780:        freeblk.df_nfree++;
        !          1781:        for( ; baseblk > 0; baseblk -= cyl)
        !          1782:                for(i = 0; i < cyl; i++) {
        !          1783:                        blk = baseblk - addr[i];
        !          1784:                        if(!outrange(blk) && !getbmap(blk)) {
        !          1785:                                superblk.s_tfree++;
        !          1786:                                if(freeblk.df_nfree >= NICFREE) {
        !          1787:                                        fbdirty();
        !          1788:                                        fileblk.b_bno = blk;
        !          1789:                                        flush(&dfile,&fileblk);
        !          1790:                                        clear((char *)&freeblk,BSIZE(big));
        !          1791:                                }
        !          1792:                                freeblk.df_free[freeblk.df_nfree] = blk;
        !          1793:                                freeblk.df_nfree++;
        !          1794:                        }
        !          1795:                }
        !          1796:        superblk.s_nfree = freeblk.df_nfree;
        !          1797:        for(i = 0; i < NICFREE; i++)
        !          1798:                superblk.s_free[i] = freeblk.df_free[i];
        !          1799:        sbdirty();
        !          1800: #endif
        !          1801: }
        !          1802: 
        !          1803: 
        !          1804: clear(p,cnt)
        !          1805: register char *p;
        !          1806: MEMSIZE cnt;
        !          1807: {
        !          1808:        while(cnt--)
        !          1809:                *p++ = 0;
        !          1810: }
        !          1811: 
        !          1812: 
        !          1813: BUFAREA *
        !          1814: search(blk)
        !          1815: daddr_t blk;
        !          1816: {
        !          1817:        register BUFAREA *pbp, *bp;
        !          1818: 
        !          1819:        for(bp = (BUFAREA *) &poolhead; bp->b_next; ) {
        !          1820:                pbp = bp;
        !          1821:                bp = pbp->b_next;
        !          1822:                if(bp->b_bno == blk)
        !          1823:                        break;
        !          1824:        }
        !          1825:        pbp->b_next = bp->b_next;
        !          1826:        bp->b_next = poolhead;
        !          1827:        poolhead = bp;
        !          1828:        return(bp);
        !          1829: }
        !          1830: 
        !          1831: 
        !          1832: findino(dirp)
        !          1833: register DIRECT *dirp;
        !          1834: {
        !          1835:        register char *p1, *p2;
        !          1836: 
        !          1837:        if(dirp->d_ino == 0)
        !          1838:                return(KEEPON);
        !          1839:        for(p1 = dirp->d_name,p2 = srchname;*p2++ == *p1; p1++) {
        !          1840:                if(*p1 == 0 || p1 == &dirp->d_name[DIRSIZ-1]) {
        !          1841:                        if(dirp->d_ino > 0 && dirp->d_ino <= imax)
        !          1842:                                parentdir = dirp->d_ino;
        !          1843:                        return(STOP);
        !          1844:                }
        !          1845:        }
        !          1846:        return(KEEPON);
        !          1847: }
        !          1848: 
        !          1849: 
        !          1850: mkentry(dirp)
        !          1851: register DIRECT *dirp;
        !          1852: {
        !          1853:        register ino_t in;
        !          1854:        register char *p;
        !          1855: 
        !          1856:        if(dirp->d_ino)
        !          1857:                return(KEEPON);
        !          1858:        dirp->d_ino = orphan;
        !          1859:        in = orphan;
        !          1860:        p = &dirp->d_name[8];
        !          1861:        *--p = 0;
        !          1862:        while(p > dirp->d_name) {
        !          1863:                *--p = (in % 10) + '0';
        !          1864:                in /= 10;
        !          1865:        }
        !          1866:        *p = '#';
        !          1867:        return(ALTERD|STOP);
        !          1868: }
        !          1869: 
        !          1870: 
        !          1871: chgdd(dirp)
        !          1872: register DIRECT *dirp;
        !          1873: {
        !          1874:        if(dirp->d_name[0] == '.' && dirp->d_name[1] == '.' &&
        !          1875:        dirp->d_name[2] == 0) {
        !          1876:                dirp->d_ino = lfdir;
        !          1877:                return(ALTERD|STOP);
        !          1878:        }
        !          1879:        return(KEEPON);
        !          1880: }
        !          1881: 
        !          1882: 
        !          1883: linkup()
        !          1884: {
        !          1885:        register DINODE *dp;
        !          1886:        register lostdir;
        !          1887:        register ino_t pdir;
        !          1888: 
        !          1889:        if((dp = ginode()) == NULL)
        !          1890:                return(NO);
        !          1891:        lostdir = DIR;
        !          1892:        pdir = parentdir;
        !          1893:        if (preen && dp->di_size == 0)
        !          1894:                return(NO);
        !          1895:        pwarn("UNREF %s ",lostdir ? "DIR" : "FILE");
        !          1896:        pinode();
        !          1897:        if (preen)
        !          1898:                printf(" (RECONNECTED)\n");
        !          1899:        else
        !          1900:                if (reply("RECONNECT") == NO)
        !          1901:                        return(NO);
        !          1902:        orphan = inum;
        !          1903:        if(lfdir == 0) {
        !          1904:                inum = ROOTINO;
        !          1905:                if((dp = ginode()) == NULL) {
        !          1906:                        inum = orphan;
        !          1907:                        return(NO);
        !          1908:                }
        !          1909:                pfunc = findino;
        !          1910:                srchname = lfname;
        !          1911:                filsize = dp->di_size;
        !          1912:                parentdir = 0;
        !          1913:                ckinode(dp,DATA);
        !          1914:                inum = orphan;
        !          1915:                if((lfdir = parentdir) == 0) {
        !          1916:                        pfatal("SORRY. NO lost+found DIRECTORY");
        !          1917:                        printf("\n\n");
        !          1918:                        return(NO);
        !          1919:                }
        !          1920:        }
        !          1921:        inum = lfdir;
        !          1922:        if((dp = ginode()) == NULL || !DIR || getstate() != FSTATE) {
        !          1923:                inum = orphan;
        !          1924:                pfatal("SORRY. NO lost+found DIRECTORY");
        !          1925:                printf("\n\n");
        !          1926:                return(NO);
        !          1927:        }
        !          1928:        if(dp->di_size & BMASK(big)) {
        !          1929:                dp->di_size = roundup(dp->di_size,BSIZE(big));
        !          1930:                inodirty();
        !          1931:        }
        !          1932:        filsize = dp->di_size;
        !          1933:        inum = orphan;
        !          1934:        pfunc = mkentry;
        !          1935:        if((ckinode(dp,DATA) & ALTERD) == 0) {
        !          1936:                pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
        !          1937:                printf("\n\n");
        !          1938:                return(NO);
        !          1939:        }
        !          1940:        declncnt();
        !          1941:        if(lostdir) {
        !          1942:                pfunc = chgdd;
        !          1943:                dp = ginode();
        !          1944:                filsize = dp->di_size;
        !          1945:                ckinode(dp,DATA);
        !          1946:                inum = lfdir;
        !          1947:                if((dp = ginode()) != NULL) {
        !          1948:                        dp->di_nlink++;
        !          1949:                        inodirty();
        !          1950:                        setlncnt(getlncnt()+1);
        !          1951:                }
        !          1952:                inum = orphan;
        !          1953:                pwarn("DIR I=%u CONNECTED. ",orphan);
        !          1954:                printf("PARENT WAS I=%u\n",pdir);
        !          1955:                if (preen == 0)
        !          1956:                        printf("\n");
        !          1957:        }
        !          1958:        return(YES);
        !          1959: }
        !          1960: 
        !          1961: 
        !          1962: bread(fcp,buf,blk,size)
        !          1963: daddr_t blk;
        !          1964: register struct filecntl *fcp;
        !          1965: register size;
        !          1966: char *buf;
        !          1967: {
        !          1968:        if(lseek(fcp->rfdes,blk<<BSHIFT(big),0) < 0)
        !          1969:                rwerr("SEEK",blk);
        !          1970:        else if(read(fcp->rfdes,buf,size) == size)
        !          1971:                return(YES);
        !          1972:        rwerr("READ",blk);
        !          1973:        return(NO);
        !          1974: }
        !          1975: 
        !          1976: 
        !          1977: bwrite(fcp,buf,blk,size)
        !          1978: daddr_t blk;
        !          1979: register struct filecntl *fcp;
        !          1980: register size;
        !          1981: char *buf;
        !          1982: {
        !          1983:        if(fcp->wfdes < 0)
        !          1984:                return(NO);
        !          1985:        if(lseek(fcp->wfdes,blk<<BSHIFT(big),0) < 0)
        !          1986:                rwerr("SEEK",blk);
        !          1987:        else if(write(fcp->wfdes,buf,size) == size) {
        !          1988:                fcp->mod = 1;
        !          1989:                return(YES);
        !          1990:        }
        !          1991:        rwerr("WRITE",blk);
        !          1992:        return(NO);
        !          1993: }
        !          1994: 
        !          1995: void
        !          1996: catch(int signo)
        !          1997: {
        !          1998:        ckfini();
        !          1999:        exit(12);
        !          2000: }
        !          2001: /*
        !          2002:  * Convert longs to and from 3-byte disk addresses
        !          2003:  */
        !          2004: /*
        !          2005: void
        !          2006: ltol3(char *cp, long *lp, int n)
        !          2007: {
        !          2008:        int i;
        !          2009:        char *a, *b;
        !          2010: 
        !          2011:        a = cp;
        !          2012:        b = (char *)lp;
        !          2013:        for (i = 0; i < n; i++) {
        !          2014:                b++;
        !          2015:                *a++ = *b++;
        !          2016:                *a++ = *b++;
        !          2017:                *a++ = *b++;
        !          2018:        }
        !          2019: }
        !          2020: 
        !          2021: void
        !          2022: l3tol(long *lp, char *cp, int n)
        !          2023: {
        !          2024:        int i;
        !          2025:        char *a, *b;
        !          2026: 
        !          2027:        a = (char *)lp;
        !          2028:        b = cp;
        !          2029:        for (i = 0; i < n; i++) {
        !          2030:                *a++ = 0;
        !          2031:                *a++ = *b++;
        !          2032:                *a++ = *b++;
        !          2033:                *a++ = *b++;
        !          2034:        }
        !          2035: }
        !          2036: */

unix.superglobalmegacorp.com

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