Annotation of coherent/d/bin/check/icheck.c, revision 1.1.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.