Annotation of 43BSDTahoe/etc/fsck/utilities.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)utilities.c        5.13 (Berkeley) 6/7/88";
        !             9: #endif not lint
        !            10: 
        !            11: #include <stdio.h>
        !            12: #include <ctype.h>
        !            13: #include <sys/param.h>
        !            14: #include <sys/inode.h>
        !            15: #include <sys/fs.h>
        !            16: #include <sys/dir.h>
        !            17: #include "fsck.h"
        !            18: 
        !            19: long   diskreads, totalreads;  /* Disk cache statistics */
        !            20: long   lseek();
        !            21: 
        !            22: ftypeok(dp)
        !            23:        DINODE *dp;
        !            24: {
        !            25:        switch (dp->di_mode & IFMT) {
        !            26: 
        !            27:        case IFDIR:
        !            28:        case IFREG:
        !            29:        case IFBLK:
        !            30:        case IFCHR:
        !            31:        case IFLNK:
        !            32:        case IFSOCK:
        !            33:                return (1);
        !            34: 
        !            35:        default:
        !            36:                if (debug)
        !            37:                        printf("bad file type 0%o\n", dp->di_mode);
        !            38:                return (0);
        !            39:        }
        !            40: }
        !            41: 
        !            42: reply(s)
        !            43:        char *s;
        !            44: {
        !            45:        char line[80];
        !            46:        int cont = (strcmp(s, "CONTINUE") == 0);
        !            47: 
        !            48:        if (preen)
        !            49:                pfatal("INTERNAL ERROR: GOT TO reply()");
        !            50:        printf("\n%s? ", s);
        !            51:        if (!cont && (nflag || dfile.wfdes < 0)) {
        !            52:                printf(" no\n\n");
        !            53:                return (0);
        !            54:        }
        !            55:        if (yflag || (cont && nflag)) {
        !            56:                printf(" yes\n\n");
        !            57:                return (1);
        !            58:        }
        !            59:        if (getline(stdin, line, sizeof(line)) == EOF)
        !            60:                errexit("\n");
        !            61:        printf("\n");
        !            62:        if (line[0] == 'y' || line[0] == 'Y')
        !            63:                return (1);
        !            64:        else
        !            65:                return (0);
        !            66: }
        !            67: 
        !            68: getline(fp, loc, maxlen)
        !            69:        FILE *fp;
        !            70:        char *loc;
        !            71: {
        !            72:        register n;
        !            73:        register char *p, *lastloc;
        !            74: 
        !            75:        p = loc;
        !            76:        lastloc = &p[maxlen-1];
        !            77:        while ((n = getc(fp)) != '\n') {
        !            78:                if (n == EOF)
        !            79:                        return (EOF);
        !            80:                if (!isspace(n) && p < lastloc)
        !            81:                        *p++ = n;
        !            82:        }
        !            83:        *p = 0;
        !            84:        return (p - loc);
        !            85: }
        !            86: 
        !            87: /*
        !            88:  * Malloc buffers and set up cache.
        !            89:  */
        !            90: bufinit()
        !            91: {
        !            92:        register BUFAREA *bp;
        !            93:        long bufcnt, i;
        !            94:        char *bufp;
        !            95: 
        !            96:        bufp = (char *)malloc(sblock.fs_bsize);
        !            97:        if (bufp == 0)
        !            98:                errexit("cannot allocate buffer pool\n");
        !            99:        cgblk.b_un.b_buf = bufp;
        !           100:        initbarea(&cgblk);
        !           101:        bufhead.b_next = bufhead.b_prev = &bufhead;
        !           102:        bufcnt = MAXBUFSPACE / sblock.fs_bsize;
        !           103:        if (bufcnt < MINBUFS)
        !           104:                bufcnt = MINBUFS;
        !           105:        for (i = 0; i < bufcnt; i++) {
        !           106:                bp = (BUFAREA *)malloc(sizeof(BUFAREA));
        !           107:                bufp = (char *)malloc(sblock.fs_bsize);
        !           108:                if (bp == 0 || bufp == 0) {
        !           109:                        if (i >= MINBUFS)
        !           110:                                break;
        !           111:                        errexit("cannot allocate buffer pool\n");
        !           112:                }
        !           113:                bp->b_un.b_buf = bufp;
        !           114:                bp->b_prev = &bufhead;
        !           115:                bp->b_next = bufhead.b_next;
        !           116:                bufhead.b_next->b_prev = bp;
        !           117:                bufhead.b_next = bp;
        !           118:                initbarea(bp);
        !           119:        }
        !           120:        bufhead.b_size = i;     /* save number of buffers */
        !           121: }
        !           122: 
        !           123: /*
        !           124:  * Manage a cache of directory blocks.
        !           125:  */
        !           126: BUFAREA *
        !           127: getdatablk(blkno, size)
        !           128:        daddr_t blkno;
        !           129:        long size;
        !           130: {
        !           131:        register BUFAREA *bp;
        !           132: 
        !           133:        for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
        !           134:                if (bp->b_bno == fsbtodb(&sblock, blkno))
        !           135:                        goto foundit;
        !           136:        for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
        !           137:                if ((bp->b_flags & B_INUSE) == 0)
        !           138:                        break;
        !           139:        if (bp == &bufhead)
        !           140:                errexit("deadlocked buffer pool\n");
        !           141:        getblk(bp, blkno, size);
        !           142:        /* fall through */
        !           143: foundit:
        !           144:        totalreads++;
        !           145:        bp->b_prev->b_next = bp->b_next;
        !           146:        bp->b_next->b_prev = bp->b_prev;
        !           147:        bp->b_prev = &bufhead;
        !           148:        bp->b_next = bufhead.b_next;
        !           149:        bufhead.b_next->b_prev = bp;
        !           150:        bufhead.b_next = bp;
        !           151:        bp->b_flags |= B_INUSE;
        !           152:        return (bp);
        !           153: }
        !           154: 
        !           155: BUFAREA *
        !           156: getblk(bp, blk, size)
        !           157:        register BUFAREA *bp;
        !           158:        daddr_t blk;
        !           159:        long size;
        !           160: {
        !           161:        register struct filecntl *fcp;
        !           162:        daddr_t dblk;
        !           163: 
        !           164:        fcp = &dfile;
        !           165:        dblk = fsbtodb(&sblock, blk);
        !           166:        if (bp->b_bno == dblk)
        !           167:                return (bp);
        !           168:        flush(fcp, bp);
        !           169:        diskreads++;
        !           170:        bp->b_errs = bread(fcp, bp->b_un.b_buf, dblk, size);
        !           171:        bp->b_bno = dblk;
        !           172:        bp->b_size = size;
        !           173:        return (bp);
        !           174: }
        !           175: 
        !           176: flush(fcp, bp)
        !           177:        struct filecntl *fcp;
        !           178:        register BUFAREA *bp;
        !           179: {
        !           180:        register int i, j;
        !           181: 
        !           182:        if (!bp->b_dirty)
        !           183:                return;
        !           184:        if (bp->b_errs != 0)
        !           185:                pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
        !           186:                    (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
        !           187:                    bp->b_bno);
        !           188:        bp->b_dirty = 0;
        !           189:        bp->b_errs = 0;
        !           190:        bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
        !           191:        if (bp != &sblk)
        !           192:                return;
        !           193:        for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
        !           194:                bwrite(&dfile, (char *)sblock.fs_csp[j],
        !           195:                    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
        !           196:                    sblock.fs_cssize - i < sblock.fs_bsize ?
        !           197:                    sblock.fs_cssize - i : sblock.fs_bsize);
        !           198:        }
        !           199: }
        !           200: 
        !           201: rwerr(s, blk)
        !           202:        char *s;
        !           203:        daddr_t blk;
        !           204: {
        !           205: 
        !           206:        if (preen == 0)
        !           207:                printf("\n");
        !           208:        pfatal("CANNOT %s: BLK %ld", s, blk);
        !           209:        if (reply("CONTINUE") == 0)
        !           210:                errexit("Program terminated\n");
        !           211: }
        !           212: 
        !           213: ckfini()
        !           214: {
        !           215:        register BUFAREA *bp;
        !           216:        int cnt = 0;
        !           217: 
        !           218:        flush(&dfile, &sblk);
        !           219:        if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
        !           220:            !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
        !           221:                sblk.b_bno = SBOFF / dev_bsize;
        !           222:                sbdirty();
        !           223:                flush(&dfile, &sblk);
        !           224:        }
        !           225:        flush(&dfile, &cgblk);
        !           226:        for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) {
        !           227:                cnt++;
        !           228:                flush(&dfile, bp);
        !           229:        }
        !           230:        if (bufhead.b_size != cnt)
        !           231:                errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt);
        !           232:        if (debug)
        !           233:                printf("cache missed %d of %d (%d%%)\n", diskreads,
        !           234:                    totalreads, diskreads * 100 / totalreads);
        !           235:        (void)close(dfile.rfdes);
        !           236:        (void)close(dfile.wfdes);
        !           237: }
        !           238: 
        !           239: bread(fcp, buf, blk, size)
        !           240:        register struct filecntl *fcp;
        !           241:        char *buf;
        !           242:        daddr_t blk;
        !           243:        long size;
        !           244: {
        !           245:        char *cp;
        !           246:        int i, errs;
        !           247: 
        !           248:        if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
        !           249:                rwerr("SEEK", blk);
        !           250:        else if (read(fcp->rfdes, buf, (int)size) == size)
        !           251:                return (0);
        !           252:        rwerr("READ", blk);
        !           253:        if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
        !           254:                rwerr("SEEK", blk);
        !           255:        errs = 0;
        !           256:        bzero(buf, size);
        !           257:        printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
        !           258:        for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
        !           259:                if (read(fcp->rfdes, cp, secsize) < 0) {
        !           260:                        lseek(fcp->rfdes, blk * dev_bsize + i + secsize, 0);
        !           261:                        if (secsize != dev_bsize && dev_bsize != 1)
        !           262:                                printf(" %d (%d),",
        !           263:                                    (blk * dev_bsize + i) / secsize,
        !           264:                                    blk + i / dev_bsize);
        !           265:                        else
        !           266:                                printf(" %d,", blk + i / dev_bsize);
        !           267:                        errs++;
        !           268:                }
        !           269:        }
        !           270:        printf("\n");
        !           271:        return (errs);
        !           272: }
        !           273: 
        !           274: bwrite(fcp, buf, blk, size)
        !           275:        register struct filecntl *fcp;
        !           276:        char *buf;
        !           277:        daddr_t blk;
        !           278:        long size;
        !           279: {
        !           280:        int i;
        !           281:        char *cp;
        !           282: 
        !           283:        if (fcp->wfdes < 0)
        !           284:                return;
        !           285:        if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
        !           286:                rwerr("SEEK", blk);
        !           287:        else if (write(fcp->wfdes, buf, (int)size) == size) {
        !           288:                fcp->mod = 1;
        !           289:                return;
        !           290:        }
        !           291:        rwerr("WRITE", blk);
        !           292:        if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
        !           293:                rwerr("SEEK", blk);
        !           294:        printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
        !           295:        for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
        !           296:                if (write(fcp->wfdes, cp, dev_bsize) < 0) {
        !           297:                        lseek(fcp->rfdes, blk * dev_bsize + i + dev_bsize, 0);
        !           298:                        printf(" %d,", blk + i / dev_bsize);
        !           299:                }
        !           300:        printf("\n");
        !           301:        return;
        !           302: }
        !           303: 
        !           304: /*
        !           305:  * allocate a data block with the specified number of fragments
        !           306:  */
        !           307: allocblk(frags)
        !           308:        int frags;
        !           309: {
        !           310:        register int i, j, k;
        !           311: 
        !           312:        if (frags <= 0 || frags > sblock.fs_frag)
        !           313:                return (0);
        !           314:        for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) {
        !           315:                for (j = 0; j <= sblock.fs_frag - frags; j++) {
        !           316:                        if (getbmap(i + j))
        !           317:                                continue;
        !           318:                        for (k = 1; k < frags; k++)
        !           319:                                if (getbmap(i + j + k))
        !           320:                                        break;
        !           321:                        if (k < frags) {
        !           322:                                j += k;
        !           323:                                continue;
        !           324:                        }
        !           325:                        for (k = 0; k < frags; k++)
        !           326:                                setbmap(i + j + k);
        !           327:                        n_blks += frags;
        !           328:                        return (i + j);
        !           329:                }
        !           330:        }
        !           331:        return (0);
        !           332: }
        !           333: 
        !           334: /*
        !           335:  * Free a previously allocated block
        !           336:  */
        !           337: freeblk(blkno, frags)
        !           338:        daddr_t blkno;
        !           339:        int frags;
        !           340: {
        !           341:        struct inodesc idesc;
        !           342: 
        !           343:        idesc.id_blkno = blkno;
        !           344:        idesc.id_numfrags = frags;
        !           345:        pass4check(&idesc);
        !           346: }
        !           347: 
        !           348: /*
        !           349:  * Find a pathname
        !           350:  */
        !           351: getpathname(namebuf, curdir, ino)
        !           352:        char *namebuf;
        !           353:        ino_t curdir, ino;
        !           354: {
        !           355:        int len;
        !           356:        register char *cp;
        !           357:        struct inodesc idesc;
        !           358:        extern int findname();
        !           359: 
        !           360:        if (statemap[ino] != DSTATE && statemap[ino] != DFOUND) {
        !           361:                strcpy(namebuf, "?");
        !           362:                return;
        !           363:        }
        !           364:        bzero(&idesc, sizeof(struct inodesc));
        !           365:        idesc.id_type = DATA;
        !           366:        cp = &namebuf[BUFSIZ - 1];
        !           367:        *cp = '\0';
        !           368:        if (curdir != ino) {
        !           369:                idesc.id_parent = curdir;
        !           370:                goto namelookup;
        !           371:        }
        !           372:        while (ino != ROOTINO) {
        !           373:                idesc.id_number = ino;
        !           374:                idesc.id_func = findino;
        !           375:                idesc.id_name = "..";
        !           376:                if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
        !           377:                        break;
        !           378:        namelookup:
        !           379:                idesc.id_number = idesc.id_parent;
        !           380:                idesc.id_parent = ino;
        !           381:                idesc.id_func = findname;
        !           382:                idesc.id_name = namebuf;
        !           383:                if ((ckinode(ginode(idesc.id_number), &idesc) & FOUND) == 0)
        !           384:                        break;
        !           385:                len = strlen(namebuf);
        !           386:                cp -= len;
        !           387:                if (cp < &namebuf[MAXNAMLEN])
        !           388:                        break;
        !           389:                bcopy(namebuf, cp, len);
        !           390:                *--cp = '/';
        !           391:                ino = idesc.id_number;
        !           392:        }
        !           393:        if (ino != ROOTINO) {
        !           394:                strcpy(namebuf, "?");
        !           395:                return;
        !           396:        }
        !           397:        bcopy(cp, namebuf, &namebuf[BUFSIZ] - cp);
        !           398: }
        !           399: 
        !           400: catch()
        !           401: {
        !           402: 
        !           403:        ckfini();
        !           404:        exit(12);
        !           405: }
        !           406: 
        !           407: /*
        !           408:  * When preening, allow a single quit to signal
        !           409:  * a special exit after filesystem checks complete
        !           410:  * so that reboot sequence may be interrupted.
        !           411:  */
        !           412: catchquit()
        !           413: {
        !           414:        extern returntosingle;
        !           415: 
        !           416:        printf("returning to single-user after filesystem check\n");
        !           417:        returntosingle = 1;
        !           418:        (void)signal(SIGQUIT, SIG_DFL);
        !           419: }
        !           420: 
        !           421: /*
        !           422:  * Ignore a single quit signal; wait and flush just in case.
        !           423:  * Used by child processes in preen.
        !           424:  */
        !           425: voidquit()
        !           426: {
        !           427: 
        !           428:        sleep(1);
        !           429:        (void)signal(SIGQUIT, SIG_IGN);
        !           430:        (void)signal(SIGQUIT, SIG_DFL);
        !           431: }
        !           432: 
        !           433: /*
        !           434:  * determine whether an inode should be fixed.
        !           435:  */
        !           436: dofix(idesc, msg)
        !           437:        register struct inodesc *idesc;
        !           438:        char *msg;
        !           439: {
        !           440: 
        !           441:        switch (idesc->id_fix) {
        !           442: 
        !           443:        case DONTKNOW:
        !           444:                if (idesc->id_type == DATA)
        !           445:                        direrr(idesc->id_number, msg);
        !           446:                else
        !           447:                        pwarn(msg);
        !           448:                if (preen) {
        !           449:                        printf(" (SALVAGED)\n");
        !           450:                        idesc->id_fix = FIX;
        !           451:                        return (ALTERED);
        !           452:                }
        !           453:                if (reply("SALVAGE") == 0) {
        !           454:                        idesc->id_fix = NOFIX;
        !           455:                        return (0);
        !           456:                }
        !           457:                idesc->id_fix = FIX;
        !           458:                return (ALTERED);
        !           459: 
        !           460:        case FIX:
        !           461:                return (ALTERED);
        !           462: 
        !           463:        case NOFIX:
        !           464:                return (0);
        !           465: 
        !           466:        default:
        !           467:                errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
        !           468:        }
        !           469:        /* NOTREACHED */
        !           470: }
        !           471: 
        !           472: /* VARARGS1 */
        !           473: errexit(s1, s2, s3, s4)
        !           474:        char *s1;
        !           475: {
        !           476:        printf(s1, s2, s3, s4);
        !           477:        exit(8);
        !           478: }
        !           479: 
        !           480: /*
        !           481:  * An inconsistency occured which shouldn't during normal operations.
        !           482:  * Die if preening, otherwise just printf.
        !           483:  */
        !           484: /* VARARGS1 */
        !           485: pfatal(s, a1, a2, a3)
        !           486:        char *s;
        !           487: {
        !           488: 
        !           489:        if (preen) {
        !           490:                printf("%s: ", devname);
        !           491:                printf(s, a1, a2, a3);
        !           492:                printf("\n");
        !           493:                printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
        !           494:                        devname);
        !           495:                exit(8);
        !           496:        }
        !           497:        printf(s, a1, a2, a3);
        !           498: }
        !           499: 
        !           500: /*
        !           501:  * Pwarn is like printf when not preening,
        !           502:  * or a warning (preceded by filename) when preening.
        !           503:  */
        !           504: /* VARARGS1 */
        !           505: pwarn(s, a1, a2, a3, a4, a5, a6)
        !           506:        char *s;
        !           507: {
        !           508: 
        !           509:        if (preen)
        !           510:                printf("%s: ", devname);
        !           511:        printf(s, a1, a2, a3, a4, a5, a6);
        !           512: }
        !           513: 
        !           514: #ifndef lint
        !           515: /*
        !           516:  * Stub for routines from kernel.
        !           517:  */
        !           518: panic(s)
        !           519:        char *s;
        !           520: {
        !           521: 
        !           522:        pfatal("INTERNAL INCONSISTENCY:");
        !           523:        errexit(s);
        !           524: }
        !           525: #endif

unix.superglobalmegacorp.com

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