#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
uint time0;
enum
{
Qroot = 0,
Qkid,
};
char *kidname;
uint kidmode;
void
fsattach(Req *r)
{
char *spec;
spec = r->ifcall.aname;
if(spec && spec[0]){
respond(r, "invalid attach specifier");
return;
}
r->ofcall.qid = (Qid){Qroot, 0, QTDIR};
r->fid->qid = r->ofcall.qid;
respond(r, nil);
}
char*
fswalk1(Fid *fid, char *name, Qid *qid)
{
switch((int)fid->qid.path){
default:
return "path not found";
case Qroot:
if(strcmp(name, "..") == 0)
break;
if(strcmp(name, kidname) == 0){
fid->qid = (Qid){Qkid, 0, kidmode>>24};
break;
}
return "path not found";
case Qkid:
if(strcmp(name, "..") == 0){
fid->qid = (Qid){Qroot, 0, QTDIR};
break;
}
return "path not found";
}
*qid = fid->qid;
return nil;
}
void
fsstat(Req *r)
{
int q;
Dir *d;
d = &r->d;
memset(d, 0, sizeof *d);
q = r->fid->qid.path;
d->qid = r->fid->qid;
switch(q){
case Qroot:
d->name = estrdup9p("/");
d->mode = DMDIR|0777;
break;
case Qkid:
d->name = estrdup9p(kidname);
d->mode = kidmode;
break;
}
d->atime = d->mtime = time0;
d->uid = estrdup9p("stub");
d->gid = estrdup9p("stub");
d->muid = estrdup9p("");
respond(r, nil);
}
int
dirgen(int off, Dir *d, void*)
{
if(off != 0)
return -1;
memset(d, 0, sizeof *d);
d->atime = d->mtime = time0;
d->name = estrdup9p(kidname);
d->mode = kidmode;
d->qid = (Qid){Qkid, 0, kidmode>>24};
d->qid.type = d->mode>>24;
d->uid = estrdup9p("stub");
d->gid = estrdup9p("stub");
d->muid = estrdup9p("");
return 0;
}
void
fsread(Req *r)
{
int q;
q = r->fid->qid.path;
switch(q){
default:
respond(r, "bug");
return;
case Qroot:
dirread9p(r, dirgen, nil);
respond(r, nil);
return;
}
}
void
fswrite(Req *r)
{
respond(r, "no writing");
}
void
fsopen(Req *r)
{
if(r->fid->qid.path != Qroot){
respond(r, "permission denied");
return;
}
if(r->ifcall.mode != OREAD)
respond(r, "permission denied");
else
respond(r, nil);
}
Srv fs = {
.attach= fsattach,
.open= fsopen,
.read= fsread,
.write= fswrite,
.stat= fsstat,
.walk1= fswalk1,
};
void
usage(void)
{
fprint(2, "usage: aux/stub [-Dd] path/name\n");
exits("usage");
}
void
main(int argc, char **argv)
{
char *p, *mtpt;
quotefmtinstall();
time0 = time(0);
ARGBEGIN{
case 'D':
chatty9p++;
break;
case 'd':
kidmode = DMDIR;
break;
default:
usage();
}ARGEND
if(argc != 1)
usage();
if((p = strrchr(argv[0], '/')) == 0){
mtpt = ".";
kidname = argv[0];
}else if(p == argv[0]){
mtpt = "/";
kidname = argv[0]+1;
}else{
mtpt = argv[0];
*p++ = '\0';
kidname = p;
}
/* don't leave standard descriptors open to confuse mk */
close(0);
close(1);
close(2);
postmountsrv(&fs, nil, mtpt, MBEFORE);
exits(nil);
}
|