| /* |
| * Copyright (c) 2015 Travis Geiselbrecht |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files |
| * (the "Software"), to deal in the Software without restriction, |
| * including without limitation the rights to use, copy, modify, merge, |
| * publish, distribute, sublicense, and/or sell copies of the Software, |
| * and to permit persons to whom the Software is furnished to do so, |
| * subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #include <err.h> |
| #include <debug.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <trace.h> |
| #include <stdlib.h> |
| #include <platform.h> |
| #include <lib/console.h> |
| #include <lib/fs.h> |
| |
| /* shell console hooks for manipulating the file system */ |
| |
| #if WITH_LIB_CONSOLE |
| |
| static char *cwd = NULL; |
| |
| static void set_cwd(const char *path) |
| { |
| if (!path) { |
| free(cwd); |
| cwd = NULL; |
| return; |
| } |
| |
| size_t len = strlen(path) + 1; |
| char *new_cwd = realloc(cwd, len); |
| if (new_cwd) { |
| cwd = new_cwd; |
| memcpy(cwd, path, len); |
| } |
| } |
| |
| static const char *get_cwd(void) |
| { |
| if (!cwd) |
| return "/"; |
| return cwd; |
| } |
| |
| static char *prepend_cwd(char *path, size_t len, const char *arg) |
| { |
| path[0] = '\0'; |
| |
| if (!arg || arg[0] != '/') { |
| strlcat(path, get_cwd(), len); |
| if (arg && path[strlen(path) - 1] != '/') |
| strlcat(path, "/", len); |
| } |
| if (arg) { |
| strlcat(path, arg, len); |
| } |
| |
| return path; |
| } |
| |
| static int cmd_ls(int argc, const cmd_args *argv) |
| { |
| status_t status = NO_ERROR; |
| |
| // construct the path |
| char *path = malloc(FS_MAX_PATH_LEN); |
| prepend_cwd(path, FS_MAX_PATH_LEN, (argc >= 2) ? argv[1].str : NULL); |
| |
| dirhandle *dhandle; |
| status = fs_open_dir(path, &dhandle); |
| if (status < 0) { |
| printf("error %d opening dir '%s'\n", status, path); |
| goto err; |
| } |
| |
| size_t pathlen = strlen(path); |
| |
| status_t err; |
| struct dirent ent; |
| while ((err = fs_read_dir(dhandle, &ent)) >= 0) { |
| struct file_stat stat; |
| filehandle *handle; |
| |
| // append our filename to the path |
| strlcat(path, "/", FS_MAX_PATH_LEN); |
| strlcat(path, ent.name, FS_MAX_PATH_LEN); |
| |
| err = fs_open_file(path, &handle); |
| |
| // restore the old path |
| path[pathlen] = '\0'; |
| |
| if (err < 0) { |
| printf("error %d opening file '%s'\n", err, path); |
| continue; |
| } |
| |
| // stat the file |
| err = fs_stat_file(handle, &stat); |
| fs_close_file(handle); |
| if (err < 0) { |
| printf("error %d statting file\n", err); |
| continue; |
| } |
| |
| printf("%c %16llu %s\n", stat.is_dir ? 'd' : ' ', stat.size, ent.name); |
| } |
| |
| fs_close_dir(dhandle); |
| |
| err: |
| free(path); |
| return status;; |
| } |
| |
| static int cmd_cd(int argc, const cmd_args *argv) |
| { |
| if (argc < 2) { |
| set_cwd(NULL); |
| } else { |
| char *path = malloc(FS_MAX_PATH_LEN); |
| prepend_cwd(path, FS_MAX_PATH_LEN, (argc >= 2) ? argv[1].str : NULL); |
| fs_normalize_path(path); |
| |
| if (strlen(path) == 0) { |
| set_cwd(NULL); |
| } else { |
| set_cwd(path); |
| } |
| free(path); |
| } |
| puts(get_cwd()); |
| |
| return 0; |
| } |
| |
| static int cmd_pwd(int argc, const cmd_args *argv) |
| { |
| puts(get_cwd()); |
| |
| return 0; |
| } |
| |
| static int cmd_mkdir(int argc, const cmd_args *argv) |
| { |
| if (argc < 2) { |
| printf("not enough arguments\n"); |
| printf("usage: %s <path>\n", argv[0].str); |
| return -1; |
| } |
| |
| char *path = malloc(FS_MAX_PATH_LEN); |
| |
| int status = fs_make_dir(prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str)); |
| if (status < 0) { |
| printf("error %d making directory '%s'\n", status, path); |
| } |
| |
| free(path); |
| return status; |
| } |
| |
| static int cmd_mkfile(int argc, const cmd_args *argv) |
| { |
| if (argc < 2) { |
| printf("not enough arguments\n"); |
| printf("usage: %s <path> [length]\n", argv[0].str); |
| return -1; |
| } |
| |
| char *path = malloc(FS_MAX_PATH_LEN); |
| prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str); |
| |
| filehandle *handle; |
| status_t status = fs_create_file(path, &handle, (argc >= 2) ? argv[2].u : 0); |
| if (status < 0) { |
| printf("error %d making file '%s'\n", status, path); |
| goto err; |
| } |
| |
| fs_close_file(handle); |
| |
| err: |
| free(path); |
| return status; |
| } |
| |
| static int cmd_rm(int argc, const cmd_args *argv) |
| { |
| if (argc < 2) { |
| printf("not enough arguments\n"); |
| printf("usage: %s <path>\n", argv[0].str); |
| return -1; |
| } |
| |
| char *path = malloc(FS_MAX_PATH_LEN); |
| prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str); |
| |
| status_t err = fs_remove_file(path); |
| if (err < 0) { |
| printf("error %d removing file '%s'\n", err, path); |
| return err; |
| } |
| |
| return 0; |
| } |
| |
| static int cmd_stat(int argc, const cmd_args *argv) |
| { |
| if (argc < 2) { |
| printf("not enough arguments\n"); |
| printf("usage: %s <path>\n", argv[0].str); |
| return -1; |
| } |
| |
| int status; |
| struct file_stat stat; |
| filehandle *handle; |
| |
| char *path = malloc(FS_MAX_PATH_LEN); |
| prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str); |
| |
| status = fs_open_file(path, &handle); |
| if (status < 0) { |
| printf("error %d opening file '%s'\n", status, path); |
| goto err; |
| } |
| |
| status = fs_stat_file(handle, &stat); |
| |
| fs_close_file(handle); |
| |
| if (status < 0) { |
| printf("error %d statting file\n", status); |
| goto err; |
| } |
| |
| printf("stat successful:\n"); |
| printf("\tis_dir: %d\n", stat.is_dir ? 1 : 0); |
| printf("\tsize: %lld\n", stat.size); |
| |
| |
| err: |
| free(path); |
| return status; |
| } |
| |
| static int cmd_cat(int argc, const cmd_args *argv) |
| { |
| status_t status = NO_ERROR; |
| |
| if (argc < 2) { |
| printf("not enough arguments\n"); |
| printf("usage: %s <path>\n", argv[0].str); |
| return -1; |
| } |
| |
| char *path = malloc(FS_MAX_PATH_LEN); |
| prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str); |
| |
| filehandle *handle; |
| status = fs_open_file(path, &handle); |
| if (status < 0) { |
| printf("error %d opening file '%s'\n", status, path); |
| goto err; |
| } |
| |
| char buf[64]; |
| ssize_t read_len; |
| off_t offset = 0; |
| while ((read_len = fs_read_file(handle, buf, offset, sizeof(buf))) > 0) { |
| for (int i = 0; i < read_len; i++) { |
| putchar(buf[i]); |
| } |
| |
| offset += read_len; |
| } |
| |
| fs_close_file(handle); |
| |
| err: |
| free(path); |
| return status; |
| } |
| |
| STATIC_COMMAND_START |
| STATIC_COMMAND("ls", "dir listing", &cmd_ls) |
| STATIC_COMMAND("cd", "change dir", &cmd_cd) |
| STATIC_COMMAND("pwd", "print working dir", &cmd_pwd) |
| STATIC_COMMAND("mkdir", "make dir", &cmd_mkdir) |
| STATIC_COMMAND("mkfile", "make file", &cmd_mkfile) |
| STATIC_COMMAND("rm", "remove file", &cmd_rm) |
| STATIC_COMMAND("stat", "stat file", &cmd_stat) |
| STATIC_COMMAND("cat", "cat file", &cmd_cat) |
| STATIC_COMMAND_END(fs_shell); |
| |
| #endif |
| |