|
|
1.1 ! root 1: #include "fs.h" ! 2: #include "sys/fblk.h" ! 3: enum {Byte=8}; /* number of bits per byte */ ! 4: int btypes[NADDR] = {Data, Data, Data, Data, Data, Data, Data, Data, Data, Data, ! 5: Ind, Ind2, Ind3}; ! 6: int dtypes[NADDR] = {First, Other, Other, Other, Other, Other, Other, Other, ! 7: Other, Other, Ind, Ind2, Ind3}; ! 8: ! 9: firstsuper() ! 10: { int i; ! 11: if(bread(1, (char *)&sblk, 1)) { ! 12: perror("superblock"); ! 13: fatal("couldn't read superblock of %s\n", file); ! 14: } ! 15: inopb = bsize / sizeof(struct dinode); ! 16: ninode = (sblk.s_isize-2) * inopb + 1; ! 17: fblk = sblk.s_isize; ! 18: pblk = sblk.s_fsize; ! 19: if(bsize >= 4096 && BITMAP*Byte*sizeof(long)+fblk < pblk) { ! 20: i = (pblk + (bsize*Byte-1))/(bsize*Byte); ! 21: lblk = pblk - i; ! 22: } ! 23: else ! 24: lblk = pblk; ! 25: if(flags['v']) ! 26: pmesg("ninode %d isize %d lblk %d pblk %d\n", ninode, fblk, lblk, ! 27: pblk); ! 28: if(ninode < 2 || lblk <= fblk || pblk < lblk) ! 29: fatal("absurd(%d inodes, lblk=%d, pblk=%d)\n", ninode, fblk, pblk); ! 30: /* allocate all the space */ ! 31: buf = (char *) malloc(buflen = fblk * bsize); ! 32: if(!buf) /* we've been too greedy, cache this stuff FIX*/ ! 33: fatal("couldn't alloc %d bytes for buffers\n", buflen); ! 34: imap = (im *) malloc(ninode*sizeof(im)); ! 35: bmap = (bm *) malloc(pblk*sizeof(bm)); ! 36: dmap = (dm *) malloc((dmaplen = 1000)*sizeof(dm)); ! 37: if(!imap || !bmap || !dmap) ! 38: fatal("couldn't alloc imap, bmap, or dmap\n"); ! 39: memset((char *)imap, 0, ninode*sizeof(im)); ! 40: memset((char *)bmap, 0, pblk*sizeof(bm)); ! 41: if(flags['v']) ! 42: pmesg("alloc: %d for bufs, %d for imap, %d for bmap\n", buflen, ! 43: ninode*sizeof(im), pblk*sizeof(bm)); ! 44: timer("alloc"); ! 45: if(bread(0, buf, fblk)) /* fragile, FIX */ ! 46: fatal("couldn't read inodes\n"); ! 47: bmap[0].type = Boot; ! 48: bmap[1].type = Sblock; ! 49: for(i = 2; i < fblk; i++) ! 50: bmap[i].type = Inode; ! 51: /* and, if necessary, the extra bitmaps */ ! 52: if(pblk > lblk) { ! 53: freeb = (char *) malloc(bsize * (pblk-lblk)); ! 54: if(!freeb || bread(lblk, freeb, pblk-lblk)) ! 55: fatal("couldn't read bitmap blocks\n"); ! 56: for(i = lblk; i < pblk; i++) ! 57: bmap[i].type = Bits; ! 58: } ! 59: } ! 60: ! 61: scaninodes() ! 62: { register int ino, *lp, *p; ! 63: register struct dinode *dp; ! 64: register im *ip; ! 65: register bm *bp; ! 66: int addr[NADDR], *ty, last; ! 67: ino = 0; ! 68: ip = imap+1; ! 69: dp = (struct dinode *) (buf+2*bsize); ! 70: for(ino = 1; ino < ninode; ino++, dp++, ip++) { ! 71: switch(dp->di_mode & IFMT) { ! 72: default: ! 73: pmesg("ino %d weird mode 0%o\n", ino, dp->di_mode); ! 74: ip->type = Weird; ! 75: continue; ! 76: case IFDIR: ! 77: ip->type = Dir; ! 78: ty = dtypes; ! 79: break; ! 80: case IFCHR: ! 81: ip->type = Chr; ! 82: continue; ! 83: case IFBLK: ! 84: ip->type = Blk; ! 85: continue; ! 86: case IFREG: ! 87: ip->type = Reg; ! 88: ty = btypes; ! 89: break; ! 90: case IFLNK: ! 91: ty = btypes; ! 92: ip->type = Lnk; ! 93: if(dp->di_size > bsize || dp->di_size == 0) ! 94: inoerr(Elinksize, ino); ! 95: break; ! 96: case 0: ! 97: if(!dp->di_mode && !dp->di_size && !dp->di_nlink) ! 98: ip->type = Unalloc; ! 99: else ! 100: ip->type = Weird; ! 101: continue; ! 102: } ! 103: /* now look through the blocks in the inode */ ! 104: l3tol(addr, dp->di_addr, NADDR); ! 105: p = addr; ! 106: lp = addr + NADDR; ! 107: for(last = -1; p < lp; p++) { ! 108: if(*p == 0) ! 109: continue; ! 110: if(*p < fblk || *p >= lblk) { ! 111: inoerr(Ebadaddr, ino, *p); ! 112: continue; ! 113: } ! 114: bp = bmap + *p; ! 115: if(bp->ino) ! 116: dupblock(bp, bp->type, 0); ! 117: bp->ino = ino; ! 118: bp->type = ty[p-addr]; ! 119: blkcnts[bp->type]++; ! 120: last = p-addr; ! 121: switch(last) { ! 122: case 10: /* indirect */ ! 123: bp->bnum = NADDR-3; ! 124: continue; ! 125: case 11: ! 126: bp->bnum = bsize/sizeof(long) + NADDR-3; ! 127: continue; ! 128: /* hard to tell if triple blocks are an error, so... */ ! 129: case 12: ! 130: if(bsize >= 4096) ! 131: bp->type = Other, inoerr(Etriple, ino, *p); ! 132: else ! 133: bp->bnum = (bsize/sizeof(long)) * ! 134: (bsize/sizeof(long) + 1) + NADDR-3; ! 135: continue; ! 136: } ! 137: } ! 138: if(ip->type == Dir && (addr[0] < fblk || addr[0] >= lblk)) ! 139: direrror(Efirst, ino); ! 140: ip->last = last; ! 141: } ! 142: } ! 143: ! 144: indblocks(old, new) ! 145: register old; ! 146: { register int *p, *ep; ! 147: register bm *bp, *obp, *mx = bmap + lblk; ! 148: int nty, delta, last; ! 149: ! 150: switch(old) { ! 151: default: ! 152: delta = 1; ! 153: break; ! 154: case Ind2: ! 155: delta = bsize/sizeof(long); ! 156: break; ! 157: case Ind3: ! 158: delta = bsize/sizeof(long) * bsize/sizeof(long); ! 159: break; ! 160: } ! 161: ep = (int *)(buf+bsize); ! 162: for(obp = bmap+1; obp < mx; obp++) { ! 163: if(obp->type != old) ! 164: continue; ! 165: if(bread(obp-bmap, buf, 1)) { ! 166: pmesg("ino %d block %d couldn't read\n", obp->ino, ! 167: obp-bmap); ! 168: obp->type = Ioerr; ! 169: inoerr(Ebadread, obp->ino, obp-bmap); ! 170: continue; ! 171: } ! 172: nty = obp->type == Dir && new == Data? Other: new; ! 173: for(last = -1, p = (long *)buf; p < ep; p++) { ! 174: if(*p == 0) ! 175: continue; ! 176: if(*p < fblk || *p >= lblk) { ! 177: inoerr(Ebadaddr, bmap[obp-bmap].ino); ! 178: break; ! 179: } ! 180: bp = bmap + *p; ! 181: if(bp->ino) ! 182: dupblock(bp, obp->type, new); ! 183: last = bp->bnum = obp->bnum + delta*(p-(long *)buf); ! 184: bp->ino = obp->ino; ! 185: bp->type = nty; ! 186: blkcnts[nty]++; ! 187: } ! 188: if(last == -1) ! 189: pmesg("ino %d had ind block (%d) all 0\n", obp->ino, ! 190: obp-bmap); ! 191: if(imap[obp->ino].last < last) ! 192: imap[obp->ino].last = last; ! 193: } ! 194: } ! 195: ! 196: dochecks() ! 197: { int i, j, k; ! 198: im *ip = imap + ROOTINO; ! 199: struct dinode *dp = (struct dinode *)(buf + 2*bsize); ! 200: for(i = ROOTINO, dp += i-1; i < ninode; i++, ip++, dp++) { ! 201: j = dp->di_nlink; ! 202: if(ip->type != Unalloc && ip->nrefs == 0 && j == 0) ! 203: inoerr(Enullable, i, 0); ! 204: else if(ip->nrefs != j) ! 205: inoerr(Elinkcnt, i, ip->nrefs-j); ! 206: switch(ip->type) { ! 207: case Dir: ! 208: if(dp->di_size < 32) /* no room for . and .. */ ! 209: direrror(Eshortdir, i, dp->di_size); ! 210: case Lnk: case Reg: ! 211: k = ip->last; ! 212: if(dp->di_size == 0 && k == -1) ! 213: continue; ! 214: j = (dp->di_size-1)/bsize; ! 215: if(j == k) ! 216: continue; ! 217: if(j < k) /* blks after end */ ! 218: inoerr(Eshort, i, k); ! 219: if(j > k) /* ends with holes */ ! 220: inoerr(Ehole, i, k); ! 221: } ! 222: } ! 223: dirtree(); ! 224: } ! 225: ! 226: checksuper() ! 227: { register int i, cnt, j, k; ! 228: bm *bp; ! 229: int last; ! 230: if(!sblk.U.B.S_valid) ! 231: supererr(Einvalid, 0, 0); ! 232: for(cnt = i = 0; i < NICINOD && i < sblk.s_ninode; i++) { ! 233: j = sblk.s_inode[i]; ! 234: if(j == 0) /* really? */ ! 235: continue; ! 236: if(j >= ninode || imap[j].type != Unalloc) { ! 237: supererr(Esuperino, j, 0); ! 238: break; ! 239: } ! 240: cnt++; ! 241: } ! 242: if(i >= NICINOD && cnt != sblk.s_ninode) ! 243: supererr(Esuperino, 0, cnt); ! 244: for(i = 1, cnt = 0; i < ninode; i++) ! 245: if(imap[i].type == Unalloc) ! 246: cnt++; ! 247: tinode = cnt; ! 248: if(cnt != sblk.s_tinode) ! 249: supererr(Esuperino, cnt, sblk.s_tinode); ! 250: if(bsize < 4096) { /* there should be a file system type FIX */ ! 251: ch1free(); ! 252: return; ! 253: } ! 254: if(pblk > lblk) { ! 255: chbitmap(); ! 256: return; ! 257: } ! 258: cnt = fblk; ! 259: bp = bmap + cnt; ! 260: for(i = 0; i < BITMAP; i++, cnt += 32) { ! 261: k = sblk.U.B.S_bfree[i]; ! 262: for(j = 0; j < 32; j++, bp++) { ! 263: if((k & (1<<j)) == 0) { ! 264: continue; ! 265: } ! 266: if(cnt+j >= lblk) { ! 267: supererr(Esuperfree, cnt+j, 0); ! 268: return; ! 269: } ! 270: if(bp->type == Unk) { ! 271: bp->type = Free; ! 272: blkcnts[Free]++; ! 273: } ! 274: else { ! 275: supererr(Esuperfree, cnt+j, bp->type); ! 276: return; ! 277: } ! 278: } ! 279: } ! 280: for(i = 1, bp = bmap + i; i < pblk; i++, bp++) ! 281: if(bp->type == Unk) { ! 282: supererr(Efreelist, i, bp->type); ! 283: return; ! 284: } ! 285: tfree = blkcnts[Free]; ! 286: if(tfree != sblk.s_tfree) ! 287: supererr(Efreelist, sblk.s_tfree, tfree); ! 288: } ! 289: ! 290: chbitmap() ! 291: { register long *p; ! 292: register int i, k, j; ! 293: register bm *bp = bmap; ! 294: for(i = 0, p = (long *)freeb; i < pblk; i += 32, p++) { ! 295: k = *p; ! 296: for(j = 0; j < 32; j++, bp++) { ! 297: if((k & (1 << j)) == 0) ! 298: continue; ! 299: if(i+j >= lblk) { ! 300: supererr(Esuperfree, i+j, 0); ! 301: continue; ! 302: } ! 303: if(bp->type == Unk) { ! 304: bp->type = Free; ! 305: blkcnts[Free]++; ! 306: } ! 307: else { ! 308: supererr(Esuperfree, i+j, bp->type); ! 309: return; ! 310: } ! 311: } ! 312: } ! 313: for(i = 1, bp = bmap + i; i < pblk; i++, bp++) ! 314: if(bp->type == Unk) { ! 315: supererr(Efreelist, i, bp->type); ! 316: return; ! 317: } ! 318: tfree = blkcnts[Free]; ! 319: if(tfree != sblk.s_tfree) ! 320: supererr(Efreelist, sblk.s_tfree, tfree); ! 321: } ! 322: ! 323: ch1free() ! 324: { int i, j, k; ! 325: daddr_t *p; ! 326: /* these could be unified if S_nfree were an int, not a short */ ! 327: for(i = 0; i < sblk.U.R.S_nfree; i++) { ! 328: j = sblk.U.R.S_free[i]; ! 329: if(j >= fblk && j < lblk && !bmap[j].ino) { ! 330: if(bmap[j].type) ! 331: adderr(Edup, j, 0); ! 332: bmap[j].type = Free; ! 333: blkcnts[Free]++; ! 334: } ! 335: else if(j) ! 336: inoerr(Ebadaddr, 0, j); ! 337: } ! 338: if((j = sblk.U.R.S_free[0]) == 0) ! 339: return; ! 340: loop: ! 341: if(bread(j, buf, 1)) { ! 342: pmesg("couldn't read free blk %d\n", j); ! 343: bmap[j].type = Ioerr; ! 344: exitcode = 1; ! 345: return; ! 346: } ! 347: k = ((struct fblk *)buf)->df_nfree; ! 348: for(p = ((struct fblk *)buf)->df_free, i = 0; i < k; i++) { ! 349: j = p[i]; ! 350: if(j >= fblk && j < lblk && !bmap[j].ino) { ! 351: if(bmap[j].type) ! 352: adderr(Edup, j, 0); ! 353: bmap[j].type = Free; ! 354: blkcnts[Free]++; ! 355: } ! 356: else if(j) ! 357: inoerr(Ebadaddr, 0, j); ! 358: } ! 359: if(j = p[0]) ! 360: goto loop; ! 361: } ! 362: ! 363: report() ! 364: { int i, cnts[32], j, k; ! 365: for(i = 0; i < iptr; i++) { ! 366: j = iarg[i]; ! 367: if(j < 1 || j >= ninode) { ! 368: pmesg("arg ino %d out of range\n", j); ! 369: continue; ! 370: } ! 371: pmesg("arg ino %s\n", prino(j)); ! 372: if(imap[j].type == Dir) { ! 373: for(k = 0; k < pblk; k++) ! 374: if(bmap[k].ino == j && bmap[k].type == First) ! 375: pmesg(" (first blk %d)\n", k); ! 376: } ! 377: } ! 378: for(i = 0; i < bptr; i++) { ! 379: j = barg[i]; ! 380: if(j < 0 || j > pblk) { ! 381: pmesg("arg blk %d out of range\n", j); ! 382: continue; ! 383: } ! 384: pmesg("arg blk %d(%s) %s\n", j, btype(bmap[j].type), ! 385: prino(bmap[j].ino)); ! 386: } ! 387: if(!flags['v']) ! 388: return; ! 389: pmesg("dmapptr %d erptr %d\n", dmapptr, erptr); ! 390: pmesg("\tinodes:\n"); ! 391: for(i = 0; i < 32; i++) ! 392: cnts[i] = 0; ! 393: for(i = 1; i < ninode; i++) ! 394: cnts[imap[i].type]++; ! 395: for(i = 0; i < 32; i++) ! 396: if(cnts[i]) ! 397: pmesg("%s %d\n", itype(i), cnts[i]); ! 398: pmesg("\tblocks:\n"); ! 399: for(i = 0; i < 32; i++) ! 400: if(blkcnts[i]) ! 401: pmesg("%s %d\n", btype(i), blkcnts[i]); ! 402: rpterrs(); ! 403: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.