[BACK]Return to pass2.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / fsck_lfs

Annotation of src/sbin/fsck_lfs/pass2.c, Revision 1.33

1.33    ! dholland    1: /* $NetBSD: pass2.c,v 1.32 2015/09/15 15:02:25 dholland Exp $   */
1.1       perseant    2:
                      3: /*
                      4:  * Copyright (c) 1980, 1986, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
1.10      agc        15:  * 3. Neither the name of the University nor the names of its contributors
1.1       perseant   16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
1.7       perseant   32: #include <sys/types.h>
1.1       perseant   33: #include <sys/param.h>
                     34: #include <sys/time.h>
1.7       perseant   35: #include <sys/mount.h>
                     36: #include <sys/buf.h>
                     37:
1.1       perseant   38: #include <ufs/lfs/lfs.h>
1.26      dholland   39: #include <ufs/lfs/lfs_accessors.h>
1.23      dholland   40: #include <ufs/lfs/lfs_inode.h>
1.1       perseant   41:
1.7       perseant   42: #include <err.h>
1.1       perseant   43: #include <stdio.h>
                     44: #include <stdlib.h>
                     45: #include <string.h>
                     46:
1.7       perseant   47: #include "bufcache.h"
                     48: #include "vnode.h"
1.15      christos   49: #include "lfs_user.h"
1.7       perseant   50:
1.1       perseant   51: #include "fsck.h"
                     52: #include "fsutil.h"
                     53: #include "extern.h"
                     54:
1.21      dholland   55: #define MINDIRSIZE     (sizeof (struct lfs_dirtemplate))
1.1       perseant   56:
1.7       perseant   57: static int pass2check(struct inodesc *);
                     58: static int blksort(const void *, const void *);
1.1       perseant   59:
                     60: void
1.11      xtraeme    61: pass2(void)
1.1       perseant   62: {
1.26      dholland   63:        union lfs_dinode *dp;
1.7       perseant   64:        struct uvnode *vp;
                     65:        struct inoinfo **inpp, *inp;
1.1       perseant   66:        struct inoinfo **inpend;
1.7       perseant   67:        struct inodesc curino;
1.26      dholland   68:        union lfs_dinode dino;
1.7       perseant   69:        char pathbuf[MAXPATHLEN + 1];
1.26      dholland   70:        uint16_t mode;
                     71:        unsigned ii;
1.1       perseant   72:
1.19      dholland   73:        switch (statemap[ULFS_ROOTINO]) {
1.1       perseant   74:
                     75:        case USTATE:
                     76:                pfatal("ROOT INODE UNALLOCATED");
                     77:                if (reply("ALLOCATE") == 0)
1.17      christos   78:                        err(EEXIT, "%s", "");
1.19      dholland   79:                if (allocdir(ULFS_ROOTINO, ULFS_ROOTINO, 0755) != ULFS_ROOTINO)
1.25      christos   80:                        err(EEXIT, "CANNOT ALLOCATE ROOT INODE");
1.1       perseant   81:                break;
                     82:
                     83:        case DCLEAR:
                     84:                pfatal("DUPS/BAD IN ROOT INODE");
                     85:                if (reply("REALLOCATE")) {
1.19      dholland   86:                        freeino(ULFS_ROOTINO);
                     87:                        if (allocdir(ULFS_ROOTINO, ULFS_ROOTINO, 0755) != ULFS_ROOTINO)
1.24      christos   88:                                err(EEXIT, "CANNOT ALLOCATE ROOT INODE");
1.1       perseant   89:                        break;
                     90:                }
                     91:                if (reply("CONTINUE") == 0)
1.17      christos   92:                        err(EEXIT, "%s", "");
1.1       perseant   93:                break;
                     94:
                     95:        case FSTATE:
                     96:        case FCLEAR:
                     97:                pfatal("ROOT INODE NOT DIRECTORY");
                     98:                if (reply("REALLOCATE")) {
1.19      dholland   99:                        freeino(ULFS_ROOTINO);
                    100:                        if (allocdir(ULFS_ROOTINO, ULFS_ROOTINO, 0755) != ULFS_ROOTINO)
1.24      christos  101:                                err(EEXIT, "CANNOT ALLOCATE ROOT INODE");
1.1       perseant  102:                        break;
                    103:                }
                    104:                if (reply("FIX") == 0)
1.17      christos  105:                        errx(EEXIT, "%s", "");
1.19      dholland  106:                vp = vget(fs, ULFS_ROOTINO);
1.7       perseant  107:                dp = VTOD(vp);
1.26      dholland  108:                mode = lfs_dino_getmode(fs, dp);
                    109:                mode &= ~LFS_IFMT;
                    110:                mode |= LFS_IFDIR;
                    111:                lfs_dino_setmode(fs, dp, mode);
1.7       perseant  112:                inodirty(VTOI(vp));
1.1       perseant  113:                break;
                    114:
                    115:        case DSTATE:
                    116:                break;
                    117:
                    118:        default:
1.24      christos  119:                errx(EEXIT, "BAD STATE %d FOR ROOT INODE", statemap[ULFS_ROOTINO]);
1.1       perseant  120:        }
1.19      dholland  121:        statemap[ULFS_WINO] = FSTATE;
1.21      dholland  122:        typemap[ULFS_WINO] = LFS_DT_WHT;
1.1       perseant  123:        /*
                    124:         * Sort the directory list into disk block order.
                    125:         */
