ref: 5c21eca829380c28769f79beabb7cc51f1787f97
dir: /find.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" /* for an invalid used block, show the directory tree leading to it BUG: if the block is a Dentry, does not find it? */ enum { Ndir = 128, }; int debug = 0; char *devfile = nil; u64 parents[Ndir]; u64 findblkno; void walkdentry(u64 blkno, s8 depth); Tag *readtag(u64 blkno, u8 *buf); static void usage(void) { fprint(2, "usage: used [-D ] fsfile blkno\n"); exits("usage"); } void main(int argc, char *argv[]) { u64 size; ARGBEGIN{ default: usage(); case 'D': debug++; break; }ARGEND if(argc != 2) usage(); devfile = argv[0]; if(devfile == nil) sysfatal("no disk file"); findblkno = atoll(argv[1]); if(findblkno == 0){ fprint(2, "invalid block number %llud\n", findblkno); exits(nil); } if(devfile == nil) sysfatal("no disk file"); if (access(devfile, AREAD) == -1) sysfatal("%s cannot access device", devfile); size = devinit(devfile); if(size == 0) panic("null size %s", devfile); if(debug) print("%s %llud bytes %llud blocks\n", devfile, size, size/Rawblocksize); walkdentry(Broot, 0); exits(0); } void showparents(void) { s8 i; for(i =0; i<Ndir-1 && parents[i] != 0; i++){ print("%d %llud\n", i, parents[i]); } } int checkvalid(u64 blkno, Tag *t, s16 tagtype, u64 qpath) { int ret = 1; if(t->type != tagtype || t->path != qpath){ /* if(debug) */ fprint(2, "checkvalid invalid %llud tag/path expected %s/%llud actual %s/%llud\n", blkno, tagnames[tagtype], qpath, tagnames[t->type], t->path); fprint(2, "used: %llud\n", blkno); ret=0; }/*else print("%llud\n", blkno);*/ if(blkno == findblkno){ showparents(); exits(nil); } return ret; } void walkindir(u64 blkno, u16 tag, u16 bottomtag, u64 qpath, s8 depth) { u8 buf[Rawblocksize], *cbuf; Tag *t, *ct; u64 cblkno, *bufa; int i; Spanid *s; u16 len; devread(blkno, buf, 1); t = (Tag*)buf; if(checkvalid(blkno, t, tag, qpath)){ if(t->type == Tind0){ s = (Spanid*)(buf+sizeof(Tag)); for(i = 0; i<Nspanidperblock; i++){ cblkno = s[i].blkno; len = s[i].len; if(cblkno == 0) return; cbuf = malloc(len*Rawblocksize); devread(cblkno, cbuf, len); ct = (Tag*)cbuf; if(ct->type == Tdentry && ct->type == bottomtag) /* another directory */ walkdentry(cblkno, depth); else checkvalid(cblkno, ct, bottomtag, qpath); free(cbuf); } }else{ bufa = (u64*)(buf+sizeof(Tag)); cbuf = malloc(Rawblocksize); for(i = 0; i<Nindperblock; i++){ cblkno = bufa[i]; if(cblkno == 0) return; devread(cblkno, cbuf, 1); /* check tag */ walkindir(cblkno, tag-1, bottomtag, qpath, depth); } free(cbuf); } } return; } void addparent(s8 depth, u64 dblkno) { s8 i; for(i =Ndir-1; i>depth; i--){ parents[i] = 0; } parents[depth] = dblkno; } void showdepth(s8 depth) { int i; for(i = 0; i<depth; i++) print(" "); } void walkdentry(u64 blkno, s8 depth) { u8 buf[Rawblocksize], *cbuf; Dentry *d; Tag *t, *ct; u64 cblkno; int i; u8 isdir; u16 len; devread(blkno, buf, 1); t = (Tag*)buf; d = (Dentry*)(buf+sizeof(Tag)); isdir = (d->mode & DMDIR) > 0; showdepth(depth); print("%llud:%s\n", blkno, d->name); if(debug) print("walkdentry %llud tag %s name %s d->qid.path %llud\n", blkno, tagnames[t->type], d->name, d->qid.path); if(t->type != Tdentry || t->path != d->qid.path){ if(debug) print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n", blkno, tagnames[Tdentry], d->qid.path, tagnames[t->type], t->path); fprint(2, "%llud\n", blkno); }/*else print("%llud\n", blkno);*/ addparent(depth, blkno); for(i = 0; i<Ndspanid; i++){ cblkno = d->dspans[i].blkno; len = d->dspans[i].len; if(cblkno == 0) return; cbuf = malloc(len*Rawblocksize); devread(cblkno, cbuf, len); ct = (Tag*)cbuf; if(isdir) walkdentry(cblkno, depth+1); else checkvalid(cblkno, ct, Tdata, d->qid.path); free(cbuf); } cbuf = malloc(Rawblocksize); for(i = 0; i<Niblock; i++){ cblkno = d->iblocks[i]; if(cblkno == 0) return; devread(cblkno, cbuf, 1); ct = (Tag*)cbuf; if(ct->type == Tind0+i){ walkindir(cblkno, Tind0+i, isdir ? Tdentry : Tdata, d->qid.path, depth); }else{ fprint(2, "invalid indir tag %llud\n", cblkno); fprint(2, "%llud\n", cblkno); } } free(cbuf); return; }