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