📄 kfsboot.c
字号:
#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "fs.h"typedef struct Tag Tag;/* * tags on block */enum{ Tnone = 0, Tsuper, /* the super block */ Tdir, /* directory contents */ Tind1, /* points to blocks */ Tind2, /* points to Tind1 */ Tfile, /* file contents */ Tfree, /* in free list */ Tbuck, /* cache fs bucket */ Tvirgo, /* fake worm virgin bits */ Tcache, /* cw cache things */ MAXTAG};#define QPDIR 0x80000000L#define QPNONE 0#define QPROOT 1#define QPSUPER 2/* DONT TOUCH, this is the disk structure */struct Tag{ short pad; short tag; long path;};static int thisblock = -1;static Fs *thisfs;static uchar *block;/* * we end up reading 2x or 3x the number of blocks we need to read. * this is okay because we need to read so few. if it wasn't okay, we could * have getblock return a pointer to a block, and keep a cache of the last * three read blocks. that would get us down to the minimum. * but this is fine. */static intgetblock(Fs *fs, ulong n){ if(!block) block = malloc(16384); if(thisblock == n && thisfs == fs) return 0; thisblock = -1; if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0) return -1; if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE) return -1; thisblock = n; thisfs = fs; return 1;}static intchecktag(Fs *fs, uchar *block, int tag, long qpath){ Tag *t; t = (Tag*)(block+fs->kfs.BUFSIZE); if(t->tag != tag) return -1; if(qpath != QPNONE && (qpath&~QPDIR) != t->path) return -1; return 1;}static intgetblocktag(Fs *fs, ulong n, int tag, long qpath){ if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0) return -1; return 1;}static intreadinfo(Fs *fs){ fs->kfs.RBUFSIZE = 512; if(getblock(fs, 0) < 0) return -1; if(memcmp(block+256, "kfs wren device\n", 16) != 0) return -1; fs->kfs.RBUFSIZE = atoi((char*)block+256+16); if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1))) return -1; fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag); fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry); fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long); fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF; return 1;}static intreadroot(Fs *fs, Dentry *d){ Dentry *d2; if(getblocktag(fs, 2, Tdir, QPROOT) < 0) return -1; d2 = (Dentry*)block; if(strcmp(d2->name, "/") != 0) return -1; *d = *(Dentry*)block; return 1;}static longindfetch(Fs *fs, long addr, long off, int tag, long path){ if(getblocktag(fs, addr, tag, path) < 0) return -1; return ((long*)block)[off];}static longrel2abs(Fs *fs, Dentry *d, long a){ long addr; if(a < NDBLOCK) return d->dblock[a]; a -= NDBLOCK; if(a < fs->kfs.INDPERBUF){ if(d->iblock == 0) return 0; addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path); if(addr == 0) print("rel2abs indfetch 0 %s %ld\n", d->name, a); return addr; } a -= fs->kfs.INDPERBUF; if(a < fs->kfs.INDPERBUF2){ if(d->diblock == 0) return 0; addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path); if(addr == 0){ print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF); return 0; } addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path); return addr; } print("rel2abs trip ind %s %ld\n", d->name, a); return -1;}static intreaddentry(Fs *fs, Dentry *d, int n, Dentry *e){ long addr, m; m = n/fs->kfs.DIRPERBUF; if((addr = rel2abs(fs, d, m)) <= 0) return addr; if(getblocktag(fs, addr, Tdir, d->qid.path) < 0) return -1; *e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry)); return 1;}static intgetdatablock(Fs *fs, Dentry *d, long a){ long addr; if((addr = rel2abs(fs, d, a)) == 0) return -1; return getblocktag(fs, addr, Tfile, QPNONE);}static intwalk(Fs *fs, Dentry *d, char *name, Dentry *e){ int i, n; Dentry x; for(i=0;; i++){ if((n=readdentry(fs, d, i, &x)) <= 0) return n; if(strcmp(x.name, name) == 0){ *e = x; return 1; } }}static longkfsread(File *f, void *va, long len){ uchar *a; long tot, off, o, n; Fs *fs; a = va; fs = f->fs; off = f->kfs.off; tot = 0; while(tot < len){ if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0) return -1; o = off%fs->kfs.BUFSIZE; n = fs->kfs.BUFSIZE - o; if(n > len-tot) n = len-tot; memmove(a+tot, block+o, n); off += n; tot += n; } f->kfs.off = off; return tot;}static intkfswalk(File *f, char *name){ int n; n = walk(f->fs, &f->kfs, name, &f->kfs); if(n < 0) return -1; f->kfs.off = 0; return 1;}intkfsinit(Fs *fs){ if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0) return -1; fs->root.fs = fs; fs->read = kfsread; fs->walk = kfswalk; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -