1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "fs.h"
7*74a4d8c2SCharles.Forsyth
8*74a4d8c2SCharles.Forsyth typedef struct Tag Tag;
9*74a4d8c2SCharles.Forsyth
10*74a4d8c2SCharles.Forsyth /*
11*74a4d8c2SCharles.Forsyth * tags on block
12*74a4d8c2SCharles.Forsyth */
13*74a4d8c2SCharles.Forsyth enum
14*74a4d8c2SCharles.Forsyth {
15*74a4d8c2SCharles.Forsyth Tnone = 0,
16*74a4d8c2SCharles.Forsyth Tsuper, /* the super block */
17*74a4d8c2SCharles.Forsyth Tdir, /* directory contents */
18*74a4d8c2SCharles.Forsyth Tind1, /* points to blocks */
19*74a4d8c2SCharles.Forsyth Tind2, /* points to Tind1 */
20*74a4d8c2SCharles.Forsyth Tfile, /* file contents */
21*74a4d8c2SCharles.Forsyth Tfree, /* in free list */
22*74a4d8c2SCharles.Forsyth Tbuck, /* cache fs bucket */
23*74a4d8c2SCharles.Forsyth Tvirgo, /* fake worm virgin bits */
24*74a4d8c2SCharles.Forsyth Tcache, /* cw cache things */
25*74a4d8c2SCharles.Forsyth MAXTAG
26*74a4d8c2SCharles.Forsyth };
27*74a4d8c2SCharles.Forsyth
28*74a4d8c2SCharles.Forsyth #define QPDIR 0x80000000L
29*74a4d8c2SCharles.Forsyth #define QPNONE 0
30*74a4d8c2SCharles.Forsyth #define QPROOT 1
31*74a4d8c2SCharles.Forsyth #define QPSUPER 2
32*74a4d8c2SCharles.Forsyth
33*74a4d8c2SCharles.Forsyth /* DONT TOUCH, this is the disk structure */
34*74a4d8c2SCharles.Forsyth struct Tag
35*74a4d8c2SCharles.Forsyth {
36*74a4d8c2SCharles.Forsyth short pad;
37*74a4d8c2SCharles.Forsyth short tag;
38*74a4d8c2SCharles.Forsyth long path;
39*74a4d8c2SCharles.Forsyth };
40*74a4d8c2SCharles.Forsyth
41*74a4d8c2SCharles.Forsyth static int thisblock = -1;
42*74a4d8c2SCharles.Forsyth static Fs *thisfs;
43*74a4d8c2SCharles.Forsyth static uchar *block;
44*74a4d8c2SCharles.Forsyth
45*74a4d8c2SCharles.Forsyth /*
46*74a4d8c2SCharles.Forsyth * we end up reading 2x or 3x the number of blocks we need to read.
47*74a4d8c2SCharles.Forsyth * this is okay because we need to read so few. if it wasn't okay, we could
48*74a4d8c2SCharles.Forsyth * have getblock return a pointer to a block, and keep a cache of the last
49*74a4d8c2SCharles.Forsyth * three read blocks. that would get us down to the minimum.
50*74a4d8c2SCharles.Forsyth * but this is fine.
51*74a4d8c2SCharles.Forsyth */
52*74a4d8c2SCharles.Forsyth static int
getblock(Fs * fs,ulong n)53*74a4d8c2SCharles.Forsyth getblock(Fs *fs, ulong n)
54*74a4d8c2SCharles.Forsyth {
55*74a4d8c2SCharles.Forsyth if(!block)
56*74a4d8c2SCharles.Forsyth block = malloc(16384);
57*74a4d8c2SCharles.Forsyth
58*74a4d8c2SCharles.Forsyth if(thisblock == n && thisfs == fs)
59*74a4d8c2SCharles.Forsyth return 0;
60*74a4d8c2SCharles.Forsyth thisblock = -1;
61*74a4d8c2SCharles.Forsyth if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0)
62*74a4d8c2SCharles.Forsyth return -1;
63*74a4d8c2SCharles.Forsyth if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE)
64*74a4d8c2SCharles.Forsyth return -1;
65*74a4d8c2SCharles.Forsyth thisblock = n;
66*74a4d8c2SCharles.Forsyth thisfs = fs;
67*74a4d8c2SCharles.Forsyth
68*74a4d8c2SCharles.Forsyth return 1;
69*74a4d8c2SCharles.Forsyth }
70*74a4d8c2SCharles.Forsyth
71*74a4d8c2SCharles.Forsyth static int
checktag(Fs * fs,uchar * block,int tag,long qpath)72*74a4d8c2SCharles.Forsyth checktag(Fs *fs, uchar *block, int tag, long qpath)
73*74a4d8c2SCharles.Forsyth {
74*74a4d8c2SCharles.Forsyth Tag *t;
75*74a4d8c2SCharles.Forsyth
76*74a4d8c2SCharles.Forsyth t = (Tag*)(block+fs->kfs.BUFSIZE);
77*74a4d8c2SCharles.Forsyth if(t->tag != tag)
78*74a4d8c2SCharles.Forsyth return -1;
79*74a4d8c2SCharles.Forsyth if(qpath != QPNONE && (qpath&~QPDIR) != t->path)
80*74a4d8c2SCharles.Forsyth return -1;
81*74a4d8c2SCharles.Forsyth return 1;
82*74a4d8c2SCharles.Forsyth }
83*74a4d8c2SCharles.Forsyth
84*74a4d8c2SCharles.Forsyth static int
getblocktag(Fs * fs,ulong n,int tag,long qpath)85*74a4d8c2SCharles.Forsyth getblocktag(Fs *fs, ulong n, int tag, long qpath)
86*74a4d8c2SCharles.Forsyth {
87*74a4d8c2SCharles.Forsyth if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0)
88*74a4d8c2SCharles.Forsyth return -1;
89*74a4d8c2SCharles.Forsyth return 1;
90*74a4d8c2SCharles.Forsyth }
91*74a4d8c2SCharles.Forsyth
92*74a4d8c2SCharles.Forsyth static int
readinfo(Fs * fs)93*74a4d8c2SCharles.Forsyth readinfo(Fs *fs)
94*74a4d8c2SCharles.Forsyth {
95*74a4d8c2SCharles.Forsyth fs->kfs.RBUFSIZE = 512;
96*74a4d8c2SCharles.Forsyth if(getblock(fs, 0) < 0)
97*74a4d8c2SCharles.Forsyth return -1;
98*74a4d8c2SCharles.Forsyth
99*74a4d8c2SCharles.Forsyth if(memcmp(block+256, "kfs wren device\n", 16) != 0)
100*74a4d8c2SCharles.Forsyth return -1;
101*74a4d8c2SCharles.Forsyth
102*74a4d8c2SCharles.Forsyth fs->kfs.RBUFSIZE = atoi((char*)block+256+16);
103*74a4d8c2SCharles.Forsyth if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1)))
104*74a4d8c2SCharles.Forsyth return -1;
105*74a4d8c2SCharles.Forsyth
106*74a4d8c2SCharles.Forsyth fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag);
107*74a4d8c2SCharles.Forsyth fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry);
108*74a4d8c2SCharles.Forsyth fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long);
109*74a4d8c2SCharles.Forsyth fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF;
110*74a4d8c2SCharles.Forsyth
111*74a4d8c2SCharles.Forsyth return 1;
112*74a4d8c2SCharles.Forsyth }
113*74a4d8c2SCharles.Forsyth
114*74a4d8c2SCharles.Forsyth static int
readroot(Fs * fs,Dentry * d)115*74a4d8c2SCharles.Forsyth readroot(Fs *fs, Dentry *d)
116*74a4d8c2SCharles.Forsyth {
117*74a4d8c2SCharles.Forsyth Dentry *d2;
118*74a4d8c2SCharles.Forsyth
119*74a4d8c2SCharles.Forsyth if(getblocktag(fs, 2, Tdir, QPROOT) < 0)
120*74a4d8c2SCharles.Forsyth return -1;
121*74a4d8c2SCharles.Forsyth d2 = (Dentry*)block;
122*74a4d8c2SCharles.Forsyth if(strcmp(d2->name, "/") != 0)
123*74a4d8c2SCharles.Forsyth return -1;
124*74a4d8c2SCharles.Forsyth *d = *(Dentry*)block;
125*74a4d8c2SCharles.Forsyth return 1;
126*74a4d8c2SCharles.Forsyth }
127*74a4d8c2SCharles.Forsyth
128*74a4d8c2SCharles.Forsyth static long
indfetch(Fs * fs,long addr,long off,int tag,long path)129*74a4d8c2SCharles.Forsyth indfetch(Fs *fs, long addr, long off, int tag, long path)
130*74a4d8c2SCharles.Forsyth {
131*74a4d8c2SCharles.Forsyth if(getblocktag(fs, addr, tag, path) < 0)
132*74a4d8c2SCharles.Forsyth return -1;
133*74a4d8c2SCharles.Forsyth return ((long*)block)[off];
134*74a4d8c2SCharles.Forsyth }
135*74a4d8c2SCharles.Forsyth
136*74a4d8c2SCharles.Forsyth static long
rel2abs(Fs * fs,Dentry * d,long a)137*74a4d8c2SCharles.Forsyth rel2abs(Fs *fs, Dentry *d, long a)
138*74a4d8c2SCharles.Forsyth {
139*74a4d8c2SCharles.Forsyth long addr;
140*74a4d8c2SCharles.Forsyth
141*74a4d8c2SCharles.Forsyth if(a < NDBLOCK)
142*74a4d8c2SCharles.Forsyth return d->dblock[a];
143*74a4d8c2SCharles.Forsyth a -= NDBLOCK;
144*74a4d8c2SCharles.Forsyth if(a < fs->kfs.INDPERBUF){
145*74a4d8c2SCharles.Forsyth if(d->iblock == 0)
146*74a4d8c2SCharles.Forsyth return 0;
147*74a4d8c2SCharles.Forsyth addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path);
148*74a4d8c2SCharles.Forsyth if(addr == 0)
149*74a4d8c2SCharles.Forsyth print("rel2abs indfetch 0 %s %ld\n", d->name, a);
150*74a4d8c2SCharles.Forsyth return addr;
151*74a4d8c2SCharles.Forsyth }
152*74a4d8c2SCharles.Forsyth a -= fs->kfs.INDPERBUF;
153*74a4d8c2SCharles.Forsyth if(a < fs->kfs.INDPERBUF2){
154*74a4d8c2SCharles.Forsyth if(d->diblock == 0)
155*74a4d8c2SCharles.Forsyth return 0;
156*74a4d8c2SCharles.Forsyth addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path);
157*74a4d8c2SCharles.Forsyth if(addr == 0){
158*74a4d8c2SCharles.Forsyth print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF);
159*74a4d8c2SCharles.Forsyth return 0;
160*74a4d8c2SCharles.Forsyth }
161*74a4d8c2SCharles.Forsyth addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path);
162*74a4d8c2SCharles.Forsyth return addr;
163*74a4d8c2SCharles.Forsyth }
164*74a4d8c2SCharles.Forsyth print("rel2abs trip ind %s %ld\n", d->name, a);
165*74a4d8c2SCharles.Forsyth return -1;
166*74a4d8c2SCharles.Forsyth }
167*74a4d8c2SCharles.Forsyth
168*74a4d8c2SCharles.Forsyth static int
readdentry(Fs * fs,Dentry * d,int n,Dentry * e)169*74a4d8c2SCharles.Forsyth readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
170*74a4d8c2SCharles.Forsyth {
171*74a4d8c2SCharles.Forsyth long addr, m;
172*74a4d8c2SCharles.Forsyth
173*74a4d8c2SCharles.Forsyth m = n/fs->kfs.DIRPERBUF;
174*74a4d8c2SCharles.Forsyth if((addr = rel2abs(fs, d, m)) <= 0)
175*74a4d8c2SCharles.Forsyth return addr;
176*74a4d8c2SCharles.Forsyth if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
177*74a4d8c2SCharles.Forsyth return -1;
178*74a4d8c2SCharles.Forsyth *e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
179*74a4d8c2SCharles.Forsyth return 1;
180*74a4d8c2SCharles.Forsyth }
181*74a4d8c2SCharles.Forsyth
182*74a4d8c2SCharles.Forsyth static int
getdatablock(Fs * fs,Dentry * d,long a)183*74a4d8c2SCharles.Forsyth getdatablock(Fs *fs, Dentry *d, long a)
184*74a4d8c2SCharles.Forsyth {
185*74a4d8c2SCharles.Forsyth long addr;
186*74a4d8c2SCharles.Forsyth
187*74a4d8c2SCharles.Forsyth if((addr = rel2abs(fs, d, a)) == 0)
188*74a4d8c2SCharles.Forsyth return -1;
189*74a4d8c2SCharles.Forsyth return getblocktag(fs, addr, Tfile, QPNONE);
190*74a4d8c2SCharles.Forsyth }
191*74a4d8c2SCharles.Forsyth
192*74a4d8c2SCharles.Forsyth static int
walk(Fs * fs,Dentry * d,char * name,Dentry * e)193*74a4d8c2SCharles.Forsyth walk(Fs *fs, Dentry *d, char *name, Dentry *e)
194*74a4d8c2SCharles.Forsyth {
195*74a4d8c2SCharles.Forsyth int i, n;
196*74a4d8c2SCharles.Forsyth Dentry x;
197*74a4d8c2SCharles.Forsyth
198*74a4d8c2SCharles.Forsyth for(i=0;; i++){
199*74a4d8c2SCharles.Forsyth if((n=readdentry(fs, d, i, &x)) <= 0)
200*74a4d8c2SCharles.Forsyth return n;
201*74a4d8c2SCharles.Forsyth if(strcmp(x.name, name) == 0){
202*74a4d8c2SCharles.Forsyth *e = x;
203*74a4d8c2SCharles.Forsyth return 1;
204*74a4d8c2SCharles.Forsyth }
205*74a4d8c2SCharles.Forsyth }
206*74a4d8c2SCharles.Forsyth }
207*74a4d8c2SCharles.Forsyth
208*74a4d8c2SCharles.Forsyth static long
kfsread(File * f,void * va,long len)209*74a4d8c2SCharles.Forsyth kfsread(File *f, void *va, long len)
210*74a4d8c2SCharles.Forsyth {
211*74a4d8c2SCharles.Forsyth uchar *a;
212*74a4d8c2SCharles.Forsyth long tot, off, o, n;
213*74a4d8c2SCharles.Forsyth Fs *fs;
214*74a4d8c2SCharles.Forsyth
215*74a4d8c2SCharles.Forsyth a = va;
216*74a4d8c2SCharles.Forsyth fs = f->fs;
217*74a4d8c2SCharles.Forsyth off = f->kfs.off;
218*74a4d8c2SCharles.Forsyth tot = 0;
219*74a4d8c2SCharles.Forsyth while(tot < len){
220*74a4d8c2SCharles.Forsyth if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0)
221*74a4d8c2SCharles.Forsyth return -1;
222*74a4d8c2SCharles.Forsyth o = off%fs->kfs.BUFSIZE;
223*74a4d8c2SCharles.Forsyth n = fs->kfs.BUFSIZE - o;
224*74a4d8c2SCharles.Forsyth if(n > len-tot)
225*74a4d8c2SCharles.Forsyth n = len-tot;
226*74a4d8c2SCharles.Forsyth memmove(a+tot, block+o, n);
227*74a4d8c2SCharles.Forsyth off += n;
228*74a4d8c2SCharles.Forsyth tot += n;
229*74a4d8c2SCharles.Forsyth }
230*74a4d8c2SCharles.Forsyth f->kfs.off = off;
231*74a4d8c2SCharles.Forsyth return tot;
232*74a4d8c2SCharles.Forsyth }
233*74a4d8c2SCharles.Forsyth
234*74a4d8c2SCharles.Forsyth static int
kfswalk(File * f,char * name)235*74a4d8c2SCharles.Forsyth kfswalk(File *f, char *name)
236*74a4d8c2SCharles.Forsyth {
237*74a4d8c2SCharles.Forsyth int n;
238*74a4d8c2SCharles.Forsyth
239*74a4d8c2SCharles.Forsyth n = walk(f->fs, &f->kfs, name, &f->kfs);
240*74a4d8c2SCharles.Forsyth if(n < 0)
241*74a4d8c2SCharles.Forsyth return -1;
242*74a4d8c2SCharles.Forsyth f->kfs.off = 0;
243*74a4d8c2SCharles.Forsyth return 1;
244*74a4d8c2SCharles.Forsyth }
245*74a4d8c2SCharles.Forsyth
246*74a4d8c2SCharles.Forsyth int
kfsinit(Fs * fs)247*74a4d8c2SCharles.Forsyth kfsinit(Fs *fs)
248*74a4d8c2SCharles.Forsyth {
249*74a4d8c2SCharles.Forsyth if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0)
250*74a4d8c2SCharles.Forsyth return -1;
251*74a4d8c2SCharles.Forsyth
252*74a4d8c2SCharles.Forsyth fs->root.fs = fs;
253*74a4d8c2SCharles.Forsyth fs->read = kfsread;
254*74a4d8c2SCharles.Forsyth fs->walk = kfswalk;
255*74a4d8c2SCharles.Forsyth return 0;
256*74a4d8c2SCharles.Forsyth }
257