Annotation of 43BSD/etc/fsck/pass2.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[] = "@(#)pass2.c    5.2 (Berkeley) 3/5/86";
                      9: #endif not lint
                     10: 
                     11: #include <sys/param.h>
                     12: #include <sys/inode.h>
                     13: #include <sys/fs.h>
                     14: #include <sys/dir.h>
                     15: #include <strings.h>
                     16: #include "fsck.h"
                     17: 
                     18: int    pass2check();
                     19: 
                     20: pass2()
                     21: {
                     22:        register DINODE *dp;
                     23:        struct inodesc rootdesc;
                     24: 
                     25:        bzero((char *)&rootdesc, sizeof(struct inodesc));
                     26:        rootdesc.id_type = ADDR;
                     27:        rootdesc.id_func = pass2check;
                     28:        rootdesc.id_number = ROOTINO;
                     29:        pathp = pathname;
                     30:        switch (statemap[ROOTINO]) {
                     31: 
                     32:        case USTATE:
                     33:                pfatal("ROOT INODE UNALLOCATED");
                     34:                if (reply("ALLOCATE") == 0)
                     35:                        errexit("");
                     36:                if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
                     37:                        errexit("CANNOT ALLOCATE ROOT INODE\n");
                     38:                descend(&rootdesc, ROOTINO);
                     39:                break;
                     40: 
                     41:        case DCLEAR:
                     42:                pfatal("DUPS/BAD IN ROOT INODE");
                     43:                if (reply("REALLOCATE")) {
                     44:                        freeino(ROOTINO);
                     45:                        if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
                     46:                                errexit("CANNOT ALLOCATE ROOT INODE\n");
                     47:                        descend(&rootdesc, ROOTINO);
                     48:                        break;
                     49:                }
                     50:                if (reply("CONTINUE") == 0)
                     51:                        errexit("");
                     52:                statemap[ROOTINO] = DSTATE;
                     53:                descend(&rootdesc, ROOTINO);
                     54:                break;
                     55: 
                     56:        case FSTATE:
                     57:        case FCLEAR:
                     58:                pfatal("ROOT INODE NOT DIRECTORY");
                     59:                if (reply("REALLOCATE")) {
                     60:                        freeino(ROOTINO);
                     61:                        if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
                     62:                                errexit("CANNOT ALLOCATE ROOT INODE\n");
                     63:                        descend(&rootdesc, ROOTINO);
                     64:                        break;
                     65:                }
                     66:                if (reply("FIX") == 0)
                     67:                        errexit("");
                     68:                dp = ginode(ROOTINO);
                     69:                dp->di_mode &= ~IFMT;
                     70:                dp->di_mode |= IFDIR;
                     71:                inodirty();
                     72:                statemap[ROOTINO] = DSTATE;
                     73:                /* fall into ... */
                     74: 
                     75:        case DSTATE:
                     76:                descend(&rootdesc, ROOTINO);
                     77:                break;
                     78: 
                     79:        default:
                     80:                errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
                     81:        }
                     82: }
                     83: 
                     84: pass2check(idesc)
                     85:        struct inodesc *idesc;
                     86: {
                     87:        register DIRECT *dirp = idesc->id_dirp;
                     88:        char *curpathloc;
                     89:        int n, entrysize, ret = 0;
                     90:        DINODE *dp;
                     91:        DIRECT proto;
                     92:        char namebuf[BUFSIZ];
                     93: 
                     94:        /* 
                     95:         * check for "."
                     96:         */
                     97:        if (idesc->id_entryno != 0)
                     98:                goto chk1;
                     99:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
                    100:                if (dirp->d_ino != idesc->id_number) {
                    101:                        direrr(idesc->id_number, "BAD INODE NUMBER FOR '.'");
                    102:                        dirp->d_ino = idesc->id_number;
                    103:                        if (reply("FIX") == 1)
                    104:                                ret |= ALTERED;
                    105:                }
                    106:                goto chk1;
                    107:        }
                    108:        direrr(idesc->id_number, "MISSING '.'");
                    109:        proto.d_ino = idesc->id_number;
                    110:        proto.d_namlen = 1;
                    111:        (void)strcpy(proto.d_name, ".");
                    112:        entrysize = DIRSIZ(&proto);
                    113:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
                    114:                pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
                    115:                        dirp->d_name);
                    116:        } else if (dirp->d_reclen < entrysize) {
                    117:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
                    118:        } else if (dirp->d_reclen < 2 * entrysize) {
                    119:                proto.d_reclen = dirp->d_reclen;
                    120:                bcopy((char *)&proto, (char *)dirp, entrysize);
                    121:                if (reply("FIX") == 1)
                    122:                        ret |= ALTERED;
                    123:        } else {
                    124:                n = dirp->d_reclen - entrysize;
                    125:                proto.d_reclen = entrysize;
                    126:                bcopy((char *)&proto, (char *)dirp, entrysize);
                    127:                idesc->id_entryno++;
                    128:                lncntp[dirp->d_ino]--;
                    129:                dirp = (DIRECT *)((char *)(dirp) + entrysize);
                    130:                bzero((char *)dirp, n);
                    131:                dirp->d_reclen = n;
                    132:                if (reply("FIX") == 1)
                    133:                        ret |= ALTERED;
                    134:        }
                    135: chk1:
                    136:        if (idesc->id_entryno > 1)
                    137:                goto chk2;
                    138:        proto.d_ino = idesc->id_parent;
                    139:        proto.d_namlen = 2;
                    140:        (void)strcpy(proto.d_name, "..");
                    141:        entrysize = DIRSIZ(&proto);
                    142:        if (idesc->id_entryno == 0) {
                    143:                n = DIRSIZ(dirp);
                    144:                if (dirp->d_reclen < n + entrysize)
                    145:                        goto chk2;
                    146:                proto.d_reclen = dirp->d_reclen - n;
                    147:                dirp->d_reclen = n;
                    148:                idesc->id_entryno++;
                    149:                lncntp[dirp->d_ino]--;
                    150:                dirp = (DIRECT *)((char *)(dirp) + n);
                    151:                bzero((char *)dirp, n);
                    152:                dirp->d_reclen = n;
                    153:        }
                    154:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
                    155:                if (dirp->d_ino != idesc->id_parent) {
                    156:                        direrr(idesc->id_number, "BAD INODE NUMBER FOR '..'");
                    157:                        dirp->d_ino = idesc->id_parent;
                    158:                        if (reply("FIX") == 1)
                    159:                                ret |= ALTERED;
                    160:                }
                    161:                goto chk2;
                    162:        }
                    163:        direrr(idesc->id_number, "MISSING '..'");
                    164:        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
                    165:                pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
                    166:                        dirp->d_name);
                    167:        } else if (dirp->d_reclen < entrysize) {
                    168:                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
                    169:        } else {
                    170:                proto.d_reclen = dirp->d_reclen;
                    171:                bcopy((char *)&proto, (char *)dirp, entrysize);
                    172:                if (reply("FIX") == 1)
                    173:                        ret |= ALTERED;
                    174:        }
                    175: chk2:
                    176:        if (dirp->d_ino == 0)
                    177:                return (ret|KEEPON);
                    178:        if (dirp->d_namlen <= 2 &&
                    179:            dirp->d_name[0] == '.' &&
                    180:            idesc->id_entryno >= 2) {
                    181:                if (dirp->d_namlen == 1) {
                    182:                        direrr(idesc->id_number, "EXTRA '.' ENTRY");
                    183:                        dirp->d_ino = 0;
                    184:                        if (reply("FIX") == 1)
                    185:                                ret |= ALTERED;
                    186:                        return (KEEPON | ret);
                    187:                }
                    188:                if (dirp->d_name[1] == '.') {
                    189:                        direrr(idesc->id_number, "EXTRA '..' ENTRY");
                    190:                        dirp->d_ino = 0;
                    191:                        if (reply("FIX") == 1)
                    192:                                ret |= ALTERED;
                    193:                        return (KEEPON | ret);
                    194:                }
                    195:        }
                    196:        curpathloc = pathp;
                    197:        *pathp++ = '/';
                    198:        if (pathp + dirp->d_namlen >= endpathname) {
                    199:                *pathp = '\0';
                    200:                errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
                    201:        }
                    202:        bcopy(dirp->d_name, pathp, dirp->d_namlen + 1);
                    203:        pathp += dirp->d_namlen;
                    204:        idesc->id_entryno++;
                    205:        n = 0;
                    206:        if (dirp->d_ino > imax || dirp->d_ino <= 0) {
                    207:                direrr(dirp->d_ino, "I OUT OF RANGE");
                    208:                n = reply("REMOVE");
                    209:        } else {
                    210: again:
                    211:                switch (statemap[dirp->d_ino]) {
                    212:                case USTATE:
                    213:                        direrr(dirp->d_ino, "UNALLOCATED");
                    214:                        n = reply("REMOVE");
                    215:                        break;
                    216: 
                    217:                case DCLEAR:
                    218:                case FCLEAR:
                    219:                        direrr(dirp->d_ino, "DUP/BAD");
                    220:                        if ((n = reply("REMOVE")) == 1)
                    221:                                break;
                    222:                        dp = ginode(dirp->d_ino);
                    223:                        statemap[dirp->d_ino] = DIRCT(dp) ? DSTATE : FSTATE;
                    224:                        goto again;
                    225: 
                    226:                case DFOUND:
                    227:                        if (idesc->id_entryno > 2) {
                    228:                                getpathname(namebuf, dirp->d_ino, dirp->d_ino);
                    229:                                pwarn("%s %s %s\n", pathname,
                    230:                                    "IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
                    231:                                    namebuf);
                    232:                                if (preen)
                    233:                                        printf(" (IGNORED)\n");
                    234:                                else if ((n = reply("REMOVE")) == 1)
                    235:                                        break;
                    236:                        }
                    237:                        /* fall through */
                    238: 
                    239:                case FSTATE:
                    240:                        lncntp[dirp->d_ino]--;
                    241:                        break;
                    242: 
                    243:                case DSTATE:
                    244:                        descend(idesc, dirp->d_ino);
                    245:                        if (statemap[dirp->d_ino] == DFOUND) {
                    246:                                lncntp[dirp->d_ino]--;
                    247:                        } else if (statemap[dirp->d_ino] == DCLEAR) {
                    248:                                dirp->d_ino = 0;
                    249:                                ret |= ALTERED;
                    250:                        } else
                    251:                                errexit("BAD RETURN STATE %d FROM DESCEND",
                    252:                                    statemap[dirp->d_ino]);
                    253:                        break;
                    254: 
                    255:                default:
                    256:                        errexit("BAD STATE %d FOR INODE I=%d",
                    257:                            statemap[dirp->d_ino], dirp->d_ino);
                    258:                }
                    259:        }
                    260:        pathp = curpathloc;
                    261:        *pathp = '\0';
                    262:        if (n == 0)
                    263:                return (ret|KEEPON);
                    264:        dirp->d_ino = 0;
                    265:        return (ret|KEEPON|ALTERED);
                    266: }

unix.superglobalmegacorp.com

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