summaryrefslogtreecommitdiff
path: root/sys/src/cmd/skelfs.c
diff options
context:
space:
mode:
authorJacob Moody <moody@posixcafe.org>2022-06-15 06:42:05 +0000
committerJacob Moody <moody@posixcafe.org>2022-06-15 06:42:05 +0000
commitc12022fd8c434860accb237b9bad9bd7cd9ed2db (patch)
treef3651ec0e98313f83a3dce393a53910e1953f359 /sys/src/cmd/skelfs.c
parentc7c0ff5db6137662e435d66338cfa4e68c64598e (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.c251
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);
+}