From f4b042906274f9d4a6723ca2a1e9ac4c362d619f Mon Sep 17 00:00:00 2001 From: Ruslan Isaev Date: Thu, 30 Oct 2025 20:26:28 +0300 Subject: [PATCH] syscalls: implement getcwd syscall --- grubshit/caller.c | 4 +- include/exec_from_file.h | 2 +- include/string.h | 1 + include/vfs.h | 3 ++ src/fs/vfs.c | 47 +++++++++++++++++++++ src/kernel/kernel.c | 2 +- src/tasking/exec_from_file.c | 10 ++--- src/tasking/syscalls.c | 54 +++++++++++++++++++++++- src/utils/string.c | 80 ++++++++++++++++++++++++++++++++++++ 9 files changed, 192 insertions(+), 11 deletions(-) diff --git a/grubshit/caller.c b/grubshit/caller.c index 21ddd66..0a2bd0b 100644 --- a/grubshit/caller.c +++ b/grubshit/caller.c @@ -9,7 +9,7 @@ int main() { // Arguments for the new program // The first argument is conventionally the program name - char *argv[] = { "/katau/core", "--help", NULL }; + char *argv[] = { "/katau/dash", "--help", NULL }; // Environment variables for the new program char *envp[] = { "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL }; @@ -18,7 +18,7 @@ int main() { // The first argument is the path to the executable // The second is the array of arguments // The third is the array of environment variables - execve("/katau/core.", argv, envp); + execve("/katau/dash.", argv, envp); // This part of the code will only be reached if execve fails perror("execve failed"); diff --git a/include/exec_from_file.h b/include/exec_from_file.h index 56950f1..1936b26 100644 --- a/include/exec_from_file.h +++ b/include/exec_from_file.h @@ -9,4 +9,4 @@ #define USER_STACK_SIZE 0x4000 // 16KB stack (4 pages) #define USER_STACK_BOTTOM (USER_STACK_TOP - USER_STACK_SIZE) -void exec_from_file(l9660_file* fs_file, const char* dirname); \ No newline at end of file +void exec_from_file(l9660_file* fs_file, l9660_dir* dir); \ No newline at end of file diff --git a/include/string.h b/include/string.h index 96d86a3..2c2ed98 100644 --- a/include/string.h +++ b/include/string.h @@ -10,5 +10,6 @@ void* memset(void*, int, size_t); size_t strlen(const char*); char *strcat(char *dest, const char *src); char *strcpy(char *dest, const char *src); +char *strtok(char *str, const char *delim); #endif diff --git a/include/vfs.h b/include/vfs.h index 4f36dfd..13a28db 100644 --- a/include/vfs.h +++ b/include/vfs.h @@ -22,4 +22,7 @@ void test_iso9660(); int vfs_read_file_by_path(const char* path, uint8_t** buffer); void follow_path(const char* path, l9660_file* file, l9660_dir* dir); +l9660_status find_name_for_sector(char* name_buf, int buf_len, l9660_dir* parent_dir, uint32_t child_sector); +bool is_root_dir(l9660_dir* dir); + #endif \ No newline at end of file diff --git a/src/fs/vfs.c b/src/fs/vfs.c index 39c85ff..5bbcd08 100644 --- a/src/fs/vfs.c +++ b/src/fs/vfs.c @@ -284,4 +284,51 @@ void follow_path(const char* path, l9660_file* file, l9660_dir* dir) debug_log("\n"); //printf("buf: %s\n", buf); debug_log("isdir: %X\n", isdir); +} + +#ifdef L9660_BIG_ENDIAN +#define READ32(v) (((v).be[3]) | ((v).be[2] << 8) | ((v).be[1]) << 16 | ((v).be[0] << 24)) +#else +#define READ32(v) (((v).le[0]) | ((v).le[1] << 8) | ((v).le[2]) << 16 | ((v).le[3] << 24)) +#endif + +bool is_root_dir(l9660_dir* dir) { + l9660_dirent* dent; + l9660_status status; + + l9660_seekdir(dir, 0);//rewind to start + l9660_readdir(dir, &dent);//reaed . + l9660_readdir(dir, &dent);//read .. + + //if .. reads to the directory itself it means that this is the root directory + if (dent != NULL && READ32(dent->sector) == dir->file.first_sector) { + return true; + } + return false; +} + +/** + * I'm bad at such loops and ESPECIALLY at such loops which involve sectors and so on + */ +l9660_status find_name_for_sector(char* name_buf, int buf_len, l9660_dir* parent_dir, uint32_t child_sector) { + l9660_dirent* dent; + l9660_status status; + + l9660_seekdir(parent_dir, 0); // Rewind parent to search from the start + + while (true) { + status = l9660_readdir(parent_dir, &dent); + if (status != L9660_OK) return status; + if (dent == NULL) break; // End of directory + + // Is this the entry we are looking for? + if (READ32(dent->sector) == child_sector) { + int len = dent->name_len; + if (len >= buf_len) len = buf_len - 1; + memcpy(name_buf, dent->name, len); + name_buf[len] = '\0'; + return L9660_OK; + } + } + return L9660_ENOENT; } \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index b987675..13fd8e5 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -136,7 +136,7 @@ void kmain(unsigned int magic, unsigned int info) follow_path("/katau/caller.", &file, &dir); - exec_from_file(&file, "."); + exec_from_file(&file, &dir); while(1) { diff --git a/src/tasking/exec_from_file.c b/src/tasking/exec_from_file.c index 621f035..50bf41c 100644 --- a/src/tasking/exec_from_file.c +++ b/src/tasking/exec_from_file.c @@ -6,17 +6,17 @@ #include "../include/paging.h" #include "../include/task.h" -void exec_from_file(l9660_file* fs_file, const char* dirname) +void exec_from_file(l9660_file* fs_file, l9660_dir* dir) { asm volatile("cli"); int err; uint8_t* file; - l9660_dir dir; + //l9660_dir dir; l9660_status status; - status = l9660_opendirat(&dir, root_dir, dirname); - debug_log("l9660_opendirat status: 0x%X\n", status); + //status = l9660_opendirat(&dir, root_dir, dirname); + //debug_log("l9660_opendirat status: 0x%X\n", status); //list_files(&dir); @@ -136,7 +136,7 @@ void exec_from_file(l9660_file* fs_file, const char* dirname) set_page_dir(curr_pd_phys); Process* p_task1 = task_create(elf_ehdr->e_entry, USER_STACK_TOP, 3, proc_pd); - *p_task1->cwd = dir; + p_task1->cwd = dir; uint32_t brk_address = DivRoundUp(bss_end+1, 0x1000)*0x1000; debug_log("initial brk address: 0x%X\n", brk_address); diff --git a/src/tasking/syscalls.c b/src/tasking/syscalls.c index 13f6edb..3830a60 100644 --- a/src/tasking/syscalls.c +++ b/src/tasking/syscalls.c @@ -416,8 +416,56 @@ int sys_chdir(TrapFrame *tf) return -1; } -int sys_getcwd(TrapFrame *tf) +#include "../include/vfs.h" +/** + * I'm very sorry before myself for this but these directory traversing things are so hard, follow_path in vfs was pretty okay, + * this is when shit got real though + */ +uint32_t sys_getcwd(TrapFrame *tf) { + l9660_dir current_dir = *(current->cwd); + + char path_reversed[256] = {0}; + char component_name[64]; + + while (!is_root_dir(¤t_dir)) { + uint32_t child_sector = current_dir.file.first_sector; + + // Open the parent directory + l9660_dir parent_dir; + l9660_opendirat(&parent_dir, ¤t_dir, ".."); + + // Find our previous directory's name within the parent + find_name_for_sector(component_name, sizeof(component_name), &parent_dir, child_sector); + + // Prepend the name to our reversed path string (e.g., "dash/" + "katau/" -> "katau/dash/") + strcat(path_reversed, component_name); + strcat(path_reversed, "/"); + + // Move up one level + current_dir = parent_dir; + } + + // Now, reverse the string "dash/katau/" to create the final path "/katau/dash" + char final_path[256] = "/"; + char* token = strtok(path_reversed, "/"); + while (token != NULL) { + // A bit of a trick to prepend tokens + char temp[256]; + strcpy(temp, "/"); + strcat(temp, token); + strcat(temp, final_path); + strcpy(final_path, temp); + + token = strtok(NULL, "/"); + } + // Handle the root case where the loop doesn't run + if (strlen(final_path) > 1) { + final_path[strlen(final_path) - 1] = '\0'; // Remove trailing slash + } + + strcpy((char*)tf->ebx, final_path); + //strcpy((char*)tf->ebx, current->cwd->fat->path); return tf->ebx; @@ -489,6 +537,8 @@ void handle_syscall(TrapFrame *tf) debug_log("EDX: %X\n", tf->edx); */ + debug_log("calling 0x%X\n", tf->eax); + switch(tf->eax) { case 1://exit @@ -544,7 +594,7 @@ void handle_syscall(TrapFrame *tf) default: debug_log("unknown syscall: %X\n", tf->eax); - tf->eax = -1; + tf->eax = -38;//-ENOSYS break; } } diff --git a/src/utils/string.c b/src/utils/string.c index d60ce5d..9a525fa 100644 --- a/src/utils/string.c +++ b/src/utils/string.c @@ -69,4 +69,84 @@ char *strcpy(char *dest, const char *src) { ; return original_dest; +} + +static char *next_token = NULL; +static char *strpbrk_custom(const char *str, const char *delim) { + if (!str || !delim) { + return NULL; + } + + while (*str) { + const char *d = delim; + while (*d) { + if (*str == *d) { + return (char *)str; + } + d++; + } + str++; + } + return NULL; +} + +char *strtok(char *str, const char *delim) { + char *token_start; + char *token_end; + + if (str != NULL) { + next_token = str; + } + + if (next_token == NULL || *next_token == '\0') { + return NULL; + } + + token_start = next_token; + while (*token_start) { + const char *d = delim; + int is_delim = 0; + while (*d) { + if (*token_start == *d) { + is_delim = 1; + break; + } + d++; + } + if (!is_delim) { + break; + } + token_start++; + } + + if (*token_start == '\0') { + next_token = NULL; + return NULL; + } + + token_end = token_start; + while (*token_end) { + const char *d = delim; + int is_delim = 0; + while (*d) { + if (*token_end == *d) { + is_delim = 1; + break; + } + d++; + } + if (is_delim) { + break; + } + token_end++; + } + + if (*token_end == '\0') { + next_token = NULL; + } else { + *token_end = '\0'; + next_token = token_end + 1; + } + + return token_start; } \ No newline at end of file