1 6e527fbc 2005-02-13 devnull #include "std.h"
2 6e527fbc 2005-02-13 devnull #include "dat.h"
7 6e527fbc 2005-02-13 devnull Qfactotum,
10 6e527fbc 2005-02-13 devnull Qprotolist,
11 6e527fbc 2005-02-13 devnull Qconfirm,
14 6e527fbc 2005-02-13 devnull Qneedkey,
18 6e527fbc 2005-02-13 devnull static int qtop;
21 6e527fbc 2005-02-13 devnull mkqid(int type, int path)
25 6e527fbc 2005-02-13 devnull q.type = type;
26 6e527fbc 2005-02-13 devnull q.path = path;
27 6e527fbc 2005-02-13 devnull q.vers = 0;
28 6e527fbc 2005-02-13 devnull return q;
31 6e527fbc 2005-02-13 devnull static struct
33 6e527fbc 2005-02-13 devnull char *name;
34 6e527fbc 2005-02-13 devnull int qidpath;
35 6e527fbc 2005-02-13 devnull ulong perm;
36 6e527fbc 2005-02-13 devnull } dirtab[] = {
37 6e527fbc 2005-02-13 devnull /* positions of confirm and needkey known below */
38 6e527fbc 2005-02-13 devnull "confirm", Qconfirm, 0600|DMEXCL,
39 6e527fbc 2005-02-13 devnull "needkey", Qneedkey, 0600|DMEXCL,
40 6e527fbc 2005-02-13 devnull "ctl", Qctl, 0600,
41 6e527fbc 2005-02-13 devnull "rpc", Qrpc, 0666,
42 6e527fbc 2005-02-13 devnull "proto", Qprotolist, 0444,
43 6e527fbc 2005-02-13 devnull "log", Qlog, 0600|DMEXCL,
44 cbeb0b26 2006-04-01 devnull "conv", Qconv, 0400
47 6e527fbc 2005-02-13 devnull static void
48 6e527fbc 2005-02-13 devnull fillstat(Dir *dir, char *name, int type, int path, ulong perm)
50 6e527fbc 2005-02-13 devnull dir->name = estrdup(name);
51 6e527fbc 2005-02-13 devnull dir->uid = estrdup(owner);
52 6e527fbc 2005-02-13 devnull dir->gid = estrdup(owner);
53 6e527fbc 2005-02-13 devnull dir->mode = perm;
54 6e527fbc 2005-02-13 devnull dir->length = 0;
55 6e527fbc 2005-02-13 devnull dir->qid = mkqid(type, path);
56 6e527fbc 2005-02-13 devnull dir->atime = time(0);
57 6e527fbc 2005-02-13 devnull dir->mtime = time(0);
58 6e527fbc 2005-02-13 devnull dir->muid = estrdup("");
61 6e527fbc 2005-02-13 devnull static int
62 6e527fbc 2005-02-13 devnull rootdirgen(int n, Dir *dir, void *v)
66 6e527fbc 2005-02-13 devnull if(n > 0)
67 6e527fbc 2005-02-13 devnull return -1;
69 6e527fbc 2005-02-13 devnull fillstat(dir, factname, QTDIR, Qfactotum, DMDIR|0555);
70 6e527fbc 2005-02-13 devnull return 0;
73 6e527fbc 2005-02-13 devnull static int
74 6e527fbc 2005-02-13 devnull fsdirgen(int n, Dir *dir, void *v)
78 6e527fbc 2005-02-13 devnull if(n >= nelem(dirtab))
79 6e527fbc 2005-02-13 devnull return -1;
80 6e527fbc 2005-02-13 devnull fillstat(dir, dirtab[n].name, 0, dirtab[n].qidpath, dirtab[n].perm);
81 6e527fbc 2005-02-13 devnull return 0;
84 6e527fbc 2005-02-13 devnull static char*
85 6e527fbc 2005-02-13 devnull fswalk1(Fid *fid, char *name, Qid *qid)
89 6e527fbc 2005-02-13 devnull switch((int)fid->qid.path){
91 6e527fbc 2005-02-13 devnull return "fswalk1: cannot happen";
92 6e527fbc 2005-02-13 devnull case Qroot:
93 6e527fbc 2005-02-13 devnull if(strcmp(name, factname) == 0){
94 6e527fbc 2005-02-13 devnull *qid = mkqid(QTDIR, Qfactotum);
95 6e527fbc 2005-02-13 devnull fid->qid = *qid;
96 6e527fbc 2005-02-13 devnull return nil;
98 6e527fbc 2005-02-13 devnull if(strcmp(name, "..") == 0){
99 6e527fbc 2005-02-13 devnull *qid = fid->qid;
100 6e527fbc 2005-02-13 devnull return nil;
102 6e527fbc 2005-02-13 devnull return "not found";
103 6e527fbc 2005-02-13 devnull case Qfactotum:
104 6e527fbc 2005-02-13 devnull for(i=0; i<nelem(dirtab); i++)
105 6e527fbc 2005-02-13 devnull if(strcmp(name, dirtab[i].name) == 0){
106 6e527fbc 2005-02-13 devnull *qid = mkqid(0, dirtab[i].qidpath);
107 6e527fbc 2005-02-13 devnull fid->qid = *qid;
108 6e527fbc 2005-02-13 devnull return nil;
110 6e527fbc 2005-02-13 devnull if(strcmp(name, "..") == 0){
111 6e527fbc 2005-02-13 devnull *qid = mkqid(QTDIR, qtop);
112 6e527fbc 2005-02-13 devnull fid->qid = *qid;
113 6e527fbc 2005-02-13 devnull return nil;
115 6e527fbc 2005-02-13 devnull return "not found";
119 6e527fbc 2005-02-13 devnull static void
120 6e527fbc 2005-02-13 devnull fsstat(Req *r)
122 6e527fbc 2005-02-13 devnull int i, path;
124 6e527fbc 2005-02-13 devnull path = r->fid->qid.path;
125 6e527fbc 2005-02-13 devnull switch(path){
126 6e527fbc 2005-02-13 devnull case Qroot:
127 6e527fbc 2005-02-13 devnull fillstat(&r->d, "/", QTDIR, Qroot, 0555|DMDIR);
129 6e527fbc 2005-02-13 devnull case Qfactotum:
130 6e527fbc 2005-02-13 devnull fillstat(&r->d, "factotum", QTDIR, Qfactotum, 0555|DMDIR);
132 6e527fbc 2005-02-13 devnull default:
133 6e527fbc 2005-02-13 devnull for(i=0; i<nelem(dirtab); i++)
134 6e527fbc 2005-02-13 devnull if(dirtab[i].qidpath == path){
135 6e527fbc 2005-02-13 devnull fillstat(&r->d, dirtab[i].name, 0, dirtab[i].qidpath, dirtab[i].perm);
136 6e527fbc 2005-02-13 devnull goto Break2;
138 6e527fbc 2005-02-13 devnull respond(r, "file not found");
142 6e527fbc 2005-02-13 devnull respond(r, nil);
145 6e527fbc 2005-02-13 devnull static int
146 6e527fbc 2005-02-13 devnull readlist(int off, int (*gen)(int, char*, uint), Req *r)
148 6e527fbc 2005-02-13 devnull char *a, *ea;
151 6e527fbc 2005-02-13 devnull a = r->ofcall.data;
152 6e527fbc 2005-02-13 devnull ea = a+r->ifcall.count;
153 6e527fbc 2005-02-13 devnull for(;;){
154 6e527fbc 2005-02-13 devnull n = (*gen)(off, a, ea-a);
155 6e527fbc 2005-02-13 devnull if(n == 0){
156 6e527fbc 2005-02-13 devnull r->ofcall.count = a - (char*)r->ofcall.data;
157 6e527fbc 2005-02-13 devnull return off;
162 bcac59d8 2005-08-11 devnull /* not reached */
165 6e527fbc 2005-02-13 devnull static int
166 6e527fbc 2005-02-13 devnull keylist(int i, char *a, uint nn)
169 ce94dbe6 2005-02-13 devnull char buf[4096];
172 6e527fbc 2005-02-13 devnull if(i >= ring.nkey)
173 6e527fbc 2005-02-13 devnull return 0;
175 6e527fbc 2005-02-13 devnull k = ring.key[i];
176 6e527fbc 2005-02-13 devnull k->attr = sortattr(k->attr);
177 6e527fbc 2005-02-13 devnull n = snprint(buf, sizeof buf, "key %A %N\n", k->attr, k->privattr);
178 6e527fbc 2005-02-13 devnull if(n >= sizeof(buf)-5)
179 6e527fbc 2005-02-13 devnull strcpy(buf+sizeof(buf)-5, "...\n");
180 6e527fbc 2005-02-13 devnull n = strlen(buf);
181 6e527fbc 2005-02-13 devnull if(n > nn)
182 6e527fbc 2005-02-13 devnull return 0;
183 6e527fbc 2005-02-13 devnull memmove(a, buf, n);
184 6e527fbc 2005-02-13 devnull return n;
187 6e527fbc 2005-02-13 devnull static int
188 6e527fbc 2005-02-13 devnull protolist(int i, char *a, uint n)
190 6e527fbc 2005-02-13 devnull if(prototab[i] == nil)
191 6e527fbc 2005-02-13 devnull return 0;
192 6e527fbc 2005-02-13 devnull if(strlen(prototab[i]->name)+1 > n)
193 6e527fbc 2005-02-13 devnull return 0;
194 6e527fbc 2005-02-13 devnull n = strlen(prototab[i]->name)+1;
195 6e527fbc 2005-02-13 devnull memmove(a, prototab[i]->name, n-1);
196 6e527fbc 2005-02-13 devnull a[n-1] = '\n';
197 6e527fbc 2005-02-13 devnull return n;
200 6e527fbc 2005-02-13 devnull /* BUG this is O(n^2) to fill in the list */
201 6e527fbc 2005-02-13 devnull static int
202 6e527fbc 2005-02-13 devnull convlist(int i, char *a, uint nn)
204 6e527fbc 2005-02-13 devnull Conv *c;
205 6e527fbc 2005-02-13 devnull char buf[512];
208 6e527fbc 2005-02-13 devnull for(c=conv; c && i-- > 0; c=c->next)
211 6e527fbc 2005-02-13 devnull if(c == nil)
212 6e527fbc 2005-02-13 devnull return 0;
214 6e527fbc 2005-02-13 devnull if(c->state)
215 6e527fbc 2005-02-13 devnull n = snprint(buf, sizeof buf, "conv state=%q %A\n", c->state, c->attr);
217 6e527fbc 2005-02-13 devnull n = snprint(buf, sizeof buf, "conv state=closed err=%q\n", c->err);
219 6e527fbc 2005-02-13 devnull if(n >= sizeof(buf)-5)
220 6e527fbc 2005-02-13 devnull strcpy(buf+sizeof(buf)-5, "...\n");
221 6e527fbc 2005-02-13 devnull n = strlen(buf);
222 6e527fbc 2005-02-13 devnull if(n > nn)
223 6e527fbc 2005-02-13 devnull return 0;
224 6e527fbc 2005-02-13 devnull memmove(a, buf, n);
225 6e527fbc 2005-02-13 devnull return n;
228 6e527fbc 2005-02-13 devnull static void
229 6e527fbc 2005-02-13 devnull fskickreply(Conv *c)
233 6e527fbc 2005-02-13 devnull if(c->hangup){
234 80097b01 2005-03-18 devnull if((r = c->req) != nil){
235 6e527fbc 2005-02-13 devnull c->req = nil;
236 80097b01 2005-03-18 devnull respond(r, "hangup");
241 6e527fbc 2005-02-13 devnull if(!c->req || !c->nreply)
244 6e527fbc 2005-02-13 devnull r = c->req;
245 6e527fbc 2005-02-13 devnull r->ofcall.count = c->nreply;
246 6e527fbc 2005-02-13 devnull r->ofcall.data = c->reply;
247 6e527fbc 2005-02-13 devnull if(r->ofcall.count > r->ifcall.count)
248 6e527fbc 2005-02-13 devnull r->ofcall.count = r->ifcall.count;
249 6e527fbc 2005-02-13 devnull c->req = nil;
250 80097b01 2005-03-18 devnull respond(r, nil);
251 6e527fbc 2005-02-13 devnull c->nreply = 0;
255 6e527fbc 2005-02-13 devnull * Some of the file system work happens in the fs proc, but
256 6e527fbc 2005-02-13 devnull * fsopen, fsread, fswrite, fsdestroyfid, and fsflush happen in
257 6e527fbc 2005-02-13 devnull * the main proc so that they can access the various shared
258 6e527fbc 2005-02-13 devnull * data structures without worrying about locking.
260 6e527fbc 2005-02-13 devnull static int inuse[nelem(dirtab)];
261 6e527fbc 2005-02-13 devnull int *confirminuse = &inuse[0];
262 6e527fbc 2005-02-13 devnull int *needkeyinuse = &inuse[1];
263 6e527fbc 2005-02-13 devnull static void
264 6e527fbc 2005-02-13 devnull fsopen(Req *r)
266 6e527fbc 2005-02-13 devnull int i, *inusep, perm;
267 6e527fbc 2005-02-13 devnull static int need[4] = { 4, 2, 6, 1 };
268 6e527fbc 2005-02-13 devnull Conv *c;
270 6e527fbc 2005-02-13 devnull inusep = nil;
271 6e527fbc 2005-02-13 devnull perm = 5; /* directory */
272 6e527fbc 2005-02-13 devnull for(i=0; i<nelem(dirtab); i++)
273 6e527fbc 2005-02-13 devnull if(dirtab[i].qidpath == r->fid->qid.path){
274 6e527fbc 2005-02-13 devnull if(dirtab[i].perm & DMEXCL)
275 6e527fbc 2005-02-13 devnull inusep = &inuse[i];
276 6e527fbc 2005-02-13 devnull if(strcmp(r->fid->uid, owner) == 0)
277 6e527fbc 2005-02-13 devnull perm = dirtab[i].perm>>6;
279 6e527fbc 2005-02-13 devnull perm = dirtab[i].perm;
283 6e527fbc 2005-02-13 devnull if((r->ifcall.mode&~(OMASK|OTRUNC))
284 6e527fbc 2005-02-13 devnull || (need[r->ifcall.mode&3] & ~perm)){
285 6e527fbc 2005-02-13 devnull respond(r, "permission denied");
289 6e527fbc 2005-02-13 devnull if(inusep){
290 6e527fbc 2005-02-13 devnull if(*inusep){
291 6e527fbc 2005-02-13 devnull respond(r, "file in use");
294 6e527fbc 2005-02-13 devnull *inusep = 1;
297 6e527fbc 2005-02-13 devnull if(r->fid->qid.path == Qrpc){
298 6e527fbc 2005-02-13 devnull if((c = convalloc(r->fid->uid)) == nil){
299 6e527fbc 2005-02-13 devnull char e[ERRMAX];
301 6e527fbc 2005-02-13 devnull rerrstr(e, sizeof e);
302 6e527fbc 2005-02-13 devnull respond(r, e);
305 6e527fbc 2005-02-13 devnull c->kickreply = fskickreply;
306 6e527fbc 2005-02-13 devnull r->fid->aux = c;
309 6e527fbc 2005-02-13 devnull respond(r, nil);
312 6e527fbc 2005-02-13 devnull static void
313 6e527fbc 2005-02-13 devnull fsread(Req *r)
315 6e527fbc 2005-02-13 devnull Conv *c;
317 6e527fbc 2005-02-13 devnull switch((int)r->fid->qid.path){
318 6e527fbc 2005-02-13 devnull default:
319 6e527fbc 2005-02-13 devnull respond(r, "fsread: cannot happen");
321 6e527fbc 2005-02-13 devnull case Qroot:
322 6e527fbc 2005-02-13 devnull dirread9p(r, rootdirgen, nil);
323 6e527fbc 2005-02-13 devnull respond(r, nil);
325 6e527fbc 2005-02-13 devnull case Qfactotum:
326 6e527fbc 2005-02-13 devnull dirread9p(r, fsdirgen, nil);
327 6e527fbc 2005-02-13 devnull respond(r, nil);
329 6e527fbc 2005-02-13 devnull case Qrpc:
330 6e527fbc 2005-02-13 devnull c = r->fid->aux;
331 6e527fbc 2005-02-13 devnull if(c->rpc.op == RpcUnknown){
332 6e527fbc 2005-02-13 devnull respond(r, "no rpc pending");
335 6e527fbc 2005-02-13 devnull if(c->req){
336 6e527fbc 2005-02-13 devnull respond(r, "read already pending");
339 6e527fbc 2005-02-13 devnull c->req = r;
340 6e527fbc 2005-02-13 devnull if(c->nreply)
341 6e527fbc 2005-02-13 devnull (*c->kickreply)(c);
343 6e527fbc 2005-02-13 devnull rpcexec(c);
345 6e527fbc 2005-02-13 devnull case Qconfirm:
346 6e527fbc 2005-02-13 devnull confirmread(r);
348 6e527fbc 2005-02-13 devnull case Qlog:
349 6e527fbc 2005-02-13 devnull logread(r);
351 6e527fbc 2005-02-13 devnull case Qctl:
352 0870ded1 2006-02-14 devnull r->fid->aux = (void*)(uintptr)readlist((uintptr)r->fid->aux, keylist, r);
353 6e527fbc 2005-02-13 devnull respond(r, nil);
355 6e527fbc 2005-02-13 devnull case Qneedkey:
356 6e527fbc 2005-02-13 devnull needkeyread(r);
358 6e527fbc 2005-02-13 devnull case Qprotolist:
359 0870ded1 2006-02-14 devnull r->fid->aux = (void*)(uintptr)readlist((uintptr)r->fid->aux, protolist, r);
360 6e527fbc 2005-02-13 devnull respond(r, nil);
362 6e527fbc 2005-02-13 devnull case Qconv:
363 0870ded1 2006-02-14 devnull r->fid->aux = (void*)(uintptr)readlist((uintptr)r->fid->aux, convlist, r);
364 6e527fbc 2005-02-13 devnull respond(r, nil);
369 6e527fbc 2005-02-13 devnull static void
370 6e527fbc 2005-02-13 devnull fswrite(Req *r)
372 6e527fbc 2005-02-13 devnull int ret;
373 6e527fbc 2005-02-13 devnull char err[ERRMAX], *s;
374 6e527fbc 2005-02-13 devnull int (*strfn)(char*);
377 6e527fbc 2005-02-13 devnull switch((int)r->fid->qid.path){
378 6e527fbc 2005-02-13 devnull default:
379 6e527fbc 2005-02-13 devnull respond(r, "fswrite: cannot happen");
381 6e527fbc 2005-02-13 devnull case Qrpc:
382 6e527fbc 2005-02-13 devnull if(rpcwrite(r->fid->aux, r->ifcall.data, r->ifcall.count) < 0){
383 6e527fbc 2005-02-13 devnull rerrstr(err, sizeof err);
384 6e527fbc 2005-02-13 devnull respond(r, err);
386 6e527fbc 2005-02-13 devnull r->ofcall.count = r->ifcall.count;
387 6e527fbc 2005-02-13 devnull respond(r, nil);
390 6e527fbc 2005-02-13 devnull case Qneedkey:
391 5f6612ba 2008-05-31 rsc name = "needkey";
392 6e527fbc 2005-02-13 devnull strfn = needkeywrite;
393 6e527fbc 2005-02-13 devnull goto string;
394 6e527fbc 2005-02-13 devnull case Qctl:
395 5f6612ba 2008-05-31 rsc name = "ctl";
396 6e527fbc 2005-02-13 devnull strfn = ctlwrite;
397 6e527fbc 2005-02-13 devnull goto string;
398 6e527fbc 2005-02-13 devnull case Qconfirm:
399 5f6612ba 2008-05-31 rsc name = "confirm";
400 6e527fbc 2005-02-13 devnull strfn = confirmwrite;
402 6e527fbc 2005-02-13 devnull s = emalloc(r->ifcall.count+1);
403 6e527fbc 2005-02-13 devnull memmove(s, r->ifcall.data, r->ifcall.count);
404 6e527fbc 2005-02-13 devnull s[r->ifcall.count] = '\0';
405 6e527fbc 2005-02-13 devnull ret = (*strfn)(s);
406 6e527fbc 2005-02-13 devnull free(s);
407 6e527fbc 2005-02-13 devnull if(ret < 0){
408 6e527fbc 2005-02-13 devnull rerrstr(err, sizeof err);
409 6e527fbc 2005-02-13 devnull respond(r, err);
410 5f6612ba 2008-05-31 rsc flog("write %s: %s", name, err);
412 6e527fbc 2005-02-13 devnull r->ofcall.count = r->ifcall.count;
413 6e527fbc 2005-02-13 devnull respond(r, nil);
419 6e527fbc 2005-02-13 devnull static void
420 6e527fbc 2005-02-13 devnull fsflush(Req *r)
422 9d4f8bfe 2012-07-14 rsc confirmflush(r->oldreq);
423 9d4f8bfe 2012-07-14 rsc logflush(r->oldreq);
424 9d4f8bfe 2012-07-14 rsc respond(r, nil);
427 6e527fbc 2005-02-13 devnull static void
428 6e527fbc 2005-02-13 devnull fsdestroyfid(Fid *fid)
430 6e527fbc 2005-02-13 devnull if(fid->qid.path == Qrpc && fid->aux){
431 6e527fbc 2005-02-13 devnull convhangup(fid->aux);
432 6e527fbc 2005-02-13 devnull convclose(fid->aux);
436 6e527fbc 2005-02-13 devnull static Channel *creq;
437 6e527fbc 2005-02-13 devnull static Channel *cfid, *cfidr;
439 6e527fbc 2005-02-13 devnull static void
440 6e527fbc 2005-02-13 devnull fsreqthread(void *v)
444 6e527fbc 2005-02-13 devnull USED(v);
446 6e527fbc 2005-02-13 devnull while((r = recvp(creq)) != nil){
447 6e527fbc 2005-02-13 devnull switch(r->ifcall.type){
448 6e527fbc 2005-02-13 devnull default:
449 6e527fbc 2005-02-13 devnull respond(r, "bug in fsreqthread");
451 6e527fbc 2005-02-13 devnull case Topen:
452 6e527fbc 2005-02-13 devnull fsopen(r);
454 6e527fbc 2005-02-13 devnull case Tread:
455 6e527fbc 2005-02-13 devnull fsread(r);
457 6e527fbc 2005-02-13 devnull case Twrite:
458 6e527fbc 2005-02-13 devnull fswrite(r);
460 6e527fbc 2005-02-13 devnull case Tflush:
461 6e527fbc 2005-02-13 devnull fsflush(r);
467 6e527fbc 2005-02-13 devnull static void
468 6e527fbc 2005-02-13 devnull fsclunkthread(void *v)
472 6e527fbc 2005-02-13 devnull USED(v);
474 6e527fbc 2005-02-13 devnull while((f = recvp(cfid)) != nil){
475 6e527fbc 2005-02-13 devnull fsdestroyfid(f);
476 6e527fbc 2005-02-13 devnull sendp(cfidr, 0);
480 6e527fbc 2005-02-13 devnull static void
481 6e527fbc 2005-02-13 devnull fsproc(void *v)
483 6e527fbc 2005-02-13 devnull USED(v);
485 6e527fbc 2005-02-13 devnull threadcreate(fsreqthread, nil, STACK);
486 6e527fbc 2005-02-13 devnull threadcreate(fsclunkthread, nil, STACK);
487 6e527fbc 2005-02-13 devnull threadexits(nil);
490 6e527fbc 2005-02-13 devnull static void
491 6e527fbc 2005-02-13 devnull fsattach(Req *r)
493 6e527fbc 2005-02-13 devnull r->fid->qid = mkqid(QTDIR, qtop);
494 6e527fbc 2005-02-13 devnull r->ofcall.qid = r->fid->qid;
495 6e527fbc 2005-02-13 devnull respond(r, nil);
498 6e527fbc 2005-02-13 devnull static void
499 6e527fbc 2005-02-13 devnull fssend(Req *r)
501 6e527fbc 2005-02-13 devnull sendp(creq, r);
504 6e527fbc 2005-02-13 devnull static void
505 6e527fbc 2005-02-13 devnull fssendclunk(Fid *f)
507 6e527fbc 2005-02-13 devnull sendp(cfid, f);
508 6e527fbc 2005-02-13 devnull recvp(cfidr);
512 6e527fbc 2005-02-13 devnull fsstart(Srv *s)
514 6e527fbc 2005-02-13 devnull USED(s);
516 6e527fbc 2005-02-13 devnull if(extrafactotumdir)
517 6e527fbc 2005-02-13 devnull qtop = Qroot;
519 6e527fbc 2005-02-13 devnull qtop = Qfactotum;
520 6e527fbc 2005-02-13 devnull creq = chancreate(sizeof(Req*), 0);
521 6e527fbc 2005-02-13 devnull cfid = chancreate(sizeof(Fid*), 0);
522 6e527fbc 2005-02-13 devnull cfidr = chancreate(sizeof(Fid*), 0);
523 6e527fbc 2005-02-13 devnull proccreate(fsproc, nil, STACK);
529 b3e7c026 2005-03-15 devnull fsinit0(void)
531 b3e7c026 2005-03-15 devnull fs.attach = fsattach;
532 b3e7c026 2005-03-15 devnull fs.walk1 = fswalk1;
533 b3e7c026 2005-03-15 devnull fs.open = fssend;
534 b3e7c026 2005-03-15 devnull fs.read = fssend;
535 b3e7c026 2005-03-15 devnull fs.write = fssend;
536 b3e7c026 2005-03-15 devnull fs.stat = fsstat;
537 b3e7c026 2005-03-15 devnull fs.flush = fssend;
538 b3e7c026 2005-03-15 devnull fs.destroyfid = fssendclunk;
539 b3e7c026 2005-03-15 devnull fs.start = fsstart;