ref: 56bd332994102b4e194819abb5e087a8895452f9
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 walkdirectory(u64 blkno, s8 depth); void walkfile(u64 blkno, s8 depth); 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/Blocksize); walkdirectory(Bdroot, 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, u8 dtag, u64 dpath, u8 tag, u64 qpath, u16 len) { int ret = 1; if(dtag != tag || dpath != qpath){ /* if(debug) */ fprint(2, "checkvalid invalid %llud tag/path expected %s/%llud actual %s/%llud\n", blkno, tagnames[tag], qpath, tagnames[dtag], dpath); fprint(2, "used: %llud\n", blkno); ret=0; }/*else print("%llud\n", blkno);*/ if(blkno <= findblkno || findblkno < blkno+len){ showparents(); exits(nil); } return ret; } void walkindir(u64 blkno, u8 tag, u8 bottomtag, u64 qpath, s8 depth) { u8 buf[Metadatablocksize], *cbuf; Indirect *t; Data *ct; u64 cblkno, *bufa; int i; devread(blkno, buf, Metadataunits); t = (Indirect*)buf; if(checkvalid(blkno, t->tag, t->path, tag, qpath, Metadataunits)){ if(t->tag == Tind0){ bufa = (u64*)buf; for(i = 0; i<Nindperblock; i++){ cblkno = bufa[i]; if(cblkno == 0) return; if(Tdentry == bottomtag) /* another directory */ walkdirectory(cblkno, depth); else{ cbuf = malloc(Blocksize); devread(cblkno, cbuf, 1); ct = (Data*)cbuf; checkvalid(cblkno, ct->tag, ct->path, bottomtag, qpath, ct->len); free(cbuf); } } }else{ for(i = 0; i<Nindperblock; i++){ cblkno = t->bufa[i]; if(cblkno == 0) return; /* check tag */ walkindir(cblkno, tag-1, bottomtag, qpath, depth); } } } 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 walkdirectory(u64 blkno, s8 depth) { u8 buf[Metadatablocksize], *cbuf; Dentry *d, *cd; Indirect *ct; u64 cblkno; int i; devread(blkno, buf, Metadataunits); d = (Dentry*)buf; showdepth(depth); print("%llud:%s\n", blkno, d->name); if(debug) print("walkdentry %llud tag %s name %s d->qpath %llud\n", blkno, tagnames[d->tag], d->name, d->qpath); if(d->tag != Tdentry || d->path != d->qpath){ if(debug) print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n", blkno, tagnames[Tdentry], d->qpath, tagnames[d->tag], d->path); fprint(2, "%llud\n", blkno); }/*else print("%llud\n", blkno);*/ addparent(depth, blkno); for(i = 0; i<Ndblock; i++){ cblkno = d->dblocks[i]; if(cblkno == 0) return; cbuf = malloc(Metadatablocksize); devread(cblkno, cbuf, Metadataunits); cd = (Dentry*)cbuf; if((cd->mode & DMDIR) > 0) walkdirectory(cblkno, depth+1); else walkfile(cblkno, depth+1); free(cbuf); } cbuf = malloc(Metadatablocksize); for(i = 0; i<Niblock; i++){ cblkno = d->iblocks[i]; if(cblkno == 0) return; devread(cblkno, cbuf, Metadataunits); ct = (Indirect*)cbuf; if(ct->tag == Tind0+i){ walkindir(cblkno, Tind0+i, Tdentry, d->qpath, depth); }else{ fprint(2, "invalid indir tag %llud\n", cblkno); fprint(2, "%llud\n", cblkno); } } free(cbuf); return; } void walkfile(u64 blkno, s8 depth) { u8 buf[Metadatablocksize], *cbuf; Dentry *d; Data *ct; Indirect *it; u64 cblkno; int i; devread(blkno, buf, Metadataunits); d = (Dentry*)buf; showdepth(depth); print("%llud:%s\n", blkno, d->name); if(debug) print("walkfile %llud tag %s name %s d->qid.path %llud\n", blkno, tagnames[d->tag], d->name, d->qpath); if(d->tag != Tdentry || d->path != d->qpath){ if(debug) print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n", blkno, tagnames[Tdentry], d->qpath, tagnames[d->tag], d->path); fprint(2, "%llud\n", blkno); }/*else print("%llud\n", blkno);*/ addparent(depth, blkno); if(d->size <= Ddatasize) return; for(i = 0; i<Ndblock; i++){ cblkno = d->dblocks[i]; if(cblkno == 0) return; cbuf = malloc(Metadatablocksize); devread(cblkno, cbuf, Metadataunits); ct = (Data*)cbuf; checkvalid(cblkno, ct->tag, ct->path, Tdata, d->qpath, ct->len); free(cbuf); } cbuf = malloc(Metadatablocksize); for(i = 0; i<Niblock; i++){ cblkno = d->iblocks[i]; if(cblkno == 0) return; devread(cblkno, cbuf, Metadataunits); it = (Indirect*)cbuf; if(it->tag == Tind0+i){ walkindir(cblkno, Tind0+i, Tdata, d->qpath, depth); }else{ fprint(2, "invalid indir tag %llud\n", cblkno); fprint(2, "%llud\n", cblkno); } } free(cbuf); return; }