9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] Pitch for devskel
@ 2022-06-05  0:57 Jacob Moody
  2022-06-06  3:16 ` Jacob Moody
  0 siblings, 1 reply; 7+ messages in thread
From: Jacob Moody @ 2022-06-05  0:57 UTC (permalink / raw)
  To: 9front

I have been trying to find ergonomic ways of building
restricted namespaces. One issue that I keep running
in to, and that I've discussed before, is the need
for skeleton directories. Devskel is an iteration
on making these skeleton directories easier to create.

This adds a new device, '#z', that can be walked to
produce a single skeleton file or directory. For example walking

#z/ls

gives you a directory with a single empty 'ls' file within it.
A 'd' attach argument can be given to have this 'ls' file become
a empty directory instead:

#zd/ls

Each attach of '#z' can at most 'make up' one skeleton;
after the first walk from the root the hierarchy becomes stable.
The 'e' attach option instead makes the root directory always
empty.

An example of using this to build a /bin with only bind and ls.

term% bind -b '#zd/bin.new' /bin
term% bind '#z/ls' /bin/bin.new
term% bind -a '#z/bind' /bin/bin.new
term% ls /bin/bin.new
/bin/bin.new/bind
/bin/bin.new/ls
term% bind /bin/bind /bin/bin.new/bind
term% bind /bin/ls /bin/bin.new/ls
term% bind /bin/bin.new /bin
term% ls /bin/
/bin/bind
/bin/ls
term%

Why devskel instead of mntgen?

1. mntgen only exposes directories
2. mntgen permits more then a single directory to be made up
3. mntgen shows folders that other clients have walked to.

3 could just be labeled as a bug. 1 and 2 could be specified
in attach options but I am not sure what the semantics should be
for specifying both. Using mntgen would also require the use
of /srv, and I do prefer having this separated from /srv.


thanks,
moody

diff 926be5e34eb633bc3e22b013705f5474d21aa735 uncommitted
--- /dev/null
+++ b//sys/src/9/port/devskel.c
@@ -1,0 +1,237 @@
+#include	"u.h"
+#include	"../port/lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"../port/error.h"
+
+#include	"netif.h"
+
+typedef struct Skel Skel;
+struct Skel {
+	int ref;
+	QLock lk;
+	char name[KNAMELEN];
+	char mode;
+};
+
+struct
+{
+	QLock lk;
+	ulong path;
+} skelalloc;
+
+enum{
+	Qroot,
+	Qdir,
+	Qskel,
+};
+
+static Chan*
+skelattach(char *spec)
+{
+	Chan *c;
+	Skel *f;
+	uvlong path;
+
+	c = devattach('z', spec);
+
+	f = smalloc(sizeof *f);
+	if(spec != nil && spec[0] != '\0' && strchr("de", spec[0]) != nil)
+		f->mode = spec[0];
+	else
+		f->mode = 'f';
+
+	f->ref = 1;
+
+	qlock(&skelalloc.lk);
+	path = skelalloc.path++;
+	qunlock(&skelalloc.lk);
+
+	mkqid(&c->qid, NETQID(path, Qroot), 0, QTDIR);
+	c->aux = f;
+	return c;
+}
+
+static int
+step(Chan *c, Dir *dp, int direction)
+{
+	Skel *f;
+	Qid qid;
+	ulong perm;
+	uvlong path;
+	char *name;
+
+	perm = 0555|DMDIR;
+	path = NETTYPE(c->qid.path);
+	f = c->aux;
+	name = f->name;
+
+	path += direction;
+	if(!f->name[0] && path != Qroot)
+		return -1;
+
+	switch(path){
+	case Qroot:
+		mkqid(&qid, Qroot, 0, QTDIR);
+		name = "#z";
+		break;
+	case Qdir:
+		mkqid(&qid, Qdir, 0, QTDIR);
+		break;
+	case Qskel:
+		switch(f->mode){
+		case 'd':
+			mkqid(&qid, Qskel, 0, QTDIR);
+			break;
+		case 'f':
+		default:
+			mkqid(&qid, Qskel, 0, QTFILE);
+			perm = 0666;
+			break;
+		}
+		break;
+	default:
+		return -1;
+	}
+
+	qid.path = NETQID(NETID(c->qid.path), qid.path);
+	devdir(c, qid, name, 0, eve, perm, dp);
+	return 1;
+}
+
+
+static int
+skelgen(Chan *c, char *name, Dirtab *, int, int s, Dir *dp)
+{
+	Skel *f;
+
+	f = c->aux;
+	//First walk away from root
+	if(name && !f->name[0] && f->mode != 'e' && NETTYPE(c->qid.path) == Qroot)
+		utfecpy(f->name, f->name + sizeof f->name, name);
+
+	if(s != DEVDOTDOT)
+		s++;
+
+	return step(c, dp, s);
+}
+
+static Walkqid*
+skelwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+	Walkqid *wq;
+	Skel *f;
+
+	f = c->aux;
+	qlock(&f->lk);
+	if(waserror()){
+		qunlock(&f->lk);
+		nexterror();
+	}
+
+	wq = devwalk(c, nc, name, nname, nil, 0, skelgen);
+	if(wq != nil && wq->clone != nil && wq->clone != c){
+		if(f->ref <= 0)
+			panic("devskel ref");
+		f->ref++;
+	}
+	qunlock(&f->lk);
+	poperror();
+	return wq;
+}
+
+static Chan*
+skelopen(Chan *c, int omode)
+{
+	if(!(c->qid.type & QTDIR))
+		error(Eperm);
+	if(omode != OREAD)
+		error(Ebadarg);
+
+	c->mode = omode;
+	c->flag |= COPEN;
+	c->offset = 0;
+	return c;
+}
+
+static void
+skelclose(Chan *c)
+{
+	Skel *f;
+
+	f = c->aux;
+	qlock(&f->lk);
+	f->ref--;
+	if(f->ref == 0){
+		qunlock(&f->lk);
+		free(f);
+	} else
+		qunlock(&f->lk);
+}
+
+static long
+skelread(Chan *c, void *va, long n, vlong)
+{
+	Skel *f;
+	long nout;
+
+	if(!(c->qid.type & QTDIR))
+		error(Eperm);
+
+	f = c->aux;
+	qlock(&f->lk);
+	if(waserror()){
+		qunlock(&f->lk);
+		nexterror();
+	}
+	nout = devdirread(c, va, n, nil, 0, skelgen);
+	qunlock(&f->lk);
+	poperror();
+	return nout;
+}
+
+static long
+skelwrite(Chan *, void *, long, vlong)
+{
+	error(Eperm);
+	return 0;
+}
+
+static int
+skelstat(Chan *c, uchar *db, int n)
+{
+	Skel *f;
+	Dir dir;
+
+	f = c->aux;
+	qlock(&f->lk);
+	step(c, &dir, 0);
+	qunlock(&f->lk);
+
+	n = convD2M(&dir, db, n);
+	if(n < BIT16SZ)
+		error(Eshortstat);
+	return n;
+}
+
+Dev skeldevtab = {
+	'z',
+	"skel",
+
+	devreset,
+	devinit,
+	devshutdown,
+	skelattach,
+	skelwalk,
+	skelstat,
+	skelopen,
+	devcreate,
+	skelclose,
+	skelread,
+	devbread,
+	skelwrite,
+	devbwrite,
+	devremove,
+	devwstat,
+};



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-06-06 15:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-05  0:57 [9front] Pitch for devskel Jacob Moody
2022-06-06  3:16 ` Jacob Moody
2022-06-06  6:41   ` Jacob Moody
2022-06-06 14:40     ` ori
2022-06-06 15:08       ` Jacob Moody
2022-06-06 15:24         ` ori
2022-06-06 15:31           ` Jacob Moody

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).