1.7       perseant  126:        qsort((char *) inpsort, (size_t) inplast, sizeof *inpsort, blksort);
1.1       perseant  127:        /*
                    128:         * Check the integrity of each directory.
                    129:         */
                    130:        memset(&curino, 0, sizeof(struct inodesc));
                    131:        curino.id_type = DATA;
                    132:        curino.id_func = pass2check;
                    133:        inpend = &inpsort[inplast];
                    134:        for (inpp = inpsort; inpp < inpend; inpp++) {
                    135:                inp = *inpp;
                    136:                if (inp->i_isize == 0)
                    137:                        continue;
                    138:                if (inp->i_isize < MINDIRSIZE) {
                    139:                        direrror(inp->i_number, "DIRECTORY TOO SHORT");
1.22      dholland  140:                        inp->i_isize = roundup(MINDIRSIZE, LFS_DIRBLKSIZ);
1.1       perseant  141:                        if (reply("FIX") == 1) {
1.7       perseant  142:                                vp = vget(fs, inp->i_number);
                    143:                                dp = VTOD(vp);
1.26      dholland  144:                                lfs_dino_setsize(fs, dp, inp->i_isize);
1.7       perseant  145:                                inodirty(VTOI(vp));
1.1       perseant  146:                        }
1.22      dholland  147:                } else if ((inp->i_isize & (LFS_DIRBLKSIZ - 1)) != 0) {
1.9       itojun    148:                        getpathname(pathbuf, sizeof(pathbuf), inp->i_number,
                    149:                            inp->i_number);
1.2       nathanw   150:                        pwarn("DIRECTORY %s: LENGTH %lu NOT MULTIPLE OF %d",
1.22      dholland  151:                            pathbuf, (unsigned long) inp->i_isize, LFS_DIRBLKSIZ);
1.1       perseant  152:                        if (preen)
                    153:                                printf(" (ADJUSTED)\n");
1.22      dholland  154:                        inp->i_isize = roundup(inp->i_isize, LFS_DIRBLKSIZ);
1.1       perseant  155:                        if (preen || reply("ADJUST") == 1) {
1.7       perseant  156:                                vp = vget(fs, inp->i_number);
                    157:                                dp = VTOD(vp);
1.26      dholland  158:                                lfs_dino_setsize(fs, dp, inp->i_isize);
1.7       perseant  159:                                inodirty(VTOI(vp));
1.1       perseant  160:                        }
                    161:                }
1.26      dholland  162:                memset(&dino, 0, sizeof(dino));
                    163:                lfs_dino_setmode(fs, &dino, LFS_IFDIR);
                    164:                lfs_dino_setsize(fs, &dino, inp->i_isize);
                    165:                for (ii = 0; ii < inp->i_numblks / sizeof(inp->i_blks[0]) &&
                    166:                             ii < ULFS_NDADDR; ii++) {
                    167:                        lfs_dino_setdb(fs, &dino, ii, inp->i_blks[ii]);
                    168:                }
                    169:                for (; ii < inp->i_numblks / sizeof(inp->i_blks[0]); ii++) {
                    170:                        lfs_dino_setib(fs, &dino, ii - ULFS_NDADDR,
                    171:                                       inp->i_blks[ii]);
                    172:                }
1.1       perseant  173:                curino.id_number = inp->i_number;
                    174:                curino.id_parent = inp->i_parent;
1.7       perseant  175:                (void) ckinode(&dino, &curino);
1.1       perseant  176:        }
                    177:        /*
                    178:         * Now that the parents of all directories have been found,
                    179:         * make another pass to verify the value of `..'
                    180:         */
                    181:        for (inpp = inpsort; inpp < inpend; inpp++) {
                    182:                inp = *inpp;
                    183:                if (inp->i_parent == 0 || inp->i_isize == 0)
                    184:                        continue;
                    185:                if (inp->i_dotdot == inp->i_parent ||
1.7       perseant  186:                    inp->i_dotdot == (ino_t) - 1)
1.1       perseant  187:                        continue;
                    188:                if (inp->i_dotdot == 0) {
                    189:                        inp->i_dotdot = inp->i_parent;
                    190:                        fileerror(inp->i_parent, inp->i_number, "MISSING '..'");
                    191:                        if (reply("FIX") == 0)
                    192:                                continue;
1.7       perseant  193:                        (void) makeentry(inp->i_number, inp->i_parent, "..");
1.1       perseant  194:                        lncntp[inp->i_parent]--;
                    195:                        continue;
                    196:                }
                    197:                fileerror(inp->i_parent, inp->i_number,
1.7       perseant  198:                    "BAD INODE NUMBER FOR '..'");
1.1       perseant  199:                if (reply("FIX") == 0)
                    200:                        continue;
                    201:                lncntp[inp->i_dotdot]++;
                    202:                lncntp[inp->i_parent]--;
                    203:                inp->i_dotdot = inp->i_parent;
1.7       perseant  204:                (void) changeino(inp->i_number, "..", inp->i_parent);
1.1       perseant  205:        }
                    206:        /*
                    207:         * Mark all the directories that can be found from the root.
                    208:         */
                    209:        propagate();
                    210: }
                    211:
                    212: static int
