commit 2a246405c053e425bd04ea2945bc5d2e642294c8
parent 8e03e0ea337ea4eca6c8d905062bbacb6dffb9c3
Author: Ambroise Vincent <ambroise.vincent@arm.com>
Date: Thu, 9 May 2019 14:32:07 +0100
[dev] Fix stat and dirstat
Change-Id: Ic127837d09ccf3af695bf62d8fbf7377fcddfa1d
Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com>
Diffstat:
4 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/drivers/dev.c b/drivers/dev.c
@@ -139,7 +139,7 @@ buf2chan(Chan *c, void *dst, void *src, int nbytes, long len)
}
static Chan *
-mntpoint(Chan *c)
+mntpoint(int type, Qid qid)
{
Chan *cn;
struct mpoint *mp;
@@ -147,7 +147,7 @@ mntpoint(Chan *c)
for (mp = mpoints; mp < &mpoints[NR_MPOINTS]; mp++) {
if ((cn = mp->new) == NULL)
continue;
- if (cn->type == c->type && cn->qid == c->qid)
+ if (cn->type == type && cn->qid == qid)
return mp->old;
}
@@ -221,7 +221,7 @@ namec(const char *name, int mode)
chanclose(c);
return NULL;
}
- mnt = mntpoint(c);
+ mnt = mntpoint(c->type, c->qid);
if (mnt)
clone(mnt, c);
}
@@ -367,7 +367,7 @@ devstat(Chan *dirc, char *file,
{
int i, r = -1;
Dir dir;
- Chan *c;
+ Chan *c, *mnt;
if ((c = namec(file, O_STAT)) == NULL)
return -1;
@@ -380,7 +380,12 @@ devstat(Chan *dirc, char *file,
r = -1;
goto leave;
case 1:
- if (dir.qid != c->qid)
+ mnt = mntpoint(dir.type, dir.qid);
+ if (mnt) {
+ dir.qid = mnt->qid;
+ dir.type = mnt->type;
+ }
+ if (dir.qid != c->qid || dir.type != c->type)
continue;
r = dirtop9(&dir, buf, n);
goto leave;
@@ -400,23 +405,28 @@ stat(char *path, void *buf, int n)
Chan *c;
char *p, dirname[NAMELEN];
- if (n < STATLEN) {
+ if (n < DIRLEN) {
errno = EINVAL;
return -1;
}
- p = strrchr(path, '/');
- if (!p) {
- errno = ENOENT;
+ len = strlen(path);
+ if (len + 1 > sizeof(dirname)) {
+ errno = ENAMETOOLONG;
return -1;
}
+ memcpy(dirname, path, len);
+ for (p = dirname + len; p > dirname; --p) {
+ if (*p != '/')
+ break;
+ }
- if ((len = p - path) > NAMELEN-1) {
- errno = EINVAL;
+ p = memrchr(dirname, '/', p - dirname);
+ if (!p) {
+ errno = ENOENT;
return -1;
}
- memcpy(dirname, path, len);
- dirname[len] = '\0';
+ dirname[p - dirname + 1] = '\0';
if ((c = namec(dirname, O_STAT)) == NULL)
return -1;
diff --git a/drivers/devfip.c b/drivers/devfip.c
@@ -153,7 +153,7 @@ fipwalk(Chan *c, const char *name)
}
static int
-fipstat((Chan *c, char *file, unsigned char *buf, int n)
+fipstat(Chan *c, char *file, unsigned char *buf, int n)
{
return devstat(c, file, buf, n, NULL, 0, fipgen);
}
diff --git a/include/string.h b/include/string.h
@@ -19,6 +19,7 @@ extern int strcoll(const char *s1, const char *s2);
extern int strncmp(const char *s1, const char *s2, size_t n);
extern size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n);
extern void *memchr(const void *s, int c, size_t n);
+extern void *memrchr(const void *s, int c, size_t n);
extern char *strchr(const char *s, int c);
extern size_t strcspn(const char *s1, const char *s2);
extern char *strpbrk(const char *s1, const char *s2);
diff --git a/src/lib9p/dirstat.c b/src/lib9p/dirstat.c
@@ -4,10 +4,10 @@
int
dirstat(char *name, Dir *dir)
{
- unsigned char buf[STATLEN];
+ unsigned char buf[DIRLEN];
int n;
- if ((n = stat(name, buf, STATLEN)) < 0)
+ if ((n = stat(name, buf, sizeof(buf))) < 0)
return -1;
if (p9todir(dir, buf, n) < 0)