|
|
1.1 ! root 1: /* ! 2: * general utility functions for phases of fsck ! 3: */ ! 4: ! 5: #include "fsck.h" ! 6: ! 7: struct stat stats; /* Used by statit() */ ! 8: ! 9: statit(name, probfun) ! 10: char *name; ! 11: int (*probfun)(); ! 12: { ! 13: ! 14: if ( stat(name, &stats) == -1 ) { ! 15: bclear(&stats, sizeof(struct stat)); ! 16: (*probfun)("Can not stat %s", name); ! 17: } ! 18: } ! 19: ! 20: ! 21: query(x) ! 22: { ! 23: while(1) { ! 24: printf("%r [yes/no]: ", &x); ! 25: ! 26: switch (daction) { ! 27: case YES: ! 28: printf("[default - YES]\n"); ! 29: return(YES); ! 30: break; ! 31: case NO: ! 32: printf("[default - NO]\n"); ! 33: return(NO); ! 34: break; ! 35: case ASK: ! 36: switch( nextchar() ) { ! 37: case 'Y': ! 38: return(YES); ! 39: case 'N': ! 40: return(NO); ! 41: } ! 42: } ! 43: } ! 44: } ! 45: ! 46: action(msg) ! 47: char *msg; ! 48: { ! 49: switch( query(msg) ) { ! 50: case YES: ! 51: return(TRUE); ! 52: case NO: ! 53: return(FALSE); ! 54: } ! 55: } ! 56: ! 57: char ! 58: nextchar() ! 59: { ! 60: char buff[8]; ! 61: int i, n, ch; ! 62: ! 63: if ( ((n=read(0,buff,8)) <= 0) || (n == 8) ) ! 64: fatal("Invalid Response"); ! 65: ! 66: for(i=0; i<n; i++) ! 67: if ( ((ch=buff[i])!=' ') && (ch!='\t') ) ! 68: break; ! 69: ! 70: if ( (ch>='a') && (ch<='z') ) ! 71: ch += 'A' - 'a'; ! 72: ! 73: return(ch); ! 74: } ! 75: ! 76: char *nfile = "FILE"; ! 77: char *ndir = "DIR"; ! 78: char *nchr = "Character Special"; ! 79: char *nblk = "Block Special"; ! 80: char *npipe = "PIPE"; ! 81: char *nunkwn = "Unknown I-node type"; ! 82: ! 83: char * ! 84: typename(ino) ! 85: ino_t ino; ! 86: { ! 87: switch( flags(ino)&MODEMASK ) { ! 88: case IREG: ! 89: return(nfile); ! 90: case IDIR: ! 91: return(ndir); ! 92: case ICHR: ! 93: return(nchr); ! 94: case IBLK: ! 95: return(nblk); ! 96: case IPIPE: ! 97: return(npipe); ! 98: default: ! 99: return(nunkwn); ! 100: } ! 101: } ! 102: ! 103: abort() ! 104: { ! 105: fatal("abort."); ! 106: } ! 107: ! 108: fatal(x) ! 109: { ! 110: printf("fsck: %r\n", &x); ! 111: _exit(1); ! 112: } ! 113: ! 114: nonfatal(x) ! 115: { ! 116: printf("fsck: %r\n", &x); ! 117: errflag = TRUE; ! 118: } ! 119: ! 120: /* ! 121: * Inode Manipulation Routines ! 122: * ptrino: returns a pointer to the wanted inode using the given ! 123: * buffer to read in the block performing canonicalization. ! 124: * writeino: writes the block containing the given inode to the ! 125: * disk performing the necessary canonicalization ! 126: * candino: canonicalize an inode ! 127: * ! 128: */ ! 129: ! 130: struct dinode * ! 131: ptrino(ino, buf) ! 132: register ino_t ino; ! 133: register char *buf; ! 134: { ! 135: register daddr_t bn; ! 136: register struct dinode *dip; ! 137: ! 138: bn = iblockn(ino); ! 139: if ( (testblock(bn)) && (bn!=INODEI) ) /* bad inode block */ ! 140: return(NULL); ! 141: bread(bn, buf); ! 142: dip = ((struct dinode *) buf) + iblocko(ino); ! 143: candino(dip); ! 144: return(dip); ! 145: } ! 146: ! 147: writeino(ino, buf) ! 148: ino_t ino; ! 149: char *buf; ! 150: { ! 151: struct dinode *dip; ! 152: ! 153: dip = ((struct dinode *) buf) + iblocko(ino); ! 154: candino(dip); ! 155: bwrite((daddr_t) iblockn(ino), buf); ! 156: } ! 157: ! 158: candino(dip) ! 159: register struct dinode *dip; ! 160: { ! 161: canshort(dip->di_mode); ! 162: canshort(dip->di_nlink); ! 163: canshort(dip->di_uid); ! 164: canshort(dip->di_gid); ! 165: cansize(dip->di_size); ! 166: cantime(dip->di_atime); ! 167: cantime(dip->di_mtime); ! 168: cantime(dip->di_ctime); ! 169: } ! 170: ! 171: /* ! 172: * Transfer a logical block number for an inode to a ! 173: * physical block number, chasing indirects as necessary. ! 174: * The inefficiency of this method is put up with since ! 175: * this is only used for directory inodes, and they tend ! 176: * not to use indirects. Pass in 'addrs' which is a pointer ! 177: * to the 13 daddr_s in the inode, and the logical block ! 178: * number you would like. (Stolen from dcheck.c) ! 179: */ ! 180: ! 181: static daddr_t ranges[] = { ! 182: ND, ! 183: ND + (daddr_t)NI*NBN, ! 184: ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN, ! 185: ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN + (daddr_t)NIII*NBN*NBN*NBN ! 186: }; ! 187: ! 188: static char index[] = { ! 189: 0, ! 190: ND, ! 191: ND+NI, ! 192: ND+NI+NII ! 193: }; ! 194: ! 195: static daddr_t coeff[] = { ! 196: 1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN ! 197: }; ! 198: ! 199: daddr_t ! 200: imap(addrs, block) ! 201: daddr_t *addrs; ! 202: register daddr_t block; ! 203: { ! 204: int i; ! 205: register daddr_t bpos; ! 206: register daddr_t *bp; ! 207: register daddr_t bn; ! 208: ! 209: for (i=0; i<4; i++) ! 210: if (block < ranges[i]) { ! 211: if (i != 0) ! 212: block -= ranges[i-1]; ! 213: bpos = block/coeff[i]; ! 214: block %= coeff[i]; ! 215: bp = &addrs[(int)bpos + index[i]]; ! 216: if ( (bn=*bp) != 0 ) { ! 217: /* ! 218: * Map through indirects here ! 219: */ ! 220: while (i-- > 0) { ! 221: bread(bn, databuf); ! 222: bpos = block/coeff[i]; ! 223: block %= coeff[i]; ! 224: bp = (daddr_t *)databuf + bpos; ! 225: if ( (bn=*bp) == 0 ) ! 226: break; ! 227: bn = *bp; ! 228: candaddr(bn); ! 229: } ! 230: } ! 231: return(bn); ! 232: } ! 233: return(0); ! 234: } ! 235: ! 236: /* ! 237: * Read the specified block number into the given buffer ! 238: */ ! 239: ! 240: char *rgblkerr = "Out of Range Block number: %U (CONTINUE)"; ! 241: char *skblkerr = "Can not Seek: Blk num: %U (CONTINUE)"; ! 242: char *rdblkerr = "Can not Read: Blk num: %U (CONTINUE)"; ! 243: char *wtblkerr = "Can not Write: Blk num: %U (CONTINUE)"; ! 244: ! 245: bread(bn, buf) ! 246: register daddr_t bn; ! 247: register char *buf; ! 248: { ! 249: #ifdef DEBUG ! 250: printf("Reading block number: %ld\n", bn); ! 251: #endif ! 252: if (bn<0 || bn >= fsize ) ! 253: switch( query(rgblkerr, bn) ) { ! 254: case YES: ! 255: bclear(buf, BSIZE); ! 256: return; ! 257: case NO: ! 258: abort(); ! 259: } ! 260: ! 261: if ( (bn<isize) && getcache(bn, buf) ) { ! 262: #if DEBUG ! 263: bdump(buf); ! 264: #endif ! 265: return; ! 266: } ! 267: ! 268: if ( lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L) ) ! 269: switch( query(skblkerr, bn) ) { ! 270: case YES: ! 271: bclear(buf, BSIZE); ! 272: return; ! 273: case NO: ! 274: abort(); ! 275: } ! 276: ! 277: if ( read(fsfd, buf, BSIZE) != BSIZE ) ! 278: switch( query(rdblkerr, bn) ) { ! 279: case YES: ! 280: bclear(buf, BSIZE); ! 281: return; ! 282: case NO: ! 283: abort(); ! 284: } ! 285: #if DEBUG ! 286: bdump(buf); ! 287: #endif ! 288: } ! 289: ! 290: /* ! 291: * Write block number bn with data in buf ! 292: */ ! 293: ! 294: bwrite(bn, buf) ! 295: daddr_t bn; ! 296: char *buf; ! 297: { ! 298: #ifdef DEBUG ! 299: printf("Writing block number: %ld\n", bn); ! 300: #endif ! 301: if (!writeflg) ! 302: return; ! 303: ! 304: if (bn<0 || bn>=fsize) ! 305: switch( query(rgblkerr, bn) ) { ! 306: case YES: ! 307: return; ! 308: case NO: ! 309: abort(); ! 310: } ! 311: ! 312: if ( lseek(fsfd, (fsize_t)BSIZE*bn, 0) == (-1L) ) ! 313: switch( query(skblkerr, bn) ) { ! 314: case YES: ! 315: return; ! 316: case NO: ! 317: abort(); ! 318: } ! 319: ! 320: if ( write(fsfd, buf, BSIZE) != BSIZE ) ! 321: switch( query(wtblkerr, bn) ) { ! 322: case YES: ! 323: return; ! 324: case NO: ! 325: abort(); ! 326: } ! 327: ! 328: if ( bn <= isize ) ! 329: chgcache(bn, buf); ! 330: changeflg = TRUE; ! 331: } ! 332: ! 333: /* ! 334: * i-node block area caching routines ! 335: */ ! 336: ! 337: static char cache[NBLK * BSIZE]; ! 338: static int low = 0; high = -1; ! 339: ! 340: getcache(bn, buf) ! 341: register daddr_t bn; ! 342: register char *buf; ! 343: { ! 344: int totsize; ! 345: ! 346: if ( bn > isize ) ! 347: return(0); ! 348: ! 349: if ( (bn>=low) && (bn<=high) ) { ! 350: blkmove(buf, &cache[BSIZE * (bn-low)]); ! 351: return(1); ! 352: } ! 353: ! 354: low = bn; ! 355: if ( (high=bn+NBLK-1) > isize ) ! 356: high = isize; ! 357: totsize = BSIZE * (high-low+1); ! 358: ! 359: if ( (lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L)) || ! 360: (read(fsfd, cache, totsize) != totsize) ) { ! 361: low = 0; high = -1; ! 362: return(0); ! 363: } ! 364: ! 365: return( getcache(bn, buf) ); ! 366: } ! 367: ! 368: chgcache(bn, buf) ! 369: register daddr_t bn; ! 370: register char *buf; ! 371: { ! 372: if ( (bn>=low) && (bn<=high) ) ! 373: blkmove(&cache[BSIZE * (bn-low)], buf); ! 374: } ! 375: ! 376: blkmove(to, from) ! 377: register char *to, *from; ! 378: { ! 379: register int num=BSIZE; ! 380: ! 381: while ( num-- ) ! 382: *to++= *from++; ! 383: } ! 384: ! 385: /* ! 386: * Clear the given block of memory ! 387: */ ! 388: ! 389: bclear(bp, nb) ! 390: register char *bp; ! 391: register unsigned nb; ! 392: { ! 393: if (nb) ! 394: do { ! 395: *bp++ = 0; ! 396: } while (--nb); ! 397: } ! 398: ! 399: ! 400: /* ! 401: * Determine if the given block is bad ! 402: */ ! 403: ! 404: bad(bn) ! 405: daddr_t bn; ! 406: { ! 407: if ( (bn >= isize) && (bn < fsize) ) ! 408: return(GOOD); ! 409: else ! 410: return(BAD); ! 411: } ! 412: ! 413: ! 414: #if DEBUG ! 415: ! 416: /* ! 417: * Debug dump a block of data. ! 418: */ ! 419: ! 420: #define NUMPLIN 16 ! 421: ! 422: bdump(buf) ! 423: register unsigned char *buf; ! 424: { ! 425: register int i; ! 426: ! 427: for (i=0; i<BSIZE; i++) { ! 428: if ( (i % NUMPLIN) == 0 ) ! 429: printf("\n0x%04x: ", i); ! 430: printf(" %02x", *buf++); ! 431: } ! 432: printf("\n\n"); ! 433: } ! 434: ! 435: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.