Annotation of 43BSDTahoe/etc/fsck/utilities.c, revision 1.1.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.