1.4       perseant  213: pass2check(struct inodesc * idesc)
1.1       perseant  214: {
1.32      dholland  215:        struct lfs_dirheader *dirp = idesc->id_dirp;
1.12      perry     216:        struct inoinfo *inp;
1.7       perseant  217:        int n, entrysize, ret = 0;
1.26      dholland  218:        union lfs_dinode *dp;
1.14      christos  219:        const char *errmsg;
1.32      dholland  220:        struct lfs_dirheader proto;
1.7       perseant  221:        char namebuf[MAXPATHLEN + 1];
                    222:        char pathbuf[MAXPATHLEN + 1];
1.1       perseant  223:
                    224:        /*
                    225:         * check for "."
                    226:         */
                    227:        if (idesc->id_entryno != 0)
                    228:                goto chk1;
1.31      dholland  229:        if (lfs_dir_getino(fs, dirp) != 0 && strcmp(lfs_dir_nameptr(fs, dirp), ".") == 0) {
1.28      dholland  230:                if (lfs_dir_getino(fs, dirp) != idesc->id_number) {
1.1       perseant  231:                        direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
1.27      dholland  232:                        if (reply("FIX") == 1) {
1.28      dholland  233:                                lfs_dir_setino(fs, dirp, idesc->id_number);
1.1       perseant  234:                                ret |= ALTERED;
1.27      dholland  235:                        }
1.1       perseant  236:                }
1.27      dholland  237:                if (lfs_dir_gettype(fs, dirp) != LFS_DT_DIR) {
1.1       perseant  238:                        direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
1.27      dholland  239:                        if (reply("FIX") == 1) {
                    240:                                lfs_dir_settype(fs, dirp, LFS_DT_DIR);
1.1       perseant  241:                                ret |= ALTERED;
1.27      dholland  242:                        }
1.1       perseant  243:                }
                    244:                goto chk1;
                    245:        }
                    246:        direrror(idesc->id_number, "MISSING '.'");
1.28      dholland  247:        lfs_dir_setino(fs, &proto, idesc->id_number);
1.27      dholland  248:        lfs_dir_settype(fs, &proto, LFS_DT_DIR);
                    249:        lfs_dir_setnamlen(fs, &proto, 1);
1.33    ! dholland  250:        entrysize = LFS_DIRECTSIZ(fs, 1);
1.29      dholland  251:        lfs_dir_setreclen(fs, &proto, entrysize);
1.31      dholland  252:        if (lfs_dir_getino(fs, dirp) != 0 && strcmp(lfs_dir_nameptr(fs, dirp), "..") != 0) {
1.1       perseant  253:                pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
1.31      dholland  254:                    lfs_dir_nameptr(fs, dirp));
1.28      dholland  255:        } else if (lfs_dir_getreclen(fs, dirp) < entrysize) {
1.1       perseant  256:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
1.28      dholland  257:        } else if (lfs_dir_getreclen(fs, dirp) < 2 * entrysize) {
1.29      dholland  258:                /* convert this entry to a . entry */
1.28      dholland  259:                lfs_dir_setreclen(fs, &proto, lfs_dir_getreclen(fs, dirp));
1.29      dholland  260:                memcpy(dirp, &proto, sizeof(proto));
1.31      dholland  261:                lfs_copydirname(fs, lfs_dir_nameptr(fs, dirp), ".", 1,
1.30      dholland  262:                                lfs_dir_getreclen(fs, dirp));
1.1       perseant  263:                if (reply("FIX") == 1)
                    264:                        ret |= ALTERED;
                    265:        } else {
1.29      dholland  266:                /* split this entry and use the beginning for the . entry */
1.28      dholland  267:                n = lfs_dir_getreclen(fs, dirp) - entrysize;
1.29      dholland  268:                memcpy(dirp, &proto, sizeof(proto));
1.31      dholland  269:                lfs_copydirname(fs, lfs_dir_nameptr(fs, dirp), ".", 1,
1.30      dholland  270:                                lfs_dir_getreclen(fs, dirp));
1.1       perseant  271:                idesc->id_entryno++;
1.28      dholland  272:                lncntp[lfs_dir_getino(fs, dirp)]--;
1.29      dholland  273:                dirp = LFS_NEXTDIR(fs, dirp);
1.7       perseant  274:                memset(dirp, 0, (size_t) n);
1.28      dholland  275:                lfs_dir_setreclen(fs, dirp, n);
1.1       perseant  276:                if (reply("FIX") == 1)
                    277:                        ret |= ALTERED;
                    278:        }
                    279: chk1:
                    280:        if (idesc->id_entryno > 1)
                    281:                goto chk2;
                    282:        inp = getinoinfo(idesc->id_number);
