aboutsummaryrefslogtreecommitdiff
path: root/lib/mlibc/options/posix/generic/sys-uio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mlibc/options/posix/generic/sys-uio.cpp')
-rw-r--r--lib/mlibc/options/posix/generic/sys-uio.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/mlibc/options/posix/generic/sys-uio.cpp b/lib/mlibc/options/posix/generic/sys-uio.cpp
new file mode 100644
index 0000000..0f14bc0
--- /dev/null
+++ b/lib/mlibc/options/posix/generic/sys-uio.cpp
@@ -0,0 +1,67 @@
+
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <frg/vector.hpp>
+#include <mlibc/allocator.hpp>
+#include <mlibc/debug.hpp>
+#include <mlibc/posix-sysdeps.hpp>
+#include <bits/ensure.h>
+
+ssize_t readv(int fd, const struct iovec *iovs, int iovc) {
+ ssize_t read_bytes = 0;
+
+ auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_readv, -1);
+
+ if (int e = sysdep(fd, iovs, iovc, &read_bytes); e) {
+ errno = e;
+ return -1;
+ }
+
+ return read_bytes;
+}
+
+ssize_t writev(int fd, const struct iovec *iovs, int iovc) {
+ __ensure(iovc);
+
+ ssize_t written = 0;
+ size_t bytes = 0;
+ for(int i = 0; i < iovc; i++) {
+ if(SSIZE_MAX - bytes < iovs[i].iov_len) {
+ errno = EINVAL;
+ return -1;
+ }
+ bytes += iovs[i].iov_len;
+ }
+ frg::vector<char, MemoryAllocator> buffer{getAllocator()};
+ buffer.resize(bytes);
+
+ size_t to_copy = bytes;
+ char *bp = buffer.data();
+ for(int i = 0; i < iovc; i++) {
+ size_t copy = frg::min(iovs[i].iov_len, to_copy);
+
+ bp = (char *)mempcpy((void *)bp, (void *)iovs[i].iov_base, copy);
+
+ to_copy -= copy;
+ if(to_copy == 0)
+ break;
+ }
+
+ written = write(fd, buffer.data(), bytes);
+ return written;
+}
+
+ssize_t preadv(int, const struct iovec *, int, off_t) {
+ __ensure(!"Not implemented");
+ __builtin_unreachable();
+}
+
+ssize_t pwritev(int, const struct iovec *, int, off_t) {
+ __ensure(!"Not implemented");
+ __builtin_unreachable();
+}