diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index 316a3cb3..ab344259 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -96,6 +96,8 @@ extern syscall_nice extern syscall_flock extern syscall_getcpu extern syscall_sysinfo +extern syscall_writev +extern syscall_readv syscalltab: dq syscall_print dq syscall_mmap @@ -194,7 +196,9 @@ dq syscall_nice dq syscall_flock dq syscall_getcpu dq syscall_sysinfo -syscallcount equ 97 +dq syscall_writev +dq syscall_readv +syscallcount equ 99 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/arch/x86-64/syscalllog.c b/kernel-src/arch/x86-64/syscalllog.c index 34ad4b1b..d4545c04 100644 --- a/kernel-src/arch/x86-64/syscalllog.c +++ b/kernel-src/arch/x86-64/syscalllog.c @@ -5,7 +5,7 @@ #ifdef SYSCALL_LOGGING -#define SYSCALL_COUNT 97 +#define SYSCALL_COUNT 99 #define LOGSTR(x) arch_e9_puts(x) static char *name[] = { @@ -105,7 +105,9 @@ static char *name[] = { "nice", "flock", "getcpu", - "sysinfo" + "sysinfo", + "writev", + "readv" }; static char *args[] = { @@ -206,6 +208,8 @@ static char *args[] = { "fd %d op %d", // flock "N/A", // getcpu "ptr %p", // sysinfo + "fd %d iov %p iovcnt %d", // writev + "fd %d iov %p iovcnt %d", // readv }; #endif diff --git a/kernel-src/sys/syscalls/readv.c b/kernel-src/sys/syscalls/readv.c new file mode 100644 index 00000000..c19cf736 --- /dev/null +++ b/kernel-src/sys/syscalls/readv.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include + +syscallret_t syscall_readv(context_t *context, int fd, iovec_t *uiov, int iovec_count) { + syscallret_t ret = { + .ret = -1 + }; + file_t *file = NULL; + + iovec_t *iovec = alloc(sizeof(iovec_t) * iovec_count); + if (iovec == NULL) { + ret.errno = ENOMEM; + return ret; + } + + ret.errno = usercopy_fromuser(iovec, uiov, sizeof(iovec_t) * iovec_count); + if (ret.errno) + goto cleanup; + + size_t buffer_size = iovec_size(iovec, iovec_count); + if (buffer_size == 0) { + ret.errno = 0; + ret.ret = 0; + goto cleanup; + } + + if (iovec_user_check(iovec, iovec_count) == false) { + ret.errno = EFAULT; + goto cleanup; + } + + file = fd_get(fd); + if (file == NULL || (file->flags & FILE_READ) == 0) { + ret.errno = EBADF; + goto cleanup; + } + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, iovec, iovec_count); + + size_t bytes_read; + uintmax_t offset = file->offset; + ret.errno = vfs_read_iovec(file->vnode, &iovec_iterator, buffer_size, offset, &bytes_read, fileflagstovnodeflags(file->flags)); + + if (ret.errno) + goto cleanup; + + file->offset = offset + bytes_read; + ret.ret = bytes_read; + +cleanup: + if (file) + fd_release(file); + + free(iovec); + + return ret; +} diff --git a/kernel-src/sys/syscalls/writev.c b/kernel-src/sys/syscalls/writev.c new file mode 100644 index 00000000..4b9a27cd --- /dev/null +++ b/kernel-src/sys/syscalls/writev.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include + +syscallret_t syscall_writev(context_t *context, int fd, iovec_t *uiov, int iovec_count) { + syscallret_t ret = { + .ret = -1 + }; + file_t *file = NULL; + + iovec_t *iovec = alloc(sizeof(iovec_t) * iovec_count); + if (iovec == NULL) { + ret.errno = ENOMEM; + return ret; + } + + ret.errno = usercopy_fromuser(iovec, uiov, sizeof(iovec_t) * iovec_count); + if (ret.errno) + goto cleanup; + + size_t buffer_size = iovec_size(iovec, iovec_count); + if (buffer_size == 0) { + ret.errno = 0; + ret.ret = 0; + goto cleanup; + } + + if (iovec_user_check(iovec, iovec_count) == false) { + ret.errno = EFAULT; + goto cleanup; + } + + file = fd_get(fd); + if (file == NULL || (file->flags & FILE_WRITE) == 0) { + ret.errno = EBADF; + goto cleanup; + } + + uintmax_t offset = file->offset; + if (file->flags & O_APPEND) { + vattr_t attr; + // TODO racey + VOP_LOCK(file->vnode); + ret.errno = VOP_GETATTR(file->vnode, &attr, ¤t_thread()->proc->cred); + VOP_UNLOCK(file->vnode); + if (ret.errno) + goto cleanup; + + offset = attr.size; + } + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, iovec, iovec_count); + + size_t bytes_written; + ret.errno = vfs_write_iovec(file->vnode, &iovec_iterator, buffer_size, offset, &bytes_written, fileflagstovnodeflags(file->flags)); + + if (ret.errno) + goto cleanup; + + file->offset = offset + bytes_written; + ret.ret = bytes_written; + +cleanup: + if (file) + fd_release(file); + + free(iovec); + + return ret; +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index 62a1e94c..137a7a53 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -281,13 +281,27 @@ index b2db152..e6438fe 100644 linker.linkObjects(object); linker.initObjects(initialRepository.get()); diff --git mlibc-clean/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp -index be7ad9e..6fb09ec 100644 +index be7ad9e..80cc8d9 100644 --- mlibc-clean/sysdeps/astral/generic/generic.cpp +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -47,6 +47,11 @@ namespace mlibc { +@@ -47,6 +47,25 @@ namespace mlibc { return 0; } ++ int sys_readv(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) { ++ long r; ++ int error = syscall(SYSCALL_READV, &r, fd, (uint64_t)iovs, iovc); ++ *bytes_read = r; ++ return error; ++ } ++ ++ int sys_writev(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_written) { ++ long r; ++ int error = syscall(SYSCALL_WRITEV, &r, fd, (uint64_t)iovs, iovc); ++ *bytes_written = r; ++ return error; ++ } ++ + int sys_sysinfo(struct sysinfo *info) { + long r; + return syscall(SYSCALL_SYSINFO, &r, (uint64_t)info); @@ -297,14 +311,16 @@ index be7ad9e..6fb09ec 100644 long ret; // can never fail diff --git mlibc-clean/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h -index 8414286..9773b9c 100644 +index 8414286..a6c4067 100644 --- mlibc-clean/sysdeps/astral/include/astral/syscall.h +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -100,6 +100,7 @@ +@@ -100,6 +100,9 @@ #define SYSCALL_NICE 93 #define SYSCALL_FLOCK 94 #define SYSCALL_GETCPU 95 +#define SYSCALL_SYSINFO 96 ++#define SYSCALL_WRITEV 97 ++#define SYSCALL_READV 98 #ifndef __MLIBC_ABI_ONLY