commit 817e5c0d2bbc5fa608d2a77914e634b323c4443e
parent 71293168373230f176f164931d60b40dacc634dc
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 1 Apr 2022 14:11:18 +0200
io: add readv, writev
Implements: https://todo.sr.ht/~sircmpwn/hare/319
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
6 files changed, 102 insertions(+), 4 deletions(-)
diff --git a/io/+freebsd/vector.ha b/io/+freebsd/vector.ha
@@ -0,0 +1,41 @@
+// License: MPL-2.0
+// (c) 2021 Drew DeVault <sir@cmpwn.com>
+use errors;
+use rt;
+
+export type vector = rt::iovec;
+
+// Creates a vector for use with [[writev]] and [[readv]].
+export fn mkvector(buf: []u8) vector = vector {
+ iov_base = buf: *[*]u8,
+ iov_len = len(buf),
+};
+
+// Performs a vectored read on the given file. A read is performed on each of
+// the vectors, prepared with [[mkvector]], in order, and the total number of
+// bytes read is returned. Note that an under-read is considered an error.
+export fn readv(fd: file, vectors: vector...) (size | EOF | error) = {
+ match (rt::readv(fd, vectors: *[*]rt::iovec, len(vectors): int)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let n: size =>
+ switch (n) {
+ case 0 =>
+ return EOF;
+ case =>
+ return n;
+ };
+ };
+};
+
+// Performs a vectored write on the given file. Each of the vectors, prepared
+// with [[mkvector]], are written to the file in order, and the total number of
+// bytes written is returned. Note that an under-write is considered an error.
+export fn writev(fd: file, vectors: vector...) (size | error) = {
+ match (rt::writev(fd, vectors: *[*]rt::iovec, len(vectors): int)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let n: size =>
+ return n;
+ };
+};
diff --git a/io/+linux/vector.ha b/io/+linux/vector.ha
@@ -0,0 +1,41 @@
+// License: MPL-2.0
+// (c) 2021 Drew DeVault <sir@cmpwn.com>
+use errors;
+use rt;
+
+export type vector = rt::iovec;
+
+// Creates a vector for use with [[writev]] and [[readv]].
+export fn mkvector(buf: []u8) vector = vector {
+ iov_base = buf: *[*]u8,
+ iov_len = len(buf),
+};
+
+// Performs a vectored read on the given file. A read is performed on each of
+// the vectors, prepared with [[mkvector]], in order, and the total number of
+// bytes read is returned. Note that an under-read is considered an error.
+export fn readv(fd: file, vectors: vector...) (size | EOF | error) = {
+ match (rt::readv(fd, vectors: *[*]rt::iovec, len(vectors): int)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let n: size =>
+ switch (n) {
+ case 0 =>
+ return EOF;
+ case =>
+ return n;
+ };
+ };
+};
+
+// Performs a vectored write on the given file. Each of the vectors, prepared
+// with [[mkvector]], are written to the file in order, and the total number of
+// bytes written is returned. Note that an under-write is considered an error.
+export fn writev(fd: file, vectors: vector...) (size | error) = {
+ match (rt::writev(fd, vectors: *[*]rt::iovec, len(vectors): int)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let n: size =>
+ return n;
+ };
+};
diff --git a/rt/+freebsd/syscalls.ha b/rt/+freebsd/syscalls.ha
@@ -53,6 +53,16 @@ export fn write(fd: int, buf: *const void, count: size) (size | errno) = {
fd: u64, buf: uintptr: u64, count: u64))?: size;
};
+export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
+ return wrap_return(syscall3(SYS_readv,
+ fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
+};
+
+export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
+ return wrap_return(syscall3(SYS_writev,
+ fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
+};
+
export fn close(fd: int) (void | errno) = {
wrap_return(syscall1(SYS_close, fd: u64))?;
};
diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha
@@ -628,14 +628,14 @@ export fn getpeername(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *
sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int;
};
-export fn readv(fd: int, iov: *const iovec, iovcnt: int) (int | errno) = {
+export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
return wrap_return(syscall3(SYS_readv,
- fd: u64, iov: uintptr: u64, iovcnt: u64))?: int;
+ fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
};
-export fn writev(fd: int, iov: *const iovec, iovcnt: int) (int | errno) = {
+export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
return wrap_return(syscall3(SYS_writev,
- fd: u64, iov: uintptr: u64, iovcnt: u64))?: int;
+ fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
};
export fn sendmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = {
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -709,6 +709,7 @@ gensrcs_io() {
println+linux.ha \
+linux/file.ha \
+linux/mmap.ha \
+ +linux/vector.ha \
copy.ha \
drain.ha \
empty.ha \
@@ -725,6 +726,7 @@ gensrcs_io() {
println+freebsd.ha \
+freebsd/file.ha \
+freebsd/mmap.ha \
+ +freebsd/vector.ha \
copy.ha \
drain.ha \
empty.ha \
diff --git a/stdlib.mk b/stdlib.mk
@@ -1222,6 +1222,7 @@ stdlib_io_linux_srcs= \
$(STDLIB)/io/println+linux.ha \
$(STDLIB)/io/+linux/file.ha \
$(STDLIB)/io/+linux/mmap.ha \
+ $(STDLIB)/io/+linux/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \
@@ -1239,6 +1240,7 @@ stdlib_io_freebsd_srcs= \
$(STDLIB)/io/println+freebsd.ha \
$(STDLIB)/io/+freebsd/file.ha \
$(STDLIB)/io/+freebsd/mmap.ha \
+ $(STDLIB)/io/+freebsd/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \
@@ -3114,6 +3116,7 @@ testlib_io_linux_srcs= \
$(STDLIB)/io/println+linux.ha \
$(STDLIB)/io/+linux/file.ha \
$(STDLIB)/io/+linux/mmap.ha \
+ $(STDLIB)/io/+linux/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \
@@ -3134,6 +3137,7 @@ testlib_io_freebsd_srcs= \
$(STDLIB)/io/println+freebsd.ha \
$(STDLIB)/io/+freebsd/file.ha \
$(STDLIB)/io/+freebsd/mmap.ha \
+ $(STDLIB)/io/+freebsd/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \