Annotation of researchv10no/cmd/fsck.c, revision 1.1.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.