1.28      dholland  283:        lfs_dir_setino(fs, &proto, inp->i_parent);
1.27      dholland  284:        lfs_dir_settype(fs, &proto, LFS_DT_DIR);
                    285:        lfs_dir_setnamlen(fs, &proto, 2);
1.33    ! dholland  286:        entrysize = LFS_DIRECTSIZ(fs, 2);
1.29      dholland  287:        lfs_dir_setreclen(fs, &proto, entrysize);
1.1       perseant  288:        if (idesc->id_entryno == 0) {
1.27      dholland  289:                n = LFS_DIRSIZ(fs, dirp);
1.28      dholland  290:                if (lfs_dir_getreclen(fs, dirp) < n + entrysize)
1.1       perseant  291:                        goto chk2;
1.28      dholland  292:                lfs_dir_setreclen(fs, &proto, lfs_dir_getreclen(fs, dirp) - n);
                    293:                lfs_dir_setreclen(fs, dirp, n);
1.1       perseant  294:                idesc->id_entryno++;
1.28      dholland  295:                lncntp[lfs_dir_getino(fs, dirp)]--;
1.32      dholland  296:                dirp = (struct lfs_dirheader *) ((char *) (dirp) + n);
1.28      dholland  297:                memset(dirp, 0, lfs_dir_getreclen(fs, &proto));
                    298:                lfs_dir_setreclen(fs, dirp, lfs_dir_getreclen(fs, &proto));
1.1       perseant  299:        }
1.31      dholland  300:        if (lfs_dir_getino(fs, dirp) != 0 && strcmp(lfs_dir_nameptr(fs, dirp), "..") == 0) {
1.28      dholland  301:                inp->i_dotdot = lfs_dir_getino(fs, dirp);
1.27      dholland  302:                if (lfs_dir_gettype(fs, dirp) != LFS_DT_DIR) {
1.1       perseant  303:                        direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
1.27      dholland  304:                        lfs_dir_settype(fs, dirp, LFS_DT_DIR);
1.1       perseant  305:                        if (reply("FIX") == 1)
                    306:                                ret |= ALTERED;
                    307:                }
                    308:                goto chk2;
                    309:        }
