diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 579baea..24dea34 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -5,6 +5,8 @@ #define SYSCALL_NR_OPEN 2 #define SYSCALL_NR_CLOSE 3 #define SYSCALL_NR_STAT 4 +#define SYSCALL_NR_GETCWD 79 +#define SYSCALL_NR_CHDIR 80 #define SYSCALL_NR_READDIR 89 #define SYSCALL_NR_BRK 12 diff --git a/sys/amd64/syscall.c b/sys/amd64/syscall.c index c87d459..b3eb824 100644 --- a/sys/amd64/syscall.c +++ b/sys/amd64/syscall.c @@ -19,6 +19,8 @@ static ssize_t sys_write(int fd, const void *buf, size_t lim); static ssize_t sys_readdir(int fd, struct dirent *ent); static int sys_open(const char *filename, int flags, int mode); static void sys_close(int fd); +static int sys_getcwd(char *buf, size_t lim); +static int sys_chdir(const char *path); static int sys_stat(const char *filename, struct stat *st); static void sys_exit(int status); static int sys_kill(int pid, int signum); @@ -50,6 +52,10 @@ intptr_t amd64_syscall(uintptr_t rdi, uintptr_t rsi, uintptr_t rdx, uintptr_t rc return sys_execve((const char *) rdi, NULL, NULL); case SYSCALL_NR_READDIR: return sys_readdir((int) rdi, (struct dirent *) rsi); + case SYSCALL_NR_GETCWD: + return sys_getcwd((char *) rdi, (size_t) rsi); + case SYSCALL_NR_CHDIR: + return sys_chdir((const char *) rdi); case SYSCALL_NRX_SIGNAL: sys_signal(rdi); @@ -137,6 +143,31 @@ static ssize_t sys_readdir(int fd, struct dirent *ent) { return src->d_reclen; } +static int sys_chdir(const char *filename) { + struct thread *thr = get_cpu()->thread; + _assert(thr); + _assert(filename); + + return vfs_chdir(&thr->ioctx, filename); +} + +// Kinda incompatible with linux, but who cares as long as it's +// POSIX on the libc side +static int sys_getcwd(char *buf, size_t lim) { + struct thread *thr = get_cpu()->thread; + _assert(thr); + _assert(buf); + + // TODO: actually implement this + if (lim < 4) { + return -1; + } + + strcpy(buf, "???"); + + return 0; +} + static int sys_open(const char *filename, int flags, int mode) { struct thread *thr = get_cpu()->thread; _assert(thr); diff --git a/sys/vfs/node.c b/sys/vfs/node.c index 817990e..420aee4 100644 --- a/sys/vfs/node.c +++ b/sys/vfs/node.c @@ -101,9 +101,6 @@ void vnode_unref(vnode_t *vn) { return; } - // TODO: don't free root nodes - char buf[1024]; - vfs_vnode_path(buf, vn); struct vfs_node *node = (struct vfs_node *) vn->tree_node; if (!node->parent) { return; @@ -117,7 +114,6 @@ void vnode_unref(vnode_t *vn) { return; } - kdebug("free %s\n", buf); // Free vnode vnode_free(vn); } diff --git a/sys/vfs/vfs.c b/sys/vfs/vfs.c index d176536..6eb46c3 100644 --- a/sys/vfs/vfs.c +++ b/sys/vfs/vfs.c @@ -378,22 +378,6 @@ static int vfs_find(vnode_t *cwd_vnode, const char *path, vnode_t **res_vnode) { } } -static void vfs_dump_node(struct vfs_node *node, int o) { - // TODO: node dumpinh -} - -void vfs_dump_tree(void) { - if (!vfs_root_node.vnode) { - return; - } - vfs_dump_node(&vfs_root_node, 0); -} - -void vfs_vnode_path(char *path, vnode_t *vn) { - // TODO: path printing - path[0] = 0; -} - int vfs_mount_internal(struct vfs_node *at, void *blkdev, const char *fs_name, const char *opt) { struct fs_class *fs_class; diff --git a/usr/init.c b/usr/init.c index bca1f35..a013bf9 100644 --- a/usr/init.c +++ b/usr/init.c @@ -75,8 +75,26 @@ static int cmd_exec(const char *cmd) { return 0; } - if (!strcmp(cmd, "ls") || !strncmp(cmd, "ls ", 3)) { + if (!strcmp(cmd, "cd") || !strncmp(cmd, "cd ", 3)) { const char *path = cmd[2] ? cmd + 3 : "/"; + int res = chdir(path); + + if (res < 0) { + perror(path); + } + return res; + } + + if (!strcmp(cmd, "pwd")) { + char buf[512]; + if (getcwd(buf, sizeof(buf))) { + puts(buf); + } + return 0; + } + + if (!strcmp(cmd, "ls") || !strncmp(cmd, "ls ", 3)) { + const char *path = cmd[2] ? cmd + 3 : "."; DIR *dir; struct dirent *ent; diff --git a/usr/libc/include/bits/syscall.h b/usr/libc/include/bits/syscall.h index ccade3f..49c21a7 100644 --- a/usr/libc/include/bits/syscall.h +++ b/usr/libc/include/bits/syscall.h @@ -17,5 +17,7 @@ int kill(int pid, int signum); void __kernel_signal(uintptr_t handler); __attribute__((noreturn)) void __kernel_sigret(void); int getpid(void); +int chdir(const char *filename); +char *getcwd(char *buf, size_t size); __attribute__((noreturn)) void exit(int code); diff --git a/usr/libc/syscall.c b/usr/libc/syscall.c index 48419a5..600d89f 100644 --- a/usr/libc/syscall.c +++ b/usr/libc/syscall.c @@ -113,6 +113,18 @@ int getpid(void) { return ASM_SYSCALL0(SYSCALL_NR_GETPID); } +int chdir(const char *filename) { + return SET_ERRNO(int, ASM_SYSCALL1(SYSCALL_NR_CHDIR, filename)); +} + +char *getcwd(char *buf, size_t lim) { + if (SET_ERRNO(int, ASM_SYSCALL2(SYSCALL_NR_GETCWD, buf, lim)) == 0) { + return buf; + } else { + return NULL; + } +} + // Although sbrk() is implemented in userspace, I guess it should also be here void *sbrk(intptr_t inc) { if (inc == 0) {