diff --git a/mkrtos_user/server/init/src/nsfs/CMakeLists.txt b/mkrtos_user/server/init/src/nsfs/CMakeLists.txt index fef1d66b4..215e1bd47 100644 --- a/mkrtos_user/server/init/src/nsfs/CMakeLists.txt +++ b/mkrtos_user/server/init/src/nsfs/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.31.5) +cmake_minimum_required(VERSION 3.29.0) project(nsfs VERSION 0.1.0 LANGUAGES C) set(CMAKE_BUILD_TYPE Debug) add_executable(nsfs ns.c nsfs.c main.c) diff --git a/mkrtos_user/server/init/src/nsfs/main.c b/mkrtos_user/server/init/src/nsfs/main.c index 9c347f754..a1b84ffaa 100644 --- a/mkrtos_user/server/init/src/nsfs/main.c +++ b/mkrtos_user/server/init/src/nsfs/main.c @@ -1,9 +1,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include "ns.h" #include "nsfs.h" #include -int nsfs_test(void) +int nsfs_mkdir_test(void) { int ret; @@ -18,12 +25,177 @@ int nsfs_test(void) ret = fs_ns_remove("/bin/tst"); assert(ret < 0); ret = fs_ns_rmdir("/bin/tst"); - assert(ret >= 0 ); + assert(ret >= 0); return 0; } +int nsfs_scan_dir_test(void) +{ +#define TEST_CN 10 + int ret; + ret = fs_ns_mkdir("/bin/"); + assert(ret >= 0); + + for (int i = 0; i < TEST_CN; i++) + { + char dir_name[32]; + + snprintf(dir_name, sizeof(dir_name), "/bin/tst%d", i); + ret = fs_ns_mkdir(dir_name); + assert(ret >= 0); + } + int fd; + + fd = fs_ns_open("/bin/", O_RDWR, 0777); + assert(fd >= 0); + struct dirent dir_info; + for (int i = 0; i < (TEST_CN + 1); i++) + { + ret = fs_ns_readdir(fd, &dir_info); + if (i < TEST_CN) + { + assert(ret >= 0); + printf("readdir info :%s\n", dir_info.d_name); + fflush(stdout); + } + else + { + assert(ret < 0); + } + } + ret = fs_ns_lseek(fd, 2, SEEK_SET); + printf("old seek: %d\n", ret); + assert(ret >= 0); + for (int i = 0; i < (TEST_CN - 2 + 1); i++) + { + ret = fs_ns_readdir(fd, &dir_info); + if (i < TEST_CN - 2) + { + assert(ret >= 0); + printf("readdir info :%s\n", dir_info.d_name); + fflush(stdout); + } + else + { + assert(ret < 0); + } + } + + ret = fs_ns_close(fd); + assert(ret >= 0); + ret = fs_ns_readdir(fd, &dir_info); + assert(ret < 0); + + for (int i = 0; i < TEST_CN; i++) + { + char dir_name[32]; + snprintf(dir_name, sizeof(dir_name), "/bin/tst%d", i); + ret = fs_ns_rmdir(dir_name); + assert(ret >= 0); + } + ret = fs_ns_rmdir("/bin"); + assert(ret >= 0); +#undef TEST_CN + return 0; +} +int nsfs_mksvr_node(void) +{ + int ret; + struct dirent dir; + + ret = fs_ns_mkdir("/bin/"); + assert(ret >= 0); + ret = ns_mknode("/bin/tst1", 10, NODE_TYPE_SVR); + assert(ret >= 0); + int fd; + + fd = fs_ns_open("/bin/tst1", O_RDWR, 0777); + assert(fd < 0); + fd = fs_ns_open("/bin/", O_RDWR, 0777); + assert(fd >= 0); + ret = fs_ns_readdir(fd, &dir); + assert(ret >= 0); + printf("readdir info :%s\n", dir.d_name); + ret = fs_ns_close(fd); + assert(ret >= 0); + + ret = fs_ns_remove("/bin/tst1/"); + assert(ret >= 0); + ret = fs_ns_rmdir("/bin/"); + assert(ret >= 0); + return 0; +} +int nsfs_query_svr_node(void) +{ + int ret; + ret = fs_ns_mkdir("/bin/"); + assert(ret >= 0); + ns_node_t *node; + ns_node_t *pnode; + int cur_inx; + int p_inx; + + node = ns_node_find_full_file("/bin/", &ret, &cur_inx); + assert(node == NULL && ret < 0); + +#define SVR_NODE "/svr_tst" + ret = ns_mknode(SVR_NODE, 10, NODE_TYPE_SVR); + assert(ret >= 0); + + node = ns_node_find_full_file(SVR_NODE, &ret, &cur_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE)); + + node = ns_node_find(&pnode, SVR_NODE "/1/2/3", &ret, &cur_inx, &p_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE) + 1); + + ret = fs_ns_mkdir(SVR_NODE "/1"); + assert(ret < 0); +#undef SVR_NODE + ret = fs_ns_remove("/svr_tst"); + assert(ret >= 0); +#define SVR_NODE "/bin/svr_tst" + ret = ns_mknode(SVR_NODE, 10, NODE_TYPE_SVR); + assert(ret >= 0); + node = ns_node_find_full_file(SVR_NODE, &ret, &cur_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE)); + node = ns_node_find_svr_file(SVR_NODE "/1/2/3", &ret, &cur_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE) + 1); + + ret = fs_ns_rmdir("/bin/"); + assert(ret < 0); + + ret = fs_ns_remove(SVR_NODE); + assert(ret >= 0); + ret = fs_ns_rmdir("/bin/"); + assert(ret >= 0); + return 0; +} +int nsfs_stat_test(void) +{ + int ret; + struct stat fst; + int fd; + + ret = fs_ns_mkdir("/tstdir/"); + assert(ret >= 0); + fd = fs_ns_open("/tstdir/", O_RDWR, 0777); + assert(fd >= 0); + ret = fs_ns_stat(fd, &fst); + assert(ret >= 0); + ret = fs_ns_close(fd); + assert(ret >= 0); + return 0; +} int main(int argc, char *argv[]) { - nsfs_test(); + nsfs_mkdir_test(); + nsfs_scan_dir_test(); + nsfs_stat_test(); + nsfs_mksvr_node(); + nsfs_query_svr_node(); return 0; } \ No newline at end of file diff --git a/mkrtos_user/server/init/src/nsfs/ns.c b/mkrtos_user/server/init/src/nsfs/ns.c index 4b3be4764..3e3825b98 100644 --- a/mkrtos_user/server/init/src/nsfs/ns.c +++ b/mkrtos_user/server/init/src/nsfs/ns.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include "ns.h" @@ -13,7 +13,6 @@ static ns_node_t root_node = { .type = NODE_TYPE_DUMMY, - .svr_hd = HANDLER_INVALID, //!< 根节点是虚拟节点 }; /** * 从路径中copy名字 @@ -42,7 +41,7 @@ static ns_node_t *ns_node_find_sub(ns_node_t *tree, const char *name) { return NULL; } - ns_node_t *cur = tree->next; + ns_node_t *cur = tree->sub; while (cur) { @@ -71,7 +70,7 @@ int ns_nodes_count(ns_node_t *tree) } static int ns_node_del(ns_node_t *tree, ns_node_t *del_node) { - ns_node_t *tmp = tree->next; + ns_node_t *tmp = tree->sub; ns_node_t *pre = NULL; while (tmp) @@ -81,7 +80,8 @@ static int ns_node_del(ns_node_t *tree, ns_node_t *del_node) if (pre == NULL) { // 删除第一个节点 - tree->next = tmp->next; + tree->sub = tmp->next; + return 0; } else { @@ -113,7 +113,7 @@ ns_node_t *ns_node_get_inx(ns_node_t *tree, int inx) assert(tree); assert(tree->type == NODE_TYPE_DUMMY); int nr = 0; - ns_node_t *cur = tree->next; + ns_node_t *cur = tree->sub; while (cur) { @@ -130,7 +130,7 @@ ns_node_t *ns_node_get_inx(ns_node_t *tree, int inx) * 查找节点,如果是dummy节点,则一直循环查找。 * 如果是svr节点,则立刻终止查找,然后返回当前节点,以及截断的位置 */ -ns_node_t *ns_node_find(ns_node_t **pnode, const char *path, int *ret, int *cur_inx) +ns_node_t *ns_node_find(ns_node_t **pnode, const char *path, int *ret, int *svr_inx, int *p_inx) { assert(ret); assert(path); @@ -179,7 +179,11 @@ ns_node_t *ns_node_find(ns_node_t **pnode, const char *path, int *ret, int *cur_ } else if (t_node->type == NODE_TYPE_SVR) { - find_node_cut_inx = i; + find_node_cut_inx = i + len + 1; + if (path[find_node_cut_inx] == '/') + { + find_node_cut_inx++; + } // 找到服务节点,那直接返回,服务节点不会有子节点。 cur_node = t_node; goto end; @@ -193,6 +197,10 @@ ns_node_t *ns_node_find(ns_node_t **pnode, const char *path, int *ret, int *cur_ } cur_node = NULL; } + if (p_inx) + { + *p_inx = i; + } if (path[i] == '/') { i++; @@ -200,7 +208,7 @@ ns_node_t *ns_node_find(ns_node_t **pnode, const char *path, int *ret, int *cur_ i += len; } end: - *cur_inx = find_node_cut_inx; + *svr_inx = find_node_cut_inx; *ret = 0; return cur_node; } @@ -214,13 +222,13 @@ int ns_delnode(const char *path) int ret; int cur_inx; - cur_node = ns_node_find(NULL, path, &ret, &cur_inx); + cur_node = ns_node_find(NULL, path, &ret, &cur_inx, NULL); if (cur_node == NULL) { printf("ns node not find.\n"); return -ENOENT; } - if (cur_node == NULL || path[cur_inx + 1] != '\0') + if (cur_node == NULL) { printf("ns path is error.\n"); // 未找到,节点不是dummy节点,路径不是结尾处 则直接退出 @@ -254,8 +262,8 @@ ns_node_t *ns_node_find_full_dir(const char *path, int *ret, int *cur_inx) assert(cur_inx); ns_node_t *dir_node; - dir_node = ns_node_find(NULL, path, ret, cur_inx); - if (dir_node == NULL || dir_node->type != NODE_TYPE_DUMMY || cur_inx != 0) + dir_node = ns_node_find(NULL, path, ret, cur_inx, NULL); + if (dir_node == NULL || dir_node->type != NODE_TYPE_DUMMY || *cur_inx != 0) { printf("ns node not find or path error.\n"); // 未找到,节点不是dummy节点,路径不是结尾处 则直接退出 @@ -275,8 +283,26 @@ ns_node_t *ns_node_find_full_file(const char *path, int *ret, int *cur_inx) assert(cur_inx); ns_node_t *dir_node; - dir_node = ns_node_find(NULL, path, ret, cur_inx); - if (dir_node == NULL || dir_node->type != NODE_TYPE_SVR || path[*cur_inx + 1] != '\0') + dir_node = ns_node_find(NULL, path, ret, cur_inx, NULL); + if (dir_node == NULL || dir_node->type != NODE_TYPE_SVR || path[*cur_inx] != '\0') + { + printf("ns node not find or path error.\n"); + // 未找到,节点不是 svr 节点,路径不是结尾处 则直接退出 + *ret = -ENOENT; + return NULL; + } + + return dir_node; +} +ns_node_t *ns_node_find_svr_file(const char *path, int *ret, int *cur_inx) +{ + assert(path); + assert(ret); + assert(cur_inx); + ns_node_t *dir_node; + + dir_node = ns_node_find(NULL, path, ret, cur_inx, NULL); + if (dir_node == NULL || dir_node->type != NODE_TYPE_SVR) { printf("ns node not find or path error.\n"); // 未找到,节点不是 svr 节点,路径不是结尾处 则直接退出 @@ -297,15 +323,16 @@ int ns_mknode(const char *path, obj_handler_t svr_hd, node_type_t type) ns_node_t *cur_node; int ret; int cur_inx; + int p_inx; char name[NS_NODE_NAME_LEN]; - cur_node = ns_node_find(&dir_node, path, &ret, &cur_inx); - if (dir_node == NULL) + cur_node = ns_node_find(&dir_node, path, &ret, &cur_inx, &p_inx); + if (dir_node == NULL || dir_node->type != NODE_TYPE_DUMMY || (cur_node != NULL && cur_node->type == NODE_TYPE_SVR)) { return -ENOENT; } // 获得节点的名字 - int name_len = ns_node_strcpy(name, path + cur_inx + 1, NS_NODE_NAME_LEN); + int name_len = ns_node_strcpy(name, path + p_inx + 1, NS_NODE_NAME_LEN); new_node = node_create(name, NODE_TYPE_DUMMY); if (new_node == NULL) @@ -313,8 +340,8 @@ int ns_mknode(const char *path, obj_handler_t svr_hd, node_type_t type) return -ENOMEM; } // 加到目录的链表中 - new_node->next = dir_node->next; - dir_node->next = new_node; + new_node->next = dir_node->sub; + dir_node->sub = new_node; new_node->type = type; new_node->parent = dir_node; if (type == NODE_TYPE_SVR) diff --git a/mkrtos_user/server/init/src/nsfs/ns.h b/mkrtos_user/server/init/src/nsfs/ns.h index a5da726fd..da154b103 100644 --- a/mkrtos_user/server/init/src/nsfs/ns.h +++ b/mkrtos_user/server/init/src/nsfs/ns.h @@ -33,9 +33,10 @@ typedef struct ns_node int ref; //!< 引用计数 } ns_node_t; -ns_node_t *ns_node_find(ns_node_t **pnode, const char *path, int *ret, int *cur_inx); +ns_node_t *ns_node_find(ns_node_t **pnode, const char *path, int *ret, int *svr_inx, int *p_inx); ns_node_t *ns_node_find_full_dir(const char *path, int *ret, int *cur_inx); ns_node_t *ns_node_find_full_file(const char *path, int *ret, int *cur_inx); +ns_node_t *ns_node_find_svr_file(const char *path, int *ret, int *cur_inx); int ns_nodes_count(ns_node_t *tree); ns_node_t *ns_node_get_inx(ns_node_t *tree, int inx); int ns_delnode(const char *path); @@ -48,5 +49,5 @@ static inline ns_node_t *ns_node_get_next(ns_node_t *tree_node, ns_node_t *cur_n static inline ns_node_t *ns_node_get_first(ns_node_t *tree_node) { assert(tree_node); - return tree_node->next; + return tree_node->sub; } diff --git a/mkrtos_user/server/init/src/nsfs/nsfs.c b/mkrtos_user/server/init/src/nsfs/nsfs.c index 896d1736e..d7736f946 100644 --- a/mkrtos_user/server/init/src/nsfs/nsfs.c +++ b/mkrtos_user/server/init/src/nsfs/nsfs.c @@ -9,6 +9,7 @@ #include #include #include "ns.h" + #define DIR_INFO_CACHE_NR 32 typedef struct dir_info_cache @@ -20,6 +21,10 @@ typedef struct dir_info_cache static dir_info_cache_t dir_info_cache_list[DIR_INFO_CACHE_NR]; static int dir_info_cache_get(ns_node_t *info) { + if (info == NULL) + { + return -EINVAL; + } for (int i = 0; i < DIR_INFO_CACHE_NR; i++) { if (dir_info_cache_list[i].info == NULL) @@ -136,7 +141,7 @@ int fs_ns_open(const char *name, int flags, int mode) enum fs_ns_type type; // 路径必须'/'卡头 - if (name[0] == '\0' || name[1] != '/') + if (name[0] == '\0' || name[0] != '/') { printf("nsfs path is error.\n"); return -EINVAL; @@ -223,11 +228,11 @@ int fs_ns_lseek(int fd, int offset, unsigned long whence) { return -ENOENT; } - if (file->tmp_fd != -1) + if (file->tmp_fd >= 0) { dir_info_cache_put(dir_info_cache_list[file->tmp_fd].info); } - dir_info_cache_get(new_dir_info); + file->tmp_fd = dir_info_cache_get(new_dir_info); } file->offset = new_offs; @@ -245,12 +250,9 @@ int fs_ns_stat(int fd, struct stat *st) { return -ENOENT; } - if (file->type != FS_NS_FILE_TYPE) - { - return -EACCES; - } + memset(st, 0, sizeof(*st)); st->st_size = 0; - st->st_mode = S_IFREG; + st->st_mode = file->type == FS_NS_FILE_TYPE ? S_IFREG : S_IFDIR; st->st_nlink = dir_info_cache_list[file->dir_info_fd].info->ref; return 0; } @@ -261,7 +263,7 @@ int fs_ns_close(int fd) { return -ENOENT; } - if (file->tmp_fd != -1) + if (file->tmp_fd >= 0) { dir_info_cache_put(dir_info_cache_list[file->tmp_fd].info); } @@ -293,6 +295,7 @@ int fs_ns_rmdir(const char *name) ret = ns_delnode(name); if (ret < 0) { + dir_info_cache_put(file); return ret; } } @@ -353,6 +356,10 @@ int fs_ns_readdir(int fd, struct dirent *_dir) } file->tmp_fd = ret; } + else if (file->tmp_fd == -2) + { + return -ENOENT; + } ns_node_t *node_info; node_info = dir_info_cache_list[file->tmp_fd].info; @@ -362,19 +369,17 @@ int fs_ns_readdir(int fd, struct dirent *_dir) _dir->d_name[sizeof(_dir->d_name) - 1] = 0; ns_node_t *next_dir_info = ns_node_get_next(dir_info_cache_list[file->dir_info_fd].info, node_info); - if (next_dir_info == NULL) - { - return -ENOENT; - } dir_info_cache_put(node_info); ret = dir_info_cache_get(next_dir_info); - if (ret < 0) + if (ret >= 0) { - return ret; + file->tmp_fd = ret; + file->offset++; + } + else + { + file->tmp_fd = -2; // -2代表结束遍历 } - - file->tmp_fd = ret; - file->offset++; return sizeof(*_dir); } int fs_ns_mkdir(char *path) diff --git a/mkrtos_user/server/init/src/nsfs/nsfs.h b/mkrtos_user/server/init/src/nsfs/nsfs.h index 397e72766..5c05c0acf 100644 --- a/mkrtos_user/server/init/src/nsfs/nsfs.h +++ b/mkrtos_user/server/init/src/nsfs/nsfs.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include "ns.h" int fs_ns_open(const char *name, int flags, int mode); int fs_ns_write(int fd, void *data, int len); int fs_ns_read(int fd, void *data, int len);