|
|
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;
173: register int mode;
174:
175: mode = dip->di_mode & IFMT;
176:
177: if ( (mode != IFREG) && (mode != IFDIR) )
178: return(STOP);
179:
180: l3tol(addrs, dip->di_addr, NADDR);
181:
182: numbad = /* number of bad blocks so far */
183: numdup = /* num dup blocks so far THIS INODE */
184: numblks = /* num used data blocks for size chk */
185: sparsecnt = 0; /* count of missed data blocks */
186:
187: for(i=0; i<NADDR; i++)
188: for (lev=0; lev<4; lev++)
189: if (i < offsets[lev]) {
190: if ( (bn=addrs[i]) != 0 ) {
191: if (doblocks(bn, ino, lev) != OK)
192: return(STOP);
193: } else
194: sparsecnt += blockcnt[lev];
195: break;
196: }
197: return(OK);
198: }
199:
200: /*
201: * Checks recursively the blocks pointed at via
202: * the inode list of blocks. 'bn' is the block number,
203: * 'ino' is the inode referencing it, and 'lev' is the
204: * level 0 == direct ... 3 = triple-indirect
205: */
206:
207: doblocks(bn, ino, lev)
208: register daddr_t bn;
209: ino_t ino;
210: int lev;
211: {
212: char buf[BSIZE];
213: register daddr_t *bnptr;
214: register char *end;
215: register int flag;
216:
217: if (lev-- == 0) { /* we have a direct block */
218: numblks += sparsecnt + 1;
219: sparsecnt = 0;
220: return(dodirect(bn, ino));
221: } else {
222: end = &buf[BSIZE];
223: if ( (flag=dodirect(bn, ino)) == OK ) {
224: bread(bn, buf);
225: bnptr = (long *) buf;
226: while ( bnptr < end ) {
227: bn = *bnptr++;
228: candaddr(bn);
229: if ( bn == 0 ) {
230: sparsecnt += blockcnt[lev];
231: continue;
232: }
233: if ( doblocks(bn, ino, lev) == STOP )
234: return(STOP);
235: }
236: return(OK);
237: } else
238: return(flag);
239: }
240: }
241:
242: /*
243: * Check the given block to determine if it is bad
244: * or if it is a duplicate. 'ino' is the inode referencing it
245: */
246:
247: dodirect(bn, ino)
248: register daddr_t bn;
249: register ino_t ino;
250: {
251: register int flag;
252:
253: if ( (flag=checkbad(bn, ino)) == OK )
254: return( checkdup(bn, ino) );
255: else
256: return(flag);
257: }
258:
259: /*
260: * Check the given block number for being bad.
261: */
262:
263: checkbad(bn, ino)
264: register daddr_t bn;
265: ino_t ino;
266: {
267: if ( (bn>=isize) && (bn<fsize) )
268: return(OK);
269:
270: else if ( (bn<isize) && (bn>=INODEI) && (ino == 1) ) {
271: /* bad block is in */
272: totfree++; /* the inode blocks */
273: return(OK);
274: }
275:
276: if (!fflag)
277: orflags(ino, IBAD_IDUP);
278:
279: printf("Bad block %U, i-number = %u\n", bn, ino);
280:
281: if (numbad++ < MAXBADOK)
282: return(BAD_DUP);
283:
284: switch ( query("Excessive Bad Blocks i-number = %u (Continue)", ino) ){
285: case NO:
286: abort();
287: case YES:
288: return(STOP);
289: }
290: }
291:
292:
293: /*
294: * Check the given block number for duplicate reference.
295: */
296:
297: checkdup(bn, ino)
298: register daddr_t bn;
299: ino_t ino;
300: {
301: if ( !testblock(bn) ) {
302: markblock(bn);
303: totfree--;
304: return(OK);
305: }
306:
307: dupflag = TRUE;
308: if (!fflag)
309: orflags(ino, IBAD_IDUP);
310: printf("Dup Block %U, i-number = %u\n", bn, ino);
311:
312: if (totdups < DUPTBLSIZE)
313: dupblck[totdups++] = bn;
314: else {
315: switch ( query("DUP Table Overflow (Continue)") ) {
316: case NO:
317: abort();
318: case YES:
319: return(BAD_DUP);
320: }
321: }
322:
323: if (numdup++ < MAXDUPOK)
324: return(BAD_DUP);
325:
326: switch ( query("Excessive Dup Blocks i-number = %u (Continue)", ino) ) {
327: case NO:
328: abort();
329: case YES:
330: return(STOP);
331: }
332: }
333:
334: /*
335: * Check For Possible File Size Error
336: */
337:
338: checksize(dip, ino)
339: register struct dinode *dip;
340: ino_t ino;
341: {
342: register int mode;
343: register fsize_t size;
344:
345: mode = dip->di_mode & IFMT;
346: size = dip->di_size;
347:
348: if ( mode == IFREG )
349: filesize(ino, size);
350: else /* mode == IFDIR */
351: dirsize(dip, ino, size);
352: }
353:
354: dirsize(dip, ino, size)
355: struct dinode *dip;
356: ino_t ino;
357: register fsize_t size;
358: {
359: if ( size <= 0 ) {
360: switch ( query("\
361: Bad Directory Size, size = %D, i-number = %u (Clear i-node)", size, ino) ) {
362: case NO:
363: break;
364: case YES:
365: zeroinode(dip);
366: setflags(ino, UNALLOC);
367: clrflg = TRUE;
368: return;
369: }
370: }
371:
372: if ( size < (2*DSIZE) )
373: printf("Directory Size too small i-number = %u\n", ino);
374:
375: if ( size % sizeof(struct direct) != 0 )
376: printf("Directory Misaligned i-number = %u\n", ino);
377:
378: if (sizerr(size))
379: printf("Possible Directory Size Error i-number = %u\n", ino);
380: }
381:
382: filesize(ino, size)
383: ino_t ino;
384: register fsize_t size;
385: {
386: if (sizerr(size))
387: printf("Possible File Size Error i-number = %u\n", ino);
388: }
389:
390: sizerr(size)
391: register fsize_t size;
392: {
393: register fsize_t calc;
394:
395: calc = (unsigned long)numblks*BSIZE;
396: if ( (size > calc) || ( calc >= (size+BSIZE) ) )
397: return(TRUE);
398: else
399: return(FALSE);
400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.