1.31      dholland  310:        if (lfs_dir_getino(fs, dirp) != 0 && strcmp(lfs_dir_nameptr(fs, dirp), ".") != 0) {
1.1       perseant  311:                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
                    312:                pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
1.31      dholland  313:                    lfs_dir_nameptr(fs, dirp));
1.7       perseant  314:                inp->i_dotdot = (ino_t) - 1;
1.28      dholland  315:        } else if (lfs_dir_getreclen(fs, dirp) < entrysize) {
1.1       perseant  316:                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
                    317:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
1.7       perseant  318:                inp->i_dotdot = (ino_t) - 1;
1.1       perseant  319:        } else if (inp->i_parent != 0) {
                    320:                /*
                    321:                 * We know the parent, so fix now.
                    322:                 */
                    323:                inp->i_dotdot = inp->i_parent;
                    324:                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
1.28      dholland  325:                lfs_dir_setreclen(fs, &proto, lfs_dir_getreclen(fs, dirp));
1.7       perseant  326:                memcpy(dirp, &proto, (size_t) entrysize);
1.31      dholland  327:                lfs_copydirname(fs, lfs_dir_nameptr(fs, dirp), "..", 2,
1.30      dholland  328:                                lfs_dir_getreclen(fs, dirp));
1.1       perseant  329:                if (reply("FIX") == 1)
                    330:                        ret |= ALTERED;
                    331:        }
                    332:        idesc->id_entryno++;
1.28      dholland  333:        if (lfs_dir_getino(fs, dirp) != 0)
                    334:                lncntp[lfs_dir_getino(fs, dirp)]--;
