Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions kernel/include/sys/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ sys_ret_t syscall_mmap(uintptr_t addr, size_t len, int prot, int flags, int fd,

sys_ret_t syscall_exit(int code);
sys_ret_t syscall_tcb_set(void *ptr);

// Filesystem

sys_ret_t syscall_getcwd(const char *path, size_t size);
sys_ret_t syscall_chdir(const char *path);

sys_ret_t syscall_mkdir(const char *path);
sys_ret_t syscall_rmdir(const char *path);
185 changes: 129 additions & 56 deletions kernel/source/sys/fs.c
Original file line number Diff line number Diff line change
@@ -1,40 +1,96 @@
// #include "sys/syscall.h"

// #include "fs/vfs.h"
// #include "uapi/errno.h"
// #include "utils/string.h"

// sys_ret_t sys_getcwd(char *path, size_t size)
// {
// const char *cwd = sys_curr_proc()->cwd;
// size_t len = strlen(cwd);

// vm_copy_to_user(sys_curr_as(), (uintptr_t)path, (void *)cwd, len);

// return (sys_ret_t) {0, EOK};
// }

// sys_ret_t sys_chdir(const char *path)
// {
// char kpath[PATH_MAX];
// if (copy_from_user(kpath, path, sizeof(kpath)) != 0)
// return -EFAULT;

// vnode_t *vn;
// int ret = vfs_lookup(kpath, 0, &vn);
// if (ret != 0)
// return ret;

// if (vn->type != VNODE_DIR)
// return -ENOTDIR;

// current_proc()->cwd = vn;
// return (sys_ret_t) {0, EOK};
// }

#include "sys/syscall.h"

#include "fs/vfs.h"
#include "mm/heap.h"
#include "mm/mm.h"
#include "sync/spinlock.h"
#include "uapi/errno.h"
#include "utils/string.h"
#include <stdint.h>
#include "sys/stat.h"

sys_ret_t syscall_getcwd(const char *buf, size_t size)
{
static volatile spinlock_t cwd_lock = SPINLOCK_INIT;
spinlock_acquire(&cwd_lock);

const char *cwd = sys_curr_proc()->cwd;
size_t len = strlen(cwd);

if (len + 1 > size)
{
spinlock_release(&cwd_lock);
return (sys_ret_t) {0, ERANGE};
}

size_t copied = vm_copy_to_user(sys_curr_as(), (uintptr_t)buf, (void *)cwd, len + 1);
if (copied != len + 1)
{
spinlock_release(&cwd_lock);
return (sys_ret_t) {0, EFAULT};
}

spinlock_release(&cwd_lock);
return (sys_ret_t) {0, EOK};
}

sys_ret_t syscall_chdir(const char *buf)
{
static volatile spinlock_t cwd_lock = SPINLOCK_INIT;
spinlock_acquire(&cwd_lock);

char kpath[PATH_MAX_NAME_LEN];
size_t copied = vm_copy_from_user(sys_curr_as(), kpath, (uintptr_t)buf, sizeof(kpath));
if (copied == 0)
{
spinlock_release(&cwd_lock);
return (sys_ret_t) {0, EFAULT};
}

kpath[PATH_MAX_NAME_LEN - 1] = '\0';

// check if dir exists
vnode_t *vn;
int ret = vfs_lookup(kpath, &vn);
if (ret != EOK)
{
spinlock_release(&cwd_lock);
return (sys_ret_t) {0, ret};
}

// check if path is dir
if (vn->type != VDIR)
{
vnode_unref(vn);
spinlock_release(&cwd_lock);
return (sys_ret_t) {0, ENOTDIR};
}
vnode_unref(vn);

// save cwd on heap for efficiency
size_t path_len = strlen(kpath);
char *new_cwd = heap_alloc(path_len + 1);
if(!new_cwd)
{
spinlock_release(&cwd_lock);
return (sys_ret_t) {0, ENOMEM};
}

memcpy(new_cwd, kpath, path_len + 1);

const char *old_cwd = sys_curr_proc()->cwd;
sys_curr_proc()->cwd = new_cwd;

if (old_cwd) heap_free((void *)old_cwd);

spinlock_release(&cwd_lock);
return (sys_ret_t) {0, EOK};
}

// --- TBD ---
// sys_ret_t sys_sync(void)
// {
// return (sys_ret_t) {0, ENOSYS};
// return (sys_ret_t) {0, EOK};
// }

// sys_ret_t sys_statfs(const char *path, struct statfs *user_buf)
Expand All @@ -48,31 +104,48 @@
// unsigned int flags,
// void *data)
// {
// return (sys_ret_t) {0, ENOSYS};
// return (sys_ret_t) {0, ENOTSUP};
// }

// sys_ret_t sys_mkdir(const char *user_path)
// {
// char kpath[PATH_MAX];
// if (copy_from_user(kpath, user_path, sizeof(kpath)) != 0)
// return -EFAULT;
// ----

// vnode_t *parent;
// const char *name;
sys_ret_t syscall_mkdir(const char *buf)
{
char kpath[PATH_MAX_NAME_LEN];
size_t copied = vm_copy_from_user(sys_curr_as(), kpath, (uintptr_t)buf, sizeof(kpath));
if (copied == 0) return (sys_ret_t) {0, EFAULT};

// // TODO: split path → parent vnode + name
// return (sys_ret_t) {0, ENOSYS};
// }
kpath[PATH_MAX_NAME_LEN - 1] = '\0';

// sys_ret_t sys_rmdir(const char *user_path)
// {
// char kpath[PATH_MAX];
// if (copy_from_user(kpath, user_path, sizeof(kpath)) != 0)
// return -EFAULT;
vnode_t *vn;
int ret = vfs_create(kpath, VDIR, &vn);
if (ret != EOK) return (sys_ret_t) {0, ret};

// vnode_t *parent;
// const char *name;
return (sys_ret_t) {0, EOK};
}

// // TODO: split path → parent vnode + name
// return (sys_ret_t) {0, EOK};
// }
sys_ret_t syscall_rmdir(const char *buf)
{
char kpath[PATH_MAX_NAME_LEN];
size_t copied = vm_copy_from_user(sys_curr_as(), kpath, (uintptr_t)buf, sizeof(kpath));
if (copied == 0) return (sys_ret_t) {0, EFAULT};

kpath[PATH_MAX_NAME_LEN - 1] ='\0';

vnode_t *vn;
// verify if path is folder
int ret = vfs_lookup(kpath, &vn);
if (ret != EOK) return (sys_ret_t) {0, ret};

if (vn->type != VDIR)
{
//vnode_unref(vn);
return (sys_ret_t) {0, ENOTDIR};
}
vnode_unref(vn);

ret = vfs_remove(kpath);
if(ret != EOK) return (sys_ret_t) {0, ret};

return (sys_ret_t) {0, EOK};
}
1 change: 1 addition & 0 deletions kernel/source/sys/meson.build
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
c_files += files(
'debug.c',
'fileio.c',
'fs.c',
'memory.c',
'misc.c',
'proc.c',
Expand Down
7 changes: 6 additions & 1 deletion kernel/source/sys/syscall.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#include "syscall.h"
#include "sys/syscall.h"

#include "proc/sched.h"


const void* syscall_table[] = {
(void *)syscall_debug_log,
(void *)syscall_open,
Expand All @@ -12,6 +13,10 @@ const void* syscall_table[] = {
(void *)syscall_mmap,
(void *)syscall_exit,
(void *)syscall_tcb_set,
(void *)syscall_getcwd,
(void *)syscall_chdir,
(void *)syscall_mkdir,
(void *)syscall_rmdir
};

const uint64_t syscall_table_length = sizeof(syscall_table) / sizeof(void*);
Expand Down