21 mkqid(int type, int path)
37 /* positions of confirm and needkey known below */
38 "confirm", Qconfirm, 0600|DMEXCL,
39 "needkey", Qneedkey, 0600|DMEXCL,
42 "proto", Qprotolist, 0444,
43 "log", Qlog, 0600|DMEXCL,
48 fillstat(Dir *dir, char *name, int type, int path, ulong perm)
50 dir->name = estrdup(name);
51 dir->uid = estrdup(owner);
52 dir->gid = estrdup(owner);
55 dir->qid = mkqid(type, path);
58 dir->muid = estrdup("");
62 rootdirgen(int n, Dir *dir, void *v)
69 fillstat(dir, factname, QTDIR, Qfactotum, DMDIR|0555);
74 fsdirgen(int n, Dir *dir, void *v)
78 if(n >= nelem(dirtab))
80 fillstat(dir, dirtab[n].name, 0, dirtab[n].qidpath, dirtab[n].perm);
85 fswalk1(Fid *fid, char *name, Qid *qid)
89 switch((int)fid->qid.path){
91 return "fswalk1: cannot happen";
93 if(strcmp(name, factname) == 0){
94 *qid = mkqid(QTDIR, Qfactotum);
98 if(strcmp(name, "..") == 0){
104 for(i=0; i<nelem(dirtab); i++)
105 if(strcmp(name, dirtab[i].name) == 0){
106 *qid = mkqid(0, dirtab[i].qidpath);
110 if(strcmp(name, "..") == 0){
111 *qid = mkqid(QTDIR, qtop);
124 path = r->fid->qid.path;
127 fillstat(&r->d, "/", QTDIR, Qroot, 0555|DMDIR);
130 fillstat(&r->d, "factotum", QTDIR, Qfactotum, 0555|DMDIR);
133 for(i=0; i<nelem(dirtab); i++)
134 if(dirtab[i].qidpath == path){
135 fillstat(&r->d, dirtab[i].name, 0, dirtab[i].qidpath, dirtab[i].perm);
138 respond(r, "file not found");
146 readlist(int off, int (*gen)(int, char*, uint), Req *r)
152 ea = a+r->ifcall.count;
154 n = (*gen)(off, a, ea-a);
156 r->ofcall.count = a - (char*)r->ofcall.data;
166 keylist(int i, char *a, uint nn)
176 k->attr = sortattr(k->attr);
177 n = snprint(buf, sizeof buf, "key %A %N\n", k->attr, k->privattr);
178 if(n >= sizeof(buf)-5)
179 strcpy(buf+sizeof(buf)-5, "...\n");
188 protolist(int i, char *a, uint n)
190 if(prototab[i] == nil)
192 if(strlen(prototab[i]->name)+1 > n)
194 n = strlen(prototab[i]->name)+1;
195 memmove(a, prototab[i]->name, n-1);
200 /* BUG this is O(n^2) to fill in the list */
202 convlist(int i, char *a, uint nn)
208 for(c=conv; c && i-- > 0; c=c->next)
215 n = snprint(buf, sizeof buf, "conv state=%q %A\n", c->state, c->attr);
217 n = snprint(buf, sizeof buf, "conv state=closed err=%q\n", c->err);
219 if(n >= sizeof(buf)-5)
220 strcpy(buf+sizeof(buf)-5, "...\n");
234 if((r = c->req) != nil){
236 respond(r, "hangup");
241 if(!c->req || !c->nreply)
245 r->ofcall.count = c->nreply;
246 r->ofcall.data = c->reply;
247 if(r->ofcall.count > r->ifcall.count)
248 r->ofcall.count = r->ifcall.count;
255 * Some of the file system work happens in the fs proc, but
256 * fsopen, fsread, fswrite, fsdestroyfid, and fsflush happen in
257 * the main proc so that they can access the various shared
258 * data structures without worrying about locking.
260 static int inuse[nelem(dirtab)];
261 int *confirminuse = &inuse[0];
262 int *needkeyinuse = &inuse[1];
266 int i, *inusep, perm;
267 static int need[4] = { 4, 2, 6, 1 };
271 perm = 5; /* directory */
272 for(i=0; i<nelem(dirtab); i++)
273 if(dirtab[i].qidpath == r->fid->qid.path){
274 if(dirtab[i].perm & DMEXCL)
276 if(strcmp(r->fid->uid, owner) == 0)
277 perm = dirtab[i].perm>>6;
279 perm = dirtab[i].perm;
283 if((r->ifcall.mode&~(OMASK|OTRUNC))
284 || (need[r->ifcall.mode&3] & ~perm)){
285 respond(r, "permission denied");
291 respond(r, "file in use");
297 if(r->fid->qid.path == Qrpc){
298 if((c = convalloc(r->fid->uid)) == nil){
301 rerrstr(e, sizeof e);
305 c->kickreply = fskickreply;
317 switch((int)r->fid->qid.path){
319 respond(r, "fsread: cannot happen");
322 dirread9p(r, rootdirgen, nil);
326 dirread9p(r, fsdirgen, nil);
331 if(c->rpc.op == RpcUnknown){
332 respond(r, "no rpc pending");
336 respond(r, "read already pending");
352 r->fid->aux = (void*)(uintptr)readlist((uintptr)r->fid->aux, keylist, r);
359 r->fid->aux = (void*)(uintptr)readlist((uintptr)r->fid->aux, protolist, r);
363 r->fid->aux = (void*)(uintptr)readlist((uintptr)r->fid->aux, convlist, r);
373 char err[ERRMAX], *s;
377 switch((int)r->fid->qid.path){
379 respond(r, "fswrite: cannot happen");
382 if(rpcwrite(r->fid->aux, r->ifcall.data, r->ifcall.count) < 0){
383 rerrstr(err, sizeof err);
386 r->ofcall.count = r->ifcall.count;
392 strfn = needkeywrite;
400 strfn = confirmwrite;
402 s = emalloc(r->ifcall.count+1);
403 memmove(s, r->ifcall.data, r->ifcall.count);
404 s[r->ifcall.count] = '\0';
408 rerrstr(err, sizeof err);
410 flog("write %s: %s", name, err);
412 r->ofcall.count = r->ifcall.count;
422 confirmflush(r->oldreq);
428 fsdestroyfid(Fid *fid)
430 if(fid->qid.path == Qrpc && fid->aux){
431 convhangup(fid->aux);
436 static Channel *creq;
437 static Channel *cfid, *cfidr;
446 while((r = recvp(creq)) != nil){
447 switch(r->ifcall.type){
449 respond(r, "bug in fsreqthread");
468 fsclunkthread(void *v)
474 while((f = recvp(cfid)) != nil){
485 threadcreate(fsreqthread, nil, STACK);
486 threadcreate(fsclunkthread, nil, STACK);
493 r->fid->qid = mkqid(QTDIR, qtop);
494 r->ofcall.qid = r->fid->qid;
520 creq = chancreate(sizeof(Req*), 0);
521 cfid = chancreate(sizeof(Fid*), 0);
522 cfidr = chancreate(sizeof(Fid*), 0);
523 proccreate(fsproc, nil, STACK);
531 fs.attach = fsattach;
538 fs.destroyfid = fssendclunk;