Annotation of 43BSD/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.2 (Berkeley) 9/10/85";
                      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   lseek();
                     20: 
                     21: ftypeok(dp)
                     22:        DINODE *dp;
                     23: {
                     24:        switch (dp->di_mode & IFMT) {
                     25: 
                     26:        case IFDIR:
                     27:        case IFREG:
                     28:        case IFBLK:
                     29:        case IFCHR:
                     30:        case IFLNK:
                     31:        case IFSOCK:
                     32:                return (1);
                     33: 
                     34:        default:
                     35:                if (debug)
                     36:                        printf("bad file type 0%o\n", dp->di_mode);
                     37:                return (0);
                     38:        }
                     39: }
                     40: 
                     41: reply(s)
                     42:        char *s;
                     43: {
                     44:        char line[80];
                     45: 
                     46:        if (preen)
                     47:                pfatal("INTERNAL ERROR: GOT TO reply()");
                     48:        printf("\n%s? ", s);
                     49:        if (nflag || dfile.wfdes < 0) {
                     50:                printf(" no\n\n");
                     51:                return (0);
                     52:        }
                     53:        if (yflag) {
                     54:                printf(" yes\n\n");
                     55:                return (1);
                     56:        }
                     57:        if (getline(stdin, line, sizeof(line)) == EOF)
                     58:                errexit("\n");
                     59:        printf("\n");
                     60:        if (line[0] == 'y' || line[0] == 'Y')
                     61:                return (1);
                     62:        else
                     63:                return (0);
                     64: }
                     65: 
                     66: getline(fp, loc, maxlen)
                     67:        FILE *fp;
                     68:        char *loc;
                     69: {
                     70:        register n;
                     71:        register char *p, *lastloc;
                     72: 
                     73:        p = loc;
                     74:        lastloc = &p[maxlen-1];
                     75:        while ((n = getc(fp)) != '\n') {
                     76:                if (n == EOF)
                     77:                        return (EOF);
                     78:                if (!isspace(n) && p < lastloc)
                     79:                        *p++ = n;
                     80:        }
                     81:        *p = 0;
                     82:        return (p - loc);
                     83: }
                     84: 
                     85: BUFAREA *
                     86: getblk(bp, blk, size)
                     87:        register BUFAREA *bp;
                     88:        daddr_t blk;
                     89:        long size;
                     90: {
                     91:        register struct filecntl *fcp;
                     92:        daddr_t dblk;
                     93: 
                     94:        fcp = &dfile;
                     95:        dblk = fsbtodb(&sblock, blk);
                     96:        if (bp->b_bno == dblk)
                     97:                return (bp);
                     98:        flush(fcp, bp);
                     99:        bp->b_errs = bread(fcp, bp->b_un.b_buf, dblk, size);
                    100:        bp->b_bno = dblk;
                    101:        bp->b_size = size;
                    102:        return (bp);
                    103: }
                    104: 
                    105: flush(fcp, bp)
                    106:        struct filecntl *fcp;
                    107:        register BUFAREA *bp;
                    108: {
                    109:        register int i, j;
                    110: 
                    111:        if (!bp->b_dirty)
                    112:                return;
                    113:        if (bp->b_errs != 0)
                    114:                pfatal("WRITING ZERO'ED BLOCK %d TO DISK\n", bp->b_bno);
                    115:        bp->b_dirty = 0;
                    116:        bp->b_errs = 0;
                    117:        bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
                    118:        if (bp != &sblk)
                    119:                return;
                    120:        for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
                    121:                bwrite(&dfile, (char *)sblock.fs_csp[j],
                    122:                    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
                    123:                    sblock.fs_cssize - i < sblock.fs_bsize ?
                    124:                    sblock.fs_cssize - i : sblock.fs_bsize);
                    125:        }
                    126: }
                    127: 
                    128: rwerr(s, blk)
                    129:        char *s;
                    130:        daddr_t blk;
                    131: {
                    132: 
                    133:        if (preen == 0)
                    134:                printf("\n");
                    135:        pfatal("CANNOT %s: BLK %ld", s, blk);
                    136:        if (reply("CONTINUE") == 0)
                    137:                errexit("Program terminated\n");
                    138: }
                    139: 
                    140: ckfini()
                    141: {
                    142: 
                    143:        flush(&dfile, &fileblk);
                    144:        flush(&dfile, &sblk);
                    145:        if (sblk.b_bno != SBLOCK) {
                    146:                sblk.b_bno = SBLOCK;
                    147:                sbdirty();
                    148:                flush(&dfile, &sblk);
                    149:        }
                    150:        flush(&dfile, &inoblk);
                    151:        flush(&dfile, &cgblk);
                    152:        (void)close(dfile.rfdes);
                    153:        (void)close(dfile.wfdes);
                    154: }
                    155: 
                    156: bread(fcp, buf, blk, size)
                    157:        register struct filecntl *fcp;
                    158:        char *buf;
                    159:        daddr_t blk;
                    160:        long size;
                    161: {
                    162:        char *cp;
                    163:        int i, errs;
                    164: 
                    165:        if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
                    166:                rwerr("SEEK", blk);
                    167:        else if (read(fcp->rfdes, buf, (int)size) == size)
                    168:                return (0);
                    169:        rwerr("READ", blk);
                    170:        if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
                    171:                rwerr("SEEK", blk);
                    172:        errs = 0;
                    173:        pfatal("THE FOLLOWING SECTORS COULD NOT BE READ:");
                    174:        for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) {
                    175:                if (read(fcp->rfdes, cp, DEV_BSIZE) < 0) {
                    176:                        printf(" %d,", blk + i / DEV_BSIZE);
                    177:                        bzero(cp, DEV_BSIZE);
                    178:                        errs++;
                    179:                }
                    180:        }
                    181:        printf("\n");
                    182:        return (errs);
                    183: }
                    184: 
                    185: bwrite(fcp, buf, blk, size)
                    186:        register struct filecntl *fcp;
                    187:        char *buf;
                    188:        daddr_t blk;
                    189:        long size;
                    190: {
                    191:        int i;
                    192:        char *cp;
                    193: 
                    194:        if (fcp->wfdes < 0)
                    195:                return;
                    196:        if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
                    197:                rwerr("SEEK", blk);
                    198:        else if (write(fcp->wfdes, buf, (int)size) == size) {
                    199:                fcp->mod = 1;
                    200:                return;
                    201:        }
                    202:        rwerr("WRITE", blk);
                    203:        if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
                    204:                rwerr("SEEK", blk);
                    205:        pfatal("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
                    206:        for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE)
                    207:                if (write(fcp->wfdes, cp, DEV_BSIZE) < 0)
                    208:                        printf(" %d,", blk + i / DEV_BSIZE);
                    209:        printf("\n");
                    210:        return;
                    211: }
                    212: 
                    213: /*
                    214:  * allocate a data block with the specified number of fragments
                    215:  */
                    216: allocblk(frags)
                    217:        int frags;
                    218: {
                    219:        register int i, j, k;
                    220: 
                    221:        if (frags <= 0 || frags > sblock.fs_frag)
                    222:                return (0);
                    223:        for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) {
                    224:                for (j = 0; j <= sblock.fs_frag - frags; j++) {
                    225:                        if (getbmap(i + j))
                    226:                                continue;
                    227:                        for (k = 1; k < frags; k++)
                    228:                                if (getbmap(i + j + k))
                    229:                                        break;
                    230:                        if (k < frags) {
                    231:                                j += k;
                    232:                                continue;
                    233:                        }
                    234:                        for (k = 0; k < frags; k++)
                    235:                                setbmap(i + j + k);
                    236:                        n_blks += frags;
                    237:                        return (i + j);
                    238:                }
                    239:        }
                    240:        return (0);
                    241: }
                    242: 
                    243: /*
                    244:  * Free a previously allocated block
                    245:  */
                    246: freeblk(blkno, frags)
                    247:        daddr_t blkno;
                    248:        int frags;
                    249: {
                    250:        struct inodesc idesc;
                    251: 
                    252:        idesc.id_blkno = blkno;
                    253:        idesc.id_numfrags = frags;
                    254:        pass4check(&idesc);
                    255: }
                    256: 
                    257: /*
                    258:  * Find a pathname
                    259:  */
                    260: getpathname(namebuf, curdir, ino)
                    261:        char *namebuf;
                    262:        ino_t curdir, ino;
                    263: {
                    264:        int len;
                    265:        register char *cp;
                    266:        struct inodesc idesc;
                    267:        extern int findname();
                    268: 
                    269:        if (statemap[ino] != DSTATE && statemap[ino] != DFOUND) {
                    270:                strcpy(namebuf, "?");
                    271:                return;
                    272:        }
                    273:        bzero(&idesc, sizeof(struct inodesc));
                    274:        idesc.id_type = DATA;
                    275:        cp = &namebuf[BUFSIZ - 1];
                    276:        *cp-- = '\0';
                    277:        if (curdir != ino) {
                    278:                idesc.id_parent = curdir;
                    279:                goto namelookup;
                    280:        }
                    281:        while (ino != ROOTINO) {
                    282:                idesc.id_number = ino;
                    283:                idesc.id_func = findino;
                    284:                idesc.id_name = "..";
                    285:                if ((ckinode(ginode(ino), &idesc) & STOP) == 0)
                    286:                        break;
                    287:        namelookup:
                    288:                idesc.id_number = idesc.id_parent;
                    289:                idesc.id_parent = ino;
                    290:                idesc.id_func = findname;
                    291:                idesc.id_name = namebuf;
                    292:                if ((ckinode(ginode(idesc.id_number), &idesc) & STOP) == 0)
                    293:                        break;
                    294:                len = strlen(namebuf);
                    295:                cp -= len;
                    296:                if (cp < &namebuf[MAXNAMLEN])
                    297:                        break;
                    298:                bcopy(namebuf, cp, len);
                    299:                *--cp = '/';
                    300:                ino = idesc.id_number;
                    301:        }
                    302:        if (ino != ROOTINO) {
                    303:                strcpy(namebuf, "?");
                    304:                return;
                    305:        }
                    306:        bcopy(cp, namebuf, &namebuf[BUFSIZ] - cp);
                    307: }
                    308: 
                    309: catch()
                    310: {
                    311: 
                    312:        ckfini();
                    313:        exit(12);
                    314: }
                    315: 
                    316: /*
                    317:  * When preening, allow a single quit to signal
                    318:  * a special exit after filesystem checks complete
                    319:  * so that reboot sequence may be interrupted.
                    320:  */
                    321: catchquit()
                    322: {
                    323:        extern returntosingle;
                    324: 
                    325:        printf("returning to single-user after filesystem check\n");
                    326:        returntosingle = 1;
                    327:        (void)signal(SIGQUIT, SIG_DFL);
                    328: }
                    329: 
                    330: /*
                    331:  * Ignore a single quit signal; wait and flush just in case.
                    332:  * Used by child processes in preen.
                    333:  */
                    334: voidquit()
                    335: {
                    336: 
                    337:        sleep(1);
                    338:        (void)signal(SIGQUIT, SIG_IGN);
                    339:        (void)signal(SIGQUIT, SIG_DFL);
                    340: }
                    341: 
                    342: /*
                    343:  * determine whether an inode should be fixed.
                    344:  */
                    345: dofix(idesc, msg)
                    346:        register struct inodesc *idesc;
                    347:        char *msg;
                    348: {
                    349: 
                    350:        switch (idesc->id_fix) {
                    351: 
                    352:        case DONTKNOW:
                    353:                if (idesc->id_type == DATA)
                    354:                        direrr(idesc->id_number, msg);
                    355:                else
                    356:                        pwarn(msg);
                    357:                if (preen) {
                    358:                        printf(" (SALVAGED)\n");
                    359:                        idesc->id_fix = FIX;
                    360:                        return (ALTERED);
                    361:                }
                    362:                if (reply("SALVAGE") == 0) {
                    363:                        idesc->id_fix = NOFIX;
                    364:                        return (0);
                    365:                }
                    366:                idesc->id_fix = FIX;
                    367:                return (ALTERED);
                    368: 
                    369:        case FIX:
                    370:                return (ALTERED);
                    371: 
                    372:        case NOFIX:
                    373:                return (0);
                    374: 
                    375:        default:
                    376:                errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
                    377:        }
                    378:        /* NOTREACHED */
                    379: }
                    380: 
                    381: /* VARARGS1 */
                    382: errexit(s1, s2, s3, s4)
                    383:        char *s1;
                    384: {
                    385:        printf(s1, s2, s3, s4);
                    386:        exit(8);
                    387: }
                    388: 
                    389: /*
                    390:  * An inconsistency occured which shouldn't during normal operations.
                    391:  * Die if preening, otherwise just printf.
                    392:  */
                    393: /* VARARGS1 */
                    394: pfatal(s, a1, a2, a3)
                    395:        char *s;
                    396: {
                    397: 
                    398:        if (preen) {
                    399:                printf("%s: ", devname);
                    400:                printf(s, a1, a2, a3);
                    401:                printf("\n");
                    402:                printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
                    403:                        devname);
                    404:                exit(8);
                    405:        }
                    406:        printf(s, a1, a2, a3);
                    407: }
                    408: 
                    409: /*
                    410:  * Pwarn is like printf when not preening,
                    411:  * or a warning (preceded by filename) when preening.
                    412:  */
                    413: /* VARARGS1 */
                    414: pwarn(s, a1, a2, a3, a4, a5, a6)
                    415:        char *s;
                    416: {
                    417: 
                    418:        if (preen)
                    419:                printf("%s: ", devname);
                    420:        printf(s, a1, a2, a3, a4, a5, a6);
                    421: }
                    422: 
                    423: #ifndef lint
                    424: /*
                    425:  * Stub for routines from kernel.
                    426:  */
                    427: panic(s)
                    428:        char *s;
                    429: {
                    430: 
                    431:        pfatal("INTERNAL INCONSISTENCY:");
                    432:        errexit(s);
                    433: }
                    434: #endif

unix.superglobalmegacorp.com

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