diff --git a/subsys/fs/Kconfig b/subsys/fs/Kconfig index fef3920e868..7d990d07abe 100644 --- a/subsys/fs/Kconfig +++ b/subsys/fs/Kconfig @@ -24,6 +24,13 @@ config FILE_SYSTEM if FILE_SYSTEM +config FILE_SYSTEM_SHELL + bool "Enable file system shell" + depends on ENABLE_SHELL + help + This shell provides basic browsing of the contents of the + file system. + config FILE_SYSTEM_FAT bool "FAT file system support" default y diff --git a/subsys/fs/Makefile b/subsys/fs/Makefile index ed9c06378f1..1d1e3005be4 100644 --- a/subsys/fs/Makefile +++ b/subsys/fs/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_FS_FAT_RAM_DISK) += fat_ram_diskio.o obj-$(CONFIG_FS_FAT_FLASH_DISK) += fat_flash_diskio.o obj-$(CONFIG_FILE_SYSTEM_FAT) += fat_fs.o +obj-$(CONFIG_FILE_SYSTEM_SHELL) += shell.o diff --git a/subsys/fs/shell.c b/subsys/fs/shell.c new file mode 100644 index 00000000000..4b2381a287c --- /dev/null +++ b/subsys/fs/shell.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed 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 +#include +#include + +#include +#include +#include +#include + +#define MAX_PATH_LEN 128 + +static char cwd[MAX_PATH_LEN] = "/"; + +static int cmd_ls(int argc, char *argv[]) +{ + char path[MAX_PATH_LEN]; + fs_dir_t dir; + int err; + + if (argc < 2) { + strcpy(path, cwd); + } else if (argv[1][0] == '/') { + strncpy(path, argv[1], sizeof(path) - 1); + path[MAX_PATH_LEN - 1] = '\0'; + } else { + if (strcmp(cwd, "/") == 0) { + snprintf(path, sizeof(path), "/%s", argv[1]); + } else { + snprintf(path, sizeof(path), "%s/%s", cwd, argv[1]); + } + } + + err = fs_opendir(&dir, path); + if (err) { + printk("Unable to open %s (err %d)\n", path, err); + return 0; + } + + while (1) { + struct fs_dirent entry; + + err = fs_readdir(&dir, &entry); + if (err) { + printk("Unable to read directory\n"); + break; + } + + /* Check for end of directory listing */ + if (entry.name[0] == '\0') { + break; + } + + if (entry.type == FS_DIR_ENTRY_DIR) { + printk("%s/\n", entry.name); + } else { + printk("%s\n", entry.name); + } + } + + fs_closedir(&dir); + + return 0; +} + +static int cmd_pwd(int argc, char *argv[]) +{ + printk("%s\n", cwd); + return 0; +} + +static int cmd_cd(int argc, char *argv[]) +{ + char path[MAX_PATH_LEN]; + struct fs_dirent entry; + int err; + + if (argc < 2) { + strcpy(cwd, "/"); + return 0; + } + + if (strcmp(argv[1], "..") == 0) { + char *prev = strrchr(cwd, '/'); + + if (!prev || prev == cwd) { + strcpy(cwd, "/"); + } else { + *prev = '\0'; + } + + /* No need to test that a parent exists */ + return 0; + } + + if (argv[1][0] == '/') { + strncpy(path, argv[1], sizeof(path) - 1); + path[MAX_PATH_LEN - 1] = '\0'; + } else { + if (strcmp(cwd, "/") == 0) { + snprintf(path, sizeof(path), "/%s", argv[1]); + } else { + snprintf(path, sizeof(path), "%s/%s", cwd, argv[1]); + } + } + + err = fs_stat(path, &entry); + if (err) { + printk("%s doesn't exist\n", path); + return 0; + } + + if (entry.type != FS_DIR_ENTRY_DIR) { + printk("%s is not a directory\n", path); + return 0; + } + + strcpy(cwd, path); + + return 0; +} + +struct shell_cmd fs_commands[] = { + { "ls", cmd_ls, "List files in current directory" }, + { "cd", cmd_cd, "Change working directory" }, + { "pwd", cmd_pwd, "Print current working directory" }, + { NULL, NULL } +}; + + +SHELL_REGISTER("fs", fs_commands);