shithub: cursedfs

Download patch

ref: 0397462f0ae8a0e097a0004738f870f898e325b4
parent: fba678b80d8c266077e12cd43d5e42d3ab6e411c
author: Sean Hinchee <[email protected]>
date: Tue Dec 4 19:42:23 EST 2018

rebase from simplefs

diff: cannot open b/9curses//null: file does not exist: 'b/9curses//null'
--- /dev/null
+++ b/.hgignore
@@ -1,0 +1,4 @@
+syntax: glob
+*.[8qkv5967o]
+*.acid
+[8qkv5967o].out
--- a/9curses.h
+++ /dev/null
@@ -1,57 +1,0 @@
-/* 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/9curses/9curses.c
@@ -1,0 +1,109 @@
+#include <u.h>
+#include <libc.h>
+#include "9curses.h"
+
+// Clear the screen
+int
+clear()
+{
+	// Stub
+	return 0;
+}
+
+// Initialize a new WINDOW
+WINDOW*
+newwin(int nlines, int ncols, int begin_y, int begin_x)
+{
+	// Stub
+	WINDOW* w = calloc(1, sizeof(WINDOW));
+	return w;
+}
+
+// Clean up and close a WINDOW
+int
+endwin()
+{
+	// Stub
+	return 0;
+}
+
+// Analogue to print for a string from origin y,x
+int
+mvprintw(int y, int x, char *fmt, ...)
+{
+	// Stub
+	return 0;
+}
+
+// Sets a character at y,x
+int
+mvaddch(int y, int x, char c)
+{
+	// Stub
+	return 0;
+}
+
+// Get a 'raw' character input from the user
+int
+getch()
+{
+	// Stub
+	return 0;
+}
+
+// Initialize the screen
+WINDOW*
+initscr()
+{
+	// Stub
+	WINDOW* w = calloc(1, sizeof(WINDOW));
+	return w;
+}
+
+// Set raw mode for the screen
+int
+raw()
+{
+	// Stub
+	return 0;
+}
+
+// Don't echo keypress characters to the screen
+int
+noecho()
+{
+	// Stub
+	return 0;
+}
+
+// Place the cursor at location y,x
+int
+curs_set(int visibility)
+{
+	// Stub
+	return 0;
+}
+
+// Set delay until escape sequence potential is ignored
+int
+set_escdelay(int timems)
+{
+	// Stub
+	return 0;
+}
+
+// Refresh the screen
+int
+refresh()
+{
+	// Stub
+	return 0;
+}
+
+// Refresh a window
+int
+wrefresh(WINDOW* w)
+{
+	// Stub
+	return 0;
+}
--- /dev/null
+++ b/9curses/9curses.h
@@ -1,0 +1,58 @@
+/* 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.
+ */
+#pragma lib "lib9curses.a"
+ 
+//  stub
+#define KEY_UP L'↑'
+//  stub
+#define KEY_DOWN L'↓'
+// Stub
+#define stdscr 0
+
+typedef struct WINDOW WINDOW;
+
+// Clear the screen
+int clear();
+
+// Initialize a new WINDOW
+WINDOW* newwin(int, int, int, int);
+
+// Clean up and close a WINDOW
+int 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
+int mvaddch(int y, int x, char c);
+
+// Get a 'raw' character input from the user
+int getch();
+
+// Initialize the screen
+WINDOW* initscr();
+
+// Set raw mode for the screen
+int raw();
+
+// Don't echo keypress characters to the screen
+int noecho();
+
+// Place the cursor at location y,x
+int curs_set(int);
+
+// Set delay until escape sequence potential is ignored
+int set_escdelay(int timems);
+
+// Refresh the screen
+int refresh();
+
+// Refresh a window
+int wrefresh(WINDOW*);
+
+struct WINDOW{
+	s8int naught;// Stub
+};
--- /dev/null
+++ b/9curses/mkfile
@@ -1,0 +1,23 @@
+</$objtype/mkfile
+
+#LIB=/$objtype/lib/lib9curses.a
+LIB=$home/lib/$objtype/lib9curses.a
+
+FILES=\
+	9curses
+
+HFILES=/sys/include/9curses.h
+
+CFILES=${FILES:%=%.c}
+
+OFILES=${FILES:%=%.$O}
+
+UPDATE=mkfile\
+	$LIB\
+	$HFILES\
+	$CFILES\
+
+</sys/src/cmd/mksyslib
+
+h:V: 9curses.h
+	cp -x $prereq /sys/include
--- a/cursed.c
+++ /dev/null
@@ -1,72 +1,0 @@
-#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;
-}
--- a/cursed.h
+++ /dev/null
@@ -1,24 +1,0 @@
-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);
--- a/cursedfs.c
+++ /dev/null
@@ -1,250 +1,0 @@
-#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/fs.h
@@ -1,0 +1,14 @@
+#define Cmdwidth	1024
+#define Ncmd		4
+#define Nfiles		2
+
+// Represents a 9p file
+typedef struct File9 File9;
+struct File9 {
+	Ref;
+	int		id;		// index in array; qid.path
+	char	*name;	// of file
+};
+
+// All available files on the 9p fs
+extern File9 *files[Nfiles];
--- /dev/null
+++ b/main.c
@@ -1,0 +1,272 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "fs.h"
+
+// All active files in the fs
+File9 *files[Nfiles];
+
+// Commands log ;; 4 entries, 1024 wide
+char clog[Ncmd][Cmdwidth];
+
+
+// Prototypes for 9p handler functions
+static void		fsattach(Req *r);
+static int		getdirent(int n, Dir *d, void *);
+static void		fsread(Req *r);
+static void		fswrite(Req *r);
+static char*	fswalk1(Fid * fid, char *name, Qid *qid);
+static char*	fsclone(Fid *fid, Fid *newfid);
+static void		fsstat(Req *r);
+
+
+// Srv structure to handle incoming 9p communications
+static Srv srvfs = 
+{
+	.attach		=	fsattach,
+	.read		=	fsread,
+	.write		=	fswrite,
+	.walk1		=	fswalk1,
+	.clone		= 	fsclone,
+	.stat		=	fsstat,
+};
+
+
+// Usage output
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-D] [-s srv] [-m mnt]\n", argv0);
+	threadexitsall("usage");
+}
+
+// Push a message into the log
+void
+logcmd(char* str)
+{
+	int i;
+	for(i = Ncmd-1; i > 0; i--)
+		strcpy(clog[i], clog[i-1]);
+	strncpy(clog[0], str, Cmdwidth);
+}
+
+// Print the log
+char*
+log2str(void)
+{
+	char str[Ncmd * Cmdwidth];
+	memset(str, '\0', Ncmd * Cmdwidth);
+
+	int i;
+	for(i = Ncmd-1; i >= 0; i--)
+		strncat(str, clog[i], strlen(clog[i]));
+
+	return str;
+}
+
+
+/* A simple 9p fileserver to show a minimal set of operations */
+void
+threadmain(int argc, char *argv[])
+{
+	char	*mnt, *srv;
+
+	srv = nil;
+	mnt = "/mnt/simplefs";
+
+	ARGBEGIN{
+	case 'D':
+		chatty9p++;
+		break;
+	case 's':
+		srv = EARGF(usage());
+		break;
+	case 'm':
+		mnt = EARGF(usage());
+		break;
+	default:
+		usage();
+	}ARGEND;
+
+	if(argc != 0)
+		usage();
+
+	// Setup ctl file
+	File9 ctl = (File9) { (Ref){ 0 }, 0, "ctl" };
+	files[0] = &ctl;
+	
+	// Setup log file
+	File9 log = (File9) { (Ref){ 0 }, 1, "log" };
+	files[1] = &log;
+
+	threadpostmountsrv(&srvfs, srv, mnt, MREPL|MCREATE);
+	threadexits(nil);
+}
+
+
+// Handle 9p attach -- independent implementation
+static void
+fsattach(Req *r)
+{
+	r->fid->qid = (Qid) { 0, 0, QTDIR };
+	r->ofcall.qid = r->fid->qid;
+	respond(r, nil);
+}
+
+// Get directory entries for stat and such -- independent implementation
+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 < Nfiles && files[n] != nil){
+		d->qid = (Qid) {n, 0, 0};
+		d->mode = 0664;
+		d->name = estrdup9p(files[n]->name);
+	}else
+		return -1;
+	return 0;
+}
+
+// Handle 9p read
+static void
+fsread(Req *r)
+{
+	Fid		*fid;
+	Qid		q;
+	char	readmsg[Ncmd * Cmdwidth];
+	readmsg[0] = '\0';
+
+	fid = r->fid;
+	q = fid->qid;
+	if(q.type & QTDIR){
+		dirread9p(r, getdirent, nil);
+		respond(r, nil);
+		return;
+	}
+
+	switch(q.path){
+	case 0:
+		// ctl file
+		strcpy(readmsg, "ctl file is unreadable.\n");
+		break;
+	case 1:
+		// log file
+		// TODO -- attach stdout to write to the read stream
+		// strcpy(readmsg, "log shows prior commands.\n");
+		strcpy(readmsg, log2str());
+		break;
+	default:
+		strcpy(readmsg, "Nothing special in this read.\n");
+	}
+	
+	// Set the read reply string
+	readstr(r, readmsg);
+	
+	// Respond to the 9p request
+	respond(r, nil);
+}
+
+// Handle 9p write
+static void
+fswrite(Req *r)
+{
+	Fid		*fid;
+	Qid		q;
+	char	str[Cmdwidth];
+
+	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;
+	
+	// At this point, str contains the written bytes
+	
+	switch(q.path){
+	case 0:
+		// ctl file
+		logcmd(str);
+		break;
+	default:
+		respond(r, "only ctl may be written to");
+		return;
+	}
+	
+	respond(r, nil);
+}
+
+// Handle 9p walk -- independent implementation
+static char *
+fswalk1(Fid * fid, char *name, Qid *qid)
+{
+	Qid q;
+	int i;
+
+	q = fid->qid;
+	if(!(q.type && QTDIR)){
+		if(!strcmp(name, "..")){
+			fid->qid = (Qid) {0, 0, QTDIR};
+			*qid = fid->qid;
+			fid->aux = nil;
+			return nil;
+		}
+	}else{
+		for(i = 0; i < Nfiles; i++)
+			if(files[i] && !strcmp(name, files[i]->name)){
+				fid->qid = (Qid){i, 0, 0};
+				incref(files[i]);
+				fid->aux = files[i];
+				*qid = fid->qid;
+				return nil;
+			}
+	}
+	return "no such directory.";
+}
+
+// Handle 9p stat -- independent implementation
+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);
+}
+
+// Handle 9p clone -- independent implementation
+static char *
+fsclone(Fid *fid, Fid *newfid)
+{
+	File9 *f;
+	
+	f = fid->aux;
+	if(f != nil)
+		incref(f);
+	newfid->aux = f;
+	return nil;
+}
--- a/mkfile
+++ b/mkfile
@@ -3,12 +3,10 @@
 TARG = cursedfs
 
 OFILES = \
-	cursed.$O \
-	cursedfs.$O
+	main.$O \
 
 HFILES = \
-	cursed.h \
-	9curses.h
+	fs.h
 
 BIN = $home/bin/$objtype