Annotation of coherent/d/bin/check/icheck.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Icheck - check i-list consistency of
        !             3:  * filesystems and (optionally) repair
        !             4:  * filesystems.
        !             5:  */
        !             6: #include <stdio.h>
        !             7: extern char *calloc();
        !             8: #include <sys/filsys.h>
        !             9: #include <sys/fblk.h>
        !            10: #include <sys/dir.h>
        !            11: #include <sys/ino.h>
        !            12: #include "check.h"
        !            13: #include <canon.h>
        !            14: #undef DIR
        !            15: 
        !            16: #define        ROOTINO 2               /* I-number of root */
        !            17: #define        NBLOCK  20              /* Maximum number of blocks to check */
        !            18: #define        NBPC    8               /* Bits per character */
        !            19: #define        BOOTB   0               /* Boot block # */
        !            20: #define        SUPERB  1               /* Super block */
        !            21: #define        INOORG  2               /* Inodes begin here */
        !            22: #define        IBLK    12              /* I-node read blocking factor */
        !            23: #define        BSIZE   512
        !            24: #define        ND      10              /* Number of direct block */
        !            25: #undef NI
        !            26: #define        NI      1
        !            27: #define        NII     1
        !            28: #define        NIII    1
        !            29: #undef NADDR
        !            30: #define        NADDR   (ND+NI+NII+NIII)
        !            31: 
        !            32: /*
        !            33:  * Flags for crawldown.
        !            34:  */
        !            35: #define        PLAIN   0
        !            36: #define        DIR     1
        !            37: #define        BAD     2
        !            38: 
        !            39: /*
        !            40:  * A chain of these structures
        !            41:  * holds all of the defective blocks found
        !            42:  * in the bad block file. The list is sorted for
        !            43:  * easy access by those parts of the program
        !            44:  * that scan blocks.
        !            45:  */
        !            46: struct defect
        !            47: {
        !            48:        struct defect   *d_next;        /* Link to next */
        !            49:        daddr_t         d_start;        /* First bad block in cluster */
        !            50:        int             d_length;       /* Size of cluster */
        !            51: };
        !            52: 
        !            53: #define        test(bn) (bitmap[((unsigned)bn)/NBPC] & 1<<(((unsigned)bn)%NBPC))
        !            54: #define        mark(bn) (bitmap[((unsigned)bn)/NBPC] |= 1<<(((unsigned)bn)%NBPC))
        !            55: 
        !            56: char   tmb[] = "Too many block numbers specified\n";
        !            57: 
        !            58: int    nblock;
        !            59: daddr_t        blocks[NBLOCK];
        !            60: ino_t  freei[NICFREE];         /* Free i-nodes to put into superblock */
        !            61: ino_t  *freeip;
        !            62: struct defect  *deflist;
        !            63: char   superb[BSIZE];
        !            64: char   ibuf[IBLK*BSIZE];
        !            65: char   fbuf[BSIZE];
        !            66: char   idbuf[3][BSIZE];                /* One for each indirect level */
        !            67: 
        !            68: /*
        !            69:  * Offsets of levels of indirection
        !            70:  * into the i-node addresses.
        !            71:  */
        !            72: char   offsets[] = {
        !            73:        0, ND, ND+NI, ND+NI+NII, ND+NI+NII+NIII,
        !            74: };
        !            75: 
        !            76: /*
        !            77:  * Types of indirect and direct blocks
        !            78:  * by name.
        !            79:  */
        !            80: char   *btypes[] = {
        !            81:        "direct",
        !            82:        "indirect",
        !            83:        "double indirect",
        !            84:        "triple indirect",
        !            85: };
        !            86: 
        !            87: int    sflag;                  /* Repair filesystem */
        !            88: int    vflag;                  /* More verbose information */
        !            89: int    exstat;                 /* Final exit status -- bits from <check.h> */
        !            90: FILE   *fs;                    /* File system i/o stream pointer */
        !            91: char   *bitmap;                /* Bit map for blocks */
        !            92: daddr_t        fsize   = SUPERB+1;     /* Allow read of super-block */
        !            93: unsigned       isize;
        !            94: 
        !            95: /* Various counters */
        !            96: unsigned nfiles;
        !            97: unsigned nreg;
        !            98: unsigned ndir;
        !            99: unsigned nbad;                 /* # of bad blocks */
        !           100: unsigned nibad;                        /* # of bad blocks that were in ilist */
        !           101: unsigned nbsp;
        !           102: unsigned ncsp;
        !           103: unsigned nmpx;
        !           104: unsigned npipe;
        !           105: long   nblk;
        !           106: long   nfblk[4];       /* # of direct, single, double, and triple indirects */
        !           107: long   ndirb;
        !           108: long   nfreeb;
        !           109: long   nmissing;
        !           110: long   nfdup;
        !           111: ino_t  nifree;
        !           112: 
        !           113: long   atol();
        !           114: 
        !           115: main(argc, argv)
        !           116: char *argv[];
        !           117: {
        !           118: 
        !           119:        while (argc>1 && *argv[1]=='-') {
        !           120:                switch (argv[1][1]) {
        !           121:                case 'b':
        !           122:                        nblock = 0;
        !           123:                        while (blocks[nblock] = atol(argv[2])) {
        !           124:                                if (nblock++ >= NBLOCK) {
        !           125:                                        fprintf(stderr, tmb);
        !           126:                                        exstat |= IC_MISC;
        !           127:                                        break;
        !           128:                                }
        !           129:                                argv++;
        !           130:                                argc--;
        !           131:                        }
        !           132:                        break;
        !           133: 
        !           134:                case 's':
        !           135:                        sflag = 1;
        !           136:                        break;
        !           137: 
        !           138:                case 'v':
        !           139:                        vflag = 1;
        !           140:                        break;
        !           141: 
        !           142: 
        !           143:                default:
        !           144:                        usage();
        !           145:                }
        !           146:                argc--;
        !           147:                argv++;
        !           148:        }
        !           149:        if (argc > 1)
        !           150:                allcheck(argv+1);
        !           151:        else
        !           152:                usage();
        !           153:        exit(exstat);
        !           154: }
        !           155: 
        !           156: /*
        !           157:  * Check the given list of filesystems
        !           158:  */
        !           159: allcheck(fsl)
        !           160: register char **fsl;
        !           161: {
        !           162:        while (*fsl != NULL)
        !           163:                if (icheck(*fsl++))
        !           164:                        return;
        !           165: }
        !           166: 
        !           167: /*
        !           168:  * Check one filesystem
        !           169:  */
        !           170: icheck(fsname)
        !           171: char *fsname;
        !           172: {
        !           173:        struct filsys *sbp;
        !           174:        register struct dinode *ip;
        !           175:        register int i;
        !           176:        register ino_t inum;
        !           177:        register char *mode;
        !           178:        int thischunk;
        !           179:        daddr_t seek, limit;
        !           180:        struct defect *cdsp;
        !           181: 
        !           182:        nfiles = 0;
        !           183:        nreg = 0;
        !           184:        ndir = 0;
        !           185:        ndirb = 0;
        !           186:        npipe = 0;
        !           187:        nbsp = 0;
        !           188:        ncsp = 0;
        !           189:        nmpx = 0;
        !           190:        nblk = 0;
        !           191:        nbad = 0;
        !           192:        nibad = 0;
        !           193:        for (i=0; i<4; i++)
        !           194:                nfblk[i] = 0;
        !           195:        nmissing = 0;
        !           196:        nfdup = 0;
        !           197:        nfreeb = 0;
        !           198:        nifree = 0;
        !           199:        freeip = freei;
        !           200:        mode = sflag ? "r+w" : "r";
        !           201:        if ((fs = fopen(fsname, mode)) == NULL) {
        !           202:                fprintf(stderr, "%s: cannot open\n", fsname);
        !           203:                exstat |= IC_MISC;
        !           204:                return;
        !           205:        }
        !           206:        printf("%s:\n", fsname);
        !           207:        if (!sflag)
        !           208:                sync();
        !           209:        bread((daddr_t)SUPERB, superb);
        !           210:        sbp = superb;
        !           211:        canint(sbp->s_isize);
        !           212:        candaddr(sbp->s_fsize);
        !           213:        canshort(sbp->s_nfree);
        !           214:        for (i=0; i<NICFREE; ++i)
        !           215:                candaddr(sbp->s_free[i]);
        !           216:        canshort(sbp->s_ninode);
        !           217:        for (i=0; i<NICINOD; ++i)
        !           218:                canino(sbp->s_inode[i]);
        !           219:        cantime(sbp->s_time);
        !           220:        candaddr(sbp->s_tfree);
        !           221:        canino(sbp->s_tinode);
        !           222:        canshort(sbp->s_m);
        !           223:        canshort(sbp->s_n);
        !           224:        canlong(sbp->s_unique);
        !           225:        fsize = sbp->s_fsize;
        !           226:        isize = sbp->s_isize;
        !           227:        if (isize<INOORG+1 || isize>=fsize || fsize<INOORG+1)
        !           228:                cerr("Ridiculous fsize/isize");
        !           229:        if ((bitmap=calloc((int)((fsize+NBPC-1)/NBPC), sizeof(char))) == NULL)
        !           230:                cerr("No space for bitmap");
        !           231:        bmark((daddr_t)BOOTB, "bootstrap", 0);
        !           232:        bmark((daddr_t)SUPERB, "super block", 0);
        !           233:        finddefective();
        !           234:        nblk = isize;
        !           235:        inum = 1;
        !           236:        seek = INOORG;
        !           237:        cdsp = deflist;
        !           238:        while (seek < isize) {
        !           239:                if (cdsp!=NULL && cdsp->d_start==seek) {
        !           240:                        nibad += cdsp->d_length;
        !           241:                        seek  += cdsp->d_length;
        !           242:                        inum  += cdsp->d_length*INOPB;
        !           243:                        cdsp   = cdsp->d_next;
        !           244:                        continue;
        !           245:                }
        !           246:                limit = seek+IBLK;
        !           247:                if (cdsp!=NULL && limit>cdsp->d_start)
        !           248:                        limit = cdsp->d_start;
        !           249:                if (limit > isize)
        !           250:                        limit = isize;
        !           251:                thischunk = limit-seek;
        !           252:                lseek(fileno(fs), seek*BSIZE, 0);
        !           253:                for (i=0; i<thischunk; ++i)
        !           254:                        bmark((daddr_t)seek++, "inodes", 0);
        !           255:                thischunk *= BSIZE;
        !           256:                if (read(fileno(fs), ibuf, thischunk) != thischunk) {
        !           257:                        fprintf(stderr, "I-node read error\n");
        !           258:                        exstat |= IC_HARD;
        !           259:                        break;
        !           260:                }
        !           261:                ip = (struct dinode *) &ibuf[0];
        !           262:                while (ip < (struct dinode *) &ibuf[thischunk]) {
        !           263:                        if (inum != BADFIN) {
        !           264:                                canshort(ip->di_mode);
        !           265:                                canshort(ip->di_nlink);
        !           266:                                canshort(ip->di_uid);
        !           267:                                canshort(ip->di_gid);
        !           268:                                cansize(ip->di_size);
        !           269:                                cantime(ip->di_atime);
        !           270:                                cantime(ip->di_mtime);
        !           271:                                cantime(ip->di_ctime);
        !           272:                                ilook(ip, inum);
        !           273:                        }
        !           274:                        ++inum;
        !           275:                        ++ip;
        !           276:                }
        !           277:        }
        !           278:        freecount();
        !           279:        free(bitmap);
        !           280:        freedefective();
        !           281:        if (nmissing != 0)
        !           282:                exstat |= IC_MISS;
        !           283:        if (nfdup != 0)
        !           284:                exstat |= IC_DUPF;
        !           285:        if (!sflag && vflag) {
        !           286:                printf("f=%u,r=%u,d=%u,b=%u,c=%u,m=%u,p=%u\n", nfiles, nreg,
        !           287:                    ndir, nbsp, ncsp, nmpx, npipe);
        !           288:                printf("blks=%ld, dirb=%ld, d=%ld, i=%ld, ii=%ld, iii=%ld\n",
        !           289:                    nblk, ndirb, nfblk[0], nfblk[1], nfblk[2], nfblk[3]);
        !           290:                printf("free = %ld\n", nfreeb);
        !           291:                printf("bad=%u (%u in I-list)\n", nbad, nibad);
        !           292:        }
        !           293:        if (!sflag) {
        !           294:                if (nmissing != 0)
        !           295:                        printf("missing = %ld\n", nmissing);
        !           296:                if (nfdup != 0)
        !           297:                        printf("%ld dups in free\n", nfdup);
        !           298:                if (sbp->s_tinode != nifree) {
        !           299:                        printf("Bad ifree list\n");
        !           300:                        exstat |= IC_BFB;
        !           301:                }
        !           302:        }
        !           303:        if (sflag)
        !           304:                makesuper();
        !           305:        fclose(fs);
        !           306:        return (0);
        !           307: }
        !           308: 
        !           309: /*
        !           310:  * Look at each inode marking used blocks
        !           311:  * and checking consistency.
        !           312:  */
        !           313: ilook(ip, inum)
        !           314: register struct dinode *ip;
        !           315: ino_t inum;
        !           316: {
        !           317:        daddr_t addrs[NADDR];
        !           318:        register i, l;
        !           319:        int flag;
        !           320: 
        !           321:        if (ip->di_mode == 0) {
        !           322:                if (freeip < &freei[NICFREE])
        !           323:                        *freeip++ = inum;
        !           324:                nifree++;
        !           325:                return;
        !           326:        }
        !           327:        nfiles++;
        !           328:        flag = PLAIN;
        !           329:        switch (ip->di_mode & IFMT) {
        !           330:        case IFREG:
        !           331:                nreg++;
        !           332:                break;
        !           333: 
        !           334:        case IFDIR:
        !           335:                ndir++;
        !           336:                flag = DIR;
        !           337:                break;
        !           338: 
        !           339:        case IFBLK:
        !           340:                nbsp++;
        !           341:                return;
        !           342: 
        !           343:        case IFCHR:
        !           344:                ncsp++;
        !           345:                return;
        !           346: 
        !           347:        case IFPIPE:
        !           348:                npipe++;
        !           349:                return;
        !           350: 
        !           351:        case IFMPB:
        !           352:        case IFMPC:
        !           353:                nmpx++;
        !           354:                return;
        !           355: 
        !           356:        default:
        !           357:                printf("%u: Bad filetype %o\n", inum, ip->di_mode&IFMT);
        !           358:                return;
        !           359:        }
        !           360:        l3tol(addrs, ip->di_addr, NADDR);
        !           361:        for (i = NADDR-1; i >= 0; i--)
        !           362:                for (l=1; l<=4; l++)
        !           363:                        if (i < offsets[l]) {
        !           364:                                crawldown(addrs[i], l-1, flag, inum);
        !           365:                                break;
        !           366:                        }
        !           367: }
        !           368: 
        !           369: /*
        !           370:  * Crawl down through `lev' levels
        !           371:  * of indirect blocks, starting at block
        !           372:  * `bn'. The `ino' argument is the inumber that
        !           373:  * started this all off; is just gets passed
        !           374:  * to `bmark'. The `flag' tells you what kind
        !           375:  * of blocks you have at level 0 (in can be BAD,
        !           376:  * DIR or PLAIN).
        !           377:  */
        !           378: crawldown(bn, lev, flag, ino)
        !           379: daddr_t bn;
        !           380: int lev;
        !           381: ino_t ino;
        !           382: {
        !           383:        register char *bp;
        !           384:        register char *type;
        !           385:        register int i;
        !           386: 
        !           387:        if (bn == 0)
        !           388:                return;
        !           389:        nblk++;
        !           390:        if (lev==0 && flag==DIR) {
        !           391:                type = "dir";
        !           392:                ndirb++;
        !           393:        } else if (lev==0 && flag==BAD) {
        !           394:                type = "bad";
        !           395:                nbad++;
        !           396:        } else {
        !           397:                type = btypes[lev];
        !           398:                nfblk[lev]++;
        !           399:        }
        !           400:        if (bmark(bn, type, ino))
        !           401:                return;
        !           402:        if (lev==0 && flag==BAD)
        !           403:                savedefective(bn);
        !           404:        if (lev-- > 0) {
        !           405:                bread(bn, bp = idbuf[lev]);
        !           406:                for (i=0; i<NBN; i++) {
        !           407:                        bn = ((long *)bp)[i];
        !           408:                        candaddr(bn);
        !           409:                        crawldown(bn, lev, flag, ino);
        !           410:                }
        !           411:        }
        !           412: }
        !           413: 
        !           414: /*
        !           415:  * This routine finds all of the
        !           416:  * defective space on the filsystem by reading
        !           417:  * the bad block file and marking all the blocks.
        !           418:  * The defective space list, used by the I-list
        !           419:  * scanner and other guys, is constructued.
        !           420:  */
        !           421: finddefective()
        !           422: {
        !           423:        register struct dinode *ip;
        !           424:        register i, level;
        !           425:        daddr_t  addrs[NADDR];
        !           426: 
        !           427:        ++nfiles;
        !           428:        lseek(fileno(fs), (long)iblockn(BADFIN)*BSIZE, 0);
        !           429:        if (read(fileno(fs), ibuf, BSIZE) != BSIZE) {
        !           430:                printf("I/O error reading bad block inode\n");
        !           431:                exstat |= IC_HARD;
        !           432:                return;
        !           433:        }
        !           434:        ip = (struct dinode *) &ibuf[0] + iblocko(BADFIN);
        !           435:        canshort(ip->di_mode);
        !           436:        if (ip->di_mode == 0)
        !           437:                return;
        !           438:        if ((ip->di_mode&IFMT) != IFREG) {
        !           439:                printf("Bad block file has bad mode\n");
        !           440:                exstat |= IC_HARD;
        !           441:                return;
        !           442:        }
        !           443:        l3tol(addrs, ip->di_addr, NADDR);
        !           444:        for (i=NADDR-1; i>=0; --i) {
        !           445:                for (level=1; level<=4; ++level) {
        !           446:                        if (i < offsets[level]) {
        !           447:                                crawldown(addrs[i], level-1, BAD, BADFIN);
        !           448:                                break;
        !           449:                        }
        !           450:                }
        !           451:        }
        !           452: }
        !           453: 
        !           454: /*
        !           455:  * Free all of the nodes
        !           456:  * in the defective space list.
        !           457:  */
        !           458: freedefective()
        !           459: {
        !           460:        register struct defect *cdsp1, *cdsp2;
        !           461: 
        !           462:        cdsp1 = deflist;
        !           463:        deflist = NULL;
        !           464:        while (cdsp1 != NULL) {
        !           465:                cdsp2 = cdsp1->d_next;
        !           466:                free((char *) cdsp1);
        !           467:                cdsp1 = cdsp2;
        !           468:        }
        !           469: }
        !           470: 
        !           471: /*
        !           472:  * Add a new, defective block
        !           473:  * into the sorted defective block chain.
        !           474:  * Merge this block with the ends of
        !           475:  * any existing entries. No check is made
        !           476:  * for entries fusing; bad blocks get scooped
        !           477:  * (in general) up in order, and the bad blocks
        !           478:  * are generally sparsely placed on the disc.
        !           479:  */
        !           480: savedefective(bn)
        !           481: daddr_t bn;
        !           482: {
        !           483:        register struct defect *cdsp1, *cdsp2, *cdsp3;
        !           484: 
        !           485:        cdsp1 = NULL;
        !           486:        cdsp2 = deflist;
        !           487:        while (cdsp2!=NULL && bn>cdsp2->d_start) {
        !           488:                cdsp1 = cdsp2;
        !           489:                cdsp2 = cdsp2->d_next;
        !           490:        }
        !           491:        if (cdsp1!=NULL && bn==cdsp1->d_start+cdsp1->d_length) {
        !           492:                ++cdsp1->d_length;
        !           493:                return;
        !           494:        }
        !           495:        if (cdsp2!=NULL && bn==cdsp2->d_start-1) {
        !           496:                --cdsp2->d_start;
        !           497:                ++cdsp2->d_length;
        !           498:                return;
        !           499:        }
        !           500:        if ((cdsp3=(struct defect *)malloc(sizeof(struct defect))) == NULL)
        !           501:                cerr("Out of space for bad blocks");
        !           502:        if (cdsp1 == NULL)
        !           503:                deflist = cdsp3; else
        !           504:                cdsp1->d_next = cdsp3;
        !           505:        cdsp3->d_next = cdsp2;
        !           506:        cdsp3->d_start = bn;
        !           507:        cdsp3->d_length = 1;
        !           508: }
        !           509: 
        !           510: /*
        !           511:  * Look at the free count for a filesystem
        !           512:  * by chasing down the free-list.
        !           513:  */
        !           514: freecount()
        !           515: {
        !           516:        register char *bmp;
        !           517:        register struct fblk *fbp;
        !           518:        struct filsys *sbp;
        !           519:        register unsigned i;
        !           520:        daddr_t bn;
        !           521:        long ntfree;
        !           522: 
        !           523:        sbp = superb;
        !           524:        fbp = &sbp->s_nfree;
        !           525:        ntfree = sbp->s_tfree;
        !           526:        while ((i = fbp->df_nfree) != 0) {
        !           527:                if ((unsigned)(fbp->df_nfree) > NICFREE) {
        !           528:                        badfreelist();
        !           529:                        return;
        !           530:                }
        !           531:                for (i=0; i<fbp->df_nfree; i++) {
        !           532:                        bn = fbp->df_free[i];
        !           533:                        bmark(bn, "free", 0);
        !           534:                        nfreeb++;
        !           535:                }
        !           536:                bread(fbp->df_free[0], fbuf);
        !           537:                fbp = fbuf;
        !           538:                canint(fbp->df_nfree);
        !           539:                for (i=0; i<NICFREE; ++i)
        !           540:                        candaddr(fbp->df_free[i]);
        !           541:        }
        !           542:        /*
        !           543:         * Count number of blocks not in bitmap
        !           544:         */
        !           545:        i = 1;
        !           546:        for (bn=0, bmp=bitmap; bn < fsize; bn++) {
        !           547:                if (i == 1<<NBPC) {
        !           548:                        i = 1;
        !           549:                        bmp++;
        !           550:                }
        !           551:                if ((*bmp & i) == 0)
        !           552:                        nmissing++;
        !           553:                i <<= 1;
        !           554:        }
        !           555:        if (sflag)
        !           556:                nmissing -= isize + nfreeb;
        !           557:        if (nfreeb != ntfree) {
        !           558:                if (!sflag)
        !           559:                        printf("Free list/tfree counts differ\n");
        !           560:                exstat |= IC_MISS;
        !           561:        }
        !           562: }
        !           563: 
        !           564: /*
        !           565:  * Remake the superblock - reconstructing
        !           566:  * the free-list if sflag is set.
        !           567:  */
        !           568: makesuper()
        !           569: {
        !           570:        register struct filsys *sbp;
        !           571:        register ino_t  *fip;
        !           572:        register        i;
        !           573:        daddr_t         bn;
        !           574: 
        !           575:        sbp = superb;
        !           576:        /*
        !           577:         * Remake list of free i-numbers.
        !           578:         */
        !           579:        fip = sbp->s_inode;
        !           580:        sbp->s_ninode = freeip-freei;
        !           581:        while (freeip > freei)
        !           582:                *fip++ = *--freeip;
        !           583:        while (fip < &sbp->s_inode[NICFREE])
        !           584:                *fip++ = 0;
        !           585:        sbp->s_tinode = nifree;
        !           586:        /*
        !           587:         * Free all remaining blocks
        !           588:         * and write last one as tail of free-list
        !           589:         */
        !           590:        sbp->s_nfree = 0;
        !           591:        sbp->s_tfree = 0;
        !           592:        bn = fsize;
        !           593:        for (bn=fsize-1; bn>=isize; --bn)
        !           594:                if (!test(bn))
        !           595:                        bfree(bn);
        !           596:        canint(sbp->s_isize);
        !           597:        candaddr(sbp->s_fsize);
        !           598:        canshort(sbp->s_nfree);
        !           599:        for (i=0; i<NICFREE; ++i)
        !           600:                candaddr(sbp->s_free[i]);
        !           601:        canshort(sbp->s_ninode);
        !           602:        for (i=0; i<NICINOD; ++i)
        !           603:                canino(sbp->s_inode[i]);
        !           604:        cantime(sbp->s_time);
        !           605:        candaddr(sbp->s_tfree);
        !           606:        canino(sbp->s_tinode);
        !           607:        canshort(sbp->s_m);
        !           608:        canshort(sbp->s_n);
        !           609:        canlong(sbp->s_unique);
        !           610:        bwrite((daddr_t)SUPERB, sbp);
        !           611: }
        !           612: 
        !           613: /*
        !           614:  * Free a block and, in so doing, construct
        !           615:  * the free list chain.
        !           616:  */
        !           617: bfree(bn)
        !           618: daddr_t bn;
        !           619: {
        !           620:        register struct filsys  *sbp;
        !           621:        register struct fblk    *fbp;
        !           622:        register                i;
        !           623: 
        !           624:        sbp = superb;
        !           625:        if (sbp->s_tfree == 0) {
        !           626:                bclear(fbuf, BSIZE);
        !           627:                bwrite(bn, fbuf);
        !           628:        }
        !           629:        if (sbp->s_nfree == NICFREE) {
        !           630:                bclear(fbp = fbuf, BSIZE);
        !           631:                fbp->df_nfree = sbp->s_nfree;
        !           632:                canint(fbp->df_nfree);
        !           633:                for (i=0; i<sbp->s_nfree; ++i) {
        !           634:                        fbp->df_free[i] = sbp->s_free[i];
        !           635:                        candaddr(fbp->df_free[i]);
        !           636:                }
        !           637:                bwrite(bn, fbuf);
        !           638:                sbp->s_nfree = 0;
        !           639:        }
        !           640:        sbp->s_free[sbp->s_nfree++] = bn;
        !           641:        sbp->s_tfree++;
        !           642: }
        !           643: 
        !           644: /*
        !           645:  * Read the specified block number
        !           646:  * into `buf'.
        !           647:  */
        !           648: bread(bn, buf)
        !           649: daddr_t bn;
        !           650: char *buf;
        !           651: {
        !           652:        if (bn<0 || bn>=fsize) {
        !           653:                badblock(bn, "any", 0);
        !           654:                bclear(buf, BSIZE);
        !           655:                return;
        !           656:        }
        !           657:        lseek(fileno(fs), (fsize_t)BSIZE * bn, 0);
        !           658:        if (read(fileno(fs), buf, BSIZE) != BSIZE) {
        !           659:                fprintf(stderr, "Read error %ld\n", (long)bn);
        !           660:                exstat |= IC_HARD;
        !           661:                bclear(buf, BSIZE);
        !           662:        }
        !           663: }
        !           664: 
        !           665: /*
        !           666:  * Write block `bn' from `buf'.
        !           667:  */
        !           668: bwrite(bn, buf)
        !           669: daddr_t bn;
        !           670: char *buf;
        !           671: {
        !           672:        if (bn<0 || bn>=fsize) {
        !           673:                badblock(bn, "any", 0);
        !           674:                return;
        !           675:        }
        !           676:        lseek(fileno(fs), (fsize_t)BSIZE * bn, 0);
        !           677:        if (write(fileno(fs), buf, BSIZE) != BSIZE) {
        !           678:                fprintf(stderr, "Write error %ld\n", (long)bn);
        !           679:                exstat |= IC_HARD;
        !           680:        }
        !           681: }
        !           682: 
        !           683: /*
        !           684:  * Mark block # `bn' as
        !           685:  * seen before an check for
        !           686:  * duplicates.
        !           687:  * Bmark only marks file blocks if `sflag' is
        !           688:  * set so that the free list can be constructed
        !           689:  * again.
        !           690:  * Return 1 when something is wrong.
        !           691:  */
        !           692: bmark(bn, type, inum)
        !           693: daddr_t bn;
        !           694: char *type;
        !           695: ino_t inum;
        !           696: {
        !           697:        register nb;
        !           698: 
        !           699:        if (bn<0 || bn>=fsize) {
        !           700:                badblock(bn, type, inum);
        !           701:                return (1);
        !           702:        }
        !           703:        if (nb = nblock) {
        !           704:                register i;
        !           705: 
        !           706:                for (i=0; i<nb; i++)
        !           707:                        if (blocks[i] == bn)
        !           708:                                printf("%ld arg, class=%s, inode=%u\n",
        !           709:                                    (long)bn, type, inum);
        !           710:        }
        !           711:        {
        !           712:                register char *bp;
        !           713:                register int mask;
        !           714: 
        !           715:                mask = 1 << ((unsigned)bn)%NBPC;
        !           716:                bp = bitmap + ((unsigned)bn)/NBPC;
        !           717:                if (*bp & mask)                 /* if (test(bn)) */
        !           718:                        dupblock(bn, type, inum);
        !           719:                else if (!sflag  || inum!=0)
        !           720:                        *bp |= mask;            /* mark(bn) */
        !           721:        }
        !           722:        return (0);
        !           723: }
        !           724: 
        !           725: /*
        !           726:  * Clear a block of memory
        !           727:  * pointed to by `bp' for size
        !           728:  * `nb' bytes.
        !           729:  */
        !           730: bclear(bp, nb)
        !           731: register char *bp;
        !           732: register unsigned nb;
        !           733: {
        !           734:        if (nb)
        !           735:                do {
        !           736:                        *bp++ = 0;
        !           737:                } while (--nb);
        !           738: }
        !           739: 
        !           740: /*
        !           741:  * Error routines
        !           742:  */
        !           743: badblock(bn, type, inum)
        !           744: daddr_t bn;
        !           745: char *type;
        !           746: ino_t inum;
        !           747: {
        !           748:        register int perr = 0;
        !           749: 
        !           750:        if (strcmp(type, "free") != 0) {
        !           751:                perr++;
        !           752:                exstat |= IC_HARD;
        !           753:        } else {
        !           754:                exstat |= IC_BADF;
        !           755:                if (!sflag)
        !           756:                        perr++;
        !           757:        }
        !           758:        if (perr)
        !           759:                printf("%ld bad, class=%s, inode=%u\n", (long)bn, type, inum);
        !           760: }
        !           761: 
        !           762: dupblock(bn, type, inum)
        !           763: daddr_t bn;
        !           764: char *type;
        !           765: ino_t inum;
        !           766: {
        !           767:        if (inum != 0)
        !           768:                exstat |= IC_HARD;
        !           769:        else
        !           770:                nfdup++;
        !           771:        if (vflag || inum!=0)
        !           772:                printf("%ld dup, class=%s, inode=%u\n", (long)bn, type, inum);
        !           773: }
        !           774: 
        !           775: badfreelist()
        !           776: {
        !           777:        if (!sflag) {
        !           778:                printf("Bad freelist\n");
        !           779:                exstat |= IC_BFB;
        !           780:        }
        !           781: }
        !           782: 
        !           783: /*
        !           784:  * Unrecoverable errors
        !           785:  */
        !           786: cerr(x)
        !           787: {
        !           788:        printf("%r", &x);
        !           789:        putchar('\n');
        !           790:        exit(IC_MISC);
        !           791: }
        !           792: 
        !           793: usage()
        !           794: {
        !           795:        cerr("Usage: icheck [-sv] [-b bn ...] filesystem ...");
        !           796: }
        !           797: 
        !           798: /*
        !           799:  * Block copy routine
        !           800:  */
        !           801: bcopy(in, out, nb)
        !           802: register char *in, *out;
        !           803: register unsigned nb;
        !           804: {
        !           805:        if (nb)
        !           806:                do {
        !           807:                        *out++ = *in++;
        !           808:                } while (--nb);
        !           809: }

unix.superglobalmegacorp.com

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