9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Mdrivers/dev.c | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mdrivers/dev.h | 18+++++++++++++-----
Mdrivers/devroot.c | 14+++++++-------
Mdrivers/devuart.c | 2+-
Minclude/rcode/rcode.h | 18+++++-------------
Msrc/ramfw/fs.c | 2+-
Mtarget/native/rom.c | 2+-
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);