summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/user/app/init/driver/tmpfs.c30
-rw-r--r--src/user/bootstrap/tar.c36
-rw-r--r--src/user/lib/fs/dir.c37
-rw-r--r--src/user/lib/fs/dir.h14
4 files changed, 69 insertions, 48 deletions
diff --git a/src/user/app/init/driver/tmpfs.c b/src/user/app/init/driver/tmpfs.c
index 7bda37f..5db78f1 100644
--- a/src/user/app/init/driver/tmpfs.c
+++ b/src/user/app/init/driver/tmpfs.c
@@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
+#include <user/lib/fs/dir.h>
struct node {
const char *name;
@@ -40,8 +41,9 @@ static struct node *tmpfs_open(const char *path, struct fs_wait_response *res) {
node = malloc(sizeof *node);
memset(node, 0, sizeof *node);
- char *namebuf = malloc(res->len);
+ char *namebuf = malloc(res->len + 1);
memcpy(namebuf, path, res->len);
+ namebuf[res->len] = '\0';
node->name = namebuf;
node->namelen = res->len;
node->next = root;
@@ -65,27 +67,11 @@ void tmpfs_drv(void) {
case VFSOP_READ:
ptr = (void*)res.id;
if (ptr == &special_root) {
- // TODO directory offset handling
- size_t buf_pos = 0;
- size_t to_skip = res.offset;
-
- for (struct node *iter = root; iter; iter = iter->next) {
- if (iter->namelen <= to_skip) {
- to_skip -= iter->namelen;
- continue;
- }
-
- if (iter->namelen + buf_pos - to_skip >= sizeof(buf)) {
- memcpy(buf + buf_pos, iter->name + to_skip, sizeof(buf) - buf_pos - to_skip);
- buf_pos = sizeof(buf);
- break;
- }
- memcpy(buf + buf_pos, iter->name + to_skip, iter->namelen - to_skip);
- buf_pos += iter->namelen - to_skip;
- buf[buf_pos++] = '\0';
- to_skip = 0;
- }
- _syscall_fs_respond(buf, buf_pos, 0);
+ struct dirbuild db;
+ dir_start(&db, res.offset, buf, sizeof buf);
+ for (struct node *iter = root; iter; iter = iter->next)
+ dir_append(&db, iter->name);
+ _syscall_fs_respond(buf, dir_finish(&db), 0);
} else {
fs_normslice(&res.offset, &res.len, ptr->size, false);
_syscall_fs_respond(ptr->buf + res.offset, res.len, 0);
diff --git a/src/user/bootstrap/tar.c b/src/user/bootstrap/tar.c
index c690f2c..2025ed1 100644
--- a/src/user/bootstrap/tar.c
+++ b/src/user/bootstrap/tar.c
@@ -5,6 +5,7 @@
#include <shared/mem.h>
#include <stdint.h>
#include <unistd.h>
+#include <user/lib/fs/dir.h>
#define BUF_SIZE 64
@@ -61,7 +62,6 @@ static void tar_read(struct fs_wait_response *res, void *base, size_t base_len)
int size;
static char buf[BUF_SIZE]; // TODO reuse a single buffer
- size_t buf_pos = 0;
if (meta == root_fakemeta) type = '5'; /* see comment in tar_open() */
@@ -74,43 +74,27 @@ static void tar_read(struct fs_wait_response *res, void *base, size_t base_len)
break;
case '5': /* directory */
- if (res->offset < 0) {
- _syscall_fs_respond(NULL, -1, 0);
- break;
- }
- size_t to_skip = res->offset;
- meta_len = strlen(meta);
+ struct dirbuild db;
+ dir_start(&db, res->offset, buf, sizeof buf);
- /* find files in dir */
+ meta_len = strlen(meta);
for (size_t off = 0; off < base_len;) {
if (0 != memcmp(base + off + 257, "ustar", 5))
break; // not a metadata sector
- // TODO more meaningful variable names and clean code up
/* check if prefix matches */
- if (0 == memcmp(base + off, meta, meta_len) &&
- *(char*)(base + off + meta_len) != '\0') {
+ if (0 == memcmp(base + off, meta, meta_len)
+ && *(char*)(base + off + meta_len) != '\0') {
char *suffix = base + off + meta_len;
- size_t suffix_len = strlen(suffix);
/* check if the path contains any non-trailing slashes */
char *next = suffix;
+ // TODO strchr
while (*next && *next != '/') next++;
if (*next == '/') next++;
+
if (*next == '\0') {
- if (to_skip > suffix_len) {
- to_skip -= suffix_len;
- } else {
- suffix += to_skip;
- suffix_len -= to_skip;
- to_skip = 0;
-
- /* it doesn't - so let's add it to the result */
- memcpy(buf + buf_pos, suffix, suffix_len);
- buf[buf_pos + suffix_len] = '\0';
- buf_pos += suffix_len + 1;
- // TODO no buffer overrun check
- }
+ if (dir_append(&db, suffix)) break;
}
}
@@ -119,7 +103,7 @@ static void tar_read(struct fs_wait_response *res, void *base, size_t base_len)
off += (size + 511) & ~511; // skip the data sectors
}
- _syscall_fs_respond(buf, buf_pos, 0);
+ _syscall_fs_respond(buf, dir_finish(&db), 0);
break;
default:
diff --git a/src/user/lib/fs/dir.c b/src/user/lib/fs/dir.c
new file mode 100644
index 0000000..25ae606
--- /dev/null
+++ b/src/user/lib/fs/dir.c
@@ -0,0 +1,37 @@
+#include <errno.h>
+#include <string.h>
+#include <user/lib/fs/dir.h>
+
+void dir_start(struct dirbuild *db, long offset, char *buf, size_t buflen) {
+ db->offset = offset;
+ db->buf = buf;
+ db->bpos = 0;
+ db->blen = buflen;
+ db->error = 0;
+
+ if (offset < 0)
+ db->error = -ENOSYS; // TODO
+}
+
+bool dir_append(struct dirbuild *db, const char *name) {
+ if (db->error) return true;
+
+ long len = strlen(name) + 1;
+
+ if (db->offset < len) {
+ name += db->offset;
+ len -= db->offset;
+ db->offset = 0;
+
+ // TODO no buffer overrun check
+ memcpy(db->buf + db->bpos, name, len);
+ db->bpos += len;
+ } else {
+ db->offset -= len;
+ }
+ return false;
+}
+
+long dir_finish(struct dirbuild *db) {
+ return db->error ? db->error : db->bpos;
+}
diff --git a/src/user/lib/fs/dir.h b/src/user/lib/fs/dir.h
new file mode 100644
index 0000000..1a8c7f5
--- /dev/null
+++ b/src/user/lib/fs/dir.h
@@ -0,0 +1,14 @@
+#pragma once
+#include <stdbool.h>
+#include <stddef.h>
+
+struct dirbuild {
+ long offset;
+ char *buf;
+ long bpos, blen;
+ long error;
+};
+
+void dir_start(struct dirbuild *db, long offset, char *buf, size_t buflen);
+bool dir_append(struct dirbuild *db, const char *name);
+long dir_finish(struct dirbuild *db);