shithub: cursedfs

Download patch

ref: fba678b80d8c266077e12cd43d5e42d3ab6e411c
author: Sean Hinchee <[email protected]>
date: Sun Sep 23 22:34:46 EDT 2018

more boilerplate before work really begins

--- /dev/null
+++ b/9curses.h
@@ -1,0 +1,57 @@
+/* This header is cursed.
+ *
+ * The functions and whatnot here are aimed at providing a layer of compatibility
+ * between ncurses-like interfaces and cursedfs to avoid too much rewriting.
+ */
+ 
+//  stub
+#define KEY_UP L'↑'
+//  stub
+#define KEY_DOWN L'↓'
+// Stub
+#define stdscr 0
+
+typedef struct WINDOW WINDOW;
+
+// Clear the screen
+void clear();
+
+// Initialize a new WINDOW
+WINDOW* newwin(uint, uint, uint, uint);
+
+// Clean up and close a WINDOW
+endwin();
+
+// Analogue to print for a string from origin y,x
+int mvprintw(int y, int x, char *fmt, ...);
+
+// Sets a character at y,x
+mvaddch(int y, int x, char c);
+
+// Get a 'raw' character input from the user
+getch();
+
+// Initialize the screen
+initscr();
+
+// Set raw mode for the screen
+raw();
+
+// Don't echo keypress characters to the screen
+noecho();
+
+// Place the cursor at location y,x
+curs_set();
+
+// Set delay until escape sequence potential is ignored
+set_escdelay();
+
+// Refresh the screen
+refresh();
+
+// Refresh a window
+wrefresh(WINDOW*);
+
+struct WINDOW{
+	s8int naught;// Stub
+};
--- /dev/null
+++ b/cursed.c
@@ -1,0 +1,72 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "cursed.h"
+
+Sem *sems[Nsems];
+
+Sem *
+newsem(char *name)
+{
+	int i;
+
+	for(i = 0; i < Nsems; i++)
+		if(sems[i] == nil)
+			break;
+	if(i == Nsems)
+		return nil;
+	sems[i] = emalloc9p(sizeof(Sem));
+	memset(sems[i], 0, sizeof(Sem));
+	sems[i]->ref = 2;
+	sems[i]->name = estrdup9p(name);
+	return sems[i];
+}
+
+void
+closesem(Sem *s)
+{
+	if(s != nil && decref(s) == 0){
+		assert(s->reqs == nil);
+		assert(sems[s->id] == s);
+		sems[s->id] = nil;
+		free(s->name);
+		free(s);
+	}
+}
+
+void
+queuereq(Sem *s, Req *r)
+{
+	QReq *q;
+	QReq **l;
+
+	q = emalloc9p(sizeof(QReq));
+	q->r = r;
+	q->next = nil;
+	for(l = &s->reqs; *l != nil; l = &(*l)->next)
+		;
+	*l = q;
+}
+
+Req *
+dequeuereq(Sem *s)
+{
+	QReq *q;
+	Req *r;
+
+	if(s->reqs == nil)
+		return nil;
+	q = s->reqs;
+	s->reqs = q->next;
+	r = q->r;
+	free(q);
+	return r;
+}
+
+int
+queuedreqs(Sem *s)
+{
+	return s->reqs != nil;
+}
--- /dev/null
+++ b/cursed.h
@@ -1,0 +1,24 @@
+typedef struct Sem Sem;
+typedef struct QReq QReq;
+
+struct Sem{
+	Ref;
+	int		id;		// index in array; qid.path
+	char		*name;	// of file
+	int		tickets;
+	QReq	*reqs;	// reads (i.e., downs) pending
+};
+
+struct QReq{
+	QReq	*next;	// in pending request list
+	Req		*r;		// the request pending
+};
+
+#define Nsems 32
+extern Sem *sems[];
+
+extern Sem *newsem(char *name);
+extern void closesem(Sem *s);
+extern void queuereq(Sem *s, Req *r);
+extern Req *dequeuereq(Sem *s);
+extern int queuedreqs(Sem *s);
--- /dev/null
+++ b/cursedfs.c
@@ -1,0 +1,250 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "cursed.h"
+
+static void
+fsattach(Req *r)
+{
+	r->fid->qid = (Qid) { 0, 0, QTDIR };
+	r->ofcall.qid = r->fid->qid;
+	respond(r, nil);
+}
+
+static void
+fscreate(Req *r)
+{
+	Fid *fid;
+	Qid q;
+	Sem *s;
+
+	fid = r->fid;
+	q = fid->qid;
+	if(!(q.type & QTDIR)){
+		respond(r, "not a directory");
+		return;
+	}
+	s = newsem(r->ifcall.name);
+	fid->qid = (Qid){s->id, 0, 0};
+	fid->aux = s;
+	fid->omode = r->ifcall.mode;
+	incref(s);
+	r->ofcall.qid = fid->qid;
+	respond(r, nil);
+}
+
+static void
+fsremove(Req *r)
+{
+	Req *q;
+	Sem *s;
+
+	s = r->fid->aux;
+	while(q = dequeuereq(s))
+		respond(q, "file has bee removed");
+	closesem(s);
+	r->fid->aux = nil;
+	closesem(s);	// release reference from sems[]
+	respond(r, nil);
+}
+
+static int
+getdirent(int n, Dir *d, void *)
+{
+	d->atime = time(nil);
+	d->mtime = d->atime;
+	d->uid = estrdup9p(getuser());
+	d->gid = estrdup9p(d->uid);
+	d->muid = estrdup9p(d->uid);
+	if(n == -1){
+		d->qid = (Qid) {0, 0, QTDIR};
+		d->mode = 0775;
+		d->name = estrdup9p("/");
+		d->length = 0;
+	}else if(n >= 0 && n < Nsems && sems[n] != nil){
+		d->qid = (Qid) {n, 0, 0};
+		d->mode = 0664;
+		d->name = estrdup9p(sems[n]->name);
+		d->length = sems[n]->tickets;
+	}else
+		return -1;
+	return 0;
+}
+
+static void
+fsread(Req *r)
+{
+	Fid *fid;
+	Qid q;
+	Sem	*s;
+	char	nl[] = "\n";
+
+	fid = r->fid;
+	q = fid->qid;
+	if(q.type & QTDIR){
+		dirread9p(r, getdirent, nil);
+		respond(r, nil);
+		return;
+	}
+	s = fid->aux;
+	if(s->tickets > 0){
+		s->tickets--;
+		readstr(r, nl);
+		respond(r, nil);
+	}else
+		queuereq(s, r);
+}
+
+static void
+fswrite(Req *r)
+{
+	Fid *fid;
+	Qid q;
+	Sem	*s;
+	Req *qr;
+	char	str[10];
+	char	nl[] = "\n";
+
+	fid = r->fid;
+	q = fid->qid;
+	if(q.type & QTDIR){
+		respond(r, "permission denied");
+		return;
+	}
+	if(r->ifcall.count > sizeof(str) - 1){
+		respond(r, "string too large");
+		return;
+	}
+	memmove(str, r->ifcall.data, r->ifcall.count);
+	str[r->ifcall.count] = 0;
+	s = fid->aux;
+	s->tickets += atoi(str);
+
+	while(s->tickets > 0 && queuedreqs(s)){
+		qr = dequeuereq(s);
+		qr->ofcall.count = 1;
+		s->tickets--;
+		readstr(qr, nl);
+		respond(qr, nil);
+	}
+	respond(r, nil);
+}
+
+static char *
+fswalkl(Fid * fid, char *name, Qid *qid)
+{
+	Qid q;
+	Sem	*s;
+	int i;
+
+	q = fid->qid;
+	s = fid->aux;
+	if(!(q.type && QTDIR)){
+		if(!strcmp(name, "..")){
+			fid->qid = (Qid) {0, 0, QTDIR};
+			*qid = fid->qid;
+			closesem(s);
+			fid->aux = nil;
+			return nil;
+		}
+	}else{
+		for(i = 0; i < Nsems; i++)
+			if(sems[i] && !strcmp(name, sems[i]->name)){
+				fid->qid = (Qid){i, 0, 0};
+				incref(sems[i]);
+				closesem(fid->aux);
+				fid->aux = sems[i];
+				*qid = fid->qid;
+				return nil;
+			}
+	}
+	return "no such file";
+}
+
+static char *
+fsclone(Fid *fid, Fid *newfid)
+{
+	Sem *s;
+
+	s  = fid->aux;
+	if(s != nil)
+		incref(s);
+	newfid->aux = s;
+	return nil;
+}
+
+static void
+fsstat(Req *r)
+{
+	Fid *fid;
+	Qid q;
+
+	fid = r->fid;
+	q = fid->qid;
+	if(q.type & QTDIR)
+		getdirent(-1, &r->d, nil);
+	else
+		getdirent(q.path, &r->d, nil);
+	respond(r, nil);
+}
+
+static void
+freefid(Fid *fid)
+{
+	Sem *s;
+
+	s = fid->aux;
+	fid->aux = nil;
+	closesem(s);
+}
+
+static Srv sfs = 
+{
+	.attach	=	fsattach,
+	.create	=	fscreate,
+	.remove	=	fsremove,
+	.read		=	fsread,
+	.write	=	fswrite,
+	.walk1	=	fswalkl,
+	.clone	=	fsclone,
+	.stat		=	fsstat,
+	.destroyfid =	freefid,
+};
+
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-D] [-s srv] [-m mnt]\n", argv0);
+	threadexitsall("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+	char	*mnt, *srv;
+
+	srv = nil;
+	mnt = "/mnt/sem";
+	ARGBEGIN{
+	case 'D':
+		chatty9p++;
+		break;
+	case 's':
+		srv = EARGF(usage());
+		break;
+	case 'm':
+		mnt = EARGF(usage());
+		break;
+	default:
+		usage();
+	}ARGEND;
+
+	if(argc != 0)
+		usage();
+	threadpostmountsrv(&sfs, srv, mnt, MREPL|MCREATE);
+	threadexits(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,15 @@
+</$objtype/mkfile
+
+TARG = cursedfs
+
+OFILES = \
+	cursed.$O \
+	cursedfs.$O
+
+HFILES = \
+	cursed.h \
+	9curses.h
+
+BIN = $home/bin/$objtype
+
+</sys/src/cmd/mkone