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

1.1     ! root        1: /*
        !             2:  * ncheck -- map an I-number into a pathname.
        !             3:  * Also, look for special and setuid files.
        !             4:  */
        !             5: 
        !             6: #include <stdio.h>
        !             7: #include <sys/filsys.h>
        !             8: #include <sys/fblk.h>
        !             9: #include <sys/dir.h>
        !            10: #include <sys/ino.h>
        !            11: #include <canon.h>
        !            12: 
        !            13: #define        NHASH   101             /* Prime provides a reasonable distribution */
        !            14: #define        NSBRK   512             /* Bytes to add each time out */
        !            15: #define        NFNAME  400             /* Longest filename generated */
        !            16: #define        NBPC    8               /* Bits per char (for bitmap) */
        !            17: #define        IBLK    12              /* I-node read blocking factor */
        !            18: #define        NINUM   20              /* Maximum number of i-numbers to look for */
        !            19: #define        ESEEN   0200            /* Seen bit for ENTRY */
        !            20: #define        unpack()        l3tol(addrs, ip->di_addr, NADDR)
        !            21: 
        !            22: /* Functions to test for directory or setuid/special i-numbers */
        !            23: #define        test(bm,i)      (bm[(i)/NBPC] & 1<<((i)%NBPC))
        !            24: #define        mark(bm,i)      (bm[(i)/NBPC] |= 1<<((i)%NBPC))
        !            25: 
        !            26: /*
        !            27:  * Tables used by imap.
        !            28:  * This effectively implements
        !            29:  * the access polynomial for the indirect
        !            30:  * blocks.
        !            31:  */
        !            32: #undef NI
        !            33: #define        NI      1
        !            34: #define        NII     1
        !            35: #define        NIII    1
        !            36: static daddr_t ranges[] = {
        !            37:        ND,
        !            38:        ND + (daddr_t)NI*NBN,
        !            39:        ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN,
        !            40:        ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN + (daddr_t)NIII*NBN*NBN*NBN,
        !            41: };
        !            42: 
        !            43: static char    offsets[] = {
        !            44:        0,
        !            45:        ND,
        !            46:        ND+NI,
        !            47:        ND+NI+NII,
        !            48: };
        !            49: 
        !            50: static daddr_t coeff[] = {
        !            51:        1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN
        !            52: };
        !            53: 
        !            54: /*
        !            55:  * Default filesystem names
        !            56:  * to check.
        !            57:  */
        !            58: char   *defnames[] = {
        !            59:        "/dev/rrm00",
        !            60:        NULL
        !            61: };
        !            62: 
        !            63: char   tmi[] = "ncheck: too many i-numbers given\n";
        !            64: char   irderr[] = "ncheck: inode read error -- pass %d\n";
        !            65: 
        !            66: /*
        !            67:  * An entry for each directory
        !            68:  * name in the system containing
        !            69:  * the current i-number and the
        !            70:  * parent and the name.
        !            71:  */
        !            72: typedef        struct  ENTRY {
        !            73:        struct ENTRY    *e_next;
        !            74:        ino_t   e_pino;                 /* Parent i-number */
        !            75:        ino_t   e_cino;                 /* Current i-number */
        !            76:        char    e_name[];               /* Name */
        !            77: }      ENTRY;
        !            78: 
        !            79: ENTRY  *entries[NHASH];                /* Hashed entries */
        !            80: 
        !            81: char   *dbmap;                         /* Directory I-node bit-map */
        !            82: char   *sbmap;                         /* Special + setuid i-node bitmap */
        !            83: 
        !            84: int    ninumber;
        !            85: ino_t  inums[NINUM];
        !            86: char   superb[BSIZE];
        !            87: char   ibuf[BSIZE*IBLK];
        !            88: char   dbuf[BSIZE];
        !            89: char   namebuf[NFNAME];
        !            90: 
        !            91: int    aflag;                  /* All (print "." and ".." names) flag */
        !            92: int    sflag;                  /* Special and setuid files */
        !            93: int    uflag;                  /* Print unreferenced structure */
        !            94: int    exstat;                 /* Exit status */
        !            95: int    fsfd;                   /* File system file descriptor */
        !            96: daddr_t        fsize   = SUPERI+1;             /* Allow read of super-block */
        !            97: ino_t  isize;
        !            98: ino_t  maxino;
        !            99: 
        !           100: daddr_t        imap();
        !           101: char   *malloc();
        !           102: 
        !           103: main(argc, argv)
        !           104: char *argv[];
        !           105: {
        !           106: 
        !           107:        while (argc>1 && *argv[1]=='-') {
        !           108:                switch (argv[1][1]) {
        !           109:                case 'a':
        !           110:                        aflag = 1;
        !           111:                        break;
        !           112: 
        !           113:                case 'i':
        !           114:                        for (;;) {
        !           115:                                if (ninumber >= NINUM) {
        !           116:                                        fprintf(stderr, tmi);
        !           117:                                        exstat = 1;
        !           118:                                        break;
        !           119:                                }
        !           120:                                if ((inums[ninumber] = atoi(argv[2])) == 0)
        !           121:                                        break;
        !           122:                                argv++;
        !           123:                                argc--;
        !           124:                                ninumber++;
        !           125:                        }
        !           126:                        break;
        !           127: 
        !           128:                case 's':
        !           129:                        sflag = 1;
        !           130:                        break;
        !           131: 
        !           132:                case 'u':       /* Unimplemented search for orphan structure */
        !           133:                        uflag = 1;
        !           134:                        break;
        !           135: 
        !           136:                default:
        !           137:                        usage();
        !           138:                }
        !           139:                argc--;
        !           140:                argv++;
        !           141:        }
        !           142:        if (argc > 1)
        !           143:                allcheck(argv+1); else
        !           144:                allcheck(defnames);
        !           145:        exit(exstat);
        !           146: }
        !           147: 
        !           148: /*
        !           149:  * Check the given list of filesystems
        !           150:  */
        !           151: allcheck(fsl)
        !           152: register char **fsl;
        !           153: {
        !           154:        while (*fsl != NULL)
        !           155:                ncheck(*fsl++);
        !           156: }
        !           157: 
        !           158: /*
        !           159:  * Do `ncheck' for each filesystem.
        !           160:  */
        !           161: ncheck(fsname)
        !           162: char *fsname;
        !           163: {
        !           164:        register struct filsys *sbp;
        !           165:        register unsigned nb;
        !           166: 
        !           167:        if ((fsfd = open(fsname, 0)) < 0) {
        !           168:                fprintf(stderr, "%s: cannot open\n", fsname);
        !           169:                exstat = 1;
        !           170:                return;
        !           171:        }
        !           172:        printf( "%s:\n", fsname);
        !           173:        sync();
        !           174:        bread((daddr_t)SUPERI, superb);
        !           175:        sbp = superb;
        !           176: 
        !           177:        canshort(sbp->s_isize);
        !           178:        candaddr(sbp->s_fsize);
        !           179: 
        !           180:        fsize = sbp->s_fsize;
        !           181:        isize = sbp->s_isize;
        !           182:        if (isize<INODEI+1 || isize>=fsize)
        !           183:                cerr("Ridiculous fsize/isize");
        !           184:        maxino = (isize-INODEI) * INOPB;
        !           185:        nb = (maxino+NBPC)/NBPC;
        !           186:        if ((dbmap = malloc(nb)) == NULL)
        !           187:                cerr("Out of memory for directory bit map");
        !           188:        bclear(dbmap, nb);
        !           189:        if (sflag) {
        !           190:                if ((sbmap = malloc(nb)) == NULL)
        !           191:                        cerr("Out of memory for special/setuid bit map");
        !           192:                bclear(sbmap, nb);
        !           193:        }
        !           194:        pass1();
        !           195:        pass2();
        !           196:        pass3();
        !           197:        mfree();
        !           198:        close(fsfd);
        !           199: }
        !           200: 
        !           201: /*
        !           202:  * Pass one consists of running down each
        !           203:  * I-node and marking those that are directories.
        !           204:  * This is used to tell which directory entries are
        !           205:  * to be saved in the hash chains in pass 2.
        !           206:  */
        !           207: pass1()
        !           208: {
        !           209:        register struct dinode *ip;
        !           210:        register ino_t inum;
        !           211:        register int i;
        !           212:        register unsigned imax;
        !           213:        fsize_t seek;
        !           214: 
        !           215:        inum = 1;
        !           216:        seek = INODEI*BSIZE;
        !           217:        for (i=maxino; i>0; i -= IBLK*INOPB) {
        !           218:                lseek(fsfd, seek, 0);
        !           219:                imax = i>IBLK*INOPB ? IBLK*INOPB : i;
        !           220:                imax *= sizeof (struct dinode);
        !           221:                seek += imax;
        !           222:                if (read(fsfd, ibuf, imax) != imax) {
        !           223:                        fprintf(stderr, irderr, 1);
        !           224:                        exstat = 1;
        !           225:                        return;
        !           226:                }
        !           227:                for (ip = ibuf; ip < &ibuf[imax]; ip++) {
        !           228:                        canshort(ip->di_mode);
        !           229:                        canshort(ip->di_nlink);
        !           230:                        if ((ip->di_mode & IFMT) == IFDIR)
        !           231:                                mark(dbmap, inum);
        !           232:                        if (sflag && ip->di_mode&(ISUID|ISGID|IFBLK|IFCHR))
        !           233:                                mark(sbmap, inum);
        !           234:                        inum++;
        !           235:                }
        !           236:        }
        !           237: }
        !           238: 
        !           239: /*
        !           240:  * Pass two scans the i-list looking for
        !           241:  * all directories.  For each directory
        !           242:  * entry in each of these found, it
        !           243:  * saves each name and i-number pair which
        !           244:  * is itself a directory (as determined
        !           245:  * by the bitmap computed in pass1).
        !           246:  */
        !           247: pass2()
        !           248: {
        !           249:        register struct dinode *ip;
        !           250:        register ino_t inum;
        !           251:        register int i;
        !           252:        register unsigned imax;
        !           253:        fsize_t seek;
        !           254: 
        !           255:        inum = 1;
        !           256:        seek = INODEI*BSIZE;
        !           257:        for (i=maxino; i>0; i -= IBLK*INOPB) {
        !           258:                lseek(fsfd, seek, 0);
        !           259:                imax = i>IBLK*INOPB ? IBLK*INOPB : i;
        !           260:                imax *= sizeof (struct dinode);
        !           261:                seek += imax;
        !           262:                if (read(fsfd, ibuf, imax) != imax) {
        !           263:                        fprintf(stderr, irderr, 2);
        !           264:                        exstat = 1;
        !           265:                        return;
        !           266:                }
        !           267:                for (ip = ibuf; ip < &ibuf[imax]; ip++) {
        !           268:                        canshort(ip->di_mode);
        !           269:                        canshort(ip->di_nlink);
        !           270:                        cansize(ip->di_size);
        !           271:                        if ((ip->di_mode & IFMT) == IFDIR)
        !           272:                                finddirs(ip, inum);
        !           273:                        inum++;
        !           274:                }
        !           275:        }
        !           276: }
        !           277: 
        !           278: /*
        !           279:  * Pass 3 uses the hashed table prodeuced
        !           280:  * during pass1 and pass2 to generate
        !           281:  * the output information that was
        !           282:  * requested by the command line.
        !           283:  */
        !           284: pass3()
        !           285: {
        !           286:        register struct dinode *ip;
        !           287:        register ino_t inum;
        !           288:        register int i;
        !           289:        register unsigned imax;
        !           290:        fsize_t seek;
        !           291: 
        !           292:        inum = 1;
        !           293:        seek = INODEI*BSIZE;
        !           294:        if (!sflag && (ninumber==0 || iarg(ROOTIN)))
        !           295:                printf( "%u\t/.\n", ROOTIN);
        !           296:        for (i=maxino; i>0; i -= IBLK*INOPB) {
        !           297:                lseek(fsfd, seek, 0);
        !           298:                imax = i>IBLK*INOPB ? IBLK*INOPB : i;
        !           299:                imax *= sizeof (struct dinode);
        !           300:                seek += imax;
        !           301:                if (read(fsfd, ibuf, imax) != imax) {
        !           302:                        fprintf(stderr, irderr, 3);
        !           303:                        exstat = 1;
        !           304:                        return;
        !           305:                }
        !           306:                for (ip = ibuf; ip < &ibuf[imax]; ip++) {
        !           307:                        canshort(ip->di_mode);
        !           308:                        canshort(ip->di_nlink);
        !           309:                        cansize(ip->di_size);
        !           310:                        if ((ip->di_mode & IFMT) == IFDIR)
        !           311:                                printdir(ip, inum);
        !           312:                        inum++;
        !           313:                }
        !           314:        }
        !           315: }
        !           316: 
        !           317: /*
        !           318:  * Find all entries in this directory i-node
        !           319:  * that are themselves directories.
        !           320:  */
        !           321: finddirs(ip, inum)
        !           322: register struct dinode *ip;
        !           323: register ino_t inum;
        !           324: {
        !           325:        fsize_t size;
        !           326:        daddr_t pb, bn;
        !           327: 
        !           328:        size = ip->di_size;
        !           329:        bn = 0;
        !           330:        while (size >= sizeof(struct direct)) {
        !           331:                register struct direct *dp;
        !           332: 
        !           333:                if ((pb = imap(ip, bn++)) == 0)
        !           334:                        break;
        !           335:                bread(pb, dbuf);
        !           336:                for (dp=dbuf; dp < &dbuf[BSIZE]; dp++) {
        !           337:                        canino( dp->d_ino);
        !           338:                        if (dp->d_ino) {
        !           339:                                if (dp->d_ino > maxino)
        !           340:                                        dirline(inum, dp, "bad");
        !           341:                                else if (test(dbmap, dp->d_ino))
        !           342:                                        direnter(dp, inum);
        !           343:                        }
        !           344:                        size -= sizeof( struct direct);
        !           345:                        if (size == 0)
        !           346:                                break;
        !           347:                }
        !           348:        }
        !           349: }
        !           350: 
        !           351: /*
        !           352:  * Print all of the names found
        !           353:  * in this directory.
        !           354:  */
        !           355: printdir(ip, ino)
        !           356: register struct dinode *ip;
        !           357: register ino_t ino;
        !           358: {
        !           359:        fsize_t size;
        !           360:        daddr_t pb, bn;
        !           361: 
        !           362:        size = ip->di_size;
        !           363:        bn = 0;
        !           364:        while (size >= sizeof(struct direct)) {
        !           365:                register struct direct *dp;
        !           366: 
        !           367:                if ((pb = imap(ip, bn++)) == 0)
        !           368:                        break;
        !           369:                bread(pb, dbuf);
        !           370:                for (dp=dbuf; dp < &dbuf[BSIZE]; dp++) {
        !           371:                        canino( dp->d_ino);
        !           372:                        if (dp->d_ino) {
        !           373:                                if (dp->d_ino > maxino)
        !           374:                                        continue;
        !           375:                                if (sflag && !test(sbmap, dp->d_ino))
        !           376:                                        continue;
        !           377:                                if (ninumber!=0 && !iarg(dp->d_ino))
        !           378:                                        continue;
        !           379:                                outname(dp, ino);
        !           380:                        }
        !           381:                        size -= sizeof( struct direct);
        !           382:                        if (size == 0)
        !           383:                                break;
        !           384:                }
        !           385:        }
        !           386: }
        !           387: 
        !           388: /*
        !           389:  * Print out the actual name by
        !           390:  * traversing the structures
        !           391:  * for a directory entry.
        !           392:  */
        !           393: outname(dp, ino)
        !           394: register struct direct *dp;
        !           395: ino_t ino;
        !           396: {
        !           397:        register char *np;
        !           398: 
        !           399:        np = dp->d_name;
        !           400:        if (!aflag && *np++=='.')
        !           401:                if ((*np=='.' && np[1]=='\0') || *np=='\0')
        !           402:                        return;
        !           403:        np = &namebuf[NFNAME];
        !           404:        *--np = '\0';
        !           405:        if (!aflag && test(dbmap, dp->d_ino)) {
        !           406:                *--np = '.';
        !           407:                *--np = '/';
        !           408:        }
        !           409:        {
        !           410:                register char *cp;
        !           411: 
        !           412:                for (cp = dp->d_name; cp < &dp->d_name[DIRSIZ]; cp++)
        !           413:                        if (*cp == '\0')
        !           414:                                break;
        !           415:                while (cp > dp->d_name)
        !           416:                        *--np = *--cp;
        !           417:                *--np = '/';
        !           418:        }
        !           419:        outpart(np, ino, dp->d_ino);
        !           420: }
        !           421: 
        !           422: /*
        !           423:  * Put out each name part.
        !           424:  * Either get to the root
        !           425:  * or find no parent.
        !           426:  * `ep' is the pointer running
        !           427:  * backwards in the namebuf.
        !           428:  */
        !           429: outpart(np, ino, oino)
        !           430: register char *np;
        !           431: ino_t ino;
        !           432: ino_t oino;
        !           433: {
        !           434:        register ENTRY *ep;
        !           435:        register char *cp;
        !           436:        register int found = 0;
        !           437:        register char *snp;
        !           438: 
        !           439:        if (ino != ROOTIN) {
        !           440:                for (ep = entries[ino%NHASH]; ep != NULL; ep = ep->e_next)
        !           441:                        if (ep->e_cino == ino) {
        !           442:                                if (ep->e_name[0] & ESEEN) {
        !           443:                                        *--np = '.';
        !           444:                                        *--np = '.';
        !           445:                                        *--np = '.';
        !           446:                                        return;
        !           447:                                }
        !           448:                                snp = np;
        !           449:                                cp = &ep->e_name[strlen(ep->e_name)];
        !           450:                                while (cp > ep->e_name)
        !           451:                                        *--np = *--cp;
        !           452:                                *--np = '/';
        !           453:                                ep->e_name[0] |= ESEEN;
        !           454:                                found = 1;
        !           455:                                if (np > namebuf+DIRSIZ)
        !           456:                                        outpart(np, ep->e_pino, oino);
        !           457:                                ep->e_name[0] &= ~ESEEN;
        !           458:                                np = snp;
        !           459:                        }
        !           460:                if (!found) {
        !           461:                        *--np = '?';
        !           462:                        *--np = '?';
        !           463:                }
        !           464:        }
        !           465:        if (!found || ino==ROOTIN)
        !           466:                printf( "%u\t%s\n", oino, np);
        !           467: }
        !           468: 
        !           469: /*
        !           470:  * Enter a directory entry and the current
        !           471:  * i-number into the chained hash table
        !           472:  * for use by pass 3.
        !           473:  */
        !           474: direnter(dp, ino)
        !           475: register struct direct *dp;
        !           476: ino_t ino;
        !           477: {
        !           478:        register ENTRY *ep;
        !           479:        register char *cp;
        !           480:        register int n;
        !           481: 
        !           482:        cp = dp->d_name;
        !           483:        if (*cp++ == '.')
        !           484:                if ((*cp=='.' && cp[1]=='\0') || *cp=='\0')
        !           485:                        return;
        !           486:        for (cp = dp->d_name; *cp != '\0'; cp++)
        !           487:                if (cp >= &dp->d_name[DIRSIZ])
        !           488:                        break;
        !           489:        n = cp - dp->d_name;
        !           490:        if ((ep = (ENTRY *)malloc(n+sizeof(char)+sizeof(ENTRY))) == NULL)
        !           491:                cerr("Out of memory for directory entries");
        !           492:        ep->e_pino = ino;
        !           493:        ep->e_cino = dp->d_ino;
        !           494:        strncpy(ep->e_name, dp->d_name, n);
        !           495:        ep->e_name[n] = '\0';
        !           496:        /*
        !           497:         * Compute hash and store in entries table.
        !           498:         */
        !           499:        n = ep->e_cino%NHASH;
        !           500:        ep->e_next = entries[n];
        !           501:        entries[n] = ep;
        !           502: }
        !           503: 
        !           504: /*
        !           505:  * Return true if the argument
        !           506:  * i-node is the one of the `-i'
        !           507:  * arguments.
        !           508:  */
        !           509: iarg(ino)
        !           510: register ino_t ino;
        !           511: {
        !           512:        register int i;
        !           513: 
        !           514:        for (i=0; i<ninumber; i++)
        !           515:                if (inums[i] == ino)
        !           516:                        return (1);
        !           517:        return (0);
        !           518: }
        !           519: 
        !           520: /*
        !           521:  * Print out a line for a directory
        !           522:  * that is found in the search (e.g.
        !           523:  * bad or argument directories).
        !           524:  */
        !           525: dirline(ino, dp, str)
        !           526: ino_t ino;
        !           527: register struct direct *dp;
        !           528: char *str;
        !           529: {
        !           530:        printf("%u %s: %u/%-*.*s\n", dp->d_ino, str, ino,
        !           531:            DIRSIZ, DIRSIZ, dp->d_name);
        !           532: }
        !           533: 
        !           534: /*
        !           535:  * For a given inode (`ip'),
        !           536:  * map a logical block number (`bn')
        !           537:  * onto a physical disc block number.
        !           538:  */
        !           539: daddr_t
        !           540: imap(ip, lb)
        !           541: register struct dinode *ip;
        !           542: daddr_t lb;
        !           543: {
        !           544:        register il;
        !           545:        daddr_t bpos, pb;
        !           546:        register daddr_t *bp;
        !           547:        register daddr_t addrs[NADDR];
        !           548: 
        !           549:        unpack();
        !           550:        for (il=0; il<4; il++)
        !           551:                if (lb < ranges[il]) {
        !           552:                        if (il != 0)
        !           553:                                lb -= ranges[il-1];
        !           554:                        bpos = lb/coeff[il];
        !           555:                        lb %= coeff[il];
        !           556:                        bp = &addrs[(int)bpos + offsets[il]];
        !           557:                        if ((pb = *bp) != 0) {
        !           558:                                /*
        !           559:                                 * Map through indirect
        !           560:                                 * blocks here.
        !           561:                                 */
        !           562:                                while (il-- > 0) {
        !           563:                                        bread(pb, dbuf);
        !           564:                                        bpos = lb/coeff[il];
        !           565:                                        lb %= coeff[il];
        !           566:                                        bp = (daddr_t *)dbuf + bpos;
        !           567:                                        if ((pb = *bp) == 0)
        !           568:                                                break;
        !           569:                                        pb = *bp;
        !           570:                                        candaddr( pb);
        !           571:                                }
        !           572:                        }
        !           573:                        return (pb);
        !           574:                }
        !           575:        return (0);
        !           576: }
        !           577: 
        !           578: /*
        !           579:  * Read the specified block number
        !           580:  * into `buf'.
        !           581:  */
        !           582: bread(bn, buf)
        !           583: daddr_t bn;
        !           584: char *buf;
        !           585: {
        !           586:        if (bn >= fsize) {
        !           587:                badblock(bn);
        !           588:                bclear(buf, BSIZE);
        !           589:                return;
        !           590:        }
        !           591:        lseek(fsfd, (fsize_t)BSIZE * bn, 0);
        !           592:        if (read(fsfd, buf, BSIZE) != BSIZE) {
        !           593:                fprintf(stderr, "ncheck: Read error %ld\n", (long)bn);
        !           594:                exstat = 1;
        !           595:                bclear(buf, BSIZE);
        !           596:        }
        !           597: }
        !           598: 
        !           599: /*
        !           600:  * Clear a block of memory
        !           601:  * pointed to by `bp' for size
        !           602:  * `nb' bytes.
        !           603:  */
        !           604: bclear(bp, nb)
        !           605: register char *bp;
        !           606: register unsigned nb;
        !           607: {
        !           608:        if (nb)
        !           609:                do {
        !           610:                        *bp++ = 0;
        !           611:                } while (--nb);
        !           612: }
        !           613: 
        !           614: /*
        !           615:  * free scratch memory
        !           616:  * Space used to check a filesystem is freed.  This includes bitmaps
        !           617:  * and directory entries.
        !           618:  */
        !           619: mfree( )
        !           620: {
        !           621:        register ENTRY  *ep,
        !           622:                        **epp;
        !           623: 
        !           624:        for (epp=entries; epp<&entries[NHASH]; ) {
        !           625:                for (ep= *epp; ep; ep=ep->e_next)
        !           626:                        free( (char *)ep);
        !           627:                *epp++ = NULL;
        !           628:        }
        !           629:        free( dbmap);
        !           630:        if (sbmap)
        !           631:                free( sbmap);
        !           632: }
        !           633: 
        !           634: /*
        !           635:  * Error routines
        !           636:  */
        !           637: badblock(bn)
        !           638: daddr_t bn;
        !           639: {
        !           640:        fprintf(stderr, "ncheck: bad block #%ld\n", (long)bn);
        !           641:        exstat = 1;
        !           642: }
        !           643: 
        !           644: /*
        !           645:  * Unrecoverable errors
        !           646:  */
        !           647: cerr(x)
        !           648: {
        !           649:        fprintf(stderr, "ncheck: %r\n", &x);
        !           650:        exit(1);
        !           651: }
        !           652: 
        !           653: usage()
        !           654: {
        !           655:        fprintf(stderr, "Usage: ncheck [-a] [-s] [-i ino ...] [filesystem ...]");
        !           656: }

unix.superglobalmegacorp.com

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