diff options
author | Jacob Moody <moody@posixcafe.org> | 2022-06-15 06:42:05 +0000 |
---|---|---|
committer | Jacob Moody <moody@posixcafe.org> | 2022-06-15 06:42:05 +0000 |
commit | c12022fd8c434860accb237b9bad9bd7cd9ed2db (patch) | |
tree | f3651ec0e98313f83a3dce393a53910e1953f359 /sys/src/cmd/skelfs.c | |
parent | c7c0ff5db6137662e435d66338cfa4e68c64598e (diff) |
skel(3) → skelfs(4)
The original intention was to put devskel in to the
kernel to detach what it provides from devsrv.
That is not a good reason, just move it to userspace.
auth/box has been changed to exec skelfs instead
of relying on '#z'.
Diffstat (limited to 'sys/src/cmd/skelfs.c')
-rw-r--r-- | sys/src/cmd/skelfs.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/sys/src/cmd/skelfs.c b/sys/src/cmd/skelfs.c new file mode 100644 index 000000000..137e19397 --- /dev/null +++ b/sys/src/cmd/skelfs.c @@ -0,0 +1,251 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> + +typedef struct Skel Skel; +struct Skel { + char name[64]; + char mode; +}; + +static uvlong sessions; +static char defmode; + +enum{ + Qroot, + Qdir, + Qskel, +}; + +#define qtype(x) (((ulong)x)&0x1f) +#define qsess(x) ((((ulong)x))>>5) +#define mkqid(i,t) ((((ulong)i)<<5)|(t)) + +static int +step(Fid *f, int way, Qid *res, Dir *dp) +{ + Skel *s; + int path; + char *name; + ulong perm; + + s = f->aux; + name = s->name; + perm = 0550|DMDIR; + path = qtype(f->qid.path) + way; + if(!name[0] && way > 0) + return -1; + + if(path < 0) + goto Root; + switch(path){ + Root: + case Qroot: + name = "/"; + /* fallthrough */ + case Qdir: + res->type = QTDIR; + break; + case Qskel: + switch(s->mode){ + case 'd': + res->type = QTDIR; + break; + case 'f': + default: + res->type = QTFILE; + perm = 0; + break; + } + break; + default: + return -1; + } + res->vers = qsess(f->qid.path); + res->path = mkqid(res->vers, path); + if(dp){ + dp->mode = perm; + dp->name = estrdup9p(name); + dp->uid = estrdup9p("sys"); + dp->gid = estrdup9p("sys"); + dp->qid = *res; + dp->length = 0; + } + return 1; +} + +static int +dirgen(int i, Dir *d, void *a) +{ + Fid *f; + Qid q; + + if(i > 0) + return -1; + f = a; + return step(f, 1, &q, d); +} + +static void +fidclunk(Fid *fid) +{ + free(fid->aux); +} + +static char* +fsclone(Fid *old, Fid *new, void*) +{ + Skel *s, *s2; + + s = old->aux; + s2 = emalloc9p(sizeof *s2); + if(s2 == nil) + return "out of memory"; + memset(s2, 0, sizeof *s2); + + s2->mode = s->mode; + utfecpy(s2->name, &s2->name[sizeof s2->name-1], s->name); + new->aux = s2; + return nil; +} + +static char* +fswalk1(Fid *old, char *name, void*) +{ + Skel *s; + + if(strcmp("..", name) == 0){ + step(old, -1, &old->qid, nil); + return nil; + } + + s = old->aux; + if(!s->name[0] && qtype(old->qid.path) == Qroot && s->mode != 'e'){ + utfecpy(s->name, &s->name[sizeof s->name-1], name); + old->qid.vers = sessions++; + old->qid.path = mkqid(old->qid.vers, qtype(old->qid.path)); + } else if(strcmp(name, s->name) != 0) + return "does not exist"; + + if(step(old, 1, &old->qid, nil) < 0) + return "does not exist"; + + return nil; +} + +static void +fswalk(Req *r) +{ + walkandclone(r, fswalk1, fsclone, nil); +} + +static void +fsattach(Req *r) +{ + Skel s; + Fid root; + char *spec; + Qid *q; + + spec = r->ifcall.aname; + if(spec && spec[0] != '\0') + s.mode = spec[0]; + else + s.mode = defmode; + + q = &r->fid->qid; + q->vers = sessions++; + q->path = mkqid(q->vers, Qroot); + q->type = QTDIR; + r->ofcall.qid = *q; + + s.name[0] = '\0'; + root.aux = &s; + respond(r, fsclone(&root, r->fid, nil)); +} + +static void +fsstat(Req *r) +{ + Qid q; + + if(step(r->fid, 0, &q, &r->d) < 0) + respond(r, "does not exist"); + respond(r, nil); +} + +static void +fsread(Req *r) +{ + dirread9p(r, dirgen, r->fid); + respond(r, nil); +} + +static void +fsopen(Req *r) +{ + r->ofcall.mode = r->ifcall.mode; + if(r->ifcall.mode != OREAD) + respond(r, "permission denied"); + else + respond(r, nil); +} + +Srv fs= +{ +.attach= fsattach, +.open= fsopen, +.read= fsread, +.stat= fsstat, +.walk= fswalk, +.destroyfid= fidclunk +}; + +void +usage(void) +{ + fprint(2, "usage: %s [ -Di ] [ -s service ] [ -t mode ] [ mntpt ]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *s, *mode; + int stdio; + + s = nil; + stdio = 0; + defmode = 'f'; + ARGBEGIN{ + case 'D': + chatty9p++; + break; + case 's': + s = EARGF(usage()); + break; + case 'i': + stdio = 1; + break; + case 't': + mode = EARGF(usage()); + defmode = mode[0]; + break; + default: + usage(); + }ARGEND + + if(argc > 1) + usage(); + + if(stdio == 0){ + postmountsrv(&fs, s, argc ? argv[0] : "/mnt/skel", MREPL); + exits(nil); + } + fs.infd = 0; + fs.outfd = 1; + srv(&fs); + exits(nil); +} |