blob: 1dbd6de8719ef28996a0f84872e334b6436ab64c [file] [log] [blame]
/*
* 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