Annotation of 43BSDReno/sbin/fsck/pass2.c, revision 1.1.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[] = "@(#)pass2.c    5.16 (Berkeley) 9/18/90";
                     22: #endif /* not lint */
                     23: 
                     24: #include <sys/param.h>
                     25: #include <ufs/dinode.h>
                     26: #include <ufs/fs.h>
                     27: #define KERNEL
                     28: #include <ufs/dir.h>
                     29: #undef KERNEL
                     30: #include <stdlib.h>
                     31: #include <string.h>
                     32: #include "fsck.h"
                     33: 
                     34: #define MINDIRSIZE     (sizeof (struct dirtemplate))
                     35: 
                     36: int    pass2check(), blksort();
                     37: 
                     38: pass2()
                     39: {
                     40:        register struct dinode *dp;
                     41:        register struct inoinfo **inpp, *inp;
                     42:        struct inoinfo **inpend;
                     43:        struct inodesc curino;
                     44:        struct dinode dino;
                     45:        char pathbuf[MAXPATHLEN + 1];
                     46: 
                     47:        switch (statemap[ROOTINO]) {
                     48: 
                     49:        case USTATE:
                     50:                pfatal("ROOT INODE UNALLOCATED");
                     51:                if (reply("ALLOCATE") == 0)
                     52:                        errexit("");
                     53:                if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
                     54:                        errexit("CANNOT ALLOCATE ROOT INODE\n");
                     55:                break;
                     56: 
                     57:        case DCLEAR:
                     58:                pfatal("DUPS/BAD IN ROOT INODE");
                     59:                if (reply("REALLOCATE")) {
                     60:                        freeino(ROOTINO);
                     61:                        if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
                     62:                                errexit("CANNOT ALLOCATE ROOT INODE\n");
                     63:                        break;
                     64:                }
                     65:                if (reply("CONTINUE") == 0)
                     66:                        errexit("");
                     67:                break;
                     68: 
                     69:        case FSTATE:
                     70:        case FCLEAR:
                     71:                pfatal("ROOT INODE NOT DIRECTORY");
                     72:                if (reply("REALLOCATE")) {
                     73:                        freeino(ROOTINO);
                     74:                        if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
                     75:                                errexit("CANNOT ALLOCATE ROOT INODE\n");
                     76:                        break;
                     77:                }
                     78:                if (reply("FIX") == 0)
                     79:                        errexit("");
                     80:                dp = ginode(ROOTINO);
                     81:                dp->di_mode &= ~IFMT;
                     82:                dp->di_mode |= IFDIR;
                     83:                inodirty();
                     84:                break;
                     85: 
                     86:        case DSTATE:
                     87:                break;
                     88: 
                     89:        default:
                     90:                errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
                     91:        }
                     92:        statemap[ROOTINO] = DFOUND;
                     93:        /*
                     94:         * Sort the directory list into disk block order.
                     95:         */
                     96:        qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort);
                     97:        /*
                     98:         * Check the integrity of each directory.
                     99:         */
                    100:        bzero((char *)&curino, sizeof(struct inodesc));
                    101:        curino.id_type = DATA;
                    102:        curino.id_func = pass2check;
                    103:        dino.di_mode = IFDIR;
                    104:        dp = &dino;
                    105:        inpend = &inpsort[inplast];
                    106:        for (inpp = inpsort; inpp < inpend; inpp++) {
                    107:                inp = *inpp;
                    108:                if (inp->i_isize == 0)
                    109:                        continue;
                    110:                if (inp->i_isize < MINDIRSIZE) {
                    111:                        direrror(inp->i_number, "DIRECTORY TOO SHORT");
                    112:                        inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ);
                    113:                        if (reply("FIX") == 1) {
                    114:                                dp = ginode(inp->i_number);
                    115:                                dp->di_size = inp->i_isize;
                    116:                                inodirty();
                    117:                                dp = &dino;
                    118:                        }
                    119:                } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
                    120:                        getpathname(pathbuf, inp->i_number, inp->i_number);
                    121:                        pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d",
                    122:                                pathbuf, inp->i_isize, DIRBLKSIZ);
                    123:                        if (preen)
                    124:                                printf(" (ADJUSTED)\n");
                    125:                        inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);
                    126:                        if (preen || reply("ADJUST") == 1) {
                    127:                                dp = ginode(inp->i_number);
                    128:                                dp->di_size = roundup(inp->i_isize, DIRBLKSIZ);
                    129:                                inodirty();
                    130:                                dp = &dino;
                    131:                        }
                    132:                }
                    133:                dp->di_size = inp->i_isize;
                    134:                bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0],
                    135:                        (size_t)inp->i_numblks);
                    136:                curino.id_number = inp->i_number;
                    137:                curino.id_parent = inp->i_parent;
                    138:                (void)ckinode(dp, &curino);
                    139:        }
                    140:        /*
                    141:         * Now that the parents of all directories have been found,
                    142:         * make another pass to verify the value of `..'
                    143:         */
                    144:        for (inpp = inpsort; inpp < inpend; inpp++) {
                    145:                inp = *inpp;
                    146:                if (inp->i_parent == 0 || inp->i_isize == 0)
                    147:                        continue;
                    148:                if (statemap[inp->i_parent] == DFOUND &&
                    149:                    statemap[inp->i_number] == DSTATE)
                    150:                        statemap[inp->i_number] = DFOUND;
                    151:                if (inp->i_dotdot == inp->i_parent ||
                    152:                    inp->i_dotdot == (ino_t)-1)
                    153:                        continue;
                    154:                if (inp->i_dotdot == 0) {
                    155:                        inp->i_dotdot = inp->i_parent;
                    156:                        fileerror(inp->i_parent, inp->i_number, "MISSING '..'");
                    157:                        if (reply("FIX") == 0)
                    158:                                continue;
                    159:                        (void)makeentry(inp->i_number, inp->i_parent, "..");
                    160:                        lncntp[inp->i_parent]--;
                    161:                        continue;
                    162:                }
                    163:                fileerror(inp->i_parent, inp->i_number,
                    164:                        "BAD INODE NUMBER FOR '..'");
                    165:                if (reply("FIX") == 0)
                    166:                        continue;
                    167:                lncntp[inp->i_dotdot]++;
                    168:                lncntp[inp->i_parent]--;
                    169:                inp->i_dotdot = inp->i_parent;
                    170:                (void)changeino(inp->i_number, "..", inp->i_parent);
                    171:        }
                    172:        /*
                    173:         * Mark all the directories that can be found from the root.
                    174:         */
                    175:        propagate();
                    176: }
                    177: 
                    178: pass2check(idesc)
                    179:        struct inodesc *idesc;
                    180: {
                    181:        register struct direct *dirp = idesc->id_dirp;
                    182:        register struct inoinfo *inp;
                    183:        int n, entrysize, ret = 0;
                    184:        struct dinode *dp;
                    185:        char *errmsg;
                    186:        struct direct proto;
                    187:        char namebuf[MAXPATHLEN + 1];
                    188:        char pathbuf[MAXPATHLEN + 1];
                    189: 
                    190:        /* 
                    191:         * check for "."
                    192:         */
                    193:        if (idesc->id_entryno != 0)
                    194:                goto chk1;
                    195:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
                    196:                if (dirp->d_ino != idesc->id_number) {
                    197:                        direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
                    198:                        dirp->d_ino = idesc->id_number;
                    199:                        if (reply("FIX") == 1)
                    200:                                ret |= ALTERED;
                    201:                }
                    202:                goto chk1;
                    203:        }
                    204:        direrror(idesc->id_number, "MISSING '.'");
                    205:        proto.d_ino = idesc->id_number;
                    206:        proto.d_namlen = 1;
                    207:        (void)strcpy(proto.d_name, ".");
                    208:        entrysize = DIRSIZ(&proto);
                    209:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
                    210:                pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
                    211:                        dirp->d_name);
                    212:        } else if (dirp->d_reclen < entrysize) {
                    213:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
                    214:        } else if (dirp->d_reclen < 2 * entrysize) {
                    215:                proto.d_reclen = dirp->d_reclen;
                    216:                bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);
                    217:                if (reply("FIX") == 1)
                    218:                        ret |= ALTERED;
                    219:        } else {
                    220:                n = dirp->d_reclen - entrysize;
                    221:                proto.d_reclen = entrysize;
                    222:                bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);
                    223:                idesc->id_entryno++;
                    224:                lncntp[dirp->d_ino]--;
                    225:                dirp = (struct direct *)((char *)(dirp) + entrysize);
                    226:                bzero((char *)dirp, (size_t)n);
                    227:                dirp->d_reclen = n;
                    228:                if (reply("FIX") == 1)
                    229:                        ret |= ALTERED;
                    230:        }
                    231: chk1:
                    232:        if (idesc->id_entryno > 1)
                    233:                goto chk2;
                    234:        inp = getinoinfo(idesc->id_number);
                    235:        proto.d_ino = inp->i_parent;
                    236:        proto.d_namlen = 2;
                    237:        (void)strcpy(proto.d_name, "..");
                    238:        entrysize = DIRSIZ(&proto);
                    239:        if (idesc->id_entryno == 0) {
                    240:                n = DIRSIZ(dirp);
                    241:                if (dirp->d_reclen < n + entrysize)
                    242:                        goto chk2;
                    243:                proto.d_reclen = dirp->d_reclen - n;
                    244:                dirp->d_reclen = n;
                    245:                idesc->id_entryno++;
                    246:                lncntp[dirp->d_ino]--;
                    247:                dirp = (struct direct *)((char *)(dirp) + n);
                    248:                bzero((char *)dirp, (size_t)proto.d_reclen);
                    249:                dirp->d_reclen = proto.d_reclen;
                    250:        }
                    251:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
                    252:                inp->i_dotdot = dirp->d_ino;
                    253:                goto chk2;
                    254:        }
                    255:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
                    256:                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
                    257:                pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
                    258:                        dirp->d_name);
                    259:                inp->i_dotdot = (ino_t)-1;
                    260:        } else if (dirp->d_reclen < entrysize) {
                    261:                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
                    262:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
                    263:                inp->i_dotdot = (ino_t)-1;
                    264:        } else if (inp->i_parent != 0) {
                    265:                /*
                    266:                 * We know the parent, so fix now.
                    267:                 */
                    268:                inp->i_dotdot = inp->i_parent;
                    269:                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
                    270:                proto.d_reclen = dirp->d_reclen;
                    271:                bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);
                    272:                if (reply("FIX") == 1)
                    273:                        ret |= ALTERED;
                    274:        }
                    275:        idesc->id_entryno++;
                    276:        if (dirp->d_ino != 0)
                    277:                lncntp[dirp->d_ino]--;
                    278:        return (ret|KEEPON);
                    279: chk2:
                    280:        if (dirp->d_ino == 0)
                    281:                return (ret|KEEPON);
                    282:        if (dirp->d_namlen <= 2 &&
                    283:            dirp->d_name[0] == '.' &&
                    284:            idesc->id_entryno >= 2) {
                    285:                if (dirp->d_namlen == 1) {
                    286:                        direrror(idesc->id_number, "EXTRA '.' ENTRY");
                    287:                        dirp->d_ino = 0;
                    288:                        if (reply("FIX") == 1)
                    289:                                ret |= ALTERED;
                    290:                        return (KEEPON | ret);
                    291:                }
                    292:                if (dirp->d_name[1] == '.') {
                    293:                        direrror(idesc->id_number, "EXTRA '..' ENTRY");
                    294:                        dirp->d_ino = 0;
                    295:                        if (reply("FIX") == 1)
                    296:                                ret |= ALTERED;
                    297:                        return (KEEPON | ret);
                    298:                }
                    299:        }
                    300:        idesc->id_entryno++;
                    301:        n = 0;
                    302:        if (dirp->d_ino > maxino || dirp->d_ino <= 0) {
                    303:                fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");
                    304:                n = reply("REMOVE");
                    305:        } else {
                    306: again:
                    307:                switch (statemap[dirp->d_ino]) {
                    308:                case USTATE:
                    309:                        if (idesc->id_entryno <= 2)
                    310:                                break;
                    311:                        fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED");
                    312:                        n = reply("REMOVE");
                    313:                        break;
                    314: 
                    315:                case DCLEAR:
                    316:                case FCLEAR:
                    317:                        if (idesc->id_entryno <= 2)
                    318:                                break;
                    319:                        if (statemap[dirp->d_ino] == DCLEAR)
                    320:                                errmsg = "ZERO LENGTH DIRECTORY";
                    321:                        else
                    322:                                errmsg = "DUP/BAD";
                    323:                        fileerror(idesc->id_number, dirp->d_ino, errmsg);
                    324:                        if ((n = reply("REMOVE")) == 1)
                    325:                                break;
                    326:                        dp = ginode(dirp->d_ino);
                    327:                        statemap[dirp->d_ino] =
                    328:                            (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
                    329:                        lncntp[dirp->d_ino] = dp->di_nlink;
                    330:                        goto again;
                    331: 
                    332:                case DSTATE:
                    333:                        if (statemap[idesc->id_number] == DFOUND)
                    334:                                statemap[dirp->d_ino] = DFOUND;
                    335:                        /* fall through */
                    336: 
                    337:                case DFOUND:
                    338:                        inp = getinoinfo(dirp->d_ino);
                    339:                        if (inp->i_parent != 0 && idesc->id_entryno > 2) {
                    340:                                getpathname(pathbuf, idesc->id_number,
                    341:                                    idesc->id_number);
                    342:                                getpathname(namebuf, dirp->d_ino, dirp->d_ino);
                    343:                                pwarn("%s %s %s\n", pathbuf,
                    344:                                    "IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
                    345:                                    namebuf);
                    346:                                if (preen)
                    347:                                        printf(" (IGNORED)\n");
                    348:                                else if ((n = reply("REMOVE")) == 1)
                    349:                                        break;
                    350:                        }
                    351:                        if (idesc->id_entryno > 2)
                    352:                                inp->i_parent = idesc->id_number;
                    353:                        /* fall through */
                    354: 
                    355:                case FSTATE:
                    356:                        lncntp[dirp->d_ino]--;
                    357:                        break;
                    358: 
                    359:                default:
                    360:                        errexit("BAD STATE %d FOR INODE I=%d",
                    361:                            statemap[dirp->d_ino], dirp->d_ino);
                    362:                }
                    363:        }
                    364:        if (n == 0)
                    365:                return (ret|KEEPON);
                    366:        dirp->d_ino = 0;
                    367:        return (ret|KEEPON|ALTERED);
                    368: }
                    369: 
                    370: /*
                    371:  * Routine to sort disk blocks.
                    372:  */
                    373: blksort(inpp1, inpp2)
                    374:        struct inoinfo **inpp1, **inpp2;
                    375: {
                    376: 
                    377:        return ((*inpp1)->i_blks[0] - (*inpp2)->i_blks[0]);
                    378: }

unix.superglobalmegacorp.com

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