ref: fba678b80d8c266077e12cd43d5e42d3ab6e411c
dir: /cursedfs.c/
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include "cursed.h"
static void
fsattach(Req *r)
{
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;
fid->omode = r->ifcall.mode;
incref(s);
r->ofcall.qid = fid->qid;
respond(r, nil);
}
static void
fsremove(Req *r)
{
Req *q;
Sem *s;
s = r->fid->aux;
while(q = dequeuereq(s))
respond(q, "file has bee removed");
closesem(s);
r->fid->aux = nil;
closesem(s); // release reference from sems[]
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[] = "\n";
fid = r->fid;
q = fid->qid;
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;
Req *qr;
char str[10];
char nl[] = "\n";
fid = r->fid;
q = fid->qid;
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 *
fswalkl(Fid * fid, char *name, Qid *qid)
{
Qid q;
Sem *s;
int i;
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
freefid(Fid *fid)
{
Sem *s;
s = fid->aux;
fid->aux = nil;
closesem(s);
}
static Srv sfs =
{
.attach = fsattach,
.create = fscreate,
.remove = fsremove,
.read = fsread,
.write = fswrite,
.walk1 = fswalkl,
.clone = fsclone,
.stat = fsstat,
.destroyfid = freefid,
};
void
usage(void)
{
fprint(2, "usage: %s [-D] [-s srv] [-m mnt]\n", argv0);
threadexitsall("usage");
}
void
threadmain(int argc, char *argv[])
{
char *mnt, *srv;
srv = nil;
mnt = "/mnt/sem";
ARGBEGIN{
case 'D':
chatty9p++;
break;
case 's':
srv = EARGF(usage());
break;
case 'm':
mnt = EARGF(usage());
break;
default:
usage();
}ARGEND;
if(argc != 0)
usage();
threadpostmountsrv(&sfs, srv, mnt, MREPL|MCREATE);
threadexits(nil);
}