1.4       perseant  335:        return (ret | KEEPON);
1.1       perseant  336: chk2:
1.28      dholland  337:        if (lfs_dir_getino(fs, dirp) == 0)
1.4       perseant  338:                return (ret | KEEPON);
1.27      dholland  339:        if (lfs_dir_getnamlen(fs, dirp) <= 2 &&
1.31      dholland  340:            lfs_dir_nameptr(fs, dirp)[0] == '.' &&
1.1       perseant  341:            idesc->id_entryno >= 2) {
1.27      dholland  342:                if (lfs_dir_getnamlen(fs, dirp) == 1) {
1.1       perseant  343:                        direrror(idesc->id_number, "EXTRA '.' ENTRY");
1.27      dholland  344:                        if (reply("FIX") == 1) {
1.28      dholland  345:                                lfs_dir_setino(fs, dirp, 0);
1.1       perseant  346:                                ret |= ALTERED;
1.27      dholland  347:                        }
1.1       perseant  348:                        return (KEEPON | ret);
                    349:                }
1.31      dholland  350:                if (lfs_dir_nameptr(fs, dirp)[1] == '.') {
1.1       perseant  351:                        direrror(idesc->id_number, "EXTRA '..' ENTRY");
1.27      dholland  352:                        if (reply("FIX") == 1) {
1.28      dholland  353:                                lfs_dir_setino(fs, dirp, 0);
1.1       perseant  354:                                ret |= ALTERED;
1.27      dholland  355:                        }
1.1       perseant  356:                        return (KEEPON | ret);
                    357:                }
                    358:        }
                    359:        idesc->id_entryno++;
                    360:        n = 0;
