9os

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

commit 4740cd137a4a385f29f383736173315b9e8b5597
parent fe622d396ffbd7f64c7dafc0ffa81c4d539e52b9
Author: Roberto Vargas <roberto.vargas@arm.com>
Date:   Thu,  9 May 2019 09:30:41 +0100

[dev] Add stat() and dirstat()

These functions are used to collect information of
a file (like for example the size, or the rights).

Change-Id: Ieb634eee4ff5be73981750d1f4f4ddfa05753d23

Diffstat:
Mdrivers/dev.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdrivers/dev.h | 14++++++++++----
Mdrivers/devar.c | 7+++++++
Mdrivers/devcons.c | 7+++++++
Mdrivers/devfip.c | 7+++++++
Mdrivers/devroot.c | 7+++++++
Mdrivers/devuart.c | 7+++++++
Minclude/rcode/io.h | 5++++-
Msrc/lib9p/Makefile | 1+
Asrc/lib9p/dirstat.c | 17+++++++++++++++++
Msrc/lib9p/p9todir.c | 5++++-
11 files changed, 139 insertions(+), 6 deletions(-)

diff --git a/drivers/dev.c b/drivers/dev.c @@ -360,6 +360,74 @@ close(int fd) } int +devstat(Chan *dirc, char *file, + unsigned char *buf, int n, + const Dirtab *tab, int ntab, + Devgen *gen) +{ + int i, r = -1; + Dir dir; + Chan *c; + + if ((c = namec(file, O_STAT)) == NULL) + return -1; + + for (i = 0; ; i++) { + switch ((*gen)(dirc, tab, ntab, i, &dir)) { + case 0: + errno = ENOENT; + case -1: + r = -1; + goto leave; + case 1: + if (dir.qid != c->qid) + continue; + r = dirtop9(&dir, buf, n); + goto leave; + } + } + +leave: + chanclose(c); + return r; +} + +int +stat(char *path, void *buf, int n) +{ + int r; + size_t len; + Chan *c; + char *p, dirname[NAMELEN]; + + if (n < STATLEN) { + errno = EINVAL; + return -1; + } + + p = strrchr(path, '/'); + if (!p) { + errno = ENOENT; + return -1; + } + + if ((len = p - path) > NAMELEN-1) { + errno = EINVAL; + return -1; + } + memcpy(dirname, path, len); + dirname[len] = '\0'; + + if ((c = namec(dirname, O_STAT)) == NULL) + return -1; + + r = devtab[c->type]->stat(c, path, buf, n); + chanclose(c); + + return r; +} + +int read(int fd, void *buf, int n) { Chan *c; diff --git a/drivers/dev.h b/drivers/dev.h @@ -24,12 +24,13 @@ struct dirtab { struct dev { char id; - Chan * (*clone)(Chan *c, Chan *nc); + int (*stat)(Chan *c, char *file, unsigned char *buf, int n); int (*walk)(Chan *c, const char *name); - Chan * (*attach)(int id, int dev); int (*read)(Chan *c, void *buf, int n); int (*write)(Chan *c, void *buf, int n); int (*seek)(Chan *c, long off, int whence); + Chan *(*clone)(Chan *c, Chan *nc); + Chan *(*attach)(int id, int dev); Chan *(*mount)(Chan *c, char *spec); }; @@ -47,8 +48,7 @@ struct attr { }; -extern Chan *devattach(int id, int dev); -extern Chan * namec(const char *name, int mode); +extern Chan *namec(const char *name, int mode); extern Chan *clone(Chan *c, Chan *nc); extern Chan *attach(int id, int dev); extern void chanclose(Chan *c); @@ -60,6 +60,7 @@ extern void mkentry(Chan *c, Dir *dir, long length, Qid qid, unsigned mode); extern void devlink(void); +extern Chan *devattach(int id, int dev); extern int devseek(Chan *c, long off, int whence); extern Chan *devclone(Chan *c, Chan *nc); extern int devgen(Chan *c, @@ -74,6 +75,11 @@ extern int dirread(Chan *c, unsigned char *buf, int nbytes, const Dirtab *tab, int ntab, Devgen *gen); +int +extern devstat(Chan *dirc, char *file, + unsigned char *buf, int n, + const Dirtab *tab, int ntab, + Devgen *gen); extern Chan *deverrmount(Chan *c, char *spec); extern int deverrwrite(Chan *c, void *buf, int n); diff --git a/drivers/devar.c b/drivers/devar.c @@ -101,6 +101,12 @@ arwalk(Chan *c, const char *name) } static int +arstat(Chan *c, char *file, unsigned char *buf, int n) +{ + return devstat(c, file, buf, n, NULL, 0, argen); +} + +static int arread(Chan *c, void *buf, int n) { long off; @@ -201,6 +207,7 @@ err: const Dev ardevtab = { .id = 'R', + .stat = arstat, .clone = devclone, .attach = devattach, .walk = arwalk, diff --git a/drivers/devcons.c b/drivers/devcons.c @@ -43,6 +43,12 @@ conswalk(Chan *c, const char *name) } static int +consstat(Chan *c, char *file, unsigned char *buf, int n) +{ + return devstat(c, file, buf, n, dirtab, NELEM(dirtab), devgen); +} + +static int consstatus(void *buf, Chan *c, int n) { int i; @@ -365,6 +371,7 @@ consread(Chan *c, void *buf, int n) const Dev consdevtab = { .id = 'c', + .stat = consstat, .clone = devclone, .attach = devattach, .walk = conswalk, diff --git a/drivers/devfip.c b/drivers/devfip.c @@ -153,6 +153,12 @@ fipwalk(Chan *c, const char *name) } static int +fipstat((Chan *c, char *file, unsigned char *buf, int n) +{ + return devstat(c, file, buf, n, NULL, 0, fipgen); +} + +static int fipread(Chan *c, void *buf, int n) { long off; @@ -249,6 +255,7 @@ err: const Dev fipdevtab = { .id = 'F', + .stat = fipstat, .clone = devclone, .attach = devattach, .walk = fipwalk, diff --git a/drivers/devroot.c b/drivers/devroot.c @@ -106,8 +106,15 @@ rootread(Chan *c, void *buf, int n) return buf2chan(c, buf, dp->data, n, dp->length); } +static int +rootstat(Chan *c, char *file, unsigned char *buf, int n) +{ + return devstat(c, file, buf, n, NULL, 0, rootgen); +} + const Dev rootdevtab = { .id = '/', + .stat = rootstat, .clone = devclone, .attach = devattach, .walk = rootwalk, diff --git a/drivers/devuart.c b/drivers/devuart.c @@ -31,6 +31,12 @@ uartwalk(Chan *c, const char *name) return devwalk(c, name, dirtab, NELEM(dirtab), devgen); } +static int +uartstat(Chan *c, char *file, unsigned char *buf, int n) +{ + return devstat(c, file, buf, n, dirtab, NELEM(dirtab), devgen); +} + static Uart * getuart(Chan *c) { @@ -243,6 +249,7 @@ uartlink(Uartphy *phy, Attr *attr) const Dev uartdevtab = { .id = 't', + .stat = uartstat, .clone = devclone, .attach = devattach, .walk = uartwalk, diff --git a/include/rcode/io.h b/include/rcode/io.h @@ -16,7 +16,7 @@ typedef unsigned short Qid; struct dir { char name[NAMELEN]; - unsigned long long length; + long length; unsigned char mode; unsigned char type; unsigned char dev; @@ -38,6 +38,7 @@ extern int p9todir(Dir *dp, unsigned char *buf, int n); extern DIR *opendir(const char *name); extern int readdir(DIR *dir, struct dirent *ent); extern int closedir(DIR *dir); +extern int dirstat(char *name, Dir *dir); enum devflags { O_READ = 1 << 0, @@ -45,6 +46,7 @@ enum devflags { O_RDWR = 1 << 2, O_BIND = 1 << 3, O_DIR = 1 << 4, + O_STAT = 1 << 5, }; /* driver functions */ @@ -56,6 +58,7 @@ extern int read(int fd, void *buf, int n); extern int write(int fd, void *buf, int n); extern int seek(int fd, long off, int whence); extern int bind(char *path, char *where); +extern int stat(char *path, void *buf, int n); extern int kin, kout, kerr; diff --git a/src/lib9p/Makefile b/src/lib9p/Makefile @@ -11,6 +11,7 @@ OBJS = tobytes.o \ opendir.o \ readdir.o \ closedir.o \ + dirstat.o \ TARGET = $(LIBDIR)/lib9p.a diff --git a/src/lib9p/dirstat.c b/src/lib9p/dirstat.c @@ -0,0 +1,17 @@ +#include <errno.h> +#include <rcode/io.h> + +int +dirstat(char *name, Dir *dir) +{ + unsigned char buf[STATLEN]; + int n; + + if ((n = stat(name, buf, STATLEN)) < 0) + return -1; + + if (p9todir(dir, buf, n) < 0) + return -1; + + return 0; +} diff --git a/src/lib9p/p9todir.c b/src/lib9p/p9todir.c @@ -1,4 +1,5 @@ #include <assert.h> +#include <errno.h> #include <stddef.h> #include <rcode/io.h> @@ -32,8 +33,10 @@ p9todir(Dir *dp, unsigned char *buf, int size) STRING(dp->name, NAMELEN, buf, n, size); /* name */ USED(l); - if (len != n) + if (len != n) { + errno = EINVAL; return -1; + } dp->qid = type << 8 | path; return n;