mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
syscalls: readv writev
This commit is contained in:
@@ -96,6 +96,8 @@ extern syscall_nice
|
|||||||
extern syscall_flock
|
extern syscall_flock
|
||||||
extern syscall_getcpu
|
extern syscall_getcpu
|
||||||
extern syscall_sysinfo
|
extern syscall_sysinfo
|
||||||
|
extern syscall_writev
|
||||||
|
extern syscall_readv
|
||||||
syscalltab:
|
syscalltab:
|
||||||
dq syscall_print
|
dq syscall_print
|
||||||
dq syscall_mmap
|
dq syscall_mmap
|
||||||
@@ -194,7 +196,9 @@ dq syscall_nice
|
|||||||
dq syscall_flock
|
dq syscall_flock
|
||||||
dq syscall_getcpu
|
dq syscall_getcpu
|
||||||
dq syscall_sysinfo
|
dq syscall_sysinfo
|
||||||
syscallcount equ 97
|
dq syscall_writev
|
||||||
|
dq syscall_readv
|
||||||
|
syscallcount equ 99
|
||||||
section .text
|
section .text
|
||||||
global arch_syscall_entry
|
global arch_syscall_entry
|
||||||
; on entry:
|
; on entry:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#ifdef SYSCALL_LOGGING
|
#ifdef SYSCALL_LOGGING
|
||||||
|
|
||||||
#define SYSCALL_COUNT 97
|
#define SYSCALL_COUNT 99
|
||||||
#define LOGSTR(x) arch_e9_puts(x)
|
#define LOGSTR(x) arch_e9_puts(x)
|
||||||
|
|
||||||
static char *name[] = {
|
static char *name[] = {
|
||||||
@@ -105,7 +105,9 @@ static char *name[] = {
|
|||||||
"nice",
|
"nice",
|
||||||
"flock",
|
"flock",
|
||||||
"getcpu",
|
"getcpu",
|
||||||
"sysinfo"
|
"sysinfo",
|
||||||
|
"writev",
|
||||||
|
"readv"
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *args[] = {
|
static char *args[] = {
|
||||||
@@ -206,6 +208,8 @@ static char *args[] = {
|
|||||||
"fd %d op %d", // flock
|
"fd %d op %d", // flock
|
||||||
"N/A", // getcpu
|
"N/A", // getcpu
|
||||||
"ptr %p", // sysinfo
|
"ptr %p", // sysinfo
|
||||||
|
"fd %d iov %p iovcnt %d", // writev
|
||||||
|
"fd %d iov %p iovcnt %d", // readv
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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, ¤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;
|
||||||
|
}
|
||||||
@@ -281,13 +281,27 @@ index b2db152..e6438fe 100644
|
|||||||
linker.linkObjects(object);
|
linker.linkObjects(object);
|
||||||
linker.initObjects(initialRepository.get());
|
linker.initObjects(initialRepository.get());
|
||||||
diff --git mlibc-clean/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
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-clean/sysdeps/astral/generic/generic.cpp
|
||||||
+++ mlibc-workdir/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;
|
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) {
|
+ int sys_sysinfo(struct sysinfo *info) {
|
||||||
+ long r;
|
+ long r;
|
||||||
+ return syscall(SYSCALL_SYSINFO, &r, (uint64_t)info);
|
+ return syscall(SYSCALL_SYSINFO, &r, (uint64_t)info);
|
||||||
@@ -297,14 +311,16 @@ index be7ad9e..6fb09ec 100644
|
|||||||
long ret;
|
long ret;
|
||||||
// can never fail
|
// can never fail
|
||||||
diff --git mlibc-clean/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
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-clean/sysdeps/astral/include/astral/syscall.h
|
||||||
+++ mlibc-workdir/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_NICE 93
|
||||||
#define SYSCALL_FLOCK 94
|
#define SYSCALL_FLOCK 94
|
||||||
#define SYSCALL_GETCPU 95
|
#define SYSCALL_GETCPU 95
|
||||||
+#define SYSCALL_SYSINFO 96
|
+#define SYSCALL_SYSINFO 96
|
||||||
|
+#define SYSCALL_WRITEV 97
|
||||||
|
+#define SYSCALL_READV 98
|
||||||
|
|
||||||
#ifndef __MLIBC_ABI_ONLY
|
#ifndef __MLIBC_ABI_ONLY
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user