文件系统支持完善

This commit is contained in:
zhangzheng
2023-12-02 23:15:33 +08:00
parent 2d68c1b480
commit 50e54e7662
15 changed files with 212 additions and 45 deletions

View File

@@ -265,7 +265,9 @@
"__memory": "c", "__memory": "c",
"optional": "c", "optional": "c",
"system_error": "c", "system_error": "c",
"__dirent.h": "c" "__dirent.h": "c",
"shell_fs.h": "c",
"shell_passthrough.h": "c"
}, },
"cortex-debug.showRTOS": false, "cortex-debug.showRTOS": false,
"cortex-debug.variableUseNaturalFormat": false, "cortex-debug.variableUseNaturalFormat": false,

View File

@@ -15,7 +15,7 @@ add_library(LetterShell
../../src/shell_companion.c ../../src/shell_companion.c
../../src/shell_ext.c ../../src/shell_ext.c
../../src/shell_cmd_list.c ../../src/shell_cmd_list.c
# ../../extensions/fs_support/shell_fs.c ../../extensions/fs_support/shell_fs.c
../../extensions/log/log.c ../../extensions/log/log.c
# ../../extensions/telnet/telnetd.c # ../../extensions/telnet/telnetd.c
../../extensions/shell_enhance/shell_passthrough.c ../../extensions/shell_enhance/shell_passthrough.c

View File

@@ -4,20 +4,44 @@
* @brief shell config * @brief shell config
* @version 3.0.0 * @version 3.0.0
* @date 2019-12-31 * @date 2019-12-31
* *
* @copyright (c) 2019 Letter * @copyright (c) 2019 Letter
* *
*/ */
#ifndef __SHELL_CFG_USER_H__ #ifndef __SHELL_CFG_USER_H__
#define __SHELL_CFG_USER_H__ #define __SHELL_CFG_USER_H__
#include <u_sys.h> #include <u_sys.h>
#include <malloc.h>
/** /**
* @brief 获取系统时间(ms) * @brief 获取系统时间(ms)
* 定义此宏为获取系统Tick如`HAL_GetTick()` * 定义此宏为获取系统Tick如`HAL_GetTick()`
* @note 此宏不定义时无法使用双击tab补全命令help无法使用shell超时锁定 * @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 #endif

View File

@@ -10,10 +10,25 @@
*/ */
#include "shell.h" #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 <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stddef.h>
#include <string.h>
#include <sys/time.h>
#include <pthread.h>
#include "cons_cli.h" #include "cons_cli.h"
#include "u_sleep.h" #include "u_sleep.h"
Shell shell; static Shell shell;
char shellBuffer[512]; static ShellFs shellFs;
static char shellBuffer[256];
static char shellPathBuffer[128] = "/mnt/";
/** /**
* @brief 用户shell写 * @brief 用户shell写
@@ -43,16 +58,53 @@ signed short userShellRead(char *data, unsigned short len)
u_sleep_ms(5); 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初始化 * @brief 用户shell初始化
* *
*/ */
void userShellInit(void) void userShellInit(void)
{ {
shellFs.getcwd = getcwd;
shellFs.chdir = chdir;
shellFs.listdir = userShellListDir;
shellFsInit(&shellFs, shellPathBuffer, sizeof(shellPathBuffer));
shell.write = userShellWrite; shell.write = userShellWrite;
shell.read = userShellRead; shell.read = userShellRead;
shellInit(&shell, shellBuffer, 512); shellSetPath(&shell, shellPathBuffer);
shellInit(&shell, shellBuffer, sizeof(shellBuffer));
shellCompanionAdd(&shell, SHELL_COMPANION_ID_FS, &shellFs);
while (1) while (1)
{ {

View File

@@ -18,7 +18,7 @@
#define SHELL_COMPANION_ID_FS -1 #define SHELL_COMPANION_ID_FS -1
#define SHELL_FS_LIST_FILE_BUFFER_MAX 4096 #define SHELL_FS_LIST_FILE_BUFFER_MAX 128
/** /**
* @brief shell文件系统支持结构体 * @brief shell文件系统支持结构体

View File

@@ -39,7 +39,7 @@
* @brief 是否使用shell伴生对象 * @brief 是否使用shell伴生对象
* 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象 * 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
*/ */
#define SHELL_USING_COMPANION 0 #define SHELL_USING_COMPANION 1
#endif /** SHELL_USING_COMPANION */ #endif /** SHELL_USING_COMPANION */
#ifndef SHELL_SUPPORT_END_LINE #ifndef SHELL_SUPPORT_END_LINE

View File

@@ -321,6 +321,7 @@ long be_lseek(long fd, long offset, long whence)
{ {
case FD_TTY: case FD_TTY:
{ {
return -ENOSYS;
} }
break; break;
case FD_FS: case FD_FS:
@@ -332,4 +333,31 @@ long be_lseek(long fd, long offset, long whence)
return -ENOSYS; return -ENOSYS;
} }
return 0; return 0;
} }
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;
}

View File

@@ -2,10 +2,12 @@
#define _DIRENT_HAVE_D_OFF #define _DIRENT_HAVE_D_OFF
#define _DIRENT_HAVE_D_TYPE #define _DIRENT_HAVE_D_TYPE
#define DIRENT_NAME_LEN 32 // 256
struct dirent { struct dirent {
ino_t d_ino; ino_t d_ino;
off_t d_off; off_t d_off;
unsigned short d_reclen; unsigned short d_reclen;
unsigned char d_type; unsigned char d_type;
char d_name[256]; char d_name[DIRENT_NAME_LEN];
}; };

View File

@@ -3,18 +3,22 @@
#include <stddef.h> #include <stddef.h>
#include "__dirent.h" #include "__dirent.h"
#include "syscall.h" #include "syscall.h"
#ifndef NO_LITTLE_MODE
typedef char dirstream_buf_alignment_check[1-2*(int)( #include "syscall_backend.h"
offsetof(struct __dirstream, buf) % sizeof(off_t))]; #endif
typedef char dirstream_buf_alignment_check[1 - 2 * (int)(offsetof(struct __dirstream, buf) % sizeof(off_t))];
struct dirent *readdir(DIR *dir) struct dirent *readdir(DIR *dir)
{ {
struct dirent *de; struct dirent *de;
if (dir->buf_pos >= dir->buf_end) { if (dir->buf_pos >= dir->buf_end)
int len = __syscall(SYS_getdents, dir->fd, dir->buf, sizeof dir->buf); {
if (len <= 0) { int len = be_getdents(dir->fd, dir->buf, sizeof dir->buf);
if (len < 0 && len != -ENOENT) errno = -len; if (len <= 0)
{
if (len < 0 && len != -ENOENT)
errno = -len;
return 0; return 0;
} }
dir->buf_end = len; dir->buf_end = len;

View File

@@ -1,8 +1,10 @@
#pragma once #pragma once
#include <stddef.h> #include <stddef.h>
#include <dirent.h>
int fs_open(const char *path, int flags, int mode); int fs_open(const char *path, int flags, int mode);
int fs_read(int fd, void *buf, size_t len); int fs_read(int fd, void *buf, size_t len);
int fs_write(int fd, void *buf, size_t len); int fs_write(int fd, void *buf, size_t len);
int fs_close(int fd); int fs_close(int fd);
int fs_lseek(int fd, int offs, int whence); int fs_lseek(int fd, int offs, int whence);
int fs_readdir(int _fd, struct dirent *dirent);

View File

@@ -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_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, flags,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, mode) 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) sd_t fs_open(const char *path, int flags, int mode)
{ {
obj_handler_t hd; 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; 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) int fs_read(sd_t _fd, void *buf, size_t len)
{ {
obj_handler_t hd = mk_sd_init_raw(_fd).hd; 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; 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) 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; 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) int fs_close(sd_t _fd)
{ {
obj_handler_t hd = mk_sd_init_raw(_fd).hd; 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); 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) int fs_lseek(sd_t _fd, int offs, int whence)
{ {
obj_handler_t hd = mk_sd_init_raw(_fd).hd; 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); return msg_tag_get_val(tag);
} }
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);
}

View File

@@ -145,7 +145,7 @@
/ When LFN is not enabled, this option has no effect. */ / 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 #define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure /* 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 / which is used to read out directory items. These values should be suffcient for

View File

@@ -9,6 +9,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <string.h>
#include "rpc_prot.h" #include "rpc_prot.h"
static fs_t fs; static fs_t fs;
void fs_svr_init(void) 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_OK)
{ {
if (ret == FR_NO_FILE) if (ret == FR_NO_FILE || ret == FR_INVALID_NAME)
{ {
// 打开的是一个目录,则作为一个目录打开 // 打开的是一个目录,则作为一个目录打开
ret = f_opendir(&file->dir, path); 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); return fatfs_err_conv(ret);
} }
file->type = 1; file->type = 1;
cons_write_str("open dir..\n"); // cons_write_str("open dir..\n");
} }
} }
else else
@@ -290,6 +291,26 @@ int fs_svr_readdir(int fd, dirent_t *dir)
{ {
return -ENOENT; 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) int fs_svr_mkdir(char *path)
{ {

View File

@@ -1,5 +1,5 @@
#define HEAP_SIZE 512 #define HEAP_SIZE 2048
#define STACK_SIZE 2048 #define STACK_SIZE 2048
#if defined(__CC_ARM) #if defined(__CC_ARM)

View File

@@ -10,8 +10,6 @@
#include <stdio.h> #include <stdio.h>
void fs_test(void) void fs_test(void)
{ {
int i = 1000;
while (i--)
{ {
char tmp[4] = "123"; char tmp[4] = "123";
int fd = open("/mnt/1.txt", O_CREAT | O_RDWR, 0777); int fd = open("/mnt/1.txt", O_CREAT | O_RDWR, 0777);
@@ -25,5 +23,13 @@ void fs_test(void)
assert(strcmp(tmp, "123") == 0); assert(strcmp(tmp, "123") == 0);
close(fd); 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__); printf("%s ok.\n", __func__);
} }