diff --git a/.vscode/settings.json b/.vscode/settings.json index d9f4234a0..595278d10 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -265,7 +265,9 @@ "__memory": "c", "optional": "c", "system_error": "c", - "__dirent.h": "c" + "__dirent.h": "c", + "shell_fs.h": "c", + "shell_passthrough.h": "c" }, "cortex-debug.showRTOS": false, "cortex-debug.variableUseNaturalFormat": false, diff --git a/mkrtos_user/lib/letter-shell/demo/mkrtos/CMakeLists.txt b/mkrtos_user/lib/letter-shell/demo/mkrtos/CMakeLists.txt index 73c064a25..613b486a3 100644 --- a/mkrtos_user/lib/letter-shell/demo/mkrtos/CMakeLists.txt +++ b/mkrtos_user/lib/letter-shell/demo/mkrtos/CMakeLists.txt @@ -15,7 +15,7 @@ add_library(LetterShell ../../src/shell_companion.c ../../src/shell_ext.c ../../src/shell_cmd_list.c - # ../../extensions/fs_support/shell_fs.c + ../../extensions/fs_support/shell_fs.c ../../extensions/log/log.c # ../../extensions/telnet/telnetd.c ../../extensions/shell_enhance/shell_passthrough.c diff --git a/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_cfg_user.h b/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_cfg_user.h index 29729461a..bd4012f66 100644 --- a/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_cfg_user.h +++ b/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_cfg_user.h @@ -4,20 +4,44 @@ * @brief shell config * @version 3.0.0 * @date 2019-12-31 - * + * * @copyright (c) 2019 Letter - * + * */ #ifndef __SHELL_CFG_USER_H__ #define __SHELL_CFG_USER_H__ #include +#include /** * @brief 获取系统时间(ms) * 定义此宏为获取系统Tick,如`HAL_GetTick()` * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定 */ -#define SHELL_GET_TICK() sys_read_tick() +#define SHELL_GET_TICK() sys_read_tick() +/** + * @brief shell内存分配 + * shell本身不需要此接口,若使用shell伴生对象,需要进行定义 + */ +#define SHELL_MALLOC(size) malloc(size) +/** + * @brief shell内存释放 + * shell本身不需要此接口,若使用shell伴生对象,需要进行定义 + */ +#define SHELL_FREE(obj) free(obj) +/** + * @brief 使用函数签名 + * 使能后,可以在声明命令时,指定函数的签名,shell 会根据函数签名进行参数转换, + * 而不是自动判断参数的类型,如果参数和函数签名不匹配,会停止执行命令 + */ +#define SHELL_USING_FUNC_SIGNATURE 1 + +/** + * @brief 支持数组参数 + * 使能后,可以在命令中使用数组参数,如`cmd [1,2,3]` + * 需要使能 `SHELL_USING_FUNC_SIGNATURE` 宏,并且配置 `SHELL_MALLOC`, `SHELL_FREE` + */ +#define SHELL_SUPPORT_ARRAY_PARAM 1 #endif diff --git a/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_port.c b/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_port.c index 8595539ea..91e8f68a0 100644 --- a/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_port.c +++ b/mkrtos_user/lib/letter-shell/demo/mkrtos/shell_port.c @@ -10,10 +10,25 @@ */ #include "shell.h" +#include "shell_ext.h" +#include "shell_fs.h" +#include "shell_passthrough.h" +#include "shell_secure_user.h" +#include "log.h" +// #include "telnetd.h" +#include +#include +#include +#include +#include +#include +#include #include "cons_cli.h" #include "u_sleep.h" -Shell shell; -char shellBuffer[512]; +static Shell shell; +static ShellFs shellFs; +static char shellBuffer[256]; +static char shellPathBuffer[128] = "/mnt/"; /** * @brief 用户shell写 @@ -43,16 +58,53 @@ signed short userShellRead(char *data, unsigned short len) u_sleep_ms(5); } } +/** + * @brief 列出文件 + * + * @param path 路径 + * @param buffer 结果缓冲 + * @param maxLen 最大缓冲长度 + * @return size_t 0 + */ +size_t userShellListDir(char *path, char *buffer, size_t maxLen) +{ + DIR *dir; + struct dirent *ptr; + int i; + if (!path) + { + return 0; + } + dir = opendir(path); + if (!dir) + { + return 0; + } + memset(buffer, 0, maxLen); + while ((ptr = readdir(dir)) != NULL) + { + strcat(buffer, ptr->d_name); + strcat(buffer, "\t"); + } + closedir(dir); + return 0; +} /** * @brief 用户shell初始化 * */ void userShellInit(void) { + shellFs.getcwd = getcwd; + shellFs.chdir = chdir; + shellFs.listdir = userShellListDir; + shellFsInit(&shellFs, shellPathBuffer, sizeof(shellPathBuffer)); shell.write = userShellWrite; shell.read = userShellRead; - shellInit(&shell, shellBuffer, 512); + shellSetPath(&shell, shellPathBuffer); + shellInit(&shell, shellBuffer, sizeof(shellBuffer)); + shellCompanionAdd(&shell, SHELL_COMPANION_ID_FS, &shellFs); while (1) { diff --git a/mkrtos_user/lib/letter-shell/extensions/fs_support/shell_fs.h b/mkrtos_user/lib/letter-shell/extensions/fs_support/shell_fs.h index 522f50eca..ff7781eca 100644 --- a/mkrtos_user/lib/letter-shell/extensions/fs_support/shell_fs.h +++ b/mkrtos_user/lib/letter-shell/extensions/fs_support/shell_fs.h @@ -18,7 +18,7 @@ #define SHELL_COMPANION_ID_FS -1 -#define SHELL_FS_LIST_FILE_BUFFER_MAX 4096 +#define SHELL_FS_LIST_FILE_BUFFER_MAX 128 /** * @brief shell文件系统支持结构体 diff --git a/mkrtos_user/lib/letter-shell/src/shell_cfg.h b/mkrtos_user/lib/letter-shell/src/shell_cfg.h index 0018dcd3b..d29ab7ae2 100644 --- a/mkrtos_user/lib/letter-shell/src/shell_cfg.h +++ b/mkrtos_user/lib/letter-shell/src/shell_cfg.h @@ -39,7 +39,7 @@ * @brief 是否使用shell伴生对象 * 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象 */ -#define SHELL_USING_COMPANION 0 +#define SHELL_USING_COMPANION 1 #endif /** SHELL_USING_COMPANION */ #ifndef SHELL_SUPPORT_END_LINE diff --git a/mkrtos_user/lib/libc_backend/src/fs_backend.c b/mkrtos_user/lib/libc_backend/src/fs_backend.c index 19daf06ec..80cbdcb4a 100644 --- a/mkrtos_user/lib/libc_backend/src/fs_backend.c +++ b/mkrtos_user/lib/libc_backend/src/fs_backend.c @@ -321,6 +321,7 @@ long be_lseek(long fd, long offset, long whence) { case FD_TTY: { + return -ENOSYS; } break; case FD_FS: @@ -332,4 +333,31 @@ long be_lseek(long fd, long offset, long whence) return -ENOSYS; } return 0; -} \ No newline at end of file +} + +long be_getdents(long fd, char *buf, size_t size) +{ + fd_map_entry_t u_fd; + int ret = fd_map_get(fd, &u_fd); + + if (ret < 0) + { + return -EBADF; + } + switch (u_fd.type) + { + case FD_TTY: + { + return -ENOSYS; + } + break; + case FD_FS: + { + ret = fs_readdir(u_fd.priv_fd, (struct dirent *)buf); + } + break; + default: + return -ENOSYS; + } + return ret; +} diff --git a/mkrtos_user/lib/mlibc/arch/generic/bits/dirent.h b/mkrtos_user/lib/mlibc/arch/generic/bits/dirent.h index c845fe82d..2820884d9 100644 --- a/mkrtos_user/lib/mlibc/arch/generic/bits/dirent.h +++ b/mkrtos_user/lib/mlibc/arch/generic/bits/dirent.h @@ -2,10 +2,12 @@ #define _DIRENT_HAVE_D_OFF #define _DIRENT_HAVE_D_TYPE +#define DIRENT_NAME_LEN 32 // 256 + struct dirent { ino_t d_ino; off_t d_off; unsigned short d_reclen; unsigned char d_type; - char d_name[256]; + char d_name[DIRENT_NAME_LEN]; }; diff --git a/mkrtos_user/lib/mlibc/src/dirent/readdir.c b/mkrtos_user/lib/mlibc/src/dirent/readdir.c index 5a03b3635..5c908ac2c 100644 --- a/mkrtos_user/lib/mlibc/src/dirent/readdir.c +++ b/mkrtos_user/lib/mlibc/src/dirent/readdir.c @@ -3,18 +3,22 @@ #include #include "__dirent.h" #include "syscall.h" - -typedef char dirstream_buf_alignment_check[1-2*(int)( - offsetof(struct __dirstream, buf) % sizeof(off_t))]; +#ifndef NO_LITTLE_MODE +#include "syscall_backend.h" +#endif +typedef char dirstream_buf_alignment_check[1 - 2 * (int)(offsetof(struct __dirstream, buf) % sizeof(off_t))]; struct dirent *readdir(DIR *dir) { struct dirent *de; - - if (dir->buf_pos >= dir->buf_end) { - int len = __syscall(SYS_getdents, dir->fd, dir->buf, sizeof dir->buf); - if (len <= 0) { - if (len < 0 && len != -ENOENT) errno = -len; + + if (dir->buf_pos >= dir->buf_end) + { + int len = be_getdents(dir->fd, dir->buf, sizeof dir->buf); + if (len <= 0) + { + if (len < 0 && len != -ENOENT) + errno = -len; return 0; } dir->buf_end = len; diff --git a/mkrtos_user/lib/sys_svr/inc/fs_cli.h b/mkrtos_user/lib/sys_svr/inc/fs_cli.h index 8d49c4646..e7c170eab 100644 --- a/mkrtos_user/lib/sys_svr/inc/fs_cli.h +++ b/mkrtos_user/lib/sys_svr/inc/fs_cli.h @@ -1,8 +1,10 @@ #pragma once #include +#include int fs_open(const char *path, int flags, int mode); int fs_read(int fd, void *buf, size_t len); int fs_write(int fd, void *buf, size_t len); int fs_close(int fd); -int fs_lseek(int fd, int offs, int whence); \ No newline at end of file +int fs_lseek(int fd, int offs, int whence); +int fs_readdir(int _fd, struct dirent *dirent); diff --git a/mkrtos_user/lib/sys_svr/src/fs_cli.c b/mkrtos_user/lib/sys_svr/src/fs_cli.c index d0e6c3994..10e2c89e1 100644 --- a/mkrtos_user/lib/sys_svr/src/fs_cli.c +++ b/mkrtos_user/lib/sys_svr/src/fs_cli.c @@ -14,23 +14,6 @@ RPC_GENERATION_CALL3(fs_t, FS_PROT, FS_OPEN, open, rpc_ref_array_uint32_t_uint8_t_32_t, rpc_array_uint32_t_uint8_t_32_t, RPC_DIR_IN, RPC_TYPE_DATA, path, rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, flags, rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, mode) -RPC_GENERATION_CALL3(fs_t, FS_PROT, FS_READ, read, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, - rpc_ref_array_uint32_t_uint8_t_32_t, rpc_array_uint32_t_uint8_t_32_t, RPC_DIR_OUT, RPC_TYPE_DATA, buf, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len) - -RPC_GENERATION_CALL3(fs_t, FS_PROT, FS_WRITE, write, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, - rpc_ref_array_uint32_t_uint8_t_32_t, rpc_array_uint32_t_uint8_t_32_t, RPC_DIR_IN, RPC_TYPE_DATA, buf, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len) - -RPC_GENERATION_CALL1(fs_t, FS_PROT, FS_CLOSE, close, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd) -RPC_GENERATION_CALL3(fs_t, FS_PROT, FS_LSEEK, lseek, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, offs, - rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, whence) - sd_t fs_open(const char *path, int flags, int mode) { obj_handler_t hd; @@ -60,6 +43,11 @@ sd_t fs_open(const char *path, int flags, int mode) return mk_sd_init2(hd, msg_tag_get_val(tag)).raw; } +RPC_GENERATION_CALL3(fs_t, FS_PROT, FS_READ, read, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, + rpc_ref_array_uint32_t_uint8_t_32_t, rpc_array_uint32_t_uint8_t_32_t, RPC_DIR_OUT, RPC_TYPE_DATA, buf, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len) + int fs_read(sd_t _fd, void *buf, size_t len) { obj_handler_t hd = mk_sd_init_raw(_fd).hd; @@ -97,6 +85,10 @@ int fs_read(sd_t _fd, void *buf, size_t len) return rlen; } +RPC_GENERATION_CALL3(fs_t, FS_PROT, FS_WRITE, write, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, + rpc_ref_array_uint32_t_uint8_t_32_t, rpc_array_uint32_t_uint8_t_32_t, RPC_DIR_IN, RPC_TYPE_DATA, buf, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len) int fs_write(sd_t _fd, void *buf, size_t len) { @@ -134,6 +126,8 @@ int fs_write(sd_t _fd, void *buf, size_t len) return wlen; } +RPC_GENERATION_CALL1(fs_t, FS_PROT, FS_CLOSE, close, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd) int fs_close(sd_t _fd) { obj_handler_t hd = mk_sd_init_raw(_fd).hd; @@ -151,6 +145,11 @@ int fs_close(sd_t _fd) return msg_tag_get_val(tag); } +RPC_GENERATION_CALL3(fs_t, FS_PROT, FS_LSEEK, lseek, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, offs, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, whence) + int fs_lseek(sd_t _fd, int offs, int whence) { obj_handler_t hd = mk_sd_init_raw(_fd).hd; @@ -173,4 +172,31 @@ int fs_lseek(sd_t _fd, int offs, int whence) } return msg_tag_get_val(tag); -} \ No newline at end of file +} +RPC_GENERATION_CALL2(fs_t, FS_PROT, FS_READDIR, readdir, + rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, + rpc_dirent_t_t, rpc_dirent_t_t, RPC_DIR_OUT, RPC_TYPE_DATA, dir) + +int fs_readdir(sd_t _fd, dirent_t *dirent) +{ + obj_handler_t hd = mk_sd_init_raw(_fd).hd; + int fd = mk_sd_init_raw(_fd).fd; + + rpc_int_t rpc_fd = { + .data = fd, + }; + rpc_dirent_t_t rpc_dient = { + .data.d_ino = 0, + }; + msg_tag_t tag = fs_t_readdir_call(hd, &rpc_fd, &rpc_dient); + + if (msg_tag_get_val(tag) >= 0) + { + if (dirent) + { + *dirent = rpc_dient.data; + } + } + + return msg_tag_get_val(tag); +} diff --git a/mkrtos_user/server/fs/fatfs/ff15/source/ffconf.h b/mkrtos_user/server/fs/fatfs/ff15/source/ffconf.h index 13168ceee..18154cb98 100644 --- a/mkrtos_user/server/fs/fatfs/ff15/source/ffconf.h +++ b/mkrtos_user/server/fs/fatfs/ff15/source/ffconf.h @@ -145,7 +145,7 @@ / When LFN is not enabled, this option has no effect. */ -#define FF_LFN_BUF 255 +#define FF_LFN_BUF 64 #define FF_SFN_BUF 12 /* This set of options defines size of file name members in the FILINFO structure / which is used to read out directory items. These values should be suffcient for diff --git a/mkrtos_user/server/fs/fatfs/fs_rpc.c b/mkrtos_user/server/fs/fatfs/fs_rpc.c index 2eda0de3d..80a4a2240 100644 --- a/mkrtos_user/server/fs/fatfs/fs_rpc.c +++ b/mkrtos_user/server/fs/fatfs/fs_rpc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "rpc_prot.h" static fs_t fs; void fs_svr_init(void) @@ -125,7 +126,7 @@ int fs_svr_open(const char *path, int flags, int mode) if (ret != FR_OK) { - if (ret == FR_NO_FILE) + if (ret == FR_NO_FILE || ret == FR_INVALID_NAME) { // 打开的是一个目录,则作为一个目录打开 ret = f_opendir(&file->dir, path); @@ -136,7 +137,7 @@ int fs_svr_open(const char *path, int flags, int mode) return fatfs_err_conv(ret); } file->type = 1; - cons_write_str("open dir..\n"); + // cons_write_str("open dir..\n"); } } else @@ -290,6 +291,26 @@ int fs_svr_readdir(int fd, dirent_t *dir) { return -ENOENT; } + FILINFO info; + FRESULT ret = f_readdir(&file->dir, &info); + + if (ret != FR_OK || info.fname[0] == 0) + { + return -ENOENT; + } + strncpy(dir->d_name, info.fname, sizeof(dir->d_name)); + dir->d_name[sizeof(dir->d_name) - 1] = 0; + dir->d_reclen = sizeof(*dir); + dir->d_off = 0; + if (info.fattrib & AM_DIR) + { /* Directory */ + dir->d_type = DT_DIR; + } + else + { /* File */ + dir->d_type = DT_CHR; + } + return sizeof(*dir); } int fs_svr_mkdir(char *path) { diff --git a/mkrtos_user/server/shell/src/heap_stack.c b/mkrtos_user/server/shell/src/heap_stack.c index fcf8574aa..bc3b6f695 100644 --- a/mkrtos_user/server/shell/src/heap_stack.c +++ b/mkrtos_user/server/shell/src/heap_stack.c @@ -1,5 +1,5 @@ -#define HEAP_SIZE 512 +#define HEAP_SIZE 2048 #define STACK_SIZE 2048 #if defined(__CC_ARM) diff --git a/mkrtos_user/server/test/test/fs_test.c b/mkrtos_user/server/test/test/fs_test.c index ffc4e5d7d..a10325ad4 100644 --- a/mkrtos_user/server/test/test/fs_test.c +++ b/mkrtos_user/server/test/test/fs_test.c @@ -10,8 +10,6 @@ #include void fs_test(void) { - int i = 1000; - while (i--) { char tmp[4] = "123"; int fd = open("/mnt/1.txt", O_CREAT | O_RDWR, 0777); @@ -25,5 +23,13 @@ void fs_test(void) assert(strcmp(tmp, "123") == 0); close(fd); } + { + DIR *dir = opendir("/mnt/"); + assert(dir); + struct dirent *d = readdir(dir); + assert(d); + printf("%s\n", d->d_name); + closedir(dir); + } printf("%s ok.\n", __func__); }