文件系统支持完善
This commit is contained in:
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -13,11 +13,35 @@
|
||||
#define __SHELL_CFG_USER_H__
|
||||
|
||||
#include <u_sys.h>
|
||||
#include <malloc.h>
|
||||
/**
|
||||
* @brief 获取系统时间(ms)
|
||||
* 定义此宏为获取系统Tick,如`HAL_GetTick()`
|
||||
* @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
|
||||
*/
|
||||
#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
|
||||
|
||||
@@ -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 <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 "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)
|
||||
{
|
||||
|
||||
@@ -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文件系统支持结构体
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -321,6 +321,7 @@ long be_lseek(long fd, long offset, long whence)
|
||||
{
|
||||
case FD_TTY:
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
break;
|
||||
case FD_FS:
|
||||
@@ -333,3 +334,30 @@ long be_lseek(long fd, long offset, long whence)
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
@@ -3,18 +3,22 @@
|
||||
#include <stddef.h>
|
||||
#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;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <dirent.h>
|
||||
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);
|
||||
int fs_readdir(int _fd, struct dirent *dirent);
|
||||
|
||||
@@ -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;
|
||||
@@ -174,3 +173,30 @@ int fs_lseek(sd_t _fd, int offs, int whence)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#define HEAP_SIZE 512
|
||||
#define HEAP_SIZE 2048
|
||||
#define STACK_SIZE 2048
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include <stdio.h>
|
||||
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__);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user