1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
#include <init/malloc.h>
#include <shared/mem.h>
#include <shared/syscalls.h>
#include <stddef.h>
struct node {
const char *name;
size_t len;
struct node *next;
};
struct node *root = NULL;
static struct node *lookup(const char *path, size_t len) {
for (struct node *iter = root; iter; iter = iter->next) {
if (iter->len == len && !memcmp(path, iter->name, len))
return iter;
}
return NULL;
}
static int tmpfs_open(const char *path, struct fs_wait_response *res) {
if (res->len == 0) return -1;
path++;
res->len--;
if (res->len == 0) return 0; /* root */
// no directory support (yet)
if (memchr(path, '/', res->len)) return -1;
if (res->flags & OPEN_CREATE) {
if (lookup(path, res->len)) return -1; /* already exists */
struct node *new = malloc(sizeof *new);
char *namebuf = malloc(res->len);
memcpy(namebuf, path, res->len);
new->name = namebuf;
new->len = res->len;
new->next = root;
root = new;
return 1;
}
return lookup(path, res->len) != 0 ? 1 : -1;
}
void tmpfs_drv(void) {
// TODO replace all the static allocations in drivers with mallocs
static char buf[512];
struct fs_wait_response res;
while (!_syscall_fs_wait(buf, sizeof buf, &res)) {
switch (res.op) {
case VFSOP_OPEN:
_syscall_fs_respond(NULL, tmpfs_open(buf, &res), 0);
break;
case VFSOP_READ:
if (res.id != 0) {
// rw unimplemented
_syscall_fs_respond(NULL, -1, 0);
break;
}
size_t buf_pos = 0;
size_t to_skip = res.offset;
for (struct node *iter = root; iter; iter = iter->next) {
if (iter->len <= to_skip) {
to_skip -= iter->len;
continue;
}
if (iter->len + 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->len - to_skip);
buf_pos += iter->len - to_skip;
buf[buf_pos++] = '\0';
to_skip = 0;
}
_syscall_fs_respond(buf, buf_pos, 0);
break;
default:
_syscall_fs_respond(NULL, -1, 0);
break;
}
}
_syscall_exit(1);
}
|