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