|
|
1.1 ! root 1: /* ! 2: * Icheck - check i-list consistency of ! 3: * filesystems and (optionally) repair ! 4: * filesystems. ! 5: */ ! 6: #include <stdio.h> ! 7: extern char *calloc(); ! 8: #include <sys/filsys.h> ! 9: #include <sys/fblk.h> ! 10: #include <sys/dir.h> ! 11: #include <sys/ino.h> ! 12: #include "check.h" ! 13: #include <canon.h> ! 14: #undef DIR ! 15: ! 16: #define ROOTINO 2 /* I-number of root */ ! 17: #define NBLOCK 20 /* Maximum number of blocks to check */ ! 18: #define NBPC 8 /* Bits per character */ ! 19: #define BOOTB 0 /* Boot block # */ ! 20: #define SUPERB 1 /* Super block */ ! 21: #define INOORG 2 /* Inodes begin here */ ! 22: #define IBLK 12 /* I-node read blocking factor */ ! 23: #define BSIZE 512 ! 24: #define ND 10 /* Number of direct block */ ! 25: #undef NI ! 26: #define NI 1 ! 27: #define NII 1 ! 28: #define NIII 1 ! 29: #undef NADDR ! 30: #define NADDR (ND+NI+NII+NIII) ! 31: ! 32: /* ! 33: * Flags for crawldown. ! 34: */ ! 35: #define PLAIN 0 ! 36: #define DIR 1 ! 37: #define BAD 2 ! 38: ! 39: /* ! 40: * A chain of these structures ! 41: * holds all of the defective blocks found ! 42: * in the bad block file. The list is sorted for ! 43: * easy access by those parts of the program ! 44: * that scan blocks. ! 45: */ ! 46: struct defect ! 47: { ! 48: struct defect *d_next; /* Link to next */ ! 49: daddr_t d_start; /* First bad block in cluster */ ! 50: int d_length; /* Size of cluster */ ! 51: }; ! 52: ! 53: #define test(bn) (bitmap[((unsigned)bn)/NBPC] & 1<<(((unsigned)bn)%NBPC)) ! 54: #define mark(bn) (bitmap[((unsigned)bn)/NBPC] |= 1<<(((unsigned)bn)%NBPC)) ! 55: ! 56: char tmb[] = "Too many block numbers specified\n"; ! 57: ! 58: int nblock; ! 59: daddr_t blocks[NBLOCK]; ! 60: ino_t freei[NICFREE]; /* Free i-nodes to put into superblock */ ! 61: ino_t *freeip; ! 62: struct defect *deflist; ! 63: char superb[BSIZE]; ! 64: char ibuf[IBLK*BSIZE]; ! 65: char fbuf[BSIZE]; ! 66: char idbuf[3][BSIZE]; /* One for each indirect level */ ! 67: ! 68: /* ! 69: * Offsets of levels of indirection ! 70: * into the i-node addresses. ! 71: */ ! 72: char offsets[] = { ! 73: 0, ND, ND+NI, ND+NI+NII, ND+NI+NII+NIII, ! 74: }; ! 75: ! 76: /* ! 77: * Types of indirect and direct blocks ! 78: * by name. ! 79: */ ! 80: char *btypes[] = { ! 81: "direct", ! 82: "indirect", ! 83: "double indirect", ! 84: "triple indirect", ! 85: }; ! 86: ! 87: int sflag; /* Repair filesystem */ ! 88: int vflag; /* More verbose information */ ! 89: int exstat; /* Final exit status -- bits from <check.h> */ ! 90: FILE *fs; /* File system i/o stream pointer */ ! 91: char *bitmap; /* Bit map for blocks */ ! 92: daddr_t fsize = SUPERB+1; /* Allow read of super-block */ ! 93: unsigned isize; ! 94: ! 95: /* Various counters */ ! 96: unsigned nfiles; ! 97: unsigned nreg; ! 98: unsigned ndir; ! 99: unsigned nbad; /* # of bad blocks */ ! 100: unsigned nibad; /* # of bad blocks that were in ilist */ ! 101: unsigned nbsp; ! 102: unsigned ncsp; ! 103: unsigned nmpx; ! 104: unsigned npipe; ! 105: long nblk; ! 106: long nfblk[4]; /* # of direct, single, double, and triple indirects */ ! 107: long ndirb; ! 108: long nfreeb; ! 109: long nmissing; ! 110: long nfdup; ! 111: ino_t nifree; ! 112: ! 113: long atol(); ! 114: ! 115: main(argc, argv) ! 116: char *argv[]; ! 117: { ! 118: ! 119: while (argc>1 && *argv[1]=='-') { ! 120: switch (argv[1][1]) { ! 121: case 'b': ! 122: nblock = 0; ! 123: while (blocks[nblock] = atol(argv[2])) { ! 124: if (nblock++ >= NBLOCK) { ! 125: fprintf(stderr, tmb); ! 126: exstat |= IC_MISC; ! 127: break; ! 128: } ! 129: argv++; ! 130: argc--; ! 131: } ! 132: break; ! 133: ! 134: case 's': ! 135: sflag = 1; ! 136: break; ! 137: ! 138: case 'v': ! 139: vflag = 1; ! 140: break; ! 141: ! 142: ! 143: default: ! 144: usage(); ! 145: } ! 146: argc--; ! 147: argv++; ! 148: } ! 149: if (argc > 1) ! 150: allcheck(argv+1); ! 151: else ! 152: usage(); ! 153: exit(exstat); ! 154: } ! 155: ! 156: /* ! 157: * Check the given list of filesystems ! 158: */ ! 159: allcheck(fsl) ! 160: register char **fsl; ! 161: { ! 162: while (*fsl != NULL) ! 163: if (icheck(*fsl++)) ! 164: return; ! 165: } ! 166: ! 167: /* ! 168: * Check one filesystem ! 169: */ ! 170: icheck(fsname) ! 171: char *fsname; ! 172: { ! 173: struct filsys *sbp; ! 174: register struct dinode *ip; ! 175: register int i; ! 176: register ino_t inum; ! 177: register char *mode; ! 178: int thischunk; ! 179: daddr_t seek, limit; ! 180: struct defect *cdsp; ! 181: ! 182: nfiles = 0; ! 183: nreg = 0; ! 184: ndir = 0; ! 185: ndirb = 0; ! 186: npipe = 0; ! 187: nbsp = 0; ! 188: ncsp = 0; ! 189: nmpx = 0; ! 190: nblk = 0; ! 191: nbad = 0; ! 192: nibad = 0; ! 193: for (i=0; i<4; i++) ! 194: nfblk[i] = 0; ! 195: nmissing = 0; ! 196: nfdup = 0; ! 197: nfreeb = 0; ! 198: nifree = 0; ! 199: freeip = freei; ! 200: mode = sflag ? "r+w" : "r"; ! 201: if ((fs = fopen(fsname, mode)) == NULL) { ! 202: fprintf(stderr, "%s: cannot open\n", fsname); ! 203: exstat |= IC_MISC; ! 204: return; ! 205: } ! 206: printf("%s:\n", fsname); ! 207: if (!sflag) ! 208: sync(); ! 209: bread((daddr_t)SUPERB, superb); ! 210: sbp = superb; ! 211: canint(sbp->s_isize); ! 212: candaddr(sbp->s_fsize); ! 213: canshort(sbp->s_nfree); ! 214: for (i=0; i<NICFREE; ++i) ! 215: candaddr(sbp->s_free[i]); ! 216: canshort(sbp->s_ninode); ! 217: for (i=0; i<NICINOD; ++i) ! 218: canino(sbp->s_inode[i]); ! 219: cantime(sbp->s_time); ! 220: candaddr(sbp->s_tfree); ! 221: canino(sbp->s_tinode); ! 222: canshort(sbp->s_m); ! 223: canshort(sbp->s_n); ! 224: canlong(sbp->s_unique); ! 225: fsize = sbp->s_fsize; ! 226: isize = sbp->s_isize; ! 227: if (isize<INOORG+1 || isize>=fsize || fsize<INOORG+1) ! 228: cerr("Ridiculous fsize/isize"); ! 229: if ((bitmap=calloc((int)((fsize+NBPC-1)/NBPC), sizeof(char))) == NULL) ! 230: cerr("No space for bitmap"); ! 231: bmark((daddr_t)BOOTB, "bootstrap", 0); ! 232: bmark((daddr_t)SUPERB, "super block", 0); ! 233: finddefective(); ! 234: nblk = isize; ! 235: inum = 1; ! 236: seek = INOORG; ! 237: cdsp = deflist; ! 238: while (seek < isize) { ! 239: if (cdsp!=NULL && cdsp->d_start==seek) { ! 240: nibad += cdsp->d_length; ! 241: seek += cdsp->d_length; ! 242: inum += cdsp->d_length*INOPB; ! 243: cdsp = cdsp->d_next; ! 244: continue; ! 245: } ! 246: limit = seek+IBLK; ! 247: if (cdsp!=NULL && limit>cdsp->d_start) ! 248: limit = cdsp->d_start; ! 249: if (limit > isize) ! 250: limit = isize; ! 251: thischunk = limit-seek; ! 252: lseek(fileno(fs), seek*BSIZE, 0); ! 253: for (i=0; i<thischunk; ++i) ! 254: bmark((daddr_t)seek++, "inodes", 0); ! 255: thischunk *= BSIZE; ! 256: if (read(fileno(fs), ibuf, thischunk) != thischunk) { ! 257: fprintf(stderr, "I-node read error\n"); ! 258: exstat |= IC_HARD; ! 259: break; ! 260: } ! 261: ip = (struct dinode *) &ibuf[0]; ! 262: while (ip < (struct dinode *) &ibuf[thischunk]) { ! 263: if (inum != BADFIN) { ! 264: canshort(ip->di_mode); ! 265: canshort(ip->di_nlink); ! 266: canshort(ip->di_uid); ! 267: canshort(ip->di_gid); ! 268: cansize(ip->di_size); ! 269: cantime(ip->di_atime); ! 270: cantime(ip->di_mtime); ! 271: cantime(ip->di_ctime); ! 272: ilook(ip, inum); ! 273: } ! 274: ++inum; ! 275: ++ip; ! 276: } ! 277: } ! 278: freecount(); ! 279: free(bitmap); ! 280: freedefective(); ! 281: if (nmissing != 0) ! 282: exstat |= IC_MISS; ! 283: if (nfdup != 0) ! 284: exstat |= IC_DUPF; ! 285: if (!sflag && vflag) { ! 286: printf("f=%u,r=%u,d=%u,b=%u,c=%u,m=%u,p=%u\n", nfiles, nreg, ! 287: ndir, nbsp, ncsp, nmpx, npipe); ! 288: printf("blks=%ld, dirb=%ld, d=%ld, i=%ld, ii=%ld, iii=%ld\n", ! 289: nblk, ndirb, nfblk[0], nfblk[1], nfblk[2], nfblk[3]); ! 290: printf("free = %ld\n", nfreeb); ! 291: printf("bad=%u (%u in I-list)\n", nbad, nibad); ! 292: } ! 293: if (!sflag) { ! 294: if (nmissing != 0) ! 295: printf("missing = %ld\n", nmissing); ! 296: if (nfdup != 0) ! 297: printf("%ld dups in free\n", nfdup); ! 298: if (sbp->s_tinode != nifree) { ! 299: printf("Bad ifree list\n"); ! 300: exstat |= IC_BFB; ! 301: } ! 302: } ! 303: if (sflag) ! 304: makesuper(); ! 305: fclose(fs); ! 306: return (0); ! 307: } ! 308: ! 309: /* ! 310: * Look at each inode marking used blocks ! 311: * and checking consistency. ! 312: */ ! 313: ilook(ip, inum) ! 314: register struct dinode *ip; ! 315: ino_t inum; ! 316: { ! 317: daddr_t addrs[NADDR]; ! 318: register i, l; ! 319: int flag; ! 320: ! 321: if (ip->di_mode == 0) { ! 322: if (freeip < &freei[NICFREE]) ! 323: *freeip++ = inum; ! 324: nifree++; ! 325: return; ! 326: } ! 327: nfiles++; ! 328: flag = PLAIN; ! 329: switch (ip->di_mode & IFMT) { ! 330: case IFREG: ! 331: nreg++; ! 332: break; ! 333: ! 334: case IFDIR: ! 335: ndir++; ! 336: flag = DIR; ! 337: break; ! 338: ! 339: case IFBLK: ! 340: nbsp++; ! 341: return; ! 342: ! 343: case IFCHR: ! 344: ncsp++; ! 345: return; ! 346: ! 347: case IFPIPE: ! 348: npipe++; ! 349: return; ! 350: ! 351: case IFMPB: ! 352: case IFMPC: ! 353: nmpx++; ! 354: return; ! 355: ! 356: default: ! 357: printf("%u: Bad filetype %o\n", inum, ip->di_mode&IFMT); ! 358: return; ! 359: } ! 360: l3tol(addrs, ip->di_addr, NADDR); ! 361: for (i = NADDR-1; i >= 0; i--) ! 362: for (l=1; l<=4; l++) ! 363: if (i < offsets[l]) { ! 364: crawldown(addrs[i], l-1, flag, inum); ! 365: break; ! 366: } ! 367: } ! 368: ! 369: /* ! 370: * Crawl down through `lev' levels ! 371: * of indirect blocks, starting at block ! 372: * `bn'. The `ino' argument is the inumber that ! 373: * started this all off; is just gets passed ! 374: * to `bmark'. The `flag' tells you what kind ! 375: * of blocks you have at level 0 (in can be BAD, ! 376: * DIR or PLAIN). ! 377: */ ! 378: crawldown(bn, lev, flag, ino) ! 379: daddr_t bn; ! 380: int lev; ! 381: ino_t ino; ! 382: { ! 383: register char *bp; ! 384: register char *type; ! 385: register int i; ! 386: ! 387: if (bn == 0) ! 388: return; ! 389: nblk++; ! 390: if (lev==0 && flag==DIR) { ! 391: type = "dir"; ! 392: ndirb++; ! 393: } else if (lev==0 && flag==BAD) { ! 394: type = "bad"; ! 395: nbad++; ! 396: } else { ! 397: type = btypes[lev]; ! 398: nfblk[lev]++; ! 399: } ! 400: if (bmark(bn, type, ino)) ! 401: return; ! 402: if (lev==0 && flag==BAD) ! 403: savedefective(bn); ! 404: if (lev-- > 0) { ! 405: bread(bn, bp = idbuf[lev]); ! 406: for (i=0; i<NBN; i++) { ! 407: bn = ((long *)bp)[i]; ! 408: candaddr(bn); ! 409: crawldown(bn, lev, flag, ino); ! 410: } ! 411: } ! 412: } ! 413: ! 414: /* ! 415: * This routine finds all of the ! 416: * defective space on the filsystem by reading ! 417: * the bad block file and marking all the blocks. ! 418: * The defective space list, used by the I-list ! 419: * scanner and other guys, is constructued. ! 420: */ ! 421: finddefective() ! 422: { ! 423: register struct dinode *ip; ! 424: register i, level; ! 425: daddr_t addrs[NADDR]; ! 426: ! 427: ++nfiles; ! 428: lseek(fileno(fs), (long)iblockn(BADFIN)*BSIZE, 0); ! 429: if (read(fileno(fs), ibuf, BSIZE) != BSIZE) { ! 430: printf("I/O error reading bad block inode\n"); ! 431: exstat |= IC_HARD; ! 432: return; ! 433: } ! 434: ip = (struct dinode *) &ibuf[0] + iblocko(BADFIN); ! 435: canshort(ip->di_mode); ! 436: if (ip->di_mode == 0) ! 437: return; ! 438: if ((ip->di_mode&IFMT) != IFREG) { ! 439: printf("Bad block file has bad mode\n"); ! 440: exstat |= IC_HARD; ! 441: return; ! 442: } ! 443: l3tol(addrs, ip->di_addr, NADDR); ! 444: for (i=NADDR-1; i>=0; --i) { ! 445: for (level=1; level<=4; ++level) { ! 446: if (i < offsets[level]) { ! 447: crawldown(addrs[i], level-1, BAD, BADFIN); ! 448: break; ! 449: } ! 450: } ! 451: } ! 452: } ! 453: ! 454: /* ! 455: * Free all of the nodes ! 456: * in the defective space list. ! 457: */ ! 458: freedefective() ! 459: { ! 460: register struct defect *cdsp1, *cdsp2; ! 461: ! 462: cdsp1 = deflist; ! 463: deflist = NULL; ! 464: while (cdsp1 != NULL) { ! 465: cdsp2 = cdsp1->d_next; ! 466: free((char *) cdsp1); ! 467: cdsp1 = cdsp2; ! 468: } ! 469: } ! 470: ! 471: /* ! 472: * Add a new, defective block ! 473: * into the sorted defective block chain. ! 474: * Merge this block with the ends of ! 475: * any existing entries. No check is made ! 476: * for entries fusing; bad blocks get scooped ! 477: * (in general) up in order, and the bad blocks ! 478: * are generally sparsely placed on the disc. ! 479: */ ! 480: savedefective(bn) ! 481: daddr_t bn; ! 482: { ! 483: register struct defect *cdsp1, *cdsp2, *cdsp3; ! 484: ! 485: cdsp1 = NULL; ! 486: cdsp2 = deflist; ! 487: while (cdsp2!=NULL && bn>cdsp2->d_start) { ! 488: cdsp1 = cdsp2; ! 489: cdsp2 = cdsp2->d_next; ! 490: } ! 491: if (cdsp1!=NULL && bn==cdsp1->d_start+cdsp1->d_length) { ! 492: ++cdsp1->d_length; ! 493: return; ! 494: } ! 495: if (cdsp2!=NULL && bn==cdsp2->d_start-1) { ! 496: --cdsp2->d_start; ! 497: ++cdsp2->d_length; ! 498: return; ! 499: } ! 500: if ((cdsp3=(struct defect *)malloc(sizeof(struct defect))) == NULL) ! 501: cerr("Out of space for bad blocks"); ! 502: if (cdsp1 == NULL) ! 503: deflist = cdsp3; else ! 504: cdsp1->d_next = cdsp3; ! 505: cdsp3->d_next = cdsp2; ! 506: cdsp3->d_start = bn; ! 507: cdsp3->d_length = 1; ! 508: } ! 509: ! 510: /* ! 511: * Look at the free count for a filesystem ! 512: * by chasing down the free-list. ! 513: */ ! 514: freecount() ! 515: { ! 516: register char *bmp; ! 517: register struct fblk *fbp; ! 518: struct filsys *sbp; ! 519: register unsigned i; ! 520: daddr_t bn; ! 521: long ntfree; ! 522: ! 523: sbp = superb; ! 524: fbp = &sbp->s_nfree; ! 525: ntfree = sbp->s_tfree; ! 526: while ((i = fbp->df_nfree) != 0) { ! 527: if ((unsigned)(fbp->df_nfree) > NICFREE) { ! 528: badfreelist(); ! 529: return; ! 530: } ! 531: for (i=0; i<fbp->df_nfree; i++) { ! 532: bn = fbp->df_free[i]; ! 533: bmark(bn, "free", 0); ! 534: nfreeb++; ! 535: } ! 536: bread(fbp->df_free[0], fbuf); ! 537: fbp = fbuf; ! 538: canint(fbp->df_nfree); ! 539: for (i=0; i<NICFREE; ++i) ! 540: candaddr(fbp->df_free[i]); ! 541: } ! 542: /* ! 543: * Count number of blocks not in bitmap ! 544: */ ! 545: i = 1; ! 546: for (bn=0, bmp=bitmap; bn < fsize; bn++) { ! 547: if (i == 1<<NBPC) { ! 548: i = 1; ! 549: bmp++; ! 550: } ! 551: if ((*bmp & i) == 0) ! 552: nmissing++; ! 553: i <<= 1; ! 554: } ! 555: if (sflag) ! 556: nmissing -= isize + nfreeb; ! 557: if (nfreeb != ntfree) { ! 558: if (!sflag) ! 559: printf("Free list/tfree counts differ\n"); ! 560: exstat |= IC_MISS; ! 561: } ! 562: } ! 563: ! 564: /* ! 565: * Remake the superblock - reconstructing ! 566: * the free-list if sflag is set. ! 567: */ ! 568: makesuper() ! 569: { ! 570: register struct filsys *sbp; ! 571: register ino_t *fip; ! 572: register i; ! 573: daddr_t bn; ! 574: ! 575: sbp = superb; ! 576: /* ! 577: * Remake list of free i-numbers. ! 578: */ ! 579: fip = sbp->s_inode; ! 580: sbp->s_ninode = freeip-freei; ! 581: while (freeip > freei) ! 582: *fip++ = *--freeip; ! 583: while (fip < &sbp->s_inode[NICFREE]) ! 584: *fip++ = 0; ! 585: sbp->s_tinode = nifree; ! 586: /* ! 587: * Free all remaining blocks ! 588: * and write last one as tail of free-list ! 589: */ ! 590: sbp->s_nfree = 0; ! 591: sbp->s_tfree = 0; ! 592: bn = fsize; ! 593: for (bn=fsize-1; bn>=isize; --bn) ! 594: if (!test(bn)) ! 595: bfree(bn); ! 596: canint(sbp->s_isize); ! 597: candaddr(sbp->s_fsize); ! 598: canshort(sbp->s_nfree); ! 599: for (i=0; i<NICFREE; ++i) ! 600: candaddr(sbp->s_free[i]); ! 601: canshort(sbp->s_ninode); ! 602: for (i=0; i<NICINOD; ++i) ! 603: canino(sbp->s_inode[i]); ! 604: cantime(sbp->s_time); ! 605: candaddr(sbp->s_tfree); ! 606: canino(sbp->s_tinode); ! 607: canshort(sbp->s_m); ! 608: canshort(sbp->s_n); ! 609: canlong(sbp->s_unique); ! 610: bwrite((daddr_t)SUPERB, sbp); ! 611: } ! 612: ! 613: /* ! 614: * Free a block and, in so doing, construct ! 615: * the free list chain. ! 616: */ ! 617: bfree(bn) ! 618: daddr_t bn; ! 619: { ! 620: register struct filsys *sbp; ! 621: register struct fblk *fbp; ! 622: register i; ! 623: ! 624: sbp = superb; ! 625: if (sbp->s_tfree == 0) { ! 626: bclear(fbuf, BSIZE); ! 627: bwrite(bn, fbuf); ! 628: } ! 629: if (sbp->s_nfree == NICFREE) { ! 630: bclear(fbp = fbuf, BSIZE); ! 631: fbp->df_nfree = sbp->s_nfree; ! 632: canint(fbp->df_nfree); ! 633: for (i=0; i<sbp->s_nfree; ++i) { ! 634: fbp->df_free[i] = sbp->s_free[i]; ! 635: candaddr(fbp->df_free[i]); ! 636: } ! 637: bwrite(bn, fbuf); ! 638: sbp->s_nfree = 0; ! 639: } ! 640: sbp->s_free[sbp->s_nfree++] = bn; ! 641: sbp->s_tfree++; ! 642: } ! 643: ! 644: /* ! 645: * Read the specified block number ! 646: * into `buf'. ! 647: */ ! 648: bread(bn, buf) ! 649: daddr_t bn; ! 650: char *buf; ! 651: { ! 652: if (bn<0 || bn>=fsize) { ! 653: badblock(bn, "any", 0); ! 654: bclear(buf, BSIZE); ! 655: return; ! 656: } ! 657: lseek(fileno(fs), (fsize_t)BSIZE * bn, 0); ! 658: if (read(fileno(fs), buf, BSIZE) != BSIZE) { ! 659: fprintf(stderr, "Read error %ld\n", (long)bn); ! 660: exstat |= IC_HARD; ! 661: bclear(buf, BSIZE); ! 662: } ! 663: } ! 664: ! 665: /* ! 666: * Write block `bn' from `buf'. ! 667: */ ! 668: bwrite(bn, buf) ! 669: daddr_t bn; ! 670: char *buf; ! 671: { ! 672: if (bn<0 || bn>=fsize) { ! 673: badblock(bn, "any", 0); ! 674: return; ! 675: } ! 676: lseek(fileno(fs), (fsize_t)BSIZE * bn, 0); ! 677: if (write(fileno(fs), buf, BSIZE) != BSIZE) { ! 678: fprintf(stderr, "Write error %ld\n", (long)bn); ! 679: exstat |= IC_HARD; ! 680: } ! 681: } ! 682: ! 683: /* ! 684: * Mark block # `bn' as ! 685: * seen before an check for ! 686: * duplicates. ! 687: * Bmark only marks file blocks if `sflag' is ! 688: * set so that the free list can be constructed ! 689: * again. ! 690: * Return 1 when something is wrong. ! 691: */ ! 692: bmark(bn, type, inum) ! 693: daddr_t bn; ! 694: char *type; ! 695: ino_t inum; ! 696: { ! 697: register nb; ! 698: ! 699: if (bn<0 || bn>=fsize) { ! 700: badblock(bn, type, inum); ! 701: return (1); ! 702: } ! 703: if (nb = nblock) { ! 704: register i; ! 705: ! 706: for (i=0; i<nb; i++) ! 707: if (blocks[i] == bn) ! 708: printf("%ld arg, class=%s, inode=%u\n", ! 709: (long)bn, type, inum); ! 710: } ! 711: { ! 712: register char *bp; ! 713: register int mask; ! 714: ! 715: mask = 1 << ((unsigned)bn)%NBPC; ! 716: bp = bitmap + ((unsigned)bn)/NBPC; ! 717: if (*bp & mask) /* if (test(bn)) */ ! 718: dupblock(bn, type, inum); ! 719: else if (!sflag || inum!=0) ! 720: *bp |= mask; /* mark(bn) */ ! 721: } ! 722: return (0); ! 723: } ! 724: ! 725: /* ! 726: * Clear a block of memory ! 727: * pointed to by `bp' for size ! 728: * `nb' bytes. ! 729: */ ! 730: bclear(bp, nb) ! 731: register char *bp; ! 732: register unsigned nb; ! 733: { ! 734: if (nb) ! 735: do { ! 736: *bp++ = 0; ! 737: } while (--nb); ! 738: } ! 739: ! 740: /* ! 741: * Error routines ! 742: */ ! 743: badblock(bn, type, inum) ! 744: daddr_t bn; ! 745: char *type; ! 746: ino_t inum; ! 747: { ! 748: register int perr = 0; ! 749: ! 750: if (strcmp(type, "free") != 0) { ! 751: perr++; ! 752: exstat |= IC_HARD; ! 753: } else { ! 754: exstat |= IC_BADF; ! 755: if (!sflag) ! 756: perr++; ! 757: } ! 758: if (perr) ! 759: printf("%ld bad, class=%s, inode=%u\n", (long)bn, type, inum); ! 760: } ! 761: ! 762: dupblock(bn, type, inum) ! 763: daddr_t bn; ! 764: char *type; ! 765: ino_t inum; ! 766: { ! 767: if (inum != 0) ! 768: exstat |= IC_HARD; ! 769: else ! 770: nfdup++; ! 771: if (vflag || inum!=0) ! 772: printf("%ld dup, class=%s, inode=%u\n", (long)bn, type, inum); ! 773: } ! 774: ! 775: badfreelist() ! 776: { ! 777: if (!sflag) { ! 778: printf("Bad freelist\n"); ! 779: exstat |= IC_BFB; ! 780: } ! 781: } ! 782: ! 783: /* ! 784: * Unrecoverable errors ! 785: */ ! 786: cerr(x) ! 787: { ! 788: printf("%r", &x); ! 789: putchar('\n'); ! 790: exit(IC_MISC); ! 791: } ! 792: ! 793: usage() ! 794: { ! 795: cerr("Usage: icheck [-sv] [-b bn ...] filesystem ..."); ! 796: } ! 797: ! 798: /* ! 799: * Block copy routine ! 800: */ ! 801: bcopy(in, out, nb) ! 802: register char *in, *out; ! 803: register unsigned nb; ! 804: { ! 805: if (nb) ! 806: do { ! 807: *out++ = *in++; ! 808: } while (--nb); ! 809: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.