mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
Stage 21
This commit is contained in:
370
clks/kernel/fs.c
370
clks/kernel/fs.c
@@ -1,5 +1,6 @@
|
||||
#include <clks/boot.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/heap.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/ramdisk.h>
|
||||
#include <clks/string.h>
|
||||
@@ -8,6 +9,8 @@
|
||||
#define CLKS_FS_MAX_NODES 512U
|
||||
#define CLKS_FS_PATH_MAX CLKS_RAMDISK_PATH_MAX
|
||||
|
||||
#define CLKS_FS_NODE_FLAG_HEAP_DATA 0x0001U
|
||||
|
||||
struct clks_fs_node {
|
||||
clks_bool used;
|
||||
enum clks_fs_node_type type;
|
||||
@@ -26,6 +29,7 @@ struct clks_fs_build_stats {
|
||||
static struct clks_fs_node clks_fs_nodes[CLKS_FS_MAX_NODES];
|
||||
static u16 clks_fs_nodes_used = 0U;
|
||||
static clks_bool clks_fs_ready = CLKS_FALSE;
|
||||
static const u8 clks_fs_empty_file_data[1] = {0U};
|
||||
|
||||
static clks_bool clks_fs_normalize_external_path(const char *path, char *out_internal, usize out_size) {
|
||||
usize in_pos = 0;
|
||||
@@ -94,6 +98,33 @@ static clks_bool clks_fs_normalize_external_path(const char *path, char *out_int
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_fs_internal_in_temp_tree(const char *internal_path) {
|
||||
if (internal_path == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (internal_path[0] != 't' ||
|
||||
internal_path[1] != 'e' ||
|
||||
internal_path[2] != 'm' ||
|
||||
internal_path[3] != 'p') {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
return (internal_path[4] == '\0' || internal_path[4] == '/') ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
static clks_bool clks_fs_internal_is_temp_file_path(const char *internal_path) {
|
||||
if (clks_fs_internal_in_temp_tree(internal_path) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (internal_path[4] == '\0') {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static i32 clks_fs_find_node_by_internal(const char *internal_path) {
|
||||
u16 i;
|
||||
|
||||
@@ -176,12 +207,54 @@ static clks_bool clks_fs_split_parent(const char *internal_path, char *parent_ou
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_fs_node_has_heap_data(u16 index) {
|
||||
return ((clks_fs_nodes[index].reserved & CLKS_FS_NODE_FLAG_HEAP_DATA) != 0U) ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
static void clks_fs_node_set_heap_data(u16 index, clks_bool value) {
|
||||
if (value == CLKS_TRUE) {
|
||||
clks_fs_nodes[index].reserved |= CLKS_FS_NODE_FLAG_HEAP_DATA;
|
||||
} else {
|
||||
clks_fs_nodes[index].reserved &= (u16)(~CLKS_FS_NODE_FLAG_HEAP_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_fs_node_release_heap_data(u16 index) {
|
||||
if (clks_fs_nodes[index].type != CLKS_FS_NODE_FILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_fs_node_has_heap_data(index) == CLKS_TRUE && clks_fs_nodes[index].data != CLKS_NULL) {
|
||||
clks_kfree((void *)clks_fs_nodes[index].data);
|
||||
}
|
||||
|
||||
clks_fs_node_set_heap_data(index, CLKS_FALSE);
|
||||
}
|
||||
|
||||
static i32 clks_fs_alloc_slot(void) {
|
||||
u16 i;
|
||||
|
||||
for (i = 0U; i < clks_fs_nodes_used; i++) {
|
||||
if (clks_fs_nodes[i].used == CLKS_FALSE) {
|
||||
return (i32)i;
|
||||
}
|
||||
}
|
||||
|
||||
if (clks_fs_nodes_used >= CLKS_FS_MAX_NODES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
clks_fs_nodes_used++;
|
||||
return (i32)(clks_fs_nodes_used - 1U);
|
||||
}
|
||||
|
||||
static i32 clks_fs_create_or_update_node(const char *internal_path,
|
||||
enum clks_fs_node_type type,
|
||||
u16 parent,
|
||||
const void *data,
|
||||
u64 size) {
|
||||
i32 existing;
|
||||
i32 slot;
|
||||
usize path_len;
|
||||
|
||||
if (internal_path == CLKS_NULL) {
|
||||
@@ -208,25 +281,28 @@ static i32 clks_fs_create_or_update_node(const char *internal_path,
|
||||
if (type == CLKS_FS_NODE_FILE) {
|
||||
node->data = data;
|
||||
node->size = size;
|
||||
node->reserved = 0U;
|
||||
}
|
||||
|
||||
node->used = CLKS_TRUE;
|
||||
return existing;
|
||||
}
|
||||
|
||||
if (clks_fs_nodes_used >= CLKS_FS_MAX_NODES) {
|
||||
slot = clks_fs_alloc_slot();
|
||||
|
||||
if (slot < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
clks_fs_nodes[clks_fs_nodes_used].used = CLKS_TRUE;
|
||||
clks_fs_nodes[clks_fs_nodes_used].type = type;
|
||||
clks_fs_nodes[clks_fs_nodes_used].parent = parent;
|
||||
clks_fs_nodes[clks_fs_nodes_used].reserved = 0U;
|
||||
clks_fs_nodes[clks_fs_nodes_used].data = (type == CLKS_FS_NODE_FILE) ? data : CLKS_NULL;
|
||||
clks_fs_nodes[clks_fs_nodes_used].size = (type == CLKS_FS_NODE_FILE) ? size : 0ULL;
|
||||
clks_memcpy(clks_fs_nodes[clks_fs_nodes_used].path, internal_path, path_len + 1U);
|
||||
clks_fs_nodes[(u16)slot].used = CLKS_TRUE;
|
||||
clks_fs_nodes[(u16)slot].type = type;
|
||||
clks_fs_nodes[(u16)slot].parent = parent;
|
||||
clks_fs_nodes[(u16)slot].reserved = 0U;
|
||||
clks_fs_nodes[(u16)slot].data = (type == CLKS_FS_NODE_FILE) ? data : CLKS_NULL;
|
||||
clks_fs_nodes[(u16)slot].size = (type == CLKS_FS_NODE_FILE) ? size : 0ULL;
|
||||
clks_memcpy(clks_fs_nodes[(u16)slot].path, internal_path, path_len + 1U);
|
||||
|
||||
clks_fs_nodes_used++;
|
||||
return (i32)(clks_fs_nodes_used - 1U);
|
||||
return slot;
|
||||
}
|
||||
|
||||
static clks_bool clks_fs_ensure_root(void) {
|
||||
@@ -372,6 +448,38 @@ static clks_bool clks_fs_ramdisk_visit(const struct clks_ramdisk_entry *entry, v
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_fs_build_file_payload(const void *data,
|
||||
u64 size,
|
||||
const void **out_data,
|
||||
clks_bool *out_heap_owned) {
|
||||
void *payload;
|
||||
|
||||
if (out_data == CLKS_NULL || out_heap_owned == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (size == 0ULL) {
|
||||
*out_data = (const void *)clks_fs_empty_file_data;
|
||||
*out_heap_owned = CLKS_FALSE;
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (data == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
payload = clks_kmalloc((usize)size);
|
||||
|
||||
if (payload == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_memcpy(payload, data, (usize)size);
|
||||
*out_data = (const void *)payload;
|
||||
*out_heap_owned = CLKS_TRUE;
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
void clks_fs_init(void) {
|
||||
const struct limine_file *module;
|
||||
struct clks_fs_build_stats stats;
|
||||
@@ -474,6 +582,10 @@ const void *clks_fs_read_all(const char *path, u64 *out_size) {
|
||||
*out_size = clks_fs_nodes[(u16)node_index].size;
|
||||
}
|
||||
|
||||
if (clks_fs_nodes[(u16)node_index].size == 0ULL) {
|
||||
return (const void *)clks_fs_empty_file_data;
|
||||
}
|
||||
|
||||
return clks_fs_nodes[(u16)node_index].data;
|
||||
}
|
||||
|
||||
@@ -563,10 +675,244 @@ clks_bool clks_fs_get_child_name(const char *dir_path, u64 index, char *out_name
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_bool clks_fs_mkdir(const char *path) {
|
||||
char internal[CLKS_FS_PATH_MAX];
|
||||
i32 node_index;
|
||||
|
||||
if (clks_fs_ready == CLKS_FALSE || path == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_normalize_external_path(path, internal, sizeof(internal)) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_internal_in_temp_tree(internal) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (internal[0] == '\0') {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_ensure_dir_hierarchy(internal) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
node_index = clks_fs_find_node_by_internal(internal);
|
||||
|
||||
if (node_index < 0) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
return (clks_fs_nodes[(u16)node_index].type == CLKS_FS_NODE_DIR) ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_bool clks_fs_write_all(const char *path, const void *data, u64 size) {
|
||||
char internal[CLKS_FS_PATH_MAX];
|
||||
char parent[CLKS_FS_PATH_MAX];
|
||||
const void *payload_data = CLKS_NULL;
|
||||
clks_bool payload_heap_owned = CLKS_FALSE;
|
||||
i32 parent_index;
|
||||
i32 node_index;
|
||||
|
||||
if (clks_fs_ready == CLKS_FALSE || path == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_normalize_external_path(path, internal, sizeof(internal)) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_internal_is_temp_file_path(internal) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_split_parent(internal, parent, sizeof(parent)) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_internal_in_temp_tree(parent) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_ensure_dir_hierarchy(parent) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
parent_index = clks_fs_find_node_by_internal(parent);
|
||||
|
||||
if (parent_index < 0 || clks_fs_nodes[(u16)parent_index].type != CLKS_FS_NODE_DIR) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
node_index = clks_fs_find_node_by_internal(internal);
|
||||
|
||||
if (node_index >= 0 && clks_fs_nodes[(u16)node_index].type != CLKS_FS_NODE_FILE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_build_file_payload(data, size, &payload_data, &payload_heap_owned) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (node_index >= 0) {
|
||||
clks_fs_node_release_heap_data((u16)node_index);
|
||||
}
|
||||
|
||||
node_index = clks_fs_create_or_update_node(
|
||||
internal,
|
||||
CLKS_FS_NODE_FILE,
|
||||
(u16)parent_index,
|
||||
payload_data,
|
||||
size
|
||||
);
|
||||
|
||||
if (node_index < 0) {
|
||||
if (payload_heap_owned == CLKS_TRUE) {
|
||||
clks_kfree((void *)payload_data);
|
||||
}
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_fs_node_set_heap_data((u16)node_index, payload_heap_owned);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
clks_bool clks_fs_append(const char *path, const void *data, u64 size) {
|
||||
char internal[CLKS_FS_PATH_MAX];
|
||||
i32 node_index;
|
||||
const void *old_data;
|
||||
u64 old_size;
|
||||
u64 new_size;
|
||||
void *merged = CLKS_NULL;
|
||||
|
||||
if (clks_fs_ready == CLKS_FALSE || path == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (size > 0ULL && data == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_normalize_external_path(path, internal, sizeof(internal)) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_internal_is_temp_file_path(internal) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
node_index = clks_fs_find_node_by_internal(internal);
|
||||
|
||||
if (node_index < 0) {
|
||||
return clks_fs_write_all(path, data, size);
|
||||
}
|
||||
|
||||
if (clks_fs_nodes[(u16)node_index].type != CLKS_FS_NODE_FILE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
old_data = clks_fs_nodes[(u16)node_index].data;
|
||||
old_size = clks_fs_nodes[(u16)node_index].size;
|
||||
|
||||
if (old_size > (0xFFFFFFFFFFFFFFFFULL - size)) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
new_size = old_size + size;
|
||||
|
||||
if (new_size == 0ULL) {
|
||||
return clks_fs_write_all(path, clks_fs_empty_file_data, 0ULL);
|
||||
}
|
||||
|
||||
merged = clks_kmalloc((usize)new_size);
|
||||
|
||||
if (merged == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (old_size > 0ULL && old_data != CLKS_NULL) {
|
||||
clks_memcpy(merged, old_data, (usize)old_size);
|
||||
}
|
||||
|
||||
if (size > 0ULL) {
|
||||
clks_memcpy((u8 *)merged + (usize)old_size, data, (usize)size);
|
||||
}
|
||||
if (clks_fs_write_all(path, merged, new_size) == CLKS_FALSE) {
|
||||
clks_kfree(merged);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_kfree(merged);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
clks_bool clks_fs_remove(const char *path) {
|
||||
char internal[CLKS_FS_PATH_MAX];
|
||||
i32 node_index;
|
||||
u16 i;
|
||||
|
||||
if (clks_fs_ready == CLKS_FALSE || path == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_normalize_external_path(path, internal, sizeof(internal)) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_internal_in_temp_tree(internal) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_strcmp(internal, "temp") == 0) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
node_index = clks_fs_find_node_by_internal(internal);
|
||||
|
||||
if (node_index < 0) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_fs_nodes[(u16)node_index].type == CLKS_FS_NODE_DIR) {
|
||||
for (i = 0U; i < clks_fs_nodes_used; i++) {
|
||||
if (clks_fs_nodes[i].used == CLKS_FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clks_fs_nodes[i].parent == (u16)node_index) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clks_fs_node_release_heap_data((u16)node_index);
|
||||
|
||||
clks_fs_nodes[(u16)node_index].used = CLKS_FALSE;
|
||||
clks_fs_nodes[(u16)node_index].type = CLKS_FS_NODE_FILE;
|
||||
clks_fs_nodes[(u16)node_index].parent = 0U;
|
||||
clks_fs_nodes[(u16)node_index].reserved = 0U;
|
||||
clks_fs_nodes[(u16)node_index].data = CLKS_NULL;
|
||||
clks_fs_nodes[(u16)node_index].size = 0ULL;
|
||||
clks_fs_nodes[(u16)node_index].path[0] = '\0';
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
u64 clks_fs_node_count(void) {
|
||||
u16 i;
|
||||
u64 used = 0ULL;
|
||||
|
||||
if (clks_fs_ready == CLKS_FALSE) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
return (u64)clks_fs_nodes_used;
|
||||
}
|
||||
for (i = 0U; i < clks_fs_nodes_used; i++) {
|
||||
if (clks_fs_nodes[i].used == CLKS_TRUE) {
|
||||
used++;
|
||||
}
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ void clks_kernel_main(void) {
|
||||
clks_tty_init();
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE18 START");
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS Stage21 START");
|
||||
|
||||
if (boot_fb == CLKS_NULL) {
|
||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||
|
||||
@@ -23,6 +23,7 @@ static char clks_shell_line[CLKS_SHELL_LINE_MAX];
|
||||
static usize clks_shell_line_len = 0U;
|
||||
static usize clks_shell_cursor = 0U;
|
||||
static usize clks_shell_rendered_len = 0U;
|
||||
static char clks_shell_cwd[CLKS_SHELL_PATH_MAX] = "/";
|
||||
|
||||
static char clks_shell_history[CLKS_SHELL_HISTORY_MAX][CLKS_SHELL_LINE_MAX];
|
||||
static u32 clks_shell_history_count = 0U;
|
||||
@@ -390,11 +391,178 @@ static clks_bool clks_shell_resolve_exec_path(const char *arg, char *out_path, u
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_path_push_component(char *path, usize path_size, usize *io_len, const char *component, usize comp_len) {
|
||||
if (path == CLKS_NULL || io_len == CLKS_NULL || component == CLKS_NULL || comp_len == 0U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (*io_len == 1U) {
|
||||
if (*io_len + comp_len >= path_size) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_memcpy(path + 1U, component, comp_len);
|
||||
*io_len = 1U + comp_len;
|
||||
path[*io_len] = '\0';
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (*io_len + 1U + comp_len >= path_size) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
path[*io_len] = '/';
|
||||
clks_memcpy(path + *io_len + 1U, component, comp_len);
|
||||
*io_len += (1U + comp_len);
|
||||
path[*io_len] = '\0';
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static void clks_shell_path_pop_component(char *path, usize *io_len) {
|
||||
if (path == CLKS_NULL || io_len == CLKS_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*io_len <= 1U) {
|
||||
path[0] = '/';
|
||||
path[1] = '\0';
|
||||
*io_len = 1U;
|
||||
return;
|
||||
}
|
||||
|
||||
while (*io_len > 1U && path[*io_len - 1U] != '/') {
|
||||
(*io_len)--;
|
||||
}
|
||||
|
||||
if (*io_len > 1U) {
|
||||
(*io_len)--;
|
||||
}
|
||||
|
||||
path[*io_len] = '\0';
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_path_parse_into(const char *src, char *out_path, usize out_size, usize *io_len) {
|
||||
usize i = 0U;
|
||||
|
||||
if (src == CLKS_NULL || out_path == CLKS_NULL || io_len == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (src[0] == '/') {
|
||||
i = 1U;
|
||||
}
|
||||
|
||||
while (src[i] != '\0') {
|
||||
usize start;
|
||||
usize len;
|
||||
|
||||
while (src[i] == '/') {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (src[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
start = i;
|
||||
|
||||
while (src[i] != '\0' && src[i] != '/') {
|
||||
i++;
|
||||
}
|
||||
|
||||
len = i - start;
|
||||
|
||||
if (len == 1U && src[start] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len == 2U && src[start] == '.' && src[start + 1U] == '.') {
|
||||
clks_shell_path_pop_component(out_path, io_len);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clks_shell_path_push_component(out_path, out_size, io_len, src + start, len) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_resolve_path(const char *arg, char *out_path, usize out_size) {
|
||||
usize len = 1U;
|
||||
|
||||
if (out_path == CLKS_NULL || out_size < 2U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
out_path[0] = '/';
|
||||
out_path[1] = '\0';
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
return clks_shell_path_parse_into(clks_shell_cwd, out_path, out_size, &len);
|
||||
}
|
||||
|
||||
if (arg[0] != '/') {
|
||||
if (clks_shell_path_parse_into(clks_shell_cwd, out_path, out_size, &len) == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return clks_shell_path_parse_into(arg, out_path, out_size, &len);
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_split_first_and_rest(const char *arg,
|
||||
char *out_first,
|
||||
usize out_first_size,
|
||||
const char **out_rest) {
|
||||
usize i = 0U;
|
||||
usize p = 0U;
|
||||
|
||||
if (arg == CLKS_NULL || out_first == CLKS_NULL || out_first_size == 0U || out_rest == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
out_first[0] = '\0';
|
||||
*out_rest = "";
|
||||
|
||||
while (arg[i] != '\0' && clks_shell_is_space(arg[i]) == CLKS_TRUE) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (arg[i] == '\0') {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
while (arg[i] != '\0' && clks_shell_is_space(arg[i]) == CLKS_FALSE) {
|
||||
if (p + 1U < out_first_size) {
|
||||
out_first[p++] = arg[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
out_first[p] = '\0';
|
||||
|
||||
while (arg[i] != '\0' && clks_shell_is_space(arg[i]) == CLKS_TRUE) {
|
||||
i++;
|
||||
}
|
||||
|
||||
*out_rest = &arg[i];
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_help(void) {
|
||||
clks_shell_writeln("commands:");
|
||||
clks_shell_writeln(" help");
|
||||
clks_shell_writeln(" ls [dir]");
|
||||
clks_shell_writeln(" cat <file>");
|
||||
clks_shell_writeln(" pwd");
|
||||
clks_shell_writeln(" cd [dir]");
|
||||
clks_shell_writeln(" mkdir <dir> (/temp only)");
|
||||
clks_shell_writeln(" touch <file> (/temp only)");
|
||||
clks_shell_writeln(" write <file> <text> (/temp only)");
|
||||
clks_shell_writeln(" append <file> <text> (/temp only)");
|
||||
clks_shell_writeln(" rm <path> (/temp only)");
|
||||
clks_shell_writeln(" exec <path|name>");
|
||||
clks_shell_writeln(" clear");
|
||||
clks_shell_writeln(" kbdstat");
|
||||
@@ -403,12 +571,18 @@ static void clks_shell_cmd_help(void) {
|
||||
|
||||
static void clks_shell_cmd_ls(const char *arg) {
|
||||
struct clks_fs_node_info info;
|
||||
const char *path = arg;
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
const char *target = arg;
|
||||
u64 count;
|
||||
u64 i;
|
||||
|
||||
if (path == CLKS_NULL || path[0] == '\0') {
|
||||
path = "/";
|
||||
if (target == CLKS_NULL || target[0] == '\0') {
|
||||
target = ".";
|
||||
}
|
||||
|
||||
if (clks_shell_resolve_path(target, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("ls: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_fs_stat(path, &info) == CLKS_FALSE || info.type != CLKS_FS_NODE_DIR) {
|
||||
@@ -439,6 +613,7 @@ static void clks_shell_cmd_cat(const char *arg) {
|
||||
const void *data;
|
||||
u64 size = 0ULL;
|
||||
u64 copy_len;
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
char out[CLKS_SHELL_CAT_LIMIT + 1U];
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
@@ -446,7 +621,12 @@ static void clks_shell_cmd_cat(const char *arg) {
|
||||
return;
|
||||
}
|
||||
|
||||
data = clks_fs_read_all(arg, &size);
|
||||
if (clks_shell_resolve_path(arg, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("cat: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
data = clks_fs_read_all(path, &size);
|
||||
|
||||
if (data == CLKS_NULL) {
|
||||
clks_shell_writeln("cat: file not found");
|
||||
@@ -469,6 +649,143 @@ static void clks_shell_cmd_cat(const char *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_pwd(void) {
|
||||
clks_shell_writeln(clks_shell_cwd);
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_cd(const char *arg) {
|
||||
struct clks_fs_node_info info;
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
const char *target = arg;
|
||||
|
||||
if (target == CLKS_NULL || target[0] == '\0') {
|
||||
target = "/";
|
||||
}
|
||||
|
||||
if (clks_shell_resolve_path(target, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("cd: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_fs_stat(path, &info) == CLKS_FALSE || info.type != CLKS_FS_NODE_DIR) {
|
||||
clks_shell_writeln("cd: directory not found");
|
||||
return;
|
||||
}
|
||||
|
||||
clks_shell_copy_line(clks_shell_cwd, sizeof(clks_shell_cwd), path);
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_mkdir(const char *arg) {
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
clks_shell_writeln("mkdir: directory path required");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_resolve_path(arg, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("mkdir: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_fs_mkdir(path) == CLKS_FALSE) {
|
||||
clks_shell_writeln("mkdir: failed (only /temp writable)");
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_touch(const char *arg) {
|
||||
static const char empty_data[1] = {'\0'};
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
clks_shell_writeln("touch: file path required");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_resolve_path(arg, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("touch: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_fs_write_all(path, empty_data, 0ULL) == CLKS_FALSE) {
|
||||
clks_shell_writeln("touch: failed (only /temp writable)");
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_write(const char *arg) {
|
||||
char path_arg[CLKS_SHELL_PATH_MAX];
|
||||
char abs_path[CLKS_SHELL_PATH_MAX];
|
||||
const char *payload;
|
||||
u64 payload_len;
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
clks_shell_writeln("write: usage write <file> <text>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_split_first_and_rest(arg, path_arg, sizeof(path_arg), &payload) == CLKS_FALSE) {
|
||||
clks_shell_writeln("write: usage write <file> <text>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_resolve_path(path_arg, abs_path, sizeof(abs_path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("write: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
payload_len = clks_strlen(payload);
|
||||
|
||||
if (clks_fs_write_all(abs_path, payload, payload_len) == CLKS_FALSE) {
|
||||
clks_shell_writeln("write: failed (only /temp writable)");
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_append(const char *arg) {
|
||||
char path_arg[CLKS_SHELL_PATH_MAX];
|
||||
char abs_path[CLKS_SHELL_PATH_MAX];
|
||||
const char *payload;
|
||||
u64 payload_len;
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
clks_shell_writeln("append: usage append <file> <text>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_split_first_and_rest(arg, path_arg, sizeof(path_arg), &payload) == CLKS_FALSE) {
|
||||
clks_shell_writeln("append: usage append <file> <text>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_resolve_path(path_arg, abs_path, sizeof(abs_path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("append: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
payload_len = clks_strlen(payload);
|
||||
|
||||
if (clks_fs_append(abs_path, payload, payload_len) == CLKS_FALSE) {
|
||||
clks_shell_writeln("append: failed (only /temp writable)");
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_rm(const char *arg) {
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
clks_shell_writeln("rm: path required");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_resolve_path(arg, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("rm: invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_fs_remove(path) == CLKS_FALSE) {
|
||||
clks_shell_writeln("rm: failed (only /temp writable; dir must be empty)");
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_exec(const char *arg) {
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
u64 status = (u64)-1;
|
||||
@@ -540,6 +857,41 @@ static void clks_shell_execute_line(const char *line) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "pwd") == CLKS_TRUE) {
|
||||
clks_shell_cmd_pwd();
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "cd") == CLKS_TRUE) {
|
||||
clks_shell_cmd_cd(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "mkdir") == CLKS_TRUE) {
|
||||
clks_shell_cmd_mkdir(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "touch") == CLKS_TRUE) {
|
||||
clks_shell_cmd_touch(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "write") == CLKS_TRUE) {
|
||||
clks_shell_cmd_write(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "append") == CLKS_TRUE) {
|
||||
clks_shell_cmd_append(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "rm") == CLKS_TRUE) {
|
||||
clks_shell_cmd_rm(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "exec") == CLKS_TRUE || clks_shell_streq(cmd, "run") == CLKS_TRUE) {
|
||||
clks_shell_cmd_exec(arg);
|
||||
return;
|
||||
@@ -686,10 +1038,12 @@ static void clks_shell_handle_char(char ch) {
|
||||
clks_shell_render_line();
|
||||
}
|
||||
}
|
||||
|
||||
void clks_shell_init(void) {
|
||||
clks_shell_reset_line();
|
||||
clks_shell_history_count = 0U;
|
||||
clks_shell_history_cancel_nav();
|
||||
clks_shell_copy_line(clks_shell_cwd, sizeof(clks_shell_cwd), "/");
|
||||
|
||||
if (clks_tty_ready() == CLKS_FALSE) {
|
||||
clks_shell_ready = CLKS_FALSE;
|
||||
@@ -702,6 +1056,7 @@ void clks_shell_init(void) {
|
||||
clks_shell_writeln("");
|
||||
clks_shell_writeln("CLeonOS interactive shell ready");
|
||||
clks_shell_writeln("type 'help' for commands");
|
||||
clks_shell_writeln("/temp is writable in kernel shell mode");
|
||||
clks_shell_prompt();
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "INTERACTIVE LOOP ONLINE");
|
||||
|
||||
Reference in New Issue
Block a user