|
|
1.1 root 1: /*
2: * phase 2 of fsck - Check Pathnames
3: */
4:
5: #include "fsck.h"
6: #include <pwd.h>
7:
8: #define MAXDEPTH 50
9: struct direct *path[MAXDEPTH];
10: int depth;
11: int fixflag; /* flags when must rewrite databuf */
12: daddr_t blocknum; /* Current block num read in */
13:
14: typedef struct list {
15: struct direct d_entry;
16: struct list *next;
17: } list;
18:
19: char buf2[BSIZE]; /* buffer for blocks */
20: daddr_t cdbn; /* current logical block number */
21:
22: /* Format errors, args to blkerr() */
23:
24: #define NULLNAME 5
25: #define NULLPAD 6
26: #define SLASHES 7
27: #define DOT 8
28: #define DOTDOT 9
29:
30: phase2()
31: {
32: if (!qflag)
33: printf("Phase 2 : Check Pathnames\n");
34: checkroot();
35: depth = 0;
36: checkpath(ROOTIN);
37: }
38:
39:
40: checkroot()
41: {
42: if ( (flags(ROOTIN)&MODEMASK) == UNALLOC )
43: fatal("Root i-node is unallocated. Terminating");
44:
45: if ( (flags(ROOTIN)&MODEMASK) != IDIR ) {
46: switch ( query("Root i-node is not a directory (FIX)") ){
47: case YES:
48: fixroot();
49: break;
50: case NO:
51: abort();
52: }
53: }
54:
55: if ( badblks(ROOTIN) ){
56: switch ( query("Dup/Bad blocks in root i-node (Continue)") ) {
57: case YES:
58: break;
59: case NO:
60: abort();
61: }
62: }
63: linkincr(ROOTIN); /* (?) Feature (?) of mkfs is */
64: /* that root inode of a file */
65: /* system has a link count one */
66: /* too large. */
67: }
68:
69: fixroot()
70: {
71: register struct dinode *dip;
72:
73: if (!writeflg)
74: fatal("File System Read-Only (NO WRITE)\n");
75:
76: setflags(ROOTIN, (flags(ROOTIN) & ~MODEMASK) | IDIR);
77:
78: /* Save change to disk */
79:
80: dip = ptrino(ROOTIN, databuf);
81: dip->di_mode &= (~IFMT);
82: dip->di_mode |= IFDIR;
83: writeino(ROOTIN, databuf);
84: }
85:
86: #define myinum ( (depth>0) ? path[depth-1]->d_ino : ROOTIN )
87: #define popinum ( (depth>1) ? path[depth-2]->d_ino : ROOTIN )
88:
89: char *memory = "Can't malloc memory, phase 2";
90:
91: list *
92: procfiles(addrs, length)
93: daddr_t *addrs;
94: fsize_t length;
95: {
96: register struct direct *elemnt;
97: register list *first, *ptr;
98:
99: if ((first=ptr=(list *)malloc(sizeof(list)))==NULL)
100: fatal(memory);
101: first->d_entry.d_ino = 0;
102: first->next = NULL;
103: if ( length < DSIZE )
104: return( first );
105: cdbn = 0;
106: nextblock(addrs);
107: fixflag = FALSE;
108: elemnt = (struct direct *) databuf;
109: cdots(elemnt++, ".", myinum, DOT);
110: ++numfiles;
111: if ( (length-=DSIZE) < DSIZE )
112: return( first );
113: cdots(elemnt++, "..", popinum, DOTDOT);
114: ++numfiles;
115: length -= DSIZE;
116:
117: while ( length >= DSIZE ) {
118: while ( (elemnt<&databuf[BSIZE]) && (length>=DSIZE) ) {
119: if (chck(elemnt)==IDIR) {
120: copy(elemnt, &ptr->d_entry,
121: sizeof(struct direct));
122: if ((ptr->next=(list *)malloc(sizeof(list))) ==
123: NULL)
124: fatal(memory);
125: ptr = ptr->next;
126: ptr->d_entry.d_ino = 0;
127: ptr->next = NULL;
128: }
129: elemnt++;
130: length -= DSIZE;
131: }
132: if (fixflag && (fixblock(addrs) == NUL) )
133: fixblkerr();
134: nextblock(addrs);
135: fixflag = FALSE;
136: elemnt = (struct direct *) databuf;
137: }
138: return(first);
139: }
140:
141: candblock(dptr)
142: register struct direct *dptr;
143: {
144: register int num, i;
145:
146: num = BSIZE/sizeof(struct direct);
147: for (i=0; i<num; i++)
148: canino(dptr[i].d_ino);
149: }
150:
151: nextblock(addrs)
152: register daddr_t *addrs;
153: {
154: register daddr_t bn;
155:
156: if ( (bn=imap(addrs, cdbn++)) == 0 ) {
157: bclear(databuf, BSIZE);
158: return;
159: }
160: bread(bn, databuf);
161: candblock(databuf);
162: blocknum = bn;
163: }
164:
165: fixblock(addrs)
166: daddr_t *addrs;
167: {
168: daddr_t bn;
169:
170: if ( (bn=imap(addrs, cdbn-1)) == 0 )
171: return(NUL);
172: candblock(databuf);
173: bwrite(bn, databuf);
174: return(TRUE);
175: }
176:
177: fixblkerr()
178: {
179: fatal("Fixblock error.");
180: }
181:
182: copy(from, to, size)
183: register char *from, *to;
184: register int size;
185: {
186: while (size--)
187: *to++=*from++;
188: }
189:
190: cdots(elemnt, dots, ino, type)
191: register struct direct *elemnt;
192: char *dots;
193: ino_t ino; /* what the inode number should be */
194: int type;
195: {
196: register char *name = elemnt->d_name;
197: register ino_t inum;
198:
199: inum = elemnt->d_ino;
200: if ( (strcmp(name, dots) != 0) || (inum != ino) ||
201: (format(name) != GOOD) ) {
202: blkerr(type);
203: return;
204: }
205: linkincr(inum);
206: }
207:
208: format(name)
209: register char *name;
210: {
211: register char *ptr=name;
212: register char *end=&name[DIRSIZ];
213:
214: while ( (ptr<end) && (*ptr++ != '\0') ) ;
215:
216: if ( (ptr-1) == name )
217: return(NULLNAME);
218:
219: if (ptr<end) {
220: while ( (ptr<end) && (*ptr++ == '\0') ) ;
221: if (ptr!=end)
222: return(NULLPAD);
223: }
224:
225: ptr = name;
226: while (ptr < end)
227: if (*ptr++ == '/')
228: return(SLASHES);
229:
230: return(GOOD);
231: }
232:
233:
234: blkerr(type)
235: int type;
236: {
237: char *errname;
238:
239: switch(type) {
240: case NULLNAME:
241: errname = "Null name";
242: break;
243: case NULLPAD:
244: errname = "Non null padded";
245: break;
246: case SLASHES:
247: errname = "Embedded slashes in";
248: break;
249: case DOT:
250: errname = "Inconsistent .";
251: break;
252: case DOTDOT:
253: errname = "Inconsistent ..";
254: break;
255: default:
256: errname = "Bad";
257: break;
258: }
259:
260: printf("%s entry in block %lu in directory\n", errname, blocknum);
261: pinfo(myinum);
262: pname(path[--depth]->d_name);
263: depth++;
264: }
265:
266: chck(elemnt)
267: register struct direct *elemnt;
268: {
269: register ino_t inum;
270: register char *name;
271: int type;
272:
273: inum = elemnt->d_ino;
274: if ( inum == 0 )
275: return(UNALLOC);
276:
277: name = elemnt->d_name;
278: if ( (type=format(name)) != GOOD )
279: blkerr(type);
280:
281: if (inum>ninodes) {
282: if ( irange(inum, name) )
283: zeroent(elemnt);
284: return(UNALLOC);
285: }
286:
287: if ( (flags(inum)&ALLOCMASK)==UNALLOC ) {
288: if ( unalloc(inum, name) )
289: zeroent(elemnt);
290: return(UNALLOC);
291: }
292:
293: if ( badblks(inum) ) {
294: if ( baddup(inum, name) ) {
295: zeroent(elemnt);
296: return(UNALLOC);
297: }
298: if ( (flags(inum)&MODEMASK)==IDIR ) {
299: linkincr(inum);
300: numfiles++;
301: return(UNALLOC); /* Don't traverse this baby */
302: }
303: }
304:
305: linkincr(inum);
306: numfiles++;
307: return( flags(inum)&MODEMASK );
308: }
309:
310: zeroent(elemnt)
311: struct direct *elemnt;
312: {
313: elemnt->d_ino = 0;
314: fixflag = TRUE;
315: }
316:
317: pname(name)
318: char *name;
319: {
320: int i=0;
321:
322: while (i<depth)
323: prdirsize(path[i++]->d_name);
324: prdirsize(name);
325: putchar('\n');
326: }
327:
328: prdirsize(name)
329: char *name;
330: {
331: if (name[DIRSIZ-1] == '\0')
332: printf("/%s", name);
333: else
334: printf("/%*s", DIRSIZ, name);
335: }
336:
337: fsize_t
338: pinfo(inum)
339: ino_t inum;
340: {
341: register struct dinode *dip;
342: register struct passwd *pwd;
343:
344: if ( (dip=ptrino(inum, buf2)) == NULL ) {
345: printf("i-number = %u is in a bad inode block.\n", inum);
346: return(0);
347: }
348:
349: printf("i-number = %u, ", inum);
350: if ( (pwd=getpwuid(dip->di_uid)) != NULL )
351: printf("Owner=%s, ", pwd->pw_name);
352: else
353: printf("Owner=%u, ", dip->di_uid);
354: printf(" Mode=0%o\n", dip->di_mode);
355: printf("Size=%lu, Mtime=%s", dip->di_size, ctime(&dip->di_mtime));
356: return(dip->di_size);
357: }
358:
359: char *remove = "(Remove)";
360:
361: irange(inum, name)
362: ino_t inum;
363: char *name;
364: {
365: printf("I-number is out of range I=%u\n", inum);
366: pname(name);
367: return(action(remove));
368: }
369:
370: unalloc(inum, name)
371: ino_t inum;
372: char *name;
373: {
374: fsize_t size;
375:
376: printf("Unallocated\n");
377: size = pinfo(inum);
378: pname(name);
379: if ( (daction != NO) && (size == 0) && (mounted == FALSE) ) {
380: printf("%s [Forced - Yes]\n", remove);
381: return(YES);
382: }
383: return(action(remove));
384: }
385:
386: baddup(inum, name)
387: ino_t inum;
388: char *name;
389: {
390: register int mode = flags(inum)&MODEMASK;
391:
392: printf("Bad or Dup blocks in %s\n", typename(inum));
393: pinfo(inum);
394: pname(name);
395: return(action(remove));
396: }
397:
398: checkpath(ino)
399: register ino_t ino;
400: {
401: static daddr_t addrs[NADDR];
402: static struct dinode *dip;
403: static list *temp;
404: register list *ptr;
405:
406: if ( (flags(ino)&VISITED)==VISITED ) {
407: circle(ino);
408: return;
409: } else
410: orflags(ino, VISITED);
411:
412: dip = ptrino(ino, databuf);
413: l3tol(addrs, dip->di_addr, NADDR);
414:
415: if ( (dip->di_mode&IFMT) != IFDIR )
416: fatal("Tried to checkpath i-node %u which is not dir.\n", ino);
417:
418: ptr = procfiles(addrs, dip->di_size);
419:
420: while (ptr->d_entry.d_ino) {
421: if (depth >= MAXDEPTH)
422: toolong();
423: path[depth++] = &ptr->d_entry;
424: checkpath(ptr->d_entry.d_ino);
425: depth--;
426: temp = ptr;
427: ptr = ptr->next;
428: free(temp);
429: }
430: free(ptr);
431: }
432:
433: circle(ino)
434: ino_t ino;
435: {
436: printf("I-node %u is a multiply referenced directory i-node.\n", ino);
437: }
438:
439: toolong()
440: {
441: printf("Name too long.\n");
442: pname("\0");
443: abort();
444: }
445:
446:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.