1: #ifndef lint 2: char *sccsid = "@(#)icheck.c 2.5"; 3: #endif 4: 5: #include <whoami.h> 6: #ifdef STANDALONE 7: # define NI 8 8: #else 9: # define NI 16 10: #endif 11: #define NB 10 12: #define BITS 8 13: #define MAXFN 500 14: 15: #ifndef STANDALONE 16: #include <stdio.h> 17: #endif 18: #include <sys/param.h> 19: #include <sys/inode.h> 20: #include <sys/ino.h> 21: #include <sys/fblk.h> 22: #include <sys/filsys.h> 23: 24: struct filsys sblock; 25: struct dinode itab[INOPB*NI]; 26: daddr_t iaddr[NADDR]; 27: daddr_t blist[NB]; 28: char *bmap; 29: 30: int sflg; 31: int mflg; 32: int dflg; 33: int fi; 34: ino_t ino; 35: 36: ino_t nrfile; 37: ino_t ndfile; 38: ino_t nbfile; 39: ino_t ncfile; 40: ino_t nqfile; 41: ino_t nlfile; 42: 43: daddr_t ndirect; 44: daddr_t nindir; 45: daddr_t niindir; 46: daddr_t niiindir; 47: daddr_t nfree; 48: daddr_t ndup; 49: 50: int nerror; 51: 52: long atol(); 53: daddr_t alloc(); 54: #ifndef STANDALONE 55: char *malloc(); 56: #endif 57: #ifdef STANDALONE 58: char module[] = "Icheck"; 59: #define STDBUFSIZ 16000 /* Small enough for 407 */ 60: char stdbuf[STDBUFSIZ]; 61: #endif 62: 63: main(argc, argv) 64: char *argv[]; 65: { 66: register i; 67: long n; 68: 69: blist[0] = -1; 70: #ifndef STANDALONE 71: while (--argc) { 72: argv++; 73: if (**argv=='-') 74: switch ((*argv)[1]) { 75: case 'd': 76: dflg++; 77: continue; 78: 79: 80: case 'm': 81: mflg++; 82: continue; 83: 84: case 's': 85: sflg++; 86: continue; 87: 88: case 'b': 89: for(i=0; i<NB; i++) { 90: n = atol(argv[1]); 91: if(n == 0) 92: break; 93: blist[i] = n; 94: argv++; 95: argc--; 96: } 97: blist[i] = -1; 98: continue; 99: 100: default: 101: printf("Bad flag\n"); 102: } 103: check(*argv); 104: } 105: #else 106: { 107: static char fname[100]; 108: printf("%s\n",module); 109: printf("File: "); 110: gets(fname); 111: check(fname); 112: } 113: #endif 114: return(nerror); 115: } 116: 117: check(file) 118: char *file; 119: { 120: register i, j; 121: ino_t mino; 122: daddr_t d; 123: long n; 124: 125: fi = open(file, sflg?2:0); 126: if (fi < 0) { 127: printf("cannot open %s\n", file); 128: nerror |= 04; 129: return; 130: } 131: printf("%s:\n", file); 132: nrfile = 0; 133: ndfile = 0; 134: ncfile = 0; 135: nbfile = 0; 136: nqfile = 0; 137: nlfile = 0; 138: 139: ndirect = 0; 140: nindir = 0; 141: niindir = 0; 142: niiindir = 0; 143: 144: ndup = 0; 145: #ifndef STANDALONE 146: sync(); 147: #endif 148: bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); 149: mino = (sblock.s_isize-2) * INOPB; 150: ino = 0; 151: n = (sblock.s_fsize - sblock.s_isize + BITS-1) / BITS; 152: if (n != (unsigned)n) { 153: printf("Check fsize and isize: %D, %u\n", 154: sblock.s_fsize, sblock.s_isize); 155: } 156: #ifdef STANDALONE 157: if((unsigned)n > STDBUFSIZ) 158: bmap = NULL; 159: else 160: bmap = stdbuf; 161: #else 162: bmap = malloc((unsigned)n); 163: #endif 164: if (bmap==NULL) { 165: printf("Not enough core; duplicates unchecked\n"); 166: dflg++; 167: sflg = 0; 168: } 169: if(!dflg) 170: for(i=0; i<(unsigned)n; i++) 171: bmap[i] = 0; 172: for(i=2;; i+=NI) { 173: if(ino >= mino) 174: break; 175: bread((daddr_t)i, (char *)itab, sizeof(itab)); 176: for(j=0; j<INOPB*NI; j++) { 177: if(ino >= mino) 178: break; 179: ino++; 180: pass1(&itab[j]); 181: } 182: } 183: ino = 0; 184: #ifndef STANDALONE 185: sync(); 186: #endif 187: bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); 188: if (sflg) { 189: makefree(); 190: close(fi); 191: #ifndef STANDALONE 192: if (bmap) 193: free(bmap); 194: #endif 195: return; 196: } 197: nfree = 0; 198: while(n = alloc()) { 199: if (chk(n, "free")) 200: break; 201: nfree++; 202: } 203: close(fi); 204: #ifndef STANDALONE 205: if (bmap) 206: free(bmap); 207: #endif 208: 209: i = nrfile + ndfile + ncfile + nbfile; 210: i += nqfile; 211: i += nlfile; 212: #ifndef STANDALONE 213: printf("files %6u (r=%u,d=%u,b=%u,c=%u,q=%u,l=%u)\n", 214: i, nrfile, ndfile, nbfile, ncfile, nqfile, nlfile); 215: #else 216: printf("files %u (r=%u,d=%u,b=%u,c=%u,q=%u,l=%u)\n", 217: i, nrfile, ndfile, nbfile, ncfile, nqfile, nlfile); 218: #endif 219: n = ndirect + nindir + niindir + niindir; 220: #ifdef STANDALONE 221: printf("used %D (i=%D,ii=%D,iii=%D,d=%D)\n", 222: n, nindir, niindir, niiindir, ndirect); 223: printf("free %D\n", nfree); 224: #else 225: printf("used %7ld (i=%D,ii=%D,iii=%D,d=%D)\n", 226: n, nindir, niindir, niiindir, ndirect); 227: printf("free %7ld\n", nfree); 228: #endif 229: if(!dflg) { 230: n = 0; 231: for(d=sblock.s_isize; d<sblock.s_fsize; d++) 232: if(!duped(d)) { 233: if(mflg) 234: printf("%D missing\n", d); 235: n++; 236: } 237: printf("missing %D\n", n); 238: } 239: } 240: 241: pass1(ip) 242: register struct dinode *ip; 243: { 244: daddr_t ind1[NINDIR]; 245: daddr_t ind2[NINDIR]; 246: daddr_t ind3[NINDIR]; 247: register i, j; 248: int k, l; 249: 250: i = ip->di_mode & IFMT; 251: if(i == 0) { 252: sblock.s_tinode++; 253: return; 254: } 255: if(i == IFCHR) { 256: ncfile++; 257: return; 258: } 259: if(i == IFBLK) { 260: nbfile++; 261: return; 262: } 263: if(i == IFQUOT) { 264: nqfile++; 265: return; 266: } 267: if(i == IFLNK) { 268: nlfile++; 269: return; 270: } 271: if(i == IFDIR) 272: ndfile++; else 273: if(i == IFREG) 274: nrfile++; 275: else { 276: printf("bad mode %u\n", ino); 277: return; 278: } 279: l3tol(iaddr, ip->di_addr, NADDR); 280: for(i=0; i<NADDR; i++) { 281: if(iaddr[i] == 0) 282: continue; 283: if(i < NADDR-3) { 284: ndirect++; 285: chk(iaddr[i], "data (small)"); 286: continue; 287: } 288: nindir++; 289: if (chk(iaddr[i], "1st indirect")) 290: continue; 291: bread(iaddr[i], (char *)ind1, BSIZE); 292: for(j=0; j<NINDIR; j++) { 293: if(ind1[j] == 0) 294: continue; 295: if(i == NADDR-3) { 296: ndirect++; 297: chk(ind1[j], "data (large)"); 298: continue; 299: } 300: niindir++; 301: if(chk(ind1[j], "2nd indirect")) 302: continue; 303: bread(ind1[j], (char *)ind2, BSIZE); 304: for(k=0; k<NINDIR; k++) { 305: if(ind2[k] == 0) 306: continue; 307: if(i == NADDR-2) { 308: ndirect++; 309: chk(ind2[k], "data (huge)"); 310: continue; 311: } 312: niiindir++; 313: if(chk(ind2[k], "3rd indirect")) 314: continue; 315: bread(ind2[k], (char *)ind3, BSIZE); 316: for(l=0; l<NINDIR; l++) 317: if(ind3[l]) { 318: ndirect++; 319: chk(ind3[l], "data (garg)"); 320: } 321: } 322: } 323: } 324: } 325: 326: chk(bno, s) 327: daddr_t bno; 328: char *s; 329: { 330: register n; 331: 332: if (bno<sblock.s_isize || bno>=sblock.s_fsize) { 333: printf("%D bad; inode=%u, class=%s\n", bno, ino, s); 334: return(1); 335: } 336: if(duped(bno)) { 337: printf("%D dup; inode=%u, class=%s\n", bno, ino, s); 338: ndup++; 339: } 340: for (n=0; blist[n] != -1; n++) 341: if (bno == blist[n]) 342: printf("%D arg; inode=%u, class=%s\n", bno, ino, s); 343: return(0); 344: } 345: 346: duped(bno) 347: daddr_t bno; 348: { 349: daddr_t d; 350: register m, n; 351: 352: if(dflg) 353: return(0); 354: d = bno - sblock.s_isize; 355: m = 1 << (d%BITS); 356: n = (d/BITS); 357: if(bmap[n] & m) 358: return(1); 359: bmap[n] |= m; 360: return(0); 361: } 362: 363: daddr_t 364: alloc() 365: { 366: int i; 367: daddr_t bno; 368: union { 369: char data[BSIZE]; 370: struct fblk fb; 371: } buf; 372: 373: sblock.s_tfree--; 374: if (sblock.s_nfree<=0) 375: return(0); 376: if (sblock.s_nfree>NICFREE) { 377: printf("Bad free list, s.b. count = %d\n", sblock.s_nfree); 378: return(0); 379: } 380: bno = sblock.s_free[--sblock.s_nfree]; 381: sblock.s_free[sblock.s_nfree] = (daddr_t)0; 382: if(bno == 0) 383: return(bno); 384: if(sblock.s_nfree <= 0) { 385: bread(bno, buf.data, BSIZE); 386: sblock.s_nfree = buf.df_nfree; 387: if (sblock.s_nfree<0 || sblock.s_nfree>NICFREE) { 388: printf("Bad free list, entry count of block %D = %d\n", 389: bno, sblock.s_nfree); 390: sblock.s_nfree = 0; 391: return(0); 392: } 393: for(i=0; i<NICFREE; i++) 394: sblock.s_free[i] = buf.df_free[i]; 395: } 396: return(bno); 397: } 398: 399: bfree(bno) 400: daddr_t bno; 401: { 402: union { 403: char data[BSIZE]; 404: struct fblk fb; 405: } buf; 406: int i; 407: 408: sblock.s_tfree++; 409: if(sblock.s_nfree >= NICFREE) { 410: for(i=0; i<BSIZE; i++) 411: buf.data[i] = 0; 412: buf.df_nfree = sblock.s_nfree; 413: for(i=0; i<NICFREE; i++) 414: buf.df_free[i] = sblock.s_free[i]; 415: bwrite(bno, buf.data); 416: sblock.s_nfree = 0; 417: } 418: sblock.s_free[sblock.s_nfree] = bno; 419: sblock.s_nfree++; 420: } 421: 422: bread(bno, buf, cnt) 423: daddr_t bno; 424: char *buf; 425: { 426: register i; 427: 428: lseek(fi, bno*BSIZE, 0); 429: if (read(fi, buf, cnt) != cnt) { 430: printf("read error %D\n", bno); 431: if (sflg) { 432: printf("No update\n"); 433: sflg = 0; 434: } 435: for(i=0; i<BSIZE; i++) 436: buf[i] = 0; 437: } 438: } 439: 440: bwrite(bno, buf) 441: daddr_t bno; 442: char *buf; 443: { 444: 445: lseek(fi, bno*BSIZE, 0); 446: if (write(fi, buf, BSIZE) != BSIZE) 447: printf("write error %D\n", bno); 448: } 449: 450: makefree() 451: { 452: char flg[MAXFN]; 453: int adr[MAXFN]; 454: register i, j; 455: daddr_t f, d; 456: int m, n; 457: 458: n = sblock.s_n; 459: if(n <= 0 || n > MAXFN) 460: n = MAXFN; 461: sblock.s_n = n; 462: m = sblock.s_m; 463: if(m <= 0 || m > sblock.s_n) 464: m = 3; 465: sblock.s_m = m; 466: 467: for(i=0; i<n; i++) 468: flg[i] = 0; 469: i = 0; 470: for(j=0; j<n; j++) { 471: while(flg[i]) 472: i = (i+1)%n; 473: adr[j] = i+1; 474: flg[i]++; 475: i = (i+m)%n; 476: } 477: 478: sblock.s_nfree = 0; 479: sblock.s_ninode = 0; 480: sblock.s_flock = 0; 481: sblock.s_ilock = 0; 482: sblock.s_fmod = 0; 483: sblock.s_ronly = 0; 484: #ifndef STANDALONE 485: time(&sblock.s_time); 486: #endif 487: sblock.s_tfree = 0; 488: sblock.s_tinode = 0; 489: 490: bfree((daddr_t)0); 491: d = sblock.s_fsize-1; 492: while(d%sblock.s_n) 493: d++; 494: for(; d > 0; d -= sblock.s_n) 495: for(i=0; i<sblock.s_n; i++) { 496: f = d - adr[i]; 497: if(f < sblock.s_fsize && f >= sblock.s_isize) 498: if(!duped(f)) 499: bfree(f); 500: } 501: bwrite((daddr_t)1, (char *)&sblock); 502: #ifndef STANDALONE 503: sync(); 504: #endif 505: return; 506: }