19 mkqid(int type, int path)
35 /* positions of confirm and needkey known below */
36 "confirm", Qconfirm, 0600|DMEXCL,
37 "needkey", Qneedkey, 0600|DMEXCL,
40 "proto", Qprotolist, 0444,
41 "log", Qlog, 0600|DMEXCL,
46 fillstat(Dir *dir, char *name, int type, int path, ulong perm)
48 dir->name = estrdup(name);
49 dir->uid = estrdup(owner);
50 dir->gid = estrdup(owner);
53 dir->qid = mkqid(type, path);
56 dir->muid = estrdup("");
60 rootdirgen(int n, Dir *dir, void *v)
67 fillstat(dir, factname, QTDIR, Qfactotum, DMDIR|0555);
72 fsdirgen(int n, Dir *dir, void *v)
76 if(n >= nelem(dirtab))
78 fillstat(dir, dirtab[n].name, 0, dirtab[n].qidpath, dirtab[n].perm);
83 fswalk1(Fid *fid, char *name, Qid *qid)
87 switch((int)fid->qid.path){
89 return "fswalk1: cannot happen";
91 if(strcmp(name, factname) == 0){
92 *qid = mkqid(QTDIR, Qfactotum);
96 if(strcmp(name, "..") == 0){
102 for(i=0; i<nelem(dirtab); i++)
103 if(strcmp(name, dirtab[i].name) == 0){
104 *qid = mkqid(0, dirtab[i].qidpath);
108 if(strcmp(name, "..") == 0){
109 *qid = mkqid(QTDIR, Qroot);
122 path = r->fid->qid.path;
125 fillstat(&r->d, "/", QTDIR, Qroot, 0555|DMDIR);
128 fillstat(&r->d, "factotum", QTDIR, Qfactotum, 0555|DMDIR);
131 for(i=0; i<nelem(dirtab); i++)
132 if(dirtab[i].qidpath == path){
133 fillstat(&r->d, dirtab[i].name, 0, dirtab[i].qidpath, dirtab[i].perm);
136 respond(r, "file not found");
144 readlist(int off, int (*gen)(int, char*, uint), Req *r)
150 ea = a+r->ifcall.count;
152 n = (*gen)(off, a, ea-a);
154 r->ofcall.count = a - (char*)r->ofcall.data;
160 return -1; /* not reached */
164 keylist(int i, char *a, uint nn)
174 k->attr = sortattr(k->attr);
175 n = snprint(buf, sizeof buf, "key %A %N\n", k->attr, k->privattr);
176 if(n >= sizeof(buf)-5)
177 strcpy(buf+sizeof(buf)-5, "...\n");
186 protolist(int i, char *a, uint n)
188 if(prototab[i] == nil)
190 if(strlen(prototab[i]->name)+1 > n)
192 n = strlen(prototab[i]->name)+1;
193 memmove(a, prototab[i]->name, n-1);
198 /* BUG this is O(n^2) to fill in the list */
200 convlist(int i, char *a, uint nn)
206 for(c=conv; c && i-- > 0; c=c->next)
213 n = snprint(buf, sizeof buf, "conv state=%q %A\n", c->state, c->attr);
215 n = snprint(buf, sizeof buf, "conv state=closed err=%q\n", c->err);
217 if(n >= sizeof(buf)-5)
218 strcpy(buf+sizeof(buf)-5, "...\n");
233 respond(c->req, "hangup");
239 if(!c->req || !c->nreply)
243 r->ofcall.count = c->nreply;
244 r->ofcall.data = c->reply;
245 if(r->ofcall.count > r->ifcall.count)
246 r->ofcall.count = r->ifcall.count;
253 * Some of the file system work happens in the fs proc, but
254 * fsopen, fsread, fswrite, fsdestroyfid, and fsflush happen in
255 * the main proc so that they can access the various shared
256 * data structures without worrying about locking.
258 static int inuse[nelem(dirtab)];
259 int *confirminuse = &inuse[0];
260 int *needkeyinuse = &inuse[1];
264 int i, *inusep, perm;
265 static int need[4] = { 4, 2, 6, 1 };
269 perm = 5; /* directory */
270 for(i=0; i<nelem(dirtab); i++)
271 if(dirtab[i].qidpath == r->fid->qid.path){
272 if(dirtab[i].perm & DMEXCL)
274 if(strcmp(r->fid->uid, owner) == 0)
275 perm = dirtab[i].perm>>6;
277 perm = dirtab[i].perm;
281 if((r->ifcall.mode&~(OMASK|OTRUNC))
282 || (need[r->ifcall.mode&3] & ~perm)){
283 respond(r, "permission denied");
289 respond(r, "file in use");
295 if(r->fid->qid.path == Qrpc){
296 if((c = convalloc(r->fid->uid)) == nil){
299 rerrstr(e, sizeof e);
303 c->kickreply = fskickreply;
315 switch((int)r->fid->qid.path){
317 respond(r, "fsread: cannot happen");
320 dirread9p(r, rootdirgen, nil);
324 dirread9p(r, fsdirgen, nil);
329 if(c->rpc.op == RpcUnknown){
330 respond(r, "no rpc pending");
334 respond(r, "read already pending");
350 r->fid->aux = (void*)readlist((int)r->fid->aux, keylist, r);
357 r->fid->aux = (void*)readlist((int)r->fid->aux, protolist, r);
361 r->fid->aux = (void*)readlist((int)r->fid->aux, convlist, r);
371 char err[ERRMAX], *s;
374 switch((int)r->fid->qid.path){
376 respond(r, "fswrite: cannot happen");
379 if(rpcwrite(r->fid->aux, r->ifcall.data, r->ifcall.count) < 0){
380 rerrstr(err, sizeof err);
383 r->ofcall.count = r->ifcall.count;
388 strfn = needkeywrite;
394 strfn = confirmwrite;
396 s = emalloc(r->ifcall.count+1);
397 memmove(s, r->ifcall.data, r->ifcall.count);
398 s[r->ifcall.count] = '\0';
402 rerrstr(err, sizeof err);
405 r->ofcall.count = r->ifcall.count;
420 fsdestroyfid(Fid *fid)
422 if(fid->qid.path == Qrpc){
423 convhangup(fid->aux);
428 static Channel *creq;
429 static Channel *cfid, *cfidr;
438 creq = chancreate(sizeof(Req*), 0);
440 while((r = recvp(creq)) != nil){
441 switch(r->ifcall.type){
443 respond(r, "bug in fsreqthread");
462 fsclunkthread(void *v)
467 cfid = chancreate(sizeof(Fid*), 0);
468 cfidr = chancreate(sizeof(Fid*), 0);
470 while((f = recvp(cfid)) != nil){
481 threadcreate(fsreqthread, nil, STACK);
482 threadcreate(fsclunkthread, nil, STACK);
489 static int first = 1;
492 proccreate(fsproc, nil, STACK);
496 r->fid->qid = mkqid(QTDIR, Qroot);
497 r->ofcall.qid = r->fid->qid;
522 .destroyfid= fssendclunk,