9os

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

commit aa2edae702f0f8b592f415d80c8c21bed635cd67
parent 3160b80b68361796fa8fc9ce898f7a215e7e0d41
Author: Dimitris Papastamos <dimitris.papastamos@arm.com>
Date:   Tue, 16 Apr 2019 10:52:56 +0100

Merge "[dev] Add mount()"
Diffstat:
Mdrivers/dev.c | 106++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mdrivers/devar.c | 224++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mdrivers/devroot.c | 3++-
Mdrivers/devuart.c | 1+
Minclude/rcode/dev.h | 8+++++++-
Minclude/rcode/rcode.h | 1+
Mscripts/rules.mk | 1+
Mtarget/hosted/rom.c | 6+-----
8 files changed, 199 insertions(+), 151 deletions(-)

diff --git a/drivers/dev.c b/drivers/dev.c @@ -10,8 +10,8 @@ #define NR_MPOINTS 4 struct mpoint { - Chan *where; Chan *new; + Chan *old; }; static Chan fdset[NR_CHANS]; @@ -140,20 +140,20 @@ buf2chan(Chan *c, void *dst, void *src, int nbytes, unsigned long long len) static Chan * mntpoint(Chan *c) { - Chan *cw; + Chan *cn; struct mpoint *mp; for (mp = mpoints; mp < &mpoints[NR_MPOINTS]; mp++) { - if ((cw = mp->where) == NULL) + if ((cn = mp->new) == NULL) continue; - if (cw->type == c->type && cw->qid == c->qid) - return mp->new; + if (cn->type == c->type && cn->qid == c->qid) + return mp->old; } return NULL; } -static Chan * +Chan * devattach(int id, int dev) { Chan *c; @@ -295,6 +295,20 @@ dirread(Chan *c, return cnt; } +void +mkentry(Chan *c, Dir *dir, + const char *name, unsigned long long length, Qid qid, unsigned mode) +{ + strcpy(dir->name, name); + dir->length = length; + dir->qid = qid; + dir->mode = mode; + if (qid & CHDIR) + dir->mode |= O_DIR; + dir->type = c->type; + dir->dev = c->dev; +} + int devgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) { @@ -304,15 +318,7 @@ devgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) return 0; dp = &tab[n]; - strcpy(dir->name, dp->name); - dir->length = dp->length; - dir->qid = dp->qid; - dir->mode = dp->perm; - if (dp->qid & CHDIR) - dir->mode |= O_DIR; - dir->type = c->type; - dir->dev = c->dev; - + mkentry(c, dir, dp->name, dp->length, dp->qid, dp->perm); return 1; } @@ -372,6 +378,13 @@ write(int fd, void *buf, int n) } int +devmount(Chan *c, char *spec) +{ + errno = EINVAL; + return -1; +} + +int devwrite(Chan *c, void *buf, int n) { errno = EINVAL; @@ -412,44 +425,81 @@ seek(int fd, long long off, int whence) return devseek(c, off,whence); } -int -bind(char *new, char *where) +static int +addmntpoint(Chan *c, char *new) { int i; + Chan *cn; struct mpoint *mp; - Chan *cw, *cn; - if ((cw = namec(where, O_READ)) == NULL) + if ((cn = namec(new, O_READ)) == NULL) goto err0; - if ((cw->qid & CHDIR) == 0) { + if ((cn->qid & CHDIR) == 0) { errno = ENOTDIR; goto err1; } - if ((cn = namec(new, O_BIND)) == NULL) - goto err1; - for (i = NR_MPOINTS-1; i >= 0; i--) { mp = &mpoints[i]; - if (!mp->where) + if (!mp->new) break; } if (i < 0) { errno = ENOMEM; - goto err2; + goto err1; } - mp->where = cw; mp->new = cn; + mp->old = c; return 0; -err2: +err1: chanclose(cn); +err0: + return -1; +} + +int +bind(char *old, char *new) +{ + Chan *c; + + if ((c = namec(old, O_BIND)) == NULL) + return -1; + + if (addmntpoint(c, new) < 0) { + chanclose(c); + return -1; + } + + return 0; +} + +int +mount(char *srv, char *where, char *spec) +{ + Chan *cs, *c; + + if ((cs = namec(srv, O_RDWR)) == NULL) + goto err0; + + c = devtab[cs->type]->mount(cs, spec); + if (!c) + goto err1; + + if (addmntpoint(c, where) < 0) + goto err2; + chanclose(cs); + + return 0; + +err2: + chanclose(c); err1: - chanclose(cw); + chanclose(cs); err0: return -1; } diff --git a/drivers/devar.c b/drivers/devar.c @@ -7,7 +7,8 @@ #include <rcode/9p.h> #include <rcode/dev.h> -#define NR_ARS 2 +#define NR_ARS 2 +#define NR_FILES 10 #define ARMAG "!<arch>\n" /* ar "magic number" */ #define SARMAG 8 /* strlen(ARMAG); */ @@ -16,24 +17,22 @@ struct ar_hdr { - char ar_name[SARNAM]; /* name */ - char ar_date[12]; /* modification time */ - char ar_uid[6]; /* user id */ - char ar_gid[6]; /* group id */ - char ar_mode[8]; /* octal file permissions */ - char ar_size[10]; /* size in bytes */ - char ar_fmag[2]; /* consistency check */ + char ar_name[SARNAM]; /* name */ + char ar_date[12]; /* modification time */ + char ar_uid[6]; /* user id */ + char ar_gid[6]; /* group id */ + char ar_mode[8]; /* octal file permissions */ + char ar_size[10]; /* size in bytes */ + char ar_fmag[2]; /* consistency check */ }; -enum Oarqid { - Qarfs, - Qctl, -}; - -static Dirtab arfstab[NR_ARS+1] = { - {"ctl", Qctl, 0, O_READ | O_WRITE}, +struct arfile { + Chan *c; + long offset[NR_FILES]; + long size[NR_FILES]; }; +static struct arfile archives[NR_ARS]; static int nars; static int @@ -42,17 +41,17 @@ gethdr(Chan *c, struct ar_hdr *hdr) int n, ch, i; n = devtab[c->type]->read(c, hdr, sizeof(*hdr)); - if (n == 0) - return 0; + if (n <= 0) + return n; + if (n != sizeof(*hdr) || strncmp(hdr->ar_fmag, ARFMAG, 2) != 0) { - errno = EFAULT; /* TODO: Put correct value */ + errno = EINVAL; return -1; } - /* TODO: Check if we do the same loop and we accept not null strings */ for (i = SARNAM-1; i >= 0; i--) { ch = hdr->ar_name[i]; - if (ch != ' ' && ch !='/') + if (ch != ' ' && ch != '/') break; hdr->ar_name[i] = '\0'; } @@ -60,48 +59,34 @@ gethdr(Chan *c, struct ar_hdr *hdr) return 1; } -/* - * TODO: This is broken, because we have a channel to - * talk with the dev, but we need an offset - * in the underlying dev. - */ static int argen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) { - Qid qid; - int len, r; + int i, r, len; Chan nc; - char buf[SARMAG]; struct ar_hdr hdr; + struct arfile *ar; - qid = (c->qid & ~CHDIR) - 1; - if (qid > nars) + if (c->dev >= nars) panic("argen"); - clone(arfstab[qid].data, &nc); - nc.offset = c->offset; + clone(archives[c->dev].c, &nc); + ar = &archives[nc.dev]; - if (nc.offset == 0) { - r = devtab[nc.type]->read(&nc, buf, SARMAG); - if (r != SARMAG || strncmp(buf, ARMAG, SARMAG)) { - errno = EFAULT; + for (i = 0; i <= n; i++) { + if (ar->offset[i] == -1) + return 0; + if (devseek(&nc, ar->offset[i], RSEEK_SET) < 0) return -1; - } + if ((r = gethdr(&nc, &hdr)) <= 0) + return r; } - if ((r = gethdr(&nc, &hdr)) <= 0) - return r; - devseek(&nc, atol(hdr.ar_size), 1); + if ((len = strlen(hdr.ar_name)) >= NAMELEN) { + errno = ENAMETOOLONG; + return -1; + } - if ((len = strlen(hdr.ar_name)) >= NAMELEN) - return 0; - memcpy(dir->name, hdr.ar_name, len); - dir->name[len] = '\0'; - dir->length = atol(hdr.ar_size); - dir->qid = (n + 1) * (NR_ARS+1) + qid; - dir->mode = O_READ; - dir->type = c->type; - dir->dev = c->dev; - c->offset = nc.offset; + mkentry(c, dir, hdr.ar_name, atol(hdr.ar_size), n, O_READ); return 1; } @@ -109,94 +94,101 @@ argen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) static int arwalk(Chan *c, const char *name) { - switch (c->qid & ~CHDIR) { - case Qarfs: - return devwalk(c, name, arfstab, nars+1, devgen); - default: - return devwalk(c, name, NULL, 0, argen); - } + return devwalk(c, name, NULL, 0, argen); } static int -ardirread(Chan *c, unsigned char *buf, int nbytes) +arread(Chan *c, void *buf, int n) { - int n, cnt; - Dir dir; + long off; + Chan cs; + struct arfile *ar; - for (cnt = 0; nbytes >= DIRLEN; cnt += n) { - switch (argen(c, NULL, 0, nbytes, &dir)) { - case 0: - return cnt; - case -1: - return (cnt > 0) ? cnt : -1; - default: - n = dirtop9(&dir, buf + cnt, nbytes); - nbytes -= n; - } - } + if (c->qid == CHDIR) + return dirread(c, buf, n, NULL, 0, argen); - return cnt; -} + if (c->dev >= nars || (c->qid & CHDIR)) + panic("arread1"); + ar = &archives[c->dev]; -static int -arread(Chan *c, void *buf, int n) -{ - Qid qid; - Chan nc; + if (c->qid >= NR_FILES || ar->offset[c->qid] == -1) + panic("arread2"); + clone(ar->c, &cs); - switch (c->qid & ~CHDIR) { - case Qarfs: - return dirread(c, buf, n, arfstab, nars+1, devgen); - case Qctl: - errno = EFAULT; /* TODO: Put a correct value */ + if (c->offset >= ar->size) + return 0; + + off = ar->offset[c->qid] + c->offset + sizeof(struct ar_hdr); + if (devseek(&cs, off, RSEEK_SET) < 0) return -1; - default: - if (c->qid & CHDIR) - return ardirread(c, buf, n); - else { - qid = c->qid % (NR_ARS + 1); - clone(arfstab[qid].data, &nc); - nc.offset = c->offset; - n = devtab[nc.type]->read(&nc, buf, n); - c->offset += n; - return n; - } - } + + n = devtab[cs.type]->read(&cs, buf, n); + c->offset += n; + + return n; } -int -arnew(char *name) +static Chan * +armount(Chan *c, char *spec) { - Qid qid; - Chan *c; - char *base; - Dirtab *dp; - - base = strrchr(name, '/'); - base = (base) ? base+1 : name; + int r, n; + long len, offhdr; + Chan *cspec; + char buf[SARMAG]; + struct ar_hdr hdr; + struct arfile *ar; - if (nars >= NR_ARS || strlen(base) >= NAMELEN) { + if (nars == NR_ARS) { errno = ENOMEM; - return -1; + return NULL; } + ar = &archives[nars]; - if ((c = namec(name, O_READ)) == NULL) - return -1; + for (n = 0; n < NR_FILES; n++) + ar->offset[n] = -1; + + if ((cspec = namec(spec, O_READ)) < 0) + return NULL; + ar->c = cspec; - qid = ++nars + Qctl; - dp = &arfstab[qid-1]; - dp->qid = CHDIR | qid; - dp->perm = O_READ; - dp->length = 0; - dp->data = c; - strcpy(dp->name, base); + r = devtab[cspec->type]->read(cspec, buf, SARMAG); + if (r < 0) + goto err; + if (r != SARMAG || strncmp(buf, ARMAG, SARMAG)) { + errno = EINVAL; + goto err; + } + + for (n = 0; n < NR_FILES; n++) { + offhdr = cspec->offset; + switch (gethdr(cspec, &hdr)) { + case 0: + return devattach('R', nars++); + case -1: + goto err; + default: + ar->offset[n] = offhdr; + len = atol(hdr.ar_size); + ar->size[n] = len; + if ((len % 2) != 0) + len++; + + if (devseek(cspec, len, RSEEK_CUR) < 0) + goto err; + break; + } + } + errno = ENOMEM; - return 0; +err: + chanclose(cspec); + return NULL; } const Dev ardevtab = { - .id = 'r', + .id = 'R', .walk = arwalk, .read = arread, .write = devwrite, + .mount = armount, }; diff --git a/drivers/devroot.c b/drivers/devroot.c @@ -1,8 +1,8 @@ #include <rcode/rcode.h> #include <rcode/9p.h> +#include <rcode/dev.h> #include <libk.h> -#include <rcode/dev.h> enum Orootqid { Qroot, @@ -103,4 +103,5 @@ const Dev rootdevtab = { .walk = rootwalk, .read = rootread, .write = devwrite, + .mount = devmount, }; diff --git a/drivers/devuart.c b/drivers/devuart.c @@ -247,4 +247,5 @@ const Dev uartdevtab = { .walk = uartwalk, .read = uartread, .write = uartwrite, + .mount = devmount, }; diff --git a/include/rcode/dev.h b/include/rcode/dev.h @@ -1,6 +1,6 @@ #include <stddef.h> -#define NR_CHANS 8 +#define NR_CHANS 20 #define NR_UARTS 2 #define NR_BINDS 4 #define NODEV 255 @@ -25,6 +25,7 @@ struct dev { int (*walk)(Chan *c, const char *name); int (*read)(Chan *c, void *buf, int n); int (*write)(Chan *c, void *buf, int n); + Chan *(*mount)(Chan *c, char *spec); }; struct chan { @@ -41,6 +42,7 @@ struct attr { }; +extern Chan *devattach(int id, int dev); extern int devseek(Chan *c, long long off, int whence); extern Chan * namec(const char *name, int mode); extern Chan *clone(Chan *c, Chan *nc); @@ -48,7 +50,11 @@ extern void chanclose(Chan *c); extern int buf2chan(Chan *c, void *dst, void *src, int nbytes, unsigned long long len); +extern void mkentry(Chan *c, Dir *dir, + const char *name, + unsigned long long length, Qid qid, unsigned mode); +extern int devmount(Chan *c, char *spec); extern void devlink(void); extern int devwrite(Chan *c, void *buf, int n); extern int devgen(Chan *c, diff --git a/include/rcode/rcode.h b/include/rcode/rcode.h @@ -102,6 +102,7 @@ extern void idev(void); extern void dumpregs(struct trapframe *fp); /* driver functions */ +extern int mount(char *srv, char *mnt, char *spec); extern int create(const char *name, int flags); extern int open(const char *name, int flags); extern int close(int fd); diff --git a/scripts/rules.mk b/scripts/rules.mk @@ -8,6 +8,7 @@ LIBDIR = $(PROJECTDIR)/lib BINDIR = $(PROJECTDIR)/bin TARGETDIR = $(PROJECTDIR)/target/$(MODE) DRVDIR = $(PROJECTDIR)/drivers +FSDIR = $(PROJECTDIR)/fs SRCDIR = $(PROJECTDIR)/src SCRIPTDIR = $(PROJECTDIR)/scripts CONFDIR = $(PROJECTDIR)/config diff --git a/target/hosted/rom.c b/target/hosted/rom.c @@ -47,8 +47,6 @@ imach(void) framep = &trapframe; } -extern int arnew(char *file); - static void namespace(void) { @@ -56,9 +54,7 @@ namespace(void) goto error; if (bind("#t0", "/dev/cons") < 0) goto error; - if (bind("#r", "/arfs") < 0) - goto error; - if (arnew("/blobs/example.a") < 0) + if (mount("#R", "/arfs", "/blobs/example.a") < 0) goto error; return;