From 9bdbdb937826f64249cca1f6830edb33f191c132 Mon Sep 17 00:00:00 2001 From: Matheus Date: Mon, 26 Jun 2023 21:32:39 -0300 Subject: [PATCH] syscalls: getdents syscall --- kernel-src/arch/x86-64/syscall.asm | 4 +- kernel-src/fs/tmpfs.c | 39 ++++++++++++++++- kernel-src/include/kernel/abi.h | 30 +++++++++++++ kernel-src/include/kernel/vfs.h | 26 ++++++++++-- kernel-src/sys/syscalls/getdent.c | 58 ++++++++++++++++++++++++++ patches/mlibc/jinx-working-patch.patch | 22 ++++++++-- 6 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 kernel-src/sys/syscalls/getdent.c diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index 43096a9b..ac7d9e8a 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -15,6 +15,7 @@ extern syscall_execve extern syscall_exit extern syscall_waitpid extern syscall_munmap +extern syscall_getdents syscalltab: dq syscall_print dq syscall_mmap @@ -32,7 +33,8 @@ dq syscall_execve dq syscall_exit dq syscall_waitpid dq syscall_munmap -syscallcount equ 16 +dq syscall_getdents +syscallcount equ 17 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/fs/tmpfs.c b/kernel-src/fs/tmpfs.c index da135fef..387fb70c 100644 --- a/kernel-src/fs/tmpfs.c +++ b/kernel-src/fs/tmpfs.c @@ -439,6 +439,42 @@ static int tmpfs_munmap(vnode_t *node, void *addr, uintmax_t offset, int flags, return 0; } + +static int tmpfs_getdents(vnode_t *node, dent_t *buffer, size_t count, uintmax_t offset, size_t *readcount) { + if (node->type != V_TYPE_DIR) + return ENOTDIR; + + VOP_LOCK(node); + + tmpfsnode_t *tmpnode = (tmpfsnode_t *)node; + + *readcount = 0; + size_t current = 0; + + HASHTABLE_FOREACH(&tmpnode->children) { + if (current < offset) { + ++current; + continue; + } + + if (*readcount == count) + break; + + dent_t *ent = &buffer[*readcount]; + + ent->d_ino = tmpnode->attr.inode; + ent->d_off = offset; + ent->d_reclen = sizeof(dent_t); + ent->d_type = vfs_getposixtype(node->type); + strcpy(ent->d_name, entry->key); + + *readcount += 1; + } + + VOP_UNLOCK(node); + return 0; +} + static int tmpfs_inactive(vnode_t *node) { freenode((tmpfsnode_t *)node); return 0; @@ -466,7 +502,8 @@ static vops_t vnops = { .readlink = tmpfs_readlink, .inactive = tmpfs_inactive, .mmap = tmpfs_mmap, - .munmap = tmpfs_munmap + .munmap = tmpfs_munmap, + .getdents = tmpfs_getdents }; static tmpfsnode_t *newnode(vfs_t *vfs, int type) { diff --git a/kernel-src/include/kernel/abi.h b/kernel-src/include/kernel/abi.h index 336dd031..dabd9ba4 100644 --- a/kernel-src/include/kernel/abi.h +++ b/kernel-src/include/kernel/abi.h @@ -44,4 +44,34 @@ typedef struct { long __unused[3]; } stat_t; +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +typedef struct { + ino_t d_ino; + off_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[1024]; +} dent_t; + +#define TYPE_FIFO 1 +#define TYPE_CHARDEV 2 +#define TYPE_DIR 4 +#define TYPE_BLOCKDEV 6 +#define TYPE_REGULAR 8 +#define TYPE_LINK 10 +#define TYPE_SOCKET 12 + +#define GETMODE(m) (0xFFF & (m)) +#define GETTYPE(m) (((m) >> 12) & 0xF) +#define MAKETYPE(m) (((m) & 0xF) << 12) + #endif diff --git a/kernel-src/include/kernel/vfs.h b/kernel-src/include/kernel/vfs.h index 80171f8e..89b2a3e9 100644 --- a/kernel-src/include/kernel/vfs.h +++ b/kernel-src/include/kernel/vfs.h @@ -89,6 +89,7 @@ typedef struct vops_t { int (*inactive)(vnode_t *node); int (*mmap)(vnode_t *node, void *addr, uintmax_t offset, int flags, cred_t *cred); int (*munmap)(vnode_t *node, void *addr, uintmax_t offset, int flags, cred_t *cred); + int (*getdents)(vnode_t *node, dent_t *buffer, size_t count, uintmax_t offset, size_t *readcount); } vops_t; #define VFS_MOUNT(vfs, mp, b, d) (vfs)->ops->mount(vfs, mp, b, d) @@ -99,7 +100,6 @@ typedef struct vops_t { #define VOP_LOCK(v) spinlock_acquire(&(v)->lock) #define VOP_UNLOCK(v) spinlock_release(&(v)->lock) -// these are expected to be called with the vnode(s) locked #define VOP_OPEN(v, f, c) (*v)->ops->open(v, f, c) #define VOP_CLOSE(v, f, c) (v)->ops->close(v, f, c) #define VOP_READ(v, b, s, o, f, r, c) (v)->ops->read(v, b, s, o, f, r, c) @@ -115,8 +115,7 @@ typedef struct vops_t { #define VOP_READLINK(v, l, c) (v)->ops->readlink(v, l, c) #define VOP_MMAP(v, a, o, f, c) (v)->ops->mmap(v, a, o, f, c) #define VOP_MUNMAP(v, a, o, f, c) (v)->ops->munmap(v, a, o, f, c) - -// lock not needed unless atomicity is desired +#define VOP_GETDENTS(v, b, c, o, rc) (v)->ops->getdents(v, b, c, o, rc) #define VOP_POLL(v, p) (v)->ops->poll(v, p); #define VOP_HOLD(v) __atomic_add_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) #define VOP_RELEASE(v) {\ @@ -145,4 +144,25 @@ int vfs_unlink(vnode_t *ref, char *path); #define VFS_LOOKUP_INTERNAL 0x80000000 int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int flags); +static inline mode_t vfs_getposixtype(int type) { + switch (type) { + case V_TYPE_REGULAR: + return TYPE_REGULAR; + case V_TYPE_DIR: + return TYPE_DIR; + case V_TYPE_CHDEV: + return TYPE_CHARDEV; + case V_TYPE_BLKDEV: + return TYPE_BLOCKDEV; + case V_TYPE_FIFO: + return TYPE_FIFO; + case V_TYPE_LINK: + return TYPE_LINK; + case V_TYPE_SOCKET: + return TYPE_SOCKET; + default: + return 0; + } +} + #endif diff --git a/kernel-src/sys/syscalls/getdent.c b/kernel-src/sys/syscalls/getdent.c new file mode 100644 index 00000000..bf9c7506 --- /dev/null +++ b/kernel-src/sys/syscalls/getdent.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +syscallret_t syscall_getdents(context_t *, int dirfd, void *ubuffer, size_t readmax) { + syscallret_t ret = { + .ret = -1 + }; + + if (ubuffer > USERSPACE_END) { + ret.errno = EFAULT; + return ret; + } + + size_t count = readmax / sizeof(dent_t); + + if (count == 0) { + ret.errno = EINVAL; + return ret; + } + + dent_t *buffer = alloc(readmax); + if (buffer == NULL) { + ret.errno = ENOMEM; + return ret; + } + + file_t *fd = fd_get(dirfd); + if (fd == NULL) { + free(buffer); + ret.errno = EBADF; + return ret; + } + + if (fd->vnode->type != V_TYPE_DIR) { + ret.errno = ENOTDIR; + goto cleanup; + } + + ret.errno = VOP_GETDENTS(fd->vnode, buffer, count, fd->offset, &ret.ret); + + if (ret.errno) + goto cleanup; + + fd->offset += ret.ret; + + ret.ret *= sizeof(dent_t); + + // TODO safe memcpy + memcpy(ubuffer, buffer, ret.ret); + + cleanup: + free(buffer); + fd_release(fd); + return ret; +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index 80013876..d5b80c56 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -133,10 +133,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..601407e +index 0000000..c177a55 --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,193 @@ +@@ -0,0 +1,206 @@ +#include +#include +#include @@ -192,6 +192,15 @@ index 0000000..601407e + return 0; + } + ++ int sys_read_entries(int handle, void *buffer, size_t max_size, size_t *bytes_read) { ++ long ret; ++ long err = syscall(SYSCALL_GETDENTS, &ret, handle, (uint64_t)buffer, max_size); ++ if (err) ++ return err; ++ *bytes_read = ret; ++ return err; ++ } ++ + int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, pid_t *ret_pid) { + long ret; + long err = syscall(SYSCALL_WAITPID, &ret, pid, (uint64_t)status, flags); @@ -280,6 +289,10 @@ index 0000000..601407e + return 0; + }; + ++ int sys_open_dir(const char *path, int *handle) { ++ return sys_open(path, O_DIRECTORY, 0, handle); ++ } ++ + int sys_read(int fd, void *buff, size_t count, ssize_t *bytes_read) { + long readc; + long error = syscall(SYSCALL_READ, &readc, fd, (uint64_t)buff, count); @@ -349,10 +362,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..1562c23 +index 0000000..6b0e993 --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,39 @@ +@@ -0,0 +1,40 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -372,6 +385,7 @@ index 0000000..1562c23 +#define SYSCALL_EXIT 13 +#define SYSCALL_WAITPID 14 +#define SYSCALL_MUNMAP 15 ++#define SYSCALL_GETDENTS 16 + +#include +#include