ref: 74dc57b5fcfa1c98de646674040741f543d358ec
dir: /fshandler.inc/
#line 0 "fshandler.inc"
typedef struct DirreadArgs DirreadArgs;
struct DirreadArgs {
int *hierarchy;
int (*func)(int,Dir*,void*);
int num;
void *aux;
};
static int
default_dirread(int i, Dir *d, void *aux)
{
int q;
int ret;
DirreadArgs *args = aux;
int *fh = args->hierarchy;
Filedata *fd;
if (!fh)
return -1;
// fprint(2, "gen: %d %d %p\n", i, args->num, args->func);
/* for some very strange reason, after setting args->num, the values are still the same for the next round. I have no idea why this could happen, and it also shouldn't hurt, it's just not clean. */
if (args->func) {
if (args->num < 0) {
ret = args->func(i, d, args->aux);
if (ret == 0)
return ret;
/* set numbers and skip future loops */
args->num = i;
}
} else {
args->num = 0;
}
// fprint(2, "pfu: %d %d %p\n", i, args->num, args->func);
i -= args->num;
Next:
q = fh[i];
if (!q)
return -1;
fd = &filedata[q];
if (fd->dir.name[0] == '{') {
/* if this is a variable, skip */
i++;
args->num++;
goto Next;
}
d->name = estrdup9p(fd->dir.name);
d->uid = estrdup9p("none");
d->gid = estrdup9p("none");
d->muid = estrdup9p("none");
return 0;
}
static void
fsread(Req *r)
{
int q;
Filedata *fd;
DirreadArgs args;
q = breakqid(r->fid->qid.path);
fd = &filedata[q];
if (fd->read) {
fd->read(r);
/* if read is implemented, it should respond */
return;
}
if (fd->dir.mode&DMDIR) {
args.hierarchy = filehierarchy[q];
args.func = fd->ls;
args.num = -1;
args.aux = r->fid->aux;
dirread9p(r, default_dirread, &args);
respond(r, nil);
return;
}
respond(r, "read error");
}
static void
fswrite(Req *r)
{
respond(r, nil);
}
static void
fsstat(Req *r)
{
int q;
Filedata *fd;
void (*func)(Req *r);
q = breakqid(r->fid->qid.path);
fd = &filedata[q];
r->d = fd->dir;
qidtype = q;
r->d.qid.path = makeqid(getqidhash(r->fid));
r->d.qid.vers = 0;
r->d.qid.type = fd->dir.mode&DMDIR ? QTDIR : QTFILE;
/* TODO: these names could leak memory! */
r->d.name = estrdup9p(fd->dir.name);
r->d.uid = estrdup9p("none");
r->d.gid = estrdup9p("none");
r->d.gid = estrdup9p("none");
if (fd->stat) {
func = fd->stat;
func(r);
/* if function exists, it should respond */
return;
}
respond(r, nil);
return;
}
static int
childrencontains(int *fh, int search)
{
int *i;
for (i = fh; *i; i++) {
if (*i == search)
return 1;
}
return 0;
}
static int
findparent(int qid)
{
for (int i = Qroot; i < Qmax; i++) {
if (childrencontains(filehierarchy[i], qid))
return i;
}
return Qroot;
}
/* 0 is root/not found, n is qid */
static int
findchild(int qid, char *name)
{
Filedata *fd;
char *s;
int n;
assert(qid >= Qroot && qid < Qmax);
if (!filehierarchy[qid]) {
return qid;
}
for (int *i = filehierarchy[qid]; *i; i++) {
fd = &filedata[*i];
s = fd->dir.name;
n = strlen(s);
if (s[0] == '{' && s[n-1] == '}')
return *i;
if (strcmp(s, name) == 0)
return *i;
}
return Qroot;
}
static char*
fswalk(Fid *fid, char *name, Qid *qid)
{
int qt, i;
Filedata *fd;
char buf[32];
char *s;
if (strcmp(name, ".") == 0) {
fid->qid = *qid;
return nil;
}
qt = breakqid(fid->qid.path);
if (strcmp(name, "..") == 0) {
qt = findparent(qt);
fd = &filedata[qt];
qidtype = qt;
qid->path = makeqid(getqidhash(fid));
qid->vers = 0;
qid->type = fd->dir.mode&DMDIR ? QTDIR : QTFILE;
fid->qid = *qid;
return nil;
}
i = findchild(qt, name);
switch (i) {
case 0:
/* invalid file */
return "file not found";
default:
/* found child */
break;
}
fd = &filedata[i];
if (fd->dir.name[0] == '{') {
strcpy(buf, fd->dir.name+1);
s = strchr(buf, '}');
*s = 0;
setvar(fid->aux, buf, name);
}
qidtype = i;
qid->path = makeqid(getqidhash(fid));
qid->vers = 0;
qid->type = fd->dir.mode&DMDIR ? QTDIR : QTFILE;
fid->qid = *qid;
return nil;
}
static char*
fsclone(Fid *ofid, Fid *nfid)
{
FileAux *src, *dst;
if (!ofid->aux) {
nfid->aux = mallocz(sizeof(FileAux), 1);
return nil;
}
src = ofid->aux;
nfid->aux = dst = mallocz(sizeof(FileAux), 1);
clonevars(src, dst);
return nil;
}
static void
fsattach(Req *r)
{
Qid q;
qidtype = Qroot;
q.path = makeqid(0);
q.vers = 0;
q.type = QTDIR;
r->ofcall.qid = r->fid->qid = q;
respond(r, nil);
}