commit a6b5d915eca0a0031e0aea86553c0dc11282ded3
parent 01759746eed33c11916492ad218f801b606d5ce5
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Thu, 7 Feb 2019 10:48:43 +0000
[drivers] Fix bind()
Change-Id: I98b26e03286da98f93e6dec46ab677563230001f
Diffstat:
7 files changed, 124 insertions(+), 48 deletions(-)
diff --git a/drivers/dev.c b/drivers/dev.c
@@ -23,6 +23,22 @@ newchan(void)
return NULL;
}
+static Bind *
+newbind(void)
+{
+ Bind *b, *lim;
+ struct devdata *dinfo = bss->devinfo;
+
+ lim = &dinfo->binds[NR_BINDS];
+ for (b = dinfo->binds; b < lim; b++) {
+ if (b->where == NULL)
+ return b;
+ }
+
+ errno = ENOMEM;
+ return NULL;
+}
+
static Chan *
fd2chan(int fd)
{
@@ -48,8 +64,6 @@ validmode(int mode)
goto err;
if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE)))
goto err;
- if ((mode & O_DIR) && (mode & (O_TRUNC)))
- goto err;
return 1;
err:
@@ -66,16 +80,14 @@ next(const char *s, char *elem)
while (*s == '/')
++s;
- if (*s == '\0')
- return NULL;
-
n = 0;
- for (t = s; *t != '/' && *t != '\0'; t++) {
- if (n == NAMELEN) {
- errno = ENAMETOOLONG;
- return NULL;
+ t = s;
+ if (*s != '\0') {
+ while (*t != '/' && *t != '\0') {
+ if (n == NAMELEN)
+ return NULL;
+ elem[n++] = *t++;
}
- elem[n++] = *t;
}
elem[n] = '\0';
@@ -104,14 +116,41 @@ clone(Chan *c, Chan *nc)
}
static int
+eqchan(Chan *c1, Chan *c2)
+{
+ return c1->qid == c2->qid &&
+ c1->type == c2->type &&
+ c1->dev == c2->dev;
+}
+
+static int
walk(Chan *c, char *name)
{
- return devtab[c->type]->walk(c, name);
+ Chan *cw, tmp;
+ Bind *bp, *lim;
+ struct devdata *dinfo = bss->devinfo;
+
+ if (devtab[c->type]->walk(c, name) == 1)
+ return 1;
+
+ lim = &dinfo->binds[NR_BINDS];
+ for (bp = dinfo->binds; bp < lim; bp++) {
+ cw = bp->where;
+ if (!cw || !eqchan(c, cw))
+ continue;
+ tmp = *bp->from;
+ if (devtab[tmp.type]->walk(&tmp, name) == 1) {
+ *c = tmp;
+ return 1;
+ }
+ }
+ return -1;
}
static void
chanclose(Chan *c)
{
+ struct devdata *dinfo = devdata();
c->qid = 0;
c->type = NODEV;
c->dev = 0;
@@ -159,13 +198,17 @@ namec(const char *name, int mode)
if (!c)
return NULL;
- for (s = next(s, elem); s; s = next(s, elem)) {
+ for (s = next(s, elem); *elem; s = next(s, elem)) {
if (walk(c, elem) < 0)
- break;
- if (*s == '\0')
- return c;
+ goto notfound;
}
+ if (!s)
+ goto notfound;
+ /* TODO: check mode */
+ return c;
+
+notfound:
chanclose(c);
errno = ENOENT;
return NULL;
@@ -362,24 +405,57 @@ seek(int fd, long long off, int whence)
}
int
-bind(char *new, char *where, int flags)
+bind(char *new, char *where)
{
- /* TODO */
+ Chan *cw, *cn;
+ Bind *b;
+
+ if ((cw = namec(where, O_READ)) == NULL)
+ goto err0;
+
+ if ((cw->qid & CHDIR) == 0) {
+ errno = ENOTDIR;
+ goto err1;
+ }
+
+ if ((cn = namec(new, O_BIND)) == NULL)
+ goto err1;
+
+ if ((b = newbind()) == NULL)
+ goto err2;
+
+ b->from = cn;
+ b->where = cw;
+
+ return 0;
+
+err2:
+ chanclose(cn);
+err1:
+ chanclose(cw);
+err0:
+ return -1;
}
void
idev(void)
{
struct devdata *dinfo;
- Chan *c, *lim;
+ Chan *c, *clim;
+ Bind *b, *blim;
dinfo = alloc(sizeof(*dinfo));
bss->devinfo = dinfo;
- lim = &dinfo->fds[NR_CHANS];
- for (c = dinfo->fds; c < lim; c++)
+ clim = &dinfo->fds[NR_CHANS];
+ for (c = dinfo->fds; c < clim; c++)
c->type = NODEV;
+
+ blim = &dinfo->binds[NR_BINDS];
+ for (b = dinfo->binds; b < blim; b++)
+ b->where = b->from = NULL;
+
if ((c = devattach(NULL, '/')) == NULL)
panic("idev:attach");
diff --git a/drivers/dev.h b/drivers/dev.h
@@ -1,7 +1,8 @@
#include <stddef.h>
-#define NR_CHANS 4
-#define NR_UARTS 2
+#define NR_CHANS 8
+#define NR_UARTS 2
+#define NR_BINDS 4
#define NODEV 255
#define CHDIR (1 << 15)
@@ -11,6 +12,7 @@ typedef struct dirtab Dirtab;
typedef int Devgen(Chan *, const Dirtab *, int, int, Dir *);
typedef struct attr Attr;
typedef struct uart Uart;
+typedef struct bind Bind;
struct dirtab {
char name[NAMELEN];
@@ -30,12 +32,11 @@ struct dev {
};
struct chan {
+ unsigned long long offset;
Qid qid;
unsigned char type;
unsigned char dev;
unsigned char mode;
-
- unsigned long long offset; /* 3 bytes of padding here */
};
struct attr {
@@ -43,10 +44,17 @@ struct attr {
char *value;
};
+struct bind {
+ Chan *where;
+ Chan *from;
+ int flags;
+};
+
struct devdata {
- Chan fds[NR_CHANS];
Chan slash;
+ Chan fds[NR_CHANS];
Uart *uarts[NR_UARTS];
+ Bind binds[NR_BINDS];
};
extern Chan *devclone(Chan *c, Chan *nc);
diff --git a/drivers/devroot.c b/drivers/devroot.c
@@ -31,13 +31,13 @@ rootattach(const char *spec)
static int
rootread(Chan *c, void *buf, int n)
{
- if (c->qid & CHDIR) {
- return devdirread(c,
- buf, n,
- dirtab, NELEM(dirtab),
- devgen);
- }
- return -1;
+ if ((c->qid & CHDIR) == 0)
+ return -1;
+
+ return devdirread(c,
+ buf, n,
+ dirtab, NELEM(dirtab),
+ devgen);
}
static int
diff --git a/drivers/devuart.c b/drivers/devuart.c
@@ -92,7 +92,7 @@ uartstatus(Uart *up, void *buf, long long offset, int n)
"b%ld c%d d%d e%d l%d m%d p%c r%d s%d i%d\n",
st.rate,
(st.hang & SIG_DCD) != 0,
- st.dtr,
+ st.dtr,
(st.hang & SIG_DSR) != 0,
st.nbits,
st.ctsflow,
diff --git a/include/rcode/rcode.h b/include/rcode/rcode.h
@@ -17,19 +17,11 @@
#define IDISABLE 0
enum devflags {
- O_CREATE = 1 << 0,
- O_READ = 1 << 1,
- O_WRITE = 1 << 2,
- O_RDWR = 1 << 3,
+ O_READ = 1 << 0,
+ O_WRITE = 1 << 1,
+ O_RDWR = 1 << 2,
+ O_BIND = 1 << 3,
O_DIR = 1 << 4,
- O_TRUNC = 1 << 5,
-};
-
-enum bindflags {
- MREPL = 1 << 0,
- MBEFORE = 1 << 1,
- MAFTER = 1 << 2,
- MCREATE = 1 << 3,
};
enum regidx {
@@ -111,7 +103,7 @@ extern int close(int fd);
extern int read(int fd, void *buf, int n);
extern int write(int fd, void *buf, int n);
extern int seek(int fd, long long off, int whence);
-extern int bind(char *path, char *where, int flags);
+extern int bind(char *path, char *where);
/* architectural functions */
extern void *alloc(size_t size);
diff --git a/src/ramfw/fs.c b/src/ramfw/fs.c
@@ -6,4 +6,4 @@ int close(int fd){return 0;}
int read(int fd, void *buf, int n){return 0;}
int write(int fd, void *buf, int n){return 0;}
int seek(int fd, long long off, int whence){return 0;}
-int bind(char *path, char *where, int flags){return 0;}
+int bind(char *path, char *where){return 0;}
diff --git a/target/native/rom.c b/target/native/rom.c
@@ -130,7 +130,7 @@ namespace(void)
{
int fd;
- if (bind("#t/", "/dev/", MREPL) < 0)
+ if (bind("#t", "/dev") < 0)
panic("openfds1");
fd = open("/dev/uart0/raw", O_READ | O_WRITE);