syscalls: readv writev

This commit is contained in:
Matheus
2025-11-04 02:04:11 -03:00
parent 2bafdee791
commit 5d79c7840d
5 changed files with 169 additions and 7 deletions
+5 -1
View File
@@ -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:
+6 -2
View File
@@ -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
+63
View File
@@ -0,0 +1,63 @@
#include <kernel/syscalls.h>
#include <kernel/vfs.h>
#include <kernel/file.h>
#include <arch/cpu.h>
#include <errno.h>
#include <logging.h>
#include <kernel/alloc.h>
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;
}
+75
View File
@@ -0,0 +1,75 @@
#include <kernel/syscalls.h>
#include <kernel/vfs.h>
#include <kernel/file.h>
#include <arch/cpu.h>
#include <errno.h>
#include <logging.h>
#include <kernel/alloc.h>
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, &current_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;
}