ref: a351bcdccdf5a4273bc8dc3360a48fbb8b8aa9ea
dir: /progs/asemfs.c.ms/
.P1 .ps -1 .ti -1i .B .BX asemfs.c .ps +1 .CW .ps -2 .vs .15i #include <u.h> #include <libc.h> #include <auth.h> #include <thread.h> #include <fcall.h> #include <9p.h> #include "sem.h" void becomenone(void) { int fd; fd = open("#c/user", OWRITE); if (fd < 0) sysfatal("#c/user: %r"); if (write(fd, "none", 4) < 0) sysfatal("can't become none"); close(fd); newns("none", nil); rfork(RFNOMNT); } static void fsattach(Req* r) { becomenone(); if (authattach(r) < 0) return; r->fid->qid = (Qid){0,0,QTDIR}; r->ofcall.qid = r->fid->qid; respond(r, nil); } static void fscreate(Req* r) { Fid* fid; Qid q; Sem* s; fid = r->fid; q = fid->qid; if (!(q.type&QTDIR)){ respond(r, "not a directory"); return; } s = newsem(r->ifcall.name); fid->qid = (Qid){s->id, 0, 0}; fid->aux = s; incref(s); r->ofcall.qid = fid->qid; respond(r, nil); } static int getdirent(int n, Dir* d, void*) { d->atime= time(nil); d->mtime= d->atime; d->uid = estrdup9p(getuser()); d->gid = estrdup9p(d->uid); d->muid= estrdup9p(d->uid); if (n == -1){ d->qid = (Qid){0, 0, QTDIR}; d->mode = 0775; d->name = estrdup9p("/"); d->length = 0; } else if (n >= 0 && n < nsems && sems[n] != nil){ d->qid = (Qid){n, 0, 0}; d->mode = 0664; d->name = estrdup9p(sems[n]->name); d->length = sems[n]->tickets; } else return -1; return 0; } static void fsread(Req* r) { Fid* fid; Qid q; Sem* s; char nl[2] = "\en"; fid = r->fid; q = fid->qid; if (q.type&QTAUTH){ authread(r); return; } if (q.type&QTDIR){ dirread9p(r, getdirent, nil); respond(r, nil); return; } s = fid->aux; if (s->tickets > 0){ s->tickets--; readstr(r, nl); respond(r, nil); } else queuereq(s, r); } static void fswrite(Req* r) { Fid* fid; Qid q; Sem* s; char str[10]; Req* qr; char nl[2] = "\en"; fid = r->fid; q = fid->qid; if (q.type&QTAUTH){ authwrite(r); return; } if (q.type&QTDIR){ respond(r, "permission denied"); return; } if (r->ifcall.count > sizeof(str) - 1){ respond(r, "string too large"); return; } memmove(str, r->ifcall.data, r->ifcall.count); str[r->ifcall.count] = 0; s = fid->aux; s->tickets += atoi(str); while(s->tickets > 0 && queuedreqs(s)){ qr = dequeuereq(s); qr->ofcall.count = 1; s->tickets--; readstr(qr, nl); respond(qr, nil); } respond(r, nil); } static char* fswalk1(Fid* fid, char* name, Qid* qid) { Qid q; int i; Sem* s; q = fid->qid; s = fid->aux; if (!(q.type&QTDIR)){ if (!strcmp(name, "..")){ fid->qid = (Qid){0,0,QTDIR}; *qid = fid->qid; closesem(s); fid->aux = nil; return nil; } } else { for (i = 0; i < nsems; i++) if (sems[i] && !strcmp(name, sems[i]->name)){ fid->qid = (Qid){i, 0, 0}; incref(sems[i]); closesem(fid->aux); fid->aux = sems[i]; *qid = fid->qid; return nil; } } return "no such file"; } static char* fsclone(Fid* fid, Fid* newfid) { Sem* s; s = fid->aux; if (s != nil) incref(s); newfid->aux = s; return nil; } static void fsstat(Req* r) { Fid* fid; Qid q; fid = r->fid; q = fid->qid; if (q.type&QTDIR) getdirent(-1, &r->d, nil); else getdirent(q.path, &r->d, nil); respond(r, nil); } static void fsremove(Req* r) { Sem* s; s = r->fid->aux; closesem(s); r->fid->aux = nil; closesem(s); // release reference from sems[] respond(r, nil); } static void freefid(Fid* fid) { Sem* s; if (fid->qid.type&QTAUTH) authdestroy(fid); else { s = fid->aux; fid->aux = nil; closesem(s); } } static Srv sfs= { .auth = auth9p, .attach = fsattach, .create = fscreate, .remove = fsremove, .read = fsread, .write = fswrite, .walk1 = fswalk1, .clone = fsclone, .stat = fsstat, .destroyfid= freefid, .keyspec = "proto=p9any role=server" }; void usage(void) { fprint(2, "usage: %s [-D] [-s srv] [-m mnt]\en", argv0); threadexitsall("usage"); } void threadmain(int argc, char **argv) { char* mnt; char* srv; srv = nil; mnt = nil; ARGBEGIN{ case 'D': chatty9p++; break; case 's': srv = EARGF(usage()); break; case 'm': mnt = EARGF(usage()); break; default: usage(); }ARGEND; if(argc!= 0) usage(); if (srv == nil && mnt == nil) mnt = "/mnt/sem"; threadpostmountsrv(&sfs, srv, mnt, MREPL|MCREATE); threadexits(nil); } .ps +2 .P2