|
| 1 | +#include <rtthread.h> |
| 2 | +#include <stdlib.h> |
| 3 | +#include <stdint.h> |
| 4 | +#include <dfs_fs.h> |
| 5 | +#include <dfs_ramfs.h> |
| 6 | + |
| 7 | +#define RAMFS_COUNT_MAX 4 |
| 8 | + |
| 9 | +static struct ramfs_entry { |
| 10 | + char* path; |
| 11 | + uint8_t* addr; |
| 12 | + struct dfs_ramfs* ramfs; |
| 13 | + uint32_t size; |
| 14 | + uint8_t f_rmdir; |
| 15 | +} ramfs_array[RAMFS_COUNT_MAX]; |
| 16 | + |
| 17 | +static uint32_t ramfs_count = 0; |
| 18 | + |
| 19 | +static void usage(void) |
| 20 | +{ |
| 21 | + rt_kprintf("mount: ramfs_tool <mountpoint> <size>\n"); |
| 22 | + rt_kprintf("unmount: ramfs_tool <mountpoint>\n"); |
| 23 | +} |
| 24 | + |
| 25 | +static int find_by_path(char* path) |
| 26 | +{ |
| 27 | + for (int i = 0; i < RAMFS_COUNT_MAX; i++) { |
| 28 | + if (ramfs_array[i].path && (rt_strcmp(ramfs_array[i].path, path) == 0)) |
| 29 | + return i; |
| 30 | + } |
| 31 | + return -1; |
| 32 | +} |
| 33 | + |
| 34 | +static int add_entry(struct ramfs_entry* entry) |
| 35 | +{ |
| 36 | + int idx = -1; |
| 37 | + |
| 38 | + for (int i = 0; i < RAMFS_COUNT_MAX; i++) { |
| 39 | + if (ramfs_array[i].path == 0) { |
| 40 | + idx = i; |
| 41 | + break; |
| 42 | + } |
| 43 | + } |
| 44 | + if (idx < 0) |
| 45 | + return -1; |
| 46 | + |
| 47 | + ramfs_array[idx] = *entry; |
| 48 | + ramfs_count++; |
| 49 | + return 0; |
| 50 | +} |
| 51 | + |
| 52 | +static int del_entry(char* path) |
| 53 | +{ |
| 54 | + int idx = find_by_path(path); |
| 55 | + if (idx < 0) |
| 56 | + return -1; |
| 57 | + |
| 58 | + rt_memheap_detach(&ramfs_array[idx].ramfs->memheap); |
| 59 | + if (ramfs_array[idx].f_rmdir) |
| 60 | + rmdir(ramfs_array[idx].path); |
| 61 | + rt_free(ramfs_array[idx].path); |
| 62 | + ramfs_array[idx].path = NULL; |
| 63 | + rt_free(ramfs_array[idx].addr); |
| 64 | + ramfs_array[idx].addr = 0; |
| 65 | + ramfs_count--; |
| 66 | + return 0; |
| 67 | +} |
| 68 | + |
| 69 | +static int ramfs_mount(char* path, uint32_t size) |
| 70 | +{ |
| 71 | + if (ramfs_count >= RAMFS_COUNT_MAX) { |
| 72 | + rt_kprintf("ramfs mount number is too many\n"); |
| 73 | + return -ENOSPC; |
| 74 | + } |
| 75 | + path = dfs_normalize_path(NULL, path); |
| 76 | + if (path == NULL) { |
| 77 | + rt_kprintf("Invalid path\n"); |
| 78 | + return -ENOTDIR; |
| 79 | + } |
| 80 | + if (find_by_path(path) >= 0) { |
| 81 | + rt_free(path); |
| 82 | + rt_kprintf("This path has been mounted\n"); |
| 83 | + return -EEXIST; |
| 84 | + } |
| 85 | + if (size == 0) { |
| 86 | + rt_free(path); |
| 87 | + rt_kprintf("This size is invalid\n"); |
| 88 | + return -EINVAL; |
| 89 | + } |
| 90 | + uint8_t* buf = rt_malloc(size); |
| 91 | + if (buf == NULL) { |
| 92 | + rt_free(path); |
| 93 | + rt_kprintf("ramfs malloc fail\n"); |
| 94 | + return -ENOMEM; |
| 95 | + } |
| 96 | + struct dfs_ramfs* ramfs = dfs_ramfs_create(buf, size); |
| 97 | + if (ramfs == NULL) { |
| 98 | + rt_free(buf); |
| 99 | + rt_free(path); |
| 100 | + rt_kprintf("ramfs create fail\n"); |
| 101 | + return -ENOMEM; |
| 102 | + } |
| 103 | + int fd = open(path, O_RDONLY | O_DIRECTORY); |
| 104 | + int f_rmdir = 0; |
| 105 | + if (fd < 0) { |
| 106 | + mkdir(path, 0); |
| 107 | + f_rmdir = 1; |
| 108 | + } else { |
| 109 | + close(fd); |
| 110 | + } |
| 111 | + if (dfs_mount(RT_NULL, path, "ram", 0, ramfs) != 0) { |
| 112 | + rt_free(buf); |
| 113 | + rt_free(path); |
| 114 | + rt_kprintf("ramfs mount fail\n"); |
| 115 | + return -EPERM; |
| 116 | + } |
| 117 | + struct ramfs_entry entry; |
| 118 | + entry.path = path; |
| 119 | + entry.addr = buf; |
| 120 | + entry.ramfs = ramfs; |
| 121 | + entry.size = size; |
| 122 | + entry.f_rmdir = f_rmdir; |
| 123 | + add_entry(&entry); |
| 124 | + return 0; |
| 125 | +} |
| 126 | + |
| 127 | +static int ramfs_unmount(char* path) |
| 128 | +{ |
| 129 | + path = dfs_normalize_path(NULL, path); |
| 130 | + if (path == NULL) { |
| 131 | + rt_kprintf("Invalid path\n"); |
| 132 | + return -ENOTDIR; |
| 133 | + } |
| 134 | + if (find_by_path(path) < 0) { |
| 135 | + rt_free(path); |
| 136 | + rt_kprintf("This path is not mounted\n"); |
| 137 | + return -EINVAL; |
| 138 | + } |
| 139 | + if (dfs_unmount(path) != 0) { |
| 140 | + rt_free(path); |
| 141 | + rt_kprintf("ramfs unmount fail\n"); |
| 142 | + return -EPERM; |
| 143 | + } |
| 144 | + del_entry(path); |
| 145 | + rt_free(path); |
| 146 | + return 0; |
| 147 | +} |
| 148 | + |
| 149 | +int ramfs_tool(int argc, char** argv) |
| 150 | +{ |
| 151 | + char* path; |
| 152 | + |
| 153 | + if (argc == 3) { |
| 154 | + path = argv[1]; |
| 155 | + uint32_t size = strtoul(argv[2], 0, 0); |
| 156 | + return ramfs_mount(path, size); |
| 157 | + } else if (argc == 2) { |
| 158 | + path = argv[1]; |
| 159 | + return ramfs_unmount(path); |
| 160 | + } else { |
| 161 | + usage(); |
| 162 | + } |
| 163 | + return 0; |
| 164 | +} |
| 165 | +MSH_CMD_EXPORT(ramfs_tool, ramfs tool); |
| 166 | + |
| 167 | +#define RAMFS_CTL_MOUNT _IOW('R', 0, int) |
| 168 | +#define RAMFS_CTL_UNMOUNT _IOW('R', 1, int) |
| 169 | + |
| 170 | +struct ramfs_ctl_args { |
| 171 | + char path[64]; |
| 172 | + uint32_t size; |
| 173 | +}; |
| 174 | + |
| 175 | +static struct rt_device ramfs_dev; |
| 176 | + |
| 177 | +static rt_err_t ramfs_open(rt_device_t dev, rt_uint16_t oflag) |
| 178 | +{ |
| 179 | + return 0; |
| 180 | +} |
| 181 | + |
| 182 | +static rt_err_t ramfs_close(rt_device_t dev) |
| 183 | +{ |
| 184 | + return 0; |
| 185 | +} |
| 186 | + |
| 187 | +static rt_err_t ramfs_control(rt_device_t dev, int cmd, void *args) |
| 188 | +{ |
| 189 | + int ret; |
| 190 | + struct ramfs_ctl_args ctl; |
| 191 | + |
| 192 | + lwp_get_from_user(&ctl, args, sizeof(ctl)); |
| 193 | + if (cmd == RAMFS_CTL_MOUNT) { |
| 194 | + ret = ramfs_mount(ctl.path, ctl.size); |
| 195 | + } else if (cmd == RAMFS_CTL_UNMOUNT) { |
| 196 | + ret = ramfs_unmount(ctl.path); |
| 197 | + } else { |
| 198 | + ret = -EINVAL; |
| 199 | + } |
| 200 | + return ret; |
| 201 | +} |
| 202 | + |
| 203 | +static const struct rt_device_ops ramfs_ops = { |
| 204 | + RT_NULL, |
| 205 | + ramfs_open, |
| 206 | + ramfs_close, |
| 207 | + RT_NULL, |
| 208 | + RT_NULL, |
| 209 | + ramfs_control, |
| 210 | +}; |
| 211 | + |
| 212 | +int ramfs_device_init(void) |
| 213 | +{ |
| 214 | + ramfs_dev.type = RT_Device_Class_Miscellaneous; |
| 215 | + ramfs_dev.user_data = RT_NULL; |
| 216 | + |
| 217 | + rt_device_register(&ramfs_dev, "ramfs", RT_DEVICE_FLAG_RDWR); |
| 218 | + |
| 219 | + ramfs_dev.ops = &ramfs_ops; |
| 220 | + |
| 221 | + return 0; |
| 222 | +} |
| 223 | +INIT_DEVICE_EXPORT(ramfs_device_init); |
0 commit comments