/* lkfs: read kfs under linux, -markus, Aug 1996 */ #include #include #include #include #include #include #include "dat.h" char *tagname[]= { "Tnone", "Tsuper", "Tdir", "Tind1", "Tind2", "Tfile", "Tfree", "Tbuck", "Tvirgo", "Tcache", "MAXTAG" }; #define QPDIR 0x80000000L #define QPNONE 0 #define QPROOT 1 #define QPSUPER 2 #define QID(a,b) (Qid){a,b} #define WMAGIC "kfs wren device\n" #define superblock 1 #define rootblock 2 #define dprint if(debug)printf int RBUFSIZE; int BUFSIZE; int DIRPERBUF; int INDPERBUF; int INDPERBUF2; int FEPERBUF; int fd; char buf[8*1024]; Tag *tag; int verbose=0; int debug=0; void panic(char *msg){ if(errno)perror(msg); else fprintf(stderr,msg); exit(1); } void getblock(long addr){ int i; static long oaddr=0; if(addr==oaddr) return; dprint("\t<< getting block#%-5ld ",addr); i = lseek(fd, addr*RBUFSIZE, SEEK_SET) < 0 || read(fd, buf, RBUFSIZE) != RBUFSIZE; if(i) panic("getblock: seek/read"); tag = (Tag*)(buf+BUFSIZE); dprint(" Tag={%d,%s,%ld} >>\n", tag->pad, (tag->tag < MAXTAG)?tagname[tag->tag]:"BADTAG", tag->path); oaddr=addr; } long indfetch(long x, long y){ getblock(x); return ((long *)buf)[y]; } long dnodebuf(Dentry *d, long a) { long addr = 0; dprint("\t<< dnodebuf #%ld >>\n",a); if(a < 0) { fprintf(stderr,"dnodebuf: neg\n"); return 0; } if(a < NDBLOCK) { addr = d->dblock[a]; return addr; } a -= NDBLOCK; if(a < INDPERBUF) { addr = d->iblock; addr = indfetch(addr, a); return addr; } a -= INDPERBUF; if(a < INDPERBUF2) { addr = d->diblock; addr = indfetch(addr, a/INDPERBUF); addr = indfetch(addr, a%INDPERBUF); return addr; } fprintf(stderr,"dnodebuf: trip indirect\n"); return 0; } void dentrydump(Dentry *d){ int i; if(!(d->mode & DALLOC)) return; printf("%o ", d->mode); printf("%5d ", d->uid); printf("%5d ", d->gid); printf("%-25s ", d->name); printf("%7ld ", d->size); printf("%ld ", d->mtime); if(verbose) printf("%ld ", d->atime); printf("(%ld.%ld) ", ~QPDIR&(d->qid.path),d->qid.version); if(verbose){ printf("[ "); for(i=0;idblock[i];i++) printf("%ld ", d->dblock[i]); if(d->iblock) printf("ib=%ld ",d->iblock); if(d->diblock) printf("dib=%ld ",d->diblock); printf("]"); } printf("\n"); } void blockdump(long block, long size){ int slot; Dentry *dp; Superb *sb; long limit; if(block) getblock(block); switch(tag->tag){ case Tdir: for(slot=0;slot>\n",limit); for(slot=0;slot>>\n"); } break; case Tsuper: sb=(Superb*)buf; printf("fstart=%ld\n", sb->super.fstart); printf("fsize=%ld\n", sb->super.fsize); printf("tfree=%ld\n", sb->super.tfree); printf("qidgen=%ld\n", sb->super.qidgen); printf("fsok=%ld\n", sb->super.fsok); printf("nfree=%ld (freelist)\n", sb->fbuf.nfree); break; default: break; } } void allblocksdump(Dentry *dp){ int i; long block; for(i=0;;i++){ block=dnodebuf(dp,i); if(!block) break; blockdump(block, dp->size - (i*BUFSIZE)); } } void init(char *file){ int i; fd = open(file, O_RDONLY); if(fd<0) panic("open"); lseek(fd, 0, 0); i = read(fd, buf, sizeof buf); if(itag != Tsuper || tag->path != QPSUPER) panic("bad tag/path for superblock"); if(verbose) blockdump(0,0); getblock(rootblock); if(tag->tag != Tdir || tag->path != QPROOT) panic("bad tag/path for rootblock"); if(verbose) blockdump(0,0); } Dentry lookup(Dentry *dir, char *name){ int slot; Dentry *dp; Dentry ret; int i; long block; memset(&ret,0,sizeof(Dentry)); if(!(dir->mode & DALLOC)){ dprint("lookup: not DALLOC\n"); return ret; } dprint("lookup: looking for %s in %s\n",name,dir->name); for(i=0;;i++){ block=dnodebuf(dir,i); if(!block) break; getblock(block); if(tag->tag==Tdir){ for(slot=0;slotname)==0) return *dp; } }else{ dprint("lookup: %s points to tag!=Tdir\n",dir->name); break; } } return ret; } int main(int argc, char ** argv){ Dentry d, root; Dentry *curr=0; int found; char *name=0; if(argc<2) panic("bad args: usage: lkfs filesys name ..."); init(argv[1]); getblock(rootblock); memmove(&root,buf,sizeof(Dentry)); curr=&root; found=1; if(argc>2) for(name=strtok(argv[2],"/"); name; name=strtok(NULL,"/")){ found=0; d=lookup(curr,name); if(!(d.mode & DALLOC)){ dprint("main: not found: %s\n",name); break; } curr=&d; found=1; dprint("main: found %s\n",name); } if(found) allblocksdump(curr); else fprintf(stderr, "main: not found\n"); return 0; }