diff --git a/components/shell/shell.c b/components/shell/shell.c index c983c75b..c602c50c 100644 --- a/components/shell/shell.c +++ b/components/shell/shell.c @@ -1,27 +1,31 @@ /** * @file shell.c - * @brief - * + * @brief + * * Copyright (c) 2021 Bouffalolab team - * + * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. - * + * */ #include "shell.h" +#if defined(SHELL_USING_FS) +#include "ff.h" +#endif + struct shell_syscall *_syscall_table_begin = NULL; struct shell_syscall *_syscall_table_end = NULL; struct shell_sysvar *_sysvar_table_begin = NULL; @@ -58,12 +62,13 @@ static char *shell_get_prompt(void) { static char shell_prompt[SHELL_CONSOLEBUF_SIZE + 1] = { 0 }; - strcpy(shell_prompt, SHELL_NAME); + strcpy(shell_prompt, "\r\n"); + strcat(shell_prompt, SHELL_NAME); #if defined(SHELL_USING_FS) /* get current working directory */ - getcwd(&shell_prompt[strlen(shell_prompt)], - SHELL_CONSOLEBUF_SIZE - strlen(shell_prompt)); + f_getcwd(&shell_prompt[strlen(shell_prompt)], + SHELL_CONSOLEBUF_SIZE - strlen(shell_prompt)); #endif strcat(shell_prompt, "/>"); @@ -135,25 +140,24 @@ static void shell_push_history(struct shell *shell) void shell_auto_complete_path(char *path) { - DIR *dir = RT_NULL; - struct dirent *dirent = RT_NULL; + DIR dir; + FILINFO fno; char *full_path, *ptr, *index; + char str_buff[256]; if (!path) return; - full_path = (char *)rt_malloc(256); - if (full_path == RT_NULL) - return; /* out of memory */ + full_path = str_buff; - if (*path != '/') { - getcwd(full_path, 256); - if (full_path[rt_strlen(full_path) - 1] != '/') - strcat(full_path, "/"); - } else - *full_path = '\0'; + // if (*path != '/') { + // f_getcwd(full_path, 256); + // if (full_path[strlen(full_path) - 1] != '/') + // strcat(full_path, "/"); + // } else + *full_path = '\0'; - index = RT_NULL; + index = NULL; ptr = path; for (;;) { if (*ptr == '/') @@ -163,10 +167,10 @@ void shell_auto_complete_path(char *path) ptr++; } - if (index == RT_NULL) + if (index == NULL) index = path; - if (index != RT_NULL) { + if (index != NULL) { char *dest = index; /* fill the parent path */ @@ -176,12 +180,10 @@ void shell_auto_complete_path(char *path) for (index = path; index != dest;) *ptr++ = *index++; - *ptr = '\0'; + *(ptr - 1) = '\0'; - dir = opendir(full_path); - if (dir == RT_NULL) /* open directory failed! */ + if (f_opendir(&dir, full_path)) /* open directory failed! */ { - rt_free(full_path); return; } @@ -192,31 +194,32 @@ void shell_auto_complete_path(char *path) /* auto complete the file or directory name */ if (*index == '\0') /* display all of files and directories */ { + f_rewinddir(&dir); for (;;) { - dirent = readdir(dir); - if (dirent == RT_NULL) + f_readdir(&dir, &fno); + if (fno.fname[0] == '\0') break; - SHELL_PRINTF("%s\n", dirent->d_name); + SHELL_PRINTF("%s%s%s\r\n", fno.fname, (fno.fattrib & AM_DIR) ? "/" : "", (fno.fattrib & AM_HID) ? "(Hidden)" : ""); } } else { - rt_size_t length, min_length; + uint32_t length, min_length = 0; - min_length = 0; + f_rewinddir(&dir); for (;;) { - dirent = readdir(dir); - if (dirent == RT_NULL) + f_readdir(&dir, &fno); + if (fno.fname[0] == '\0') break; /* matched the prefix string */ - if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) { + if (strncmp(index, fno.fname, strlen(index)) == 0) { if (min_length == 0) { - min_length = rt_strlen(dirent->d_name); + min_length = strlen(fno.fname); /* save dirent name */ - strcpy(full_path, dirent->d_name); + strcpy(full_path, fno.fname); } - length = str_common(dirent->d_name, full_path); + length = str_common(fno.fname, full_path); if (length < min_length) { min_length = length; @@ -225,17 +228,16 @@ void shell_auto_complete_path(char *path) } if (min_length) { - if (min_length < rt_strlen(full_path)) { + if (min_length < strlen(full_path)) { /* list the candidate */ - rewinddir(dir); - + f_rewinddir(&dir); for (;;) { - dirent = readdir(dir); - if (dirent == RT_NULL) + f_readdir(&dir, &fno); + if (fno.fname[0] == '\0') break; - if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) - SHELL_PRINTF("%s\n", dirent->d_name); + if (strncmp(index, fno.fname, strlen(index)) == 0) + SHELL_PRINTF("%s%s%s\r\n", fno.fname, (fno.fattrib & AM_DIR) ? "/" : "", (fno.fattrib & AM_HID) ? "(Hidden)" : ""); } } @@ -245,8 +247,7 @@ void shell_auto_complete_path(char *path) } } - closedir(dir); - rt_free(full_path); + f_closedir(&dir); } #endif @@ -529,11 +530,11 @@ int shell_exec(char *cmd, uint32_t length) } #ifdef SHELL_USING_FS - extern int shell_exec_script(char *cmd, uint32_t length); + // extern int shell_exec_script(char *cmd, uint32_t length); - if (shell_exec_script(cmd, length) == 0) { - return 0; - } + // if (shell_exec_script(cmd, length) == 0) { + // return 0; + // } #endif @@ -633,7 +634,6 @@ void shell_handler(uint8_t data) SHELL_PRINTF("%c", shell->line[shell->line_curpos]); shell->line_curpos++; } - return; } } diff --git a/components/shell/shell_fs.c b/components/shell/shell_fs.c new file mode 100644 index 00000000..96a22420 --- /dev/null +++ b/components/shell/shell_fs.c @@ -0,0 +1,198 @@ +#include "shell.h" +#include "ff.h" +#include "fatfs_posix_api.h" + +#if defined(SHELL_USING_FS) +/* +static void *(*shell_malloc)(size_t size) = mmheap_alloc; +static void (*shell_free)(void *ptr) = mmheap_free; +*/ + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +const char *fatfs_table[] = { + "FR_OK:成功", /* (0) Succeeded */ + "FR_DISK_ERR:底层硬件错误", /* (1) A hard error occurred in the low level disk I/O layer */ + "FR_INT_ERR:断言失败", /* (2) Assertion failed */ + "FR_NOT_READY:物理驱动没有工作", /* (3) The physical drive cannot work */ + "FR_NO_FILE:文件不存在", /* (4) Could not find the file */ + "FR_NO_PATH:路径不存在", /* (5) Could not find the path */ + "FR_INVALID_NAME:无效文件名", /* (6) The path name format is invalid */ + "FR_DENIED:由于禁止访问或者目录已满访问被拒绝", /* (7) Access denied due to prohibited access or directory full */ + "FR_EXIST:文件已经存在", /* (8) Access denied due to prohibited access */ + "FR_INVALID_OBJECT:文件或者目录对象无效", /* (9) The file/directory object is invalid */ + "FR_WRITE_PROTECTED:物理驱动被写保护", /* (10) The physical drive is write protected */ + "FR_INVALID_DRIVE:逻辑驱动号无效", /* (11) The logical drive number is invalid */ + "FR_NOT_ENABLED:卷中无工作区", /* (12) The volume has no work area */ + "FR_NO_FILESYSTEM:没有有效的FAT卷", /* (13) There is no valid FAT volume */ + "FR_MKFS_ABORTED:由于参数错误f_mkfs()被终止", /* (14) The f_mkfs() aborted due to any parameter error */ + "FR_TIMEOUT:在规定的时间内无法获得访问卷的许可", /* (15) Could not get a grant to access the volume within defined period */ + "FR_LOCKED:由于文件共享策略操作被拒绝", /* (16) The operation is rejected according to the file sharing policy */ + "FR_NOT_ENOUGH_CORE:无法分配长文件名工作区", /* (17) LFN working buffer could not be allocated */ + "FR_TOO_MANY_OPEN_FILES:当前打开的文件数大于_FS_SHARE", /* (18) Number of open files > _FS_SHARE */ + "FR_INVALID_PARAMETER:参数无效" /* (19) Given parameter is invalid */ +}; + +static char path[SHELL_CONSOLEBUF_SIZE] = { 0 }; + +#ifdef DFS_USING_WORKDIR +extern char working_directory[]; +#endif + +int cmd_ls(int argc, char **argv) +{ + FILINFO entry = { 0 }; + DIR dir; + int err; + uint8_t flag = 0; + + for (uint8_t i = 1; i < argc; i++) { + //cmd + if (argv[i][0] == '-') { + if (strcmp(argv[i], "-a") == 0) { + flag |= 0x01; + } else { + MSG("参数错误 %s\r\n", argv[i]); + return -1; + } + } + //path + else { + if ((flag & 0x80) == 0) { + strcpy(path, argv[i]); + flag |= 0x80; + } else { + MSG("参数错误 %s\r\n", argv[i]); + return -1; + } + } + } + + if ((flag & 0x80) == 0) { + strcpy(path, "."); + } + + err = f_opendir(&dir, path); + + if (err) { + MSG("%s %s\r\n", fatfs_table[err], path); + return -1; + } + + while (1) { + err = f_readdir(&dir, &entry); + + if (err) { + MSG("%s %s\r\n", fatfs_table[err], path); + break; + } + + /* Check for end of directory listing */ + if (entry.fname[0] == '\0') { + break; + } + + if ((entry.fattrib & AM_HID) && !(flag & 0x01)) { + continue; + } + + MSG("%s%s%s\r\n", entry.fname, (entry.fattrib & AM_DIR) ? "/" : "", (entry.fattrib & AM_HID) ? "(Hidden)" : ""); + } + + f_closedir(&dir); + + return 0; +} +SHELL_CMD_EXPORT_ALIAS(cmd_ls, ls, List information about the FILEs.); + +int cmd_rm(int argc, char **argv) +{ + int err; + + if (argc < 2) { + MSG("缺少参数\r\n"); + MSG("rm \r\n"); + return -1; + } else { + strcpy(path, argv[1]); + } + + err = f_unlink(path); + + if (err) { + MSG("%s %s\r\n", fatfs_table[err], path); + err = -1; + } + + return err; +} +SHELL_CMD_EXPORT_ALIAS(cmd_rm, rm, Remove(unlink) the FILE(s).); + +int cmd_cd(int argc, char **argv) +{ + int err; + + if (argc < 2) { + strcpy(path, "."); + } else { + strcpy(path, argv[1]); + } + + for (uint16_t i = strlen(path) - 1; i > 0; i--) { + if (path[i] == '/') + path[i] = '\0'; + else + break; + } + + err = f_chdir(path); + + if (err) { + MSG("%s %s\r\n", fatfs_table[err], path); + return -1; + } + + return 0; +} +SHELL_CMD_EXPORT_ALIAS(cmd_cd, cd, Change the shell working directory.); + +int cmd_pwd(int argc, char **argv) +{ + int err; + err = f_getcwd(path, SHELL_CONSOLEBUF_SIZE); + + if (err) { + MSG("%s\r\n", fatfs_table[err]); + return -1; + } + + MSG("%s\r\n", path); + + return 0; +} +SHELL_CMD_EXPORT_ALIAS(cmd_pwd, pwd, Print the name of the current working directory.); + +int cmd_mkdir(int argc, char **argv) +{ + int err; + + if (argc < 2) { + strcpy(path, "new_dir"); + } else { + strcpy(path, argv[1]); + } + + err = f_mkdir(path); + + if (err) { + MSG("%s %s\r\n", fatfs_table[err], path); + err = -1; + } + + return err; +} +SHELL_CMD_EXPORT_ALIAS(cmd_mkdir, mkdir, Create the DIRECTORY.); + +#endif \ No newline at end of file