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:
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;