|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.