1.28      dholland  361:        if (lfs_dir_getino(fs, dirp) >= maxino) {
                    362:                fileerror(idesc->id_number, lfs_dir_getino(fs, dirp), "I OUT OF RANGE");
1.1       perseant  363:                n = reply("REMOVE");
1.28      dholland  364:        } else if (lfs_dir_getino(fs, dirp) == LFS_IFILE_INUM &&
1.19      dholland  365:            idesc->id_number == ULFS_ROOTINO) {
1.27      dholland  366:                if (lfs_dir_gettype(fs, dirp) != LFS_DT_REG) {
1.28      dholland  367:                        fileerror(idesc->id_number, lfs_dir_getino(fs, dirp),
1.7       perseant  368:                            "BAD TYPE FOR IFILE");
1.27      dholland  369:                        if (reply("FIX") == 1) {
                    370:                                lfs_dir_settype(fs, dirp, LFS_DT_REG);
1.4       perseant  371:                                ret |= ALTERED;
1.27      dholland  372:                        }
1.4       perseant  373:                }
1.28      dholland  374:        } else if (((lfs_dir_getino(fs, dirp) == ULFS_WINO && lfs_dir_gettype(fs, dirp) != LFS_DT_WHT) ||
                    375:                (lfs_dir_getino(fs, dirp) != ULFS_WINO && lfs_dir_gettype(fs, dirp) == LFS_DT_WHT))) {
                    376:                fileerror(idesc->id_number, lfs_dir_getino(fs, dirp), "BAD WHITEOUT ENTRY");
1.27      dholland  377:                if (reply("FIX") == 1) {
1.28      dholland  378:                        lfs_dir_setino(fs, dirp, ULFS_WINO);
1.27      dholland  379:                        lfs_dir_settype(fs, dirp, LFS_DT_WHT);
1.1       perseant  380:                        ret |= ALTERED;
1.27      dholland  381:                }
1.1       perseant  382:        } else {
                    383: again:
1.28      dholland  384:                switch (statemap[lfs_dir_getino(fs, dirp)]) {
1.1       perseant  385:                case USTATE:
                    386:                        if (idesc->id_entryno <= 2)
                    387:                                break;
1.28      dholland  388:                        fileerror(idesc->id_number, lfs_dir_getino(fs, dirp),
                    389:                            "UNALLOCATED");
1.1       perseant  390:                        n = reply("REMOVE");
                    391:                        break;
                    392:
                    393:                case DCLEAR:
                    394:                case FCLEAR:
                    395:                        if (idesc->id_entryno <= 2)
                    396:                                break;
1.28      dholland  397:                        if (statemap[lfs_dir_getino(fs, dirp)] == FCLEAR)
1.1       perseant  398:                                errmsg = "DUP/BAD";
                    399:                        else if (!preen)
                    400:                                errmsg = "ZERO LENGTH DIRECTORY";
                    401:                        else {
                    402:                                n = 1;
                    403:                                break;
                    404:                        }
1.28      dholland  405:                        fileerror(idesc->id_number, lfs_dir_getino(fs, dirp), errmsg);
1.1       perseant  406:                        if ((n = reply("REMOVE")) == 1)
                    407:                                break;
1.28      dholland  408:                        dp = ginode(lfs_dir_getino(fs, dirp));
                    409:                        statemap[lfs_dir_getino(fs, dirp)] =
1.26      dholland  410:                            (lfs_dino_getmode(fs, dp) & LFS_IFMT) == LFS_IFDIR ? DSTATE : FSTATE;
1.28      dholland  411:                        lncntp[lfs_dir_getino(fs, dirp)] = lfs_dino_getnlink(fs, dp);
1.1       perseant  412:                        goto again;
                    413:
                    414:                case DSTATE:
                    415:                case DFOUND:
1.28      dholland  416:                        inp = getinoinfo(lfs_dir_getino(fs, dirp));
1.1       perseant  417:                        if (inp->i_parent != 0 && idesc->id_entryno > 2) {
1.9       itojun    418:                                getpathname(pathbuf, sizeof(pathbuf),
                    419:                                    idesc->id_number, idesc->id_number);
                    420:                                getpathname(namebuf, sizeof(namebuf),
1.28      dholland  421:                                    lfs_dir_getino(fs, dirp),
                    422:                                    lfs_dir_getino(fs, dirp));
1.1       perseant  423:                                pwarn("%s %s %s\n", pathbuf,
1.7       perseant  424:                                    "IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
                    425:                                    namebuf);
1.1       perseant  426:                                if (preen)
                    427:                                        printf(" (IGNORED)\n");
                    428:                                else if ((n = reply("REMOVE")) == 1)
                    429:                                        break;
                    430:                        }
                    431:                        if (idesc->id_entryno > 2)
                    432:                                inp->i_parent = idesc->id_number;
                    433:                        /* fall through */
                    434:
                    435:                case FSTATE:
1.28      dholland  436:                        if (lfs_dir_gettype(fs, dirp) != typemap[lfs_dir_getino(fs, dirp)]) {
                    437:                                fileerror(idesc->id_number,
                    438:                                    lfs_dir_getino(fs, dirp),
1.7       perseant  439:                                    "BAD TYPE VALUE");
1.13      perseant  440:                                if (debug)
                    441:                                        pwarn("dir has %d, typemap has %d\n",
1.28      dholland  442:                                                lfs_dir_gettype(fs, dirp), typemap[lfs_dir_getino(fs, dirp)]);
                    443:                                lfs_dir_settype(fs, dirp, typemap[lfs_dir_getino(fs, dirp)]);
1.1       perseant  444:                                if (reply("FIX") == 1)
                    445:                                        ret |= ALTERED;
                    446:                        }
1.28      dholland  447:                        lncntp[lfs_dir_getino(fs, dirp)]--;
1.1       perseant  448:                        break;
                    449:
                    450:                default:
1.28      dholland  451:                        errx(EEXIT, "BAD STATE %d FOR INODE I=%ju",
                    452:                            statemap[lfs_dir_getino(fs, dirp)],
                    453:                            (uintmax_t)lfs_dir_getino(fs, dirp));
1.1       perseant  454:                }
                    455:        }
                    456:        if (n == 0)
1.4       perseant  457:                return (ret | KEEPON);
1.28      dholland  458:        lfs_dir_setino(fs, dirp, 0);
1.4       perseant  459:        return (ret | KEEPON | ALTERED);
1.1       perseant  460: }
                    461: /*
                    462:  * Routine to sort disk blocks.
                    463:  */
                    464: static int
1.4       perseant  465: blksort(const void *inpp1, const void *inpp2)
1.1       perseant  466: {
1.14      christos  467:        return ((*(const struct inoinfo *const *) inpp1)->i_blks[0] -
                    468:            (*(const struct inoinfo *const *) inpp2)->i_blks[0]);
1.1       perseant  469: }

CVSweb <webmaster@jp.NetBSD.org>