summaryrefslogtreecommitdiff
path: root/emu/port/devroot.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2009-03-25 15:55:14 +0000
committerCharles.Forsyth <devnull@localhost>2009-03-25 15:55:14 +0000
commitdfd1934d5e1ddbeb326f77fc0e52307c801a1a3e (patch)
treef1e8b23278caae95e01d88b00421d6c3642357ef /emu/port/devroot.c
parent78dfdcbd59dc8f36975e7695933e3f753957474c (diff)
x20090325-1554
Diffstat (limited to 'emu/port/devroot.c')
-rw-r--r--emu/port/devroot.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/emu/port/devroot.c b/emu/port/devroot.c
new file mode 100644
index 00000000..695d151c
--- /dev/null
+++ b/emu/port/devroot.c
@@ -0,0 +1,150 @@
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+extern Rootdata rootdata[];
+extern Dirtab roottab[];
+extern int rootmaxq;
+
+static Chan*
+rootattach(char *spec)
+{
+ int i;
+ ulong len;
+ Rootdata *r;
+
+ if(*spec)
+ error(Ebadspec);
+ for (i = 0; i < rootmaxq; i++){
+ r = &rootdata[i];
+ if (r->sizep){
+ len = *r->sizep;
+ r->size = len;
+ roottab[i].length = len;
+ }
+ }
+ return devattach('/', spec);
+}
+
+static int
+rootgen(Chan *c, char *name, Dirtab *tab, int nd, int s, Dir *dp)
+{
+ int p, i;
+ Rootdata *r;
+
+ if(s == DEVDOTDOT){
+ p = rootdata[c->qid.path].dotdot;
+ c->qid.path = p;
+ c->qid.type = QTDIR;
+ name = "#/";
+ if(p != 0){
+ for(i = 0; i < rootmaxq; i++)
+ if(roottab[i].qid.path == c->qid.path){
+ name = roottab[i].name;
+ break;
+ }
+ }
+ devdir(c, c->qid, name, 0, eve, 0555, dp);
+ return 1;
+ }
+ if(name != nil){
+ isdir(c);
+ r = &rootdata[(int)c->qid.path];
+ tab = r->ptr;
+ for(i=0; i<r->size; i++, tab++)
+ if(strcmp(tab->name, name) == 0){
+ devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
+ return 1;
+ }
+ return -1;
+ }
+ if(s >= nd)
+ return -1;
+ tab += s;
+ devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
+ return 1;
+}
+
+static Walkqid*
+rootwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ ulong p;
+
+ p = c->qid.path;
+ if(nname == 0)
+ p = rootdata[p].dotdot;
+ return devwalk(c, nc, name, nname, rootdata[p].ptr, rootdata[p].size, rootgen);
+}
+
+static int
+rootstat(Chan *c, uchar *dp, int n)
+{
+ int p;
+
+ p = rootdata[c->qid.path].dotdot;
+ return devstat(c, dp, n, rootdata[p].ptr, rootdata[p].size, rootgen);
+}
+
+static Chan*
+rootopen(Chan *c, int omode)
+{
+ int p;
+
+ p = rootdata[c->qid.path].dotdot;
+ return devopen(c, omode, rootdata[p].ptr, rootdata[p].size, rootgen);
+}
+
+/*
+ * sysremove() knows this is a nop
+ */
+static void
+rootclose(Chan *c)
+{
+ USED(c);
+}
+
+static long
+rootread(Chan *c, void *buf, long n, vlong offset)
+{
+ ulong p, len;
+ uchar *data;
+
+ p = c->qid.path;
+ if(c->qid.type & QTDIR)
+ return devdirread(c, buf, n, rootdata[p].ptr, rootdata[p].size, rootgen);
+ len = rootdata[p].size;
+ if(offset < 0 || offset >= len)
+ return 0;
+ if(offset+n > len)
+ n = len - offset;
+ data = rootdata[p].ptr;
+ memmove(buf, data+offset, n);
+ return n;
+}
+
+static long
+rootwrite(Chan *c, void *a, long n, vlong off)
+{
+ USED(c); USED(a); USED(n); USED(off);
+ error(Eperm);
+ return 0;
+}
+
+Dev rootdevtab = {
+ '/',
+ "root",
+
+ devinit,
+ rootattach,
+ rootwalk,
+ rootstat,
+ rootopen,
+ devcreate,
+ rootclose,
+ rootread,
+ devbread,
+ rootwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};