Annotation of 43BSDReno/sbin/fsck/utilities.c, revision 1.1

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

unix.superglobalmegacorp.com

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