diff options
author | dzwdz | 2022-07-30 20:18:51 +0200 |
---|---|---|
committer | dzwdz | 2022-07-30 20:18:51 +0200 |
commit | fdeac40f867ca0c43ade53cce4b77bb146b10aae (patch) | |
tree | 9845e8708cb12d7e27a633d37a83b40eab7ea396 /src | |
parent | b26399ad055aae9ef4b01694967515235568cd85 (diff) |
user/fs: create a shared library for handling directory reads
Diffstat (limited to 'src')
-rw-r--r-- | src/user/app/init/driver/tmpfs.c | 30 | ||||
-rw-r--r-- | src/user/bootstrap/tar.c | 36 | ||||
-rw-r--r-- | src/user/lib/fs/dir.c | 37 | ||||
-rw-r--r-- | src/user/lib/fs/dir.h | 14 |
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); |