|
|
1.1 root 1: /*
2: * phase 1 of fsck - Check Blocks and Sizes
3: */
4:
5: #include "fsck.h"
6:
7: char databuf[BSIZE]; /* buffer for blocks */
8:
9: int clrflg; /* indicates when to clear an inode */
10: int dupflag; /* indicates whether there are any dups */
11:
12: int numbad; /* number of bad blocks in the inode */
13: int numdup; /* number of duplicate blocks in inode */
14: long numblks; /* number of data blks for size check */
15: long sparsecnt; /* count for sparse blocks for size check */
16:
17: /* The following is a table of the number of direct blocks pointed at by the
18: * four types of blocks direct, ..., triple-indirect, to help count sparse
19: * blocks.
20: */
21:
22: daddr_t blockcnt[] = {1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN};
23:
24: phase1()
25: {
26: if (!qflag)
27: printf("Phase 1 : Check Blocks and Sizes\n");
28: dupflag = FALSE;
29: inodescan();
30: if (dupflag)
31: phase1b();
32: }
33:
34: inodescan()
35: {
36: register daddr_t bn;
37: register struct dinode *dip;
38: register ino_t ino;
39: int i;
40:
41: ino = 1;
42:
43: for (bn=INODEI; bn<isize; bn++) {
44: if (testblock(bn)) { /* block is bad via inode 1 */
45: ino += INOPB;
46: continue;
47: }
48: bread(bn, databuf);
49: clrflg = FALSE;
50: dip = (struct dinode *) databuf;
51: for (i=0; i<INOPB; i++) {
52: candino(dip);
53: if (inuse(dip) == TRUE) {
54: if (!fflag)
55: checkmode(dip, ino);
56: if ( checkblks(dip, ino) != STOP )
57: if ( qflag == FALSE )
58: checksize(dip, ino);
59: }
60: candino(dip);
61: ino++;
62: dip++;
63: }
64: if (clrflg)
65: bwrite(bn, databuf);
66: }
67: }
68:
69: /*
70: * Determine if the given inode is in use.
71: */
72:
73: inuse(dip)
74: register struct dinode *dip;
75: {
76: #ifdef NOT_ALL_ZERO_INODE
77:
78: if ( (dip->di_mode != 0) || (dip->di_nlink != 0) )
79: return(TRUE);
80: else
81: return(FALSE);
82: #endif
83: #ifdef ALL_ZERO_INODE
84:
85: register char *ptr;
86: register struct dinode *next;
87:
88: ptr = (char *) dip;
89: next = dip + 1;
90: while (ptr < next)
91: if (*ptr++ != 0)
92: return(TRUE);
93:
94: return(FALSE);
95: #endif
96: }
97:
98: /*
99: * Check the mode of the given inode
100: */
101:
102: checkmode(dip, ino)
103: register struct dinode *dip;
104: register ino_t ino;
105: {
106: register unsigned short mode;
107:
108: mode = dip->di_mode & IFMT;
109:
110: switch (mode) {
111: case IFREG:
112: setflags(ino, IREG);
113: return;
114: case IFDIR:
115: setflags(ino, IDIR);
116: return;
117: case IFCHR:
118: setflags(ino, ICHR);
119: return;
120: case IFBLK:
121: setflags(ino, IBLK);
122: return;
123: case IFPIPE:
124: setflags(ino, IPIPE);
125: return;
126: default:
127: setflags(ino, UNKNOWN);
128: break;
129: }
130:
131: switch ( query("Unknown File Type i-number = %u (Clear)", ino) ){
132: case NO:
133: return;
134: case YES:
135: zeroinode(dip);
136: setflags(ino, UNALLOC);
137: clrflg = TRUE;
138: break;
139: }
140: }
141:
142: /*
143: * Zero the given inode
144: */
145:
146: zeroinode(dip)
147: struct dinode *dip;
148: {
149: register char *ptr;
150: register struct dinode *next;
151:
152: lostsize += dip->di_size;
153: next = dip+1;
154: ptr = (char *) dip;
155:
156: while (ptr < next)
157: *ptr++ = 0;
158:
159: }
160:
161: /*
162: * Check the blocks associated with the given inode to determine
163: * if any are bad or duplicate
164: */
165:
166: checkblks(dip, ino)
167: struct dinode *dip;
168: ino_t ino;
169: {
170: daddr_t addrs[NADDR];
171: register daddr_t bn;
172: register int i, lev, naddr;
173: register int mode;
174:
175: mode = dip->di_mode & IFMT;
176:
177: if ( (mode == IFREG) || (mode == IFDIR) )
178: l3tol(addrs, dip->di_addr, naddr=NADDR);
179: else if ( mode == IFPIPE )
180: l3tol(addrs, dip->di_addp, naddr=ND);
181: else
182: return(STOP);
183:
184: numbad = /* number of bad blocks so far */
185: numdup = /* num dup blocks so far THIS INODE */
186: numblks = /* num used data blocks for size chk */
187: sparsecnt = 0; /* count of missed data blocks */
188:
189: for(i=0; i<naddr; i++)
190: for (lev=0; lev<4; lev++)
191: if (i < offsets[lev]) {
192: if ( (bn=addrs[i]) != 0 ) {
193: if (doblocks(bn, ino, lev) == STOP)
194: return(STOP);
195: } else
196: sparsecnt += blockcnt[lev];
197: break;
198: }
199: return(OK);
200: }
201:
202: /*
203: * Checks recursively the blocks pointed at via
204: * the inode list of blocks. 'bn' is the block number,
205: * 'ino' is the inode referencing it, and 'lev' is the
206: * level 0 == direct ... 3 = triple-indirect
207: */
208:
209: doblocks(bn, ino, lev)
210: register daddr_t bn;
211: ino_t ino;
212: int lev;
213: {
214: char buf[BSIZE];
215: register daddr_t *bnptr;
216: register char *end;
217: register int flag;
218:
219: if (lev-- == 0) { /* we have a direct block */
220: numblks += sparsecnt + 1;
221: sparsecnt = 0;
222: return(dodirect(bn, ino));
223: } else {
224: end = &buf[BSIZE];
225: if ( (flag=dodirect(bn, ino)) == OK ) {
226: bread(bn, buf);
227: bnptr = (long *) buf;
228: while ( bnptr < end ) {
229: bn = *bnptr++;
230: candaddr(bn);
231: if ( bn == 0 ) {
232: sparsecnt += blockcnt[lev];
233: continue;
234: }
235: if ( doblocks(bn, ino, lev) == STOP )
236: return(STOP);
237: }
238: return(OK);
239: } else
240: return(flag);
241: }
242: }
243:
244: /*
245: * Check the given block to determine if it is bad
246: * or if it is a duplicate. 'ino' is the inode referencing it
247: */
248:
249: dodirect(bn, ino)
250: register daddr_t bn;
251: register ino_t ino;
252: {
253: register int flag;
254:
255: if ( (flag=checkbad(bn, ino)) == OK )
256: return( checkdup(bn, ino) );
257: else
258: return(flag);
259: }
260:
261: /*
262: * Check the given block number for being bad.
263: */
264:
265: checkbad(bn, ino)
266: register daddr_t bn;
267: ino_t ino;
268: {
269: if ( (bn>=isize) && (bn<fsize) )
270: return(OK);
271:
272: else if ( (bn<isize) && (bn>=INODEI) && (ino == 1) ) {
273: /* bad block is in */
274: totfree++; /* the inode blocks */
275: return(OK);
276: }
277:
278: if (!fflag)
279: orflags(ino, IBAD_IDUP);
280:
281: printf("Bad block %lu, i-number = %u\n", bn, ino);
282:
283: if (numbad++ < MAXBADOK)
284: return(BAD_DUP);
285:
286: switch ( query("Excessive Bad Blocks i-number = %u (Continue)", ino) ){
287: case NO:
288: abort();
289: case YES:
290: return(STOP);
291: }
292: }
293:
294:
295: /*
296: * Check the given block number for duplicate reference.
297: */
298:
299: checkdup(bn, ino)
300: register daddr_t bn;
301: ino_t ino;
302: {
303: if ( !testblock(bn) ) {
304: markblock(bn);
305: totfree--;
306: return(OK);
307: }
308:
309: dupflag = TRUE;
310: if (!fflag)
311: orflags(ino, IBAD_IDUP);
312: printf("Dup Block %lu, i-number = %u\n", bn, ino);
313:
314: if (totdups < DUPTBLSIZE)
315: dupblck[totdups++] = bn;
316: else {
317: switch ( query("DUP Table Overflow (Continue)") ) {
318: case NO:
319: abort();
320: case YES:
321: return(BAD_DUP);
322: }
323: }
324:
325: if (numdup++ < MAXDUPOK)
326: return(BAD_DUP);
327:
328: switch ( query("Excessive Dup Blocks i-number = %u (Continue)", ino) ) {
329: case NO:
330: abort();
331: case YES:
332: return(STOP);
333: }
334: }
335:
336: /*
337: * Check For Possible File Size Error
338: */
339:
340: checksize(dip, ino)
341: register struct dinode *dip;
342: ino_t ino;
343: {
344: register int mode;
345: register fsize_t size;
346:
347: mode = dip->di_mode & IFMT;
348: size = dip->di_size;
349:
350: if ( mode == IFREG )
351: filesize(ino, size);
352: else if ( mode == IFDIR )
353: dirsize(dip, ino, size);
354: else if ( mode == IFPIPE )
355: pipesize(dip, ino, size);
356: }
357:
358: dirsize(dip, ino, size)
359: struct dinode *dip;
360: ino_t ino;
361: register fsize_t size;
362: {
363: if ( size <= 0 ) {
364: switch ( query("\
365: Bad Directory Size, size = %D, i-number = %u (Clear i-node)", size, ino) ) {
366: case NO:
367: break;
368: case YES:
369: zeroinode(dip);
370: setflags(ino, UNALLOC);
371: clrflg = TRUE;
372: return;
373: }
374: }
375:
376: if ( size < (2*DSIZE) )
377: printf("Directory Size too small i-number = %u\n", ino);
378:
379: if ( size % sizeof(struct direct) != 0 )
380: printf("Directory Misaligned i-number = %u\n", ino);
381:
382: if (sizerr(size))
383: printf("Possible Directory Size Error i-number = %u\n", ino);
384: }
385:
386: filesize(ino, size)
387: ino_t ino;
388: register fsize_t size;
389: {
390: if (sizerr(size))
391: printf("Possible File Size Error i-number = %u\n", ino);
392: }
393:
394: pipesize(dip, ino, size)
395: struct dinode *dip;
396: ino_t ino;
397: register fsize_t size;
398: {
399: if (sizerr(size))
400: printf("Possible PIPE Size Error i-number = %u\n", ino);
401: return;
402: }
403:
404: sizerr(size)
405: register fsize_t size;
406: {
407: register fsize_t calc;
408:
409: calc = (unsigned long)numblks*BSIZE;
410: if ( (size > calc) || ( calc >= (size+BSIZE) ) )
411: return(TRUE);
412: else
413: return(FALSE);
414: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.