From 29bbcea4357e47f91c68436f8ea4dc0642fc2f14 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Wed, 25 Feb 2026 16:25:43 +0100 Subject: [PATCH] Implement read_dir_entry () VFS op, CE add ls command --- ce/ce.c | 49 ++++++++++++++++++++++++++++++-- include/dir_entry.h | 10 +++++++ include/status.h | 2 ++ include/syscall_defs.h | 1 + kernel/fs/tarfs.c | 61 +++++++++++++++++++++++++++++++++------- kernel/fs/tarfs.h | 4 +++ kernel/fs/vfs.c | 25 ++++++++++++++-- kernel/fs/vfs.h | 12 ++++++-- kernel/proc/proc.c | 4 +-- kernel/syscall/syscall.c | 36 ++++++++++++++++++++++-- libsystem/system.c | 4 +++ libsystem/system.h | 4 +++ 12 files changed, 189 insertions(+), 23 deletions(-) create mode 100644 include/dir_entry.h diff --git a/ce/ce.c b/ce/ce.c index 99fde6f..c4dfb64 100644 --- a/ce/ce.c +++ b/ce/ce.c @@ -108,13 +108,54 @@ static void cmd_cat (struct list_node_link* tokens) { } } +static void cmd_ls (struct list_node_link* tokens) { + if (tokens == NULL) { + printf ("ERROR no directory path provided\n"); + return; + } + + struct token* token = list_entry (tokens, struct token, tokens_link); + struct desc desc; + char volume[VOLUME_MAX]; + const char* path; + int ret; + struct dir_entry entry; + + if (!path_parse (token->buffer, volume, &path)) { + printf ("ERROR bad path '%s'\n", token->buffer); + return; + } + + if ((ret = volume_open (volume)) < 0) { + printf ("ERROR could not open volume '%s': %s\n", volume, str_status[-ret]); + return; + } + + describe (path, &desc); + + if (desc.type != FS_DIR) { + volume_close (); + } + + size_t entries = desc.size; + for (size_t entry_num = 0; entry_num < entries; entry_num++) { + read_dir_entry (path, &entry, entry_num); + describe (entry.path, &desc); + + printf ("%-40s%c %-40zu\n", entry.path, (desc.type == FS_DIR ? '*' : ' '), desc.size); + } + + volume_close (); +} + static void cmd_help (struct list_node_link* tokens) { (void)tokens; printf ("Available commands:\n"); - printf ("\techo ...\n"); - printf ("\thelp\n"); - printf ("\tcat \n"); + printf ("echo ...\n"); + printf ("help\n"); + printf ("cat \n"); + printf ("ls \n"); } static void exec_tokens (struct list_node_link* tokens) { @@ -126,6 +167,8 @@ static void exec_tokens (struct list_node_link* tokens) { cmd_help (tokens->next); } else if (strcmp (cmd_token->buffer, "cat") == 0) { cmd_cat (tokens->next); + } else if (strcmp (cmd_token->buffer, "ls") == 0) { + cmd_ls (tokens->next); } else { printf ("ERROR: unknown command '%s'\n", cmd_token->buffer); } diff --git a/include/dir_entry.h b/include/dir_entry.h new file mode 100644 index 0000000..4f15681 --- /dev/null +++ b/include/dir_entry.h @@ -0,0 +1,10 @@ +#ifndef _DIR_ENTRY_H +#define _DIR_ENTRY_H + +#include + +struct dir_entry { + char path[PATH_MAX]; +}; + +#endif // _DIR_ENTRY_H diff --git a/include/status.h b/include/status.h index fc1a7b5..a7847e5 100644 --- a/include/status.h +++ b/include/status.h @@ -16,5 +16,7 @@ #define ST_EXEC_ERROR 12 #define ST_MOUNT_ERROR 13 #define ST_TRY_AGAIN 14 +#define ST_NOT_DIR 15 +#define ST_DIR_NO_ENTRIES 16 #endif // _M_STATUS_H diff --git a/include/syscall_defs.h b/include/syscall_defs.h index 3631ff5..6aee081 100644 --- a/include/syscall_defs.h +++ b/include/syscall_defs.h @@ -22,5 +22,6 @@ #define SYS_MAIL_RECEIVE 19 #define SYS_GET_PROCGROUP 20 #define SYS_GET_EXEC_PID 21 +#define SYS_READ_DIR_ENTRY 22 #endif // _M_SYSCALL_DEFS_H diff --git a/kernel/fs/tarfs.c b/kernel/fs/tarfs.c index 0bb0632..8234107 100644 --- a/kernel/fs/tarfs.c +++ b/kernel/fs/tarfs.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -114,22 +115,35 @@ int tarfs_mount (struct vfs_volume* volume, struct proc* proc, struct reschedule } int tarfs_describe (struct vfs_volume* volume, const char* path, struct desc* desc) { - (void)volume; + struct tarfs* tarfs = volume->udata; - const char* filename = path_basename (path); + if (strncmp (path, "/", PATH_MAX) == 0) { + desc->size = 0; + desc->type = FS_DIR; - if (filename == NULL) - return -ST_BAD_PATH; + for (size_t i = 0; i < TARFS_FILES_MAX; i++) { + if (tarfs->tarfs_files[i].header != NULL) { + desc->size++; + } + } - struct tar_file* file = tar_get_file ((struct tarfs*)volume->udata, filename); + return ST_OK; + } else { + const char* filename = path_basename (path); - if (file == NULL) - return -ST_NOT_FOUND; + if (filename == NULL) + return -ST_BAD_PATH; - desc->size = file->size; - desc->type = FS_FILE; + struct tar_file* file = tar_get_file (tarfs, filename); - return ST_OK; + if (file == NULL) + return -ST_NOT_FOUND; + + desc->size = file->size; + desc->type = FS_FILE; + + return ST_OK; + } } int tarfs_read (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, @@ -150,3 +164,30 @@ int tarfs_read (struct vfs_volume* volume, const char* path, uint8_t* buffer, si return ST_OK; } + +int tarfs_read_dir_entry (struct vfs_volume* volume, const char* path, struct dir_entry* entry, + size_t entry_num) { + struct tarfs* tarfs = volume->udata; + + if (strncmp (path, "/", PATH_MAX) != 0) { + return -ST_NOT_DIR; + } + + struct tar_file* tar_file = NULL; + + size_t entry_counter = 0; + for (size_t i = 0; i < TARFS_FILES_MAX; i++) { + if ((tarfs->tarfs_files[i].header != NULL) && (entry_num == entry_counter)) { + tar_file = &tarfs->tarfs_files[i]; + break; + } + entry_counter++; + } + + if (tar_file != NULL) { + sprintf (entry->path, "/%s", tar_file->header->filename); + return ST_NOT_DIR; + } + + return ST_DIR_NO_ENTRIES; +} diff --git a/kernel/fs/tarfs.h b/kernel/fs/tarfs.h index 075366c..853c1ea 100644 --- a/kernel/fs/tarfs.h +++ b/kernel/fs/tarfs.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -40,4 +41,7 @@ int tarfs_describe (struct vfs_volume* volume, const char* path, struct desc* de int tarfs_read (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, size_t size); +int tarfs_read_dir_entry (struct vfs_volume* volume, const char* path, struct dir_entry* entry, + size_t entry_num); + #endif // _KERNEL_FS_TARFS_H diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 1df1afb..ba0609e 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -56,6 +56,7 @@ int vfs_create_volume (const char* key, int fs_type, struct device* back_device, volume->driver_ops.mount = &tarfs_mount; volume->driver_ops.describe = &tarfs_describe; volume->driver_ops.read = &tarfs_read; + volume->driver_ops.read_dir_entry = &tarfs_read_dir_entry; } break; default: { free (volume); @@ -147,7 +148,7 @@ int vfs_volume_close (struct proc* proc, const char* volume_name, struct resched } int vfs_read (struct proc* proc, const char* volume_name, const char* path, uint8_t* buffer, - size_t off, size_t size, struct reschedule_ctx* rctx) { + size_t off, size_t size) { struct vfs_volume* volume = vfs_find_volume (volume_name); if (volume == NULL) @@ -165,8 +166,7 @@ int vfs_read (struct proc* proc, const char* volume_name, const char* path, uint return volume->driver_ops.read (volume, path, buffer, off, size); } -int vfs_describe (struct proc* proc, const char* volume_name, const char* path, struct desc* desc, - struct reschedule_ctx* rctx) { +int vfs_describe (struct proc* proc, const char* volume_name, const char* path, struct desc* desc) { struct vfs_volume* volume = vfs_find_volume (volume_name); if (volume == NULL) @@ -184,6 +184,25 @@ int vfs_describe (struct proc* proc, const char* volume_name, const char* path, return volume->driver_ops.describe (volume, path, desc); } +int vfs_read_dir_entry (struct proc* proc, const char* volume_name, const char* path, + struct dir_entry* entry, size_t entry_num) { + struct vfs_volume* volume = vfs_find_volume (volume_name); + + if (volume == NULL) + return -ST_NOT_FOUND; + + spin_lock (&volume->lock); + + if (volume->locked && volume->owner != proc) { + spin_unlock (&volume->lock); + return -ST_PERMISSION_ERROR; + } + + spin_unlock (&volume->lock); + + return volume->driver_ops.read_dir_entry (volume, path, entry, entry_num); +} + void vfs_init (void) { memset (&volume_table, 0, sizeof (volume_table)); diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index 3c6a9ab..f8c2a62 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,9 @@ struct vfs_volume { int (*read) (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, size_t size); + + int (*read_dir_entry) (struct vfs_volume* volume, const char* path, struct dir_entry* entry, + size_t entry_num); } driver_ops; struct device* back_device; void* udata @@ -53,10 +57,12 @@ int vfs_volume_open (struct proc* proc, const char* volume, struct reschedule_ct int vfs_volume_close (struct proc* proc, const char* volume, struct reschedule_ctx* rctx); int vfs_read (struct proc* proc, const char* volume, const char* path, uint8_t* buffer, size_t off, - size_t size, struct reschedule_ctx* rctx); + size_t size); -int vfs_describe (struct proc* proc, const char* volume, const char* path, struct desc* desc, - struct reschedule_ctx* rctx); +int vfs_describe (struct proc* proc, const char* volume, const char* path, struct desc* desc); + +int vfs_read_dir_entry (struct proc* proc, const char* volume, const char* path, + struct dir_entry* entry, size_t entry_num); void vfs_init (void); diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index e9bcfb4..d88c086 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -132,7 +132,7 @@ struct proc* proc_from_file (struct proc* proc1, const char* volume, const char* break; } - if ((ret = vfs_describe (proc1, volume, path, &desc, rctx)) < 0) { + if ((ret = vfs_describe (proc1, volume, path, &desc)) < 0) { vfs_volume_close (proc1, volume, rctx); return NULL; } @@ -149,7 +149,7 @@ struct proc* proc_from_file (struct proc* proc1, const char* volume, const char* return NULL; } - if ((ret = vfs_read (proc1, volume, path, temp_buffer, 0, desc.size, rctx)) < 0) { + if ((ret = vfs_read (proc1, volume, path, temp_buffer, 0, desc.size)) < 0) { free (temp_buffer); vfs_volume_close (proc1, volume, rctx); return NULL; diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 938fc16..1d1ea20 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -371,7 +371,7 @@ DEFINE_SYSCALL (sys_read) { return SYSRESULT (-ST_BAD_ADDRESS_SPACE); spin_lock (&proc->lock); - int ret = vfs_read (proc, proc->cwv, path, buffer, off, size, rctx); + int ret = vfs_read (proc, proc->cwv, path, buffer, off, size); spin_unlock (&proc->lock); return SYSRESULT (ret); @@ -401,7 +401,7 @@ DEFINE_SYSCALL (sys_describe) { return SYSRESULT (-ST_BAD_ADDRESS_SPACE); spin_lock (&proc->lock); - int ret = vfs_describe (proc, proc->cwv, path, desc, rctx); + int ret = vfs_describe (proc, proc->cwv, path, desc); spin_unlock (&proc->lock); return SYSRESULT (ret); @@ -419,6 +419,37 @@ DEFINE_SYSCALL (sys_get_procgroup) { return SYSRESULT (target_proc->procgroup->pgid); } +/* int read_dir_entry (char* path, struct dir_entry* entry, size_t entry_num) */ +DEFINE_SYSCALL (sys_read_dir_entry) { + uintptr_t uvaddr_path = a1; + uintptr_t uvaddr_entry = a2; + size_t entry_num = (size_t)a3; + + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + uintptr_t out_paddr; + + spin_lock (&proc->procgroup->lock); + out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path); + spin_unlock (&proc->procgroup->lock); + + if (out_paddr == 0) + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + + const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr); + + struct dir_entry* entry = sys_get_user_buffer (proc, uvaddr_entry, sizeof (struct dir_entry)); + + if (entry == NULL) + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + + spin_lock (&proc->lock); + int ret = vfs_read_dir_entry (proc, proc->cwv, path, entry, entry_num); + spin_unlock (&proc->lock); + + return SYSRESULT (ret); +} + /* int get_exec_pid (void) */ DEFINE_SYSCALL (sys_get_exec_pid) { return SYSRESULT (proc->exec_pid); } @@ -444,6 +475,7 @@ static syscall_handler_func_t handler_table[] = { [SYS_MAIL_RECEIVE] = &sys_mail_receive, [SYS_GET_PROCGROUP] = &sys_get_procgroup, [SYS_GET_EXEC_PID] = &sys_get_exec_pid, + [SYS_READ_DIR_ENTRY] = &sys_read_dir_entry, }; syscall_handler_func_t syscall_find_handler (int syscall_num) { diff --git a/libsystem/system.c b/libsystem/system.c index 10a9fa2..24bcbbc 100644 --- a/libsystem/system.c +++ b/libsystem/system.c @@ -64,3 +64,7 @@ int mail_receive (void* mesg, size_t mesg_size) { int get_procgroup (int pid) { return (int)do_syscall (SYS_GET_PROCGROUP, pid); } int get_exec_pid (void) { return (int)do_syscall (SYS_GET_EXEC_PID, 0); } + +int read_dir_entry (const char* path, struct dir_entry* entry, size_t entry_num) { + return (int)do_syscall (SYS_READ_DIR_ENTRY, path, entry, entry_num); +} diff --git a/libsystem/system.h b/libsystem/system.h index 6526dce..afa38a1 100644 --- a/libsystem/system.h +++ b/libsystem/system.h @@ -2,6 +2,7 @@ #define _LIBMSL_M_SYSTEM_H #include +#include #include #include @@ -77,4 +78,7 @@ int get_procgroup (int pid); /* get PID of process, which exec'ed the current process */ int get_exec_pid (void); +/* Read directory entry */ +int read_dir_entry (const char* path, struct dir_entry* entry, size_t entry_num); + #endif // _LIBMSL_M_SYSTEM_H