|
|
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.