ref: 0397462f0ae8a0e097a0004738f870f898e325b4
parent: fba678b80d8c266077e12cd43d5e42d3ab6e411c
author: Sean Hinchee <henesy@users.noreply.github.com>
date: Tue Dec 4 19:42:23 EST 2018
rebase from simplefs
--- /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