swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 1 | #include "vfs.h" |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 2 | #include "io.h" |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 3 | |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 4 | struct fs_node root, dev, initrd; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 5 | struct fs_vtable root_v, dev_v; |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 6 | |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 7 | uint fs_read(struct fs_node *node, size_t offset, size_t size, uchar *buffer) |
| 8 | { |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 9 | if (node->mount) |
| 10 | node = node->mount; |
| 11 | |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 12 | if (!node || !node->vtable || !node->vtable->read) |
| 13 | return 0; |
| 14 | |
| 15 | return node->vtable->read(node, offset, size, buffer); |
| 16 | } |
| 17 | |
| 18 | uint fs_write(struct fs_node *node, size_t offset, size_t size, uchar *buffer) |
| 19 | { |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 20 | if (node->mount) |
| 21 | node = node->mount; |
| 22 | |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 23 | if (!node || !node->vtable || !node->vtable->write) |
| 24 | return 0; |
| 25 | |
| 26 | return node->vtable->write(node, offset, size, buffer); |
| 27 | } |
| 28 | |
| 29 | void fs_open(struct fs_node *node) |
| 30 | { |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 31 | if (node->mount) |
| 32 | node = node->mount; |
| 33 | |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 34 | if (!node || !node->vtable || !node->vtable->open) |
| 35 | return; |
| 36 | |
| 37 | node->vtable->open(node); |
| 38 | } |
| 39 | |
| 40 | void fs_close(struct fs_node *node) |
| 41 | { |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 42 | if (node->mount) |
| 43 | node = node->mount; |
| 44 | |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 45 | if (!node || !node->vtable || !node->vtable->close) |
| 46 | return; |
| 47 | |
| 48 | node->vtable->close(node); |
| 49 | } |
| 50 | |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 51 | bool fs_readdir(struct fs_node *node, uint index, struct fs_dirent *out) |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 52 | { |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 53 | if (node->mount) |
| 54 | node = node->mount; |
| 55 | |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 56 | if (!node || !node->vtable || !node->vtable->readdir || |
| 57 | (node->flags & 7) != FS_DIRECTORY) |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 58 | return false; |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 59 | |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 60 | return node->vtable->readdir(node, index, out); |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 61 | } |
| 62 | |
swissChili | 480f176 | 2021-07-26 22:17:34 -0700 | [diff] [blame] | 63 | struct fs_node *fs_finddir(struct fs_node *node, char *name, uint name_len) |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 64 | { |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 65 | if (node->mount) |
| 66 | node = node->mount; |
| 67 | |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 68 | if (!node || !node->vtable || !node->vtable->finddir || |
| 69 | (node->flags & 7) != FS_DIRECTORY) |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 70 | return NULL; |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 71 | |
swissChili | 480f176 | 2021-07-26 22:17:34 -0700 | [diff] [blame] | 72 | return node->vtable->finddir(node, name, name_len); |
swissChili | 8efa492 | 2021-03-02 16:34:49 -0800 | [diff] [blame] | 73 | } |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 74 | |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 75 | bool root_readdir(struct fs_node *node, uint index, struct fs_dirent *out) |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 76 | { |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 77 | if (node == &root && index == 0) |
| 78 | { |
| 79 | // devfs |
| 80 | memcpy(out->name, "dev", 4); |
| 81 | out->inode = -1; |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 82 | |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 83 | return true; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 84 | } |
| 85 | else |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 86 | return false; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 87 | } |
| 88 | |
swissChili | 480f176 | 2021-07-26 22:17:34 -0700 | [diff] [blame] | 89 | struct fs_node *root_finddir(struct fs_node *node, char *name, uint name_len) |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 90 | { |
swissChili | 480f176 | 2021-07-26 22:17:34 -0700 | [diff] [blame] | 91 | if (!strncmp(name, "dev", name_len)) |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 92 | { |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 93 | return &dev; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 94 | } |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 95 | else return NULL; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 96 | } |
| 97 | |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 98 | bool dev_readdir(struct fs_node *node, uint index, struct fs_dirent *out) |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 99 | { |
| 100 | if (node == &dev && index == 0) |
| 101 | { |
| 102 | // initrd |
| 103 | memcpy(out->name, "dirent", 7); |
| 104 | out->inode = -1; |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 105 | return true; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 106 | } |
| 107 | else |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 108 | return false; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 109 | } |
| 110 | |
swissChili | 480f176 | 2021-07-26 22:17:34 -0700 | [diff] [blame] | 111 | struct fs_node *dev_finddir(struct fs_node *node, char *name, uint name_len) |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 112 | { |
| 113 | if (node != &dev) |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 114 | return NULL; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 115 | |
swissChili | 480f176 | 2021-07-26 22:17:34 -0700 | [diff] [blame] | 116 | if (!strncmp(name, "initrd", MIN(name_len, FS_MAX_NAME_LEN))) |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 117 | { |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 118 | return &initrd; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 119 | } |
| 120 | |
swissChili | b7fe899 | 2021-03-10 16:25:47 -0800 | [diff] [blame] | 121 | return NULL; |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 122 | } |
| 123 | |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 124 | static struct fs_vtable root_vt = |
| 125 | { |
| 126 | NULL, |
| 127 | }; |
| 128 | |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 129 | void init_vfs() |
| 130 | { |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 131 | root.mount = NULL; |
| 132 | root.inode = 0; // fake inode |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 133 | root.flags = FS_DIRECTORY; |
swissChili | a664e72 | 2021-07-27 17:47:55 -0700 | [diff] [blame] | 134 | root.mask = ~0; |
| 135 | root.gid = root.uid = 0; |
| 136 | root.size = 0; |
| 137 | root.vtable = &root_vt; |
swissChili | f544862 | 2021-03-08 20:17:36 -0800 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | uint fs_mount(struct fs_node *target, struct fs_node *source) |
| 141 | { |
| 142 | if (target->flags ^ FS_DIRECTORY) |
| 143 | return 1; // target is not a directory |
| 144 | |
| 145 | if (target->flags & FS_MOUNT) |
| 146 | return 2; // already mounted |
| 147 | |
| 148 | if (source->flags ^ FS_DIRECTORY) |
| 149 | return 3; // source is not a directory |
| 150 | |
| 151 | target->flags |= FS_MOUNT; |
| 152 | target->mount = source; |
| 153 | |
| 154 | return 0; |
swissChili | 6c0519e | 2021-03-07 19:40:23 -0800 | [diff] [blame] | 155 | } |