commit 5dce7e124ce0295bdbad9200116ca0f05936ace7
parent a6b5d915eca0a0031e0aea86553c0dc11282ded3
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Tue, 12 Feb 2019 13:01:30 +0000
[drivers] Add diretory read support
Change-Id: I389769409ef6fceb14ac7273fddac974be6c611c
Diffstat:
21 files changed, 264 insertions(+), 58 deletions(-)
diff --git a/drivers/dev.c b/drivers/dev.c
@@ -241,6 +241,7 @@ devattach(const char *spec, int id)
return NULL;
c->qid = CHDIR;
c->type = devtype(id);
+
return c;
}
@@ -285,10 +286,10 @@ devdirread(Chan *c,
case -1:
return cnt;
case 0:
- c->offset += DIRLEN;
break;
case 1:
- n = dirto9p(&dir, buf + cnt, -1);
+ c->offset += DIRLEN;
+ n = dirto9p(&dir, buf + cnt, nbytes);
nbytes -= n;
cnt += n;
}
@@ -354,7 +355,6 @@ read(int fd, void *buf, int n)
return -1;
}
n = devtab[c->type]->read(c, buf, n);
- c->offset += n;
return n;
}
@@ -372,7 +372,6 @@ write(int fd, void *buf, int n)
}
n = devtab[c->type]->write(c, buf, n);
- c->offset += n;
return n;
}
diff --git a/include/libk.h b/include/libk.h
@@ -1,8 +1,20 @@
#include <stdarg.h>
#include <stddef.h>
+#include <rcode/9p.h>
+
#include "features.h"
+struct dirent {
+ char d_name[NAMELEN];
+};
+
+typedef struct {
+ int fd;
+ unsigned char buf[DIRLEN];
+ struct dirent ent;
+} DIR;
+
extern int kprint(const char *fmt, ...) KPRINTFMT;
extern int ksnprint(char *str, size_t len, const char *fmt, ...) KSNPRINTFMT;
extern char *kgets(char *s, int n);
@@ -12,3 +24,7 @@ extern int kputs(const char *s);
extern int kvprint(const char *fmt, va_list va);
extern void kerror(const char *s);
extern int putenv(char *name);
+
+extern DIR *kopendir(DIR *dir, const char *name);
+extern struct dirent *kreaddir(DIR *dir);
+extern int kclosedir(DIR *dir);
diff --git a/include/rcode/9p.h b/include/rcode/9p.h
@@ -1,3 +1,6 @@
+#ifndef LIBK_H_
+#define LIBK_H_
+
#define NAMELEN 8
#define STATLEN 41
#define ROOTLEN (2 + 4)
@@ -16,4 +19,7 @@ struct dir {
Qid qid;
};
-extern int dirto9p(Dir *dp, unsigned char *buf, int n);
+extern int dirtop9(Dir *dp, unsigned char *buf, int n);
+extern int p9todir(Dir *dp, unsigned char *buf, int n);
+
+#endif
diff --git a/scripts/rules.mk b/scripts/rules.mk
@@ -12,7 +12,7 @@ SRCDIR = $(PROJECTDIR)/src
SCRIPTDIR = $(PROJECTDIR)/scripts
CONFDIR = $(PROJECTDIR)/config
INCLUDES = -I$(INCDIR) -I$(INCDIR)/bits/$(ARCH)/ -I$(INCDIR)/bits/$(SYS)
-LIBS = -l9p -lhdl -lrmu -lk -lc
+LIBS = -lhdl -lrmu -lk -l9p -lc
DRIVERS = $(PROJECTDIR)/drivers/builtin.o
ENVIRON = $(SCRIPTDIR)/env.sh
diff --git a/src/lib9p/Makefile b/src/lib9p/Makefile
@@ -4,7 +4,11 @@ include $(PROJECTDIR)/scripts/rules.mk
OBJS = tobytes.o \
tostring.o \
- dirto9p.o \
+ dirtop9.o \
+ frombytes.o \
+ fromstring.o \
+ p9todir.o \
+
TARGET = $(LIBDIR)/lib9p.a
diff --git a/src/lib9p/conv.h b/src/lib9p/conv.h
@@ -1,8 +0,0 @@
-#define CHAR(x,p) (p = tobytes(p, x, 1))
-#define SHORT(x,p) (p = tobytes(p, x, 2))
-#define LONG(x,p) (p = tobytes(p, x, 4))
-#define LLONG(x,p) (p = tobytes(p, x, 8))
-#define STRING(s,p) (p = tostring(p, s))
-
-unsigned char *tobytes(unsigned char *p, unsigned long long v, int nbytes);
-unsigned char *tostring(unsigned char *p, char *s);
diff --git a/src/lib9p/convfr9p.h b/src/lib9p/convfr9p.h
@@ -0,0 +1,8 @@
+#define CHAR(v, b, n, m) (v = frombytes(b, &n, m, 1))
+#define SHORT(v, b, n, m) (v = frombytes(b, &n, m, 2))
+#define LONG(v, b, n, m) (v = frombytes(b, &n, m, 4))
+#define LLONG(v, b, n, m) (v = frombytes(b, &n, m, 8))
+#define STRING(str, s, b, n, m) (fromstring(b, &n, m, str, s))
+
+extern long long frombytes(unsigned char *b, int *n, int max, int nbytes);
+extern char *fromstring(unsigned char *b, int *n, int max, char *str, int s);
diff --git a/src/lib9p/convto9p.h b/src/lib9p/convto9p.h
@@ -0,0 +1,8 @@
+#define CHAR(x,p) (p = tobytes(p, x, 1))
+#define SHORT(x,p) (p = tobytes(p, x, 2))
+#define LONG(x,p) (p = tobytes(p, x, 4))
+#define LLONG(x,p) (p = tobytes(p, x, 8))
+#define STRING(s,p) (p = tostring(p, s))
+
+unsigned char *tobytes(unsigned char *p, unsigned long long v, int nbytes);
+unsigned char *tostring(unsigned char *p, char *s);
diff --git a/src/lib9p/dirto9p.c b/src/lib9p/dirto9p.c
@@ -1,36 +0,0 @@
-#include <assert.h>
-
-#include <rcode/9p.h>
-
-#include "conv.h"
-
-int
-dirto9p(Dir *dp, unsigned char *buf, int n)
-{
- int len;
- unsigned char *p;
-
- if (n < DIRLEN)
- return 0;
-
- p = buf + 2;
- SHORT(dp->type, p); /* type */
- LONG(dp->dev, p); /* dev */
- CHAR(dp->qid >> 8, p); /* qid.type */
- LONG(0, p); /* qid.vers */
- LLONG(dp->qid, p); /* qid.path */
- LONG(0, p); /* mode */
- LONG(0, p); /* atime */
- LONG(0, p); /* mtime */
- LLONG(dp->length, p); /* length */
- STRING(dp->name, p); /* name */
- STRING("root", p); /* uid */
- STRING("root", p); /* gid */
- STRING("root", p); /* muid */
- len = p -buf;
- SHORT(len, buf); /* size */
-
- assert(len < DIRLEN);
-
- return len;
-}
diff --git a/src/lib9p/dirtop9.c b/src/lib9p/dirtop9.c
@@ -0,0 +1,36 @@
+#include <assert.h>
+
+#include <rcode/9p.h>
+
+#include "convto9p.h"
+
+int
+dirto9p(Dir *dp, unsigned char *buf, int n)
+{
+ int len;
+ unsigned char *p;
+
+ if (n < DIRLEN)
+ return 0;
+
+ p = buf + 2;
+ SHORT(dp->type, p); /* type */
+ LONG(dp->dev, p); /* dev */
+ CHAR(dp->qid >> 8, p); /* qid.type */
+ LONG(0, p); /* qid.vers */
+ LLONG(dp->qid, p); /* qid.path */
+ LONG(0, p); /* mode */
+ LONG(0, p); /* atime */
+ LONG(0, p); /* mtime */
+ LLONG(dp->length, p); /* length */
+ STRING("root", p); /* uid */
+ STRING("root", p); /* gid */
+ STRING("root", p); /* muid */
+ STRING(dp->name, p); /* name */
+ len = p - buf;
+ SHORT(len, buf); /* size */
+
+ assert(len < DIRLEN);
+
+ return len;
+}
diff --git a/src/lib9p/frombytes.c b/src/lib9p/frombytes.c
@@ -0,0 +1,24 @@
+#include "convfr9p.h"
+
+long long
+frombytes(unsigned char *bp, int *n, int max, int nbytes)
+{
+ int i;
+ unsigned long long v;
+
+ if (*n == -1)
+ return 0;
+
+ if (*n + nbytes > max) {
+ *n = -1;
+ return -1;
+ }
+
+ bp += *n;
+ *n += nbytes;
+ v = 0;
+ for (i = 0; i < nbytes; i++)
+ v |= bp[ i] << (8 * i);
+
+ return v;
+}
diff --git a/src/lib9p/fromstring.c b/src/lib9p/fromstring.c
@@ -0,0 +1,34 @@
+#include <string.h>
+
+#include "convfr9p.h"
+
+char *
+fromstring(unsigned char *p, int *n, int max, char *s, int size)
+{
+ int len;
+
+ if (*n == -1)
+ goto error;
+
+ len = frombytes(p, n, max, 2);
+ if (len == -1)
+ goto error;
+
+ if (*n + len > max)
+ goto error;
+
+ if (len >= size)
+ goto error;
+
+ if (s) {
+ memcpy(s, p + *n, len);
+ s[len] = '\0';
+ }
+ *n += len;
+
+ return s;
+
+error:
+ *n = -1;
+ return NULL;
+}
diff --git a/src/lib9p/p9todir.c b/src/lib9p/p9todir.c
@@ -0,0 +1,40 @@
+#include <assert.h>
+#include <stddef.h>
+
+#include <rcode/9p.h>
+
+#include "convfr9p.h"
+
+#define USED(x) ((void) x)
+#define USERLEN 20
+
+int
+p9todir(Dir *dp, unsigned char *buf, int size)
+{
+ int n, len;
+ long l;
+ unsigned long long type, path;
+
+ n = 0;
+ SHORT(len, buf, n, size); /* len */
+ SHORT(dp->type, buf, n, size); /* type */
+ LONG(dp->dev, buf, n, size); /* dev */
+ CHAR(type, buf, n, size); /* qid.type */
+ LONG(l, buf, n, size); /* qid.vers */
+ LLONG(path, buf, n, size); /* qid.path */
+ LONG(l, buf, n, size); /* mode */
+ LONG(l, buf, n, size); /* atime */
+ LONG(l, buf, n, size); /* mtime */
+ LLONG(dp->length, buf, n, size); /* length */
+ STRING(NULL, USERLEN, buf, n, size); /* uid */
+ STRING(NULL, USERLEN, buf, n, size); /* gid */
+ STRING(NULL, USERLEN, buf, n, size); /* muid */
+ STRING(dp->name, NAMELEN, buf, n, size); /* name */
+ USED(l);
+
+ if (len != n)
+ return -1;
+ dp->qid = type << 8 | path;
+
+ return n;
+}
diff --git a/src/lib9p/tobytes.c b/src/lib9p/tobytes.c
@@ -1,4 +1,4 @@
-#include "conv.h"
+#include "convto9p.h"
unsigned char *
tobytes(unsigned char *p, unsigned long long v, int n)
diff --git a/src/lib9p/tostring.c b/src/lib9p/tostring.c
@@ -1,6 +1,6 @@
#include <string.h>
-#include "conv.h"
+#include "convto9p.h"
unsigned char *
tostring(unsigned char *p, char *s)
diff --git a/src/libk/Makefile b/src/libk/Makefile
@@ -12,6 +12,9 @@ OBJS = doprnt.o \
kgets.o \
kerror.o \
putenv-$(MODE).o \
+ kopendir.o \
+ kreaddir.o \
+ kclosedir.o \
__assert.o \
TARGET = $(LIBDIR)/libk.a
diff --git a/src/libk/kclosedir.c b/src/libk/kclosedir.c
@@ -0,0 +1,8 @@
+#include <libk.h>
+#include <rcode/rcode.h>
+
+int
+kclosedir(DIR *dir)
+{
+ return close(dir->fd);
+}
diff --git a/src/libk/kopendir.c b/src/libk/kopendir.c
@@ -0,0 +1,20 @@
+#include <errno.h>
+
+#include <libk.h>
+#include <rcode/rcode.h>
+
+DIR *
+kopendir(DIR *dir, const char *name)
+{
+ int fd;
+
+ if ((fd = open(name, O_READ)) < 0) {
+ errno = ENOENT;
+ return NULL;
+ }
+ dir->fd = fd;
+
+ /* TODO: check that it is actually a directory */
+
+ return dir;
+}
diff --git a/src/libk/kreaddir.c b/src/libk/kreaddir.c
@@ -0,0 +1,21 @@
+#include <string.h>
+
+#include <libk.h>
+#include <rcode/rcode.h>
+
+struct dirent *
+kreaddir(DIR *dir)
+{
+ int n;
+ Dir dentry;
+
+ if ((n = read(dir->fd, dir->buf, sizeof(dir->buf))) < 0)
+ return NULL;
+
+ if (p9todir(&dentry, dir->buf, n) < 0)
+ return NULL;
+
+ strcpy(dir->ent.d_name, dentry.name);
+
+ return &dir->ent;
+}
diff --git a/src/romfw/dlang.c b/src/romfw/dlang.c
@@ -238,6 +238,24 @@ do_cat(const struct cmd *cmd, struct args *args)
}
static int
+do_ls(const struct cmd *cmd, struct args *args)
+{
+ DIR dir;
+ struct dirent *d;
+
+ if (!kopendir(&dir, args->argv[1]))
+ return -1;
+
+ while ((d = kreaddir(&dir)) != NULL)
+ kprint(PREFIX "%s\n", d->d_name);
+
+ if (kclosedir(&dir))
+ return -1;
+
+ return 0;
+}
+
+static int
do_chdir(const struct cmd *cmd, struct args *args)
{
return 0;
@@ -411,6 +429,13 @@ static const struct cmd cmds[] = {
.helpmsg = "change the current directory: cd path",
},
{
+ .name = "ls",
+ .eval = do_ls,
+ .min = 2,
+ .max = 2,
+ .helpmsg = "list content of a directory: ls path",
+ },
+ {
.name = NULL
}
};
diff --git a/target/native/rom.c b/target/native/rom.c
@@ -131,12 +131,10 @@ namespace(void)
int fd;
if (bind("#t", "/dev") < 0)
- panic("openfds1");
+ panic("namespace:bind");
- fd = open("/dev/uart0/raw", O_READ | O_WRITE);
-
- if (fd != 0)
- panic("openfds2");
+ if (open("/dev/uart0/raw", O_READ | O_WRITE) != 0)
+ panic("namespace:open");
}
void