commit 1775202449eec49bbd5cdc0f63c06b811271bedb
parent 2365ddceeb4688826c6bdef3986c22d23112fdb7
Author: Lorenz (xha) <me@xha.li>
Date: Sat, 25 Nov 2023 15:18:07 +0100
OpenBSD: add io
Signed-off-by: Lorenz (xha) <me@xha.li>
Diffstat:
5 files changed, 232 insertions(+), 2 deletions(-)
diff --git a/io/+openbsd/dup.ha b/io/+openbsd/dup.ha
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use rt;
+
+// Flags for [[dup]] and [[dup2]] operations.
+export type dupflag = enum {
+ NONE = 0,
+
+ // Causes [[dup]] and [[dup2]] not to set the CLOEXEC flag on the
+ // duplicated file descriptor. By default, CLOEXEC is set.
+ NOCLOEXEC = rt::FD_CLOEXEC,
+};
+
+// Duplicates a file descriptor.
+export fn dup(old: file, flags: dupflag) (file | error) = {
+ flags ^= dupflag::NOCLOEXEC; // Invert CLOEXEC
+
+ match (rt::dup2(old, -1)) {
+ case let fd: int =>
+ const fl = rt::fcntl(fd, rt::F_GETFD, 0)!;
+ rt::fcntl(fd, rt::F_SETFD, fl | rt::FD_CLOEXEC)!;
+ return fd;
+ case let e: rt::errno =>
+ return errors::errno(e);
+ };
+};
+
+// Duplicates a file descriptor and stores the new file at a specific file
+// descriptor number. If the file indicated by "new" already refers to an open
+// file, this file will be closed before the file descriptor is reused.
+export fn dup2(old: file, new: file, flags: dupflag) (file | error) = {
+ flags ^= dupflag::NOCLOEXEC; // Invert CLOEXEC
+
+ match (rt::dup2(old, new)) {
+ case let fd: int =>
+ const fl = rt::fcntl(fd, rt::F_GETFD, 0)!;
+ rt::fcntl(fd, rt::F_SETFD, fl | flags)!;
+ return fd;
+ case let e: rt::errno =>
+ return errors::errno(e);
+ };
+};
+\ No newline at end of file
diff --git a/io/+openbsd/mmap.ha b/io/+openbsd/mmap.ha
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use rt;
+
+// Values for the [[mmap]] prot parameter. Only the EXEC, READ, WRITE, and NONE
+// values are portable.
+export type prot = enum int {
+ NONE = rt::PROT_NONE,
+ READ = rt::PROT_READ,
+ WRITE = rt::PROT_WRITE,
+ EXEC = rt::PROT_EXEC,
+};
+
+// Values for the [[mmap]] flags parameter. Only the SHARED, PRIVATE, and FIXED
+// values are portable.
+export type mflag = enum int {
+ SHARED = rt::MAP_SHARED,
+ PRIVATE = rt::MAP_PRIVATE,
+ FIXED = rt::MAP_FIXED,
+ ANON = rt::MAP_ANON,
+ STACK = rt::MAP_STACK,
+ CONCEAL = rt::MAP_CONCEAL
+};
+
+// Performs the mmap syscall. Consult your system for documentation on this
+// function.
+export fn mmap(
+ addr: nullable *opaque,
+ length: size,
+ prot: prot,
+ flags: mflag,
+ fd: file,
+ offs: size
+) (*opaque | errors::error) = {
+ match (rt::mmap(addr, length, prot, flags, fd, offs: i64)) {
+ case let ptr: *opaque =>
+ return ptr;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
+
+// Unmaps memory previously mapped with [[mmap]].
+export fn munmap(addr: *opaque, length: size) (void | errors::error) = {
+ match (rt::munmap(addr, length)) {
+ case void =>
+ return;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
diff --git a/io/+openbsd/platform_file.ha b/io/+openbsd/platform_file.ha
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use rt;
+
+// This is an opaque type which encloses an OS-level file handle resource. It
+// can be used as a [[handle]] in most situations, but there are some APIs which
+// require a [[file]] with some OS-level handle backing it - this type is used
+// for such APIs.
+//
+// On OpenBSD, [[file]] is a file descriptor.
+export type file = int;
+
+// Opens a Unix file descriptor as a file. This is a low-level interface, to
+// open files most programs will use something like [[os::open]]. This function
+// is not portable.
+export fn fdopen(fd: int) file = fd;
+
+fn fd_read(fd: file, buf: []u8) (size | EOF | error) = {
+ match (rt::read(fd, buf: *[*]u8, len(buf))) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let n: size =>
+ switch (n) {
+ case 0 =>
+ return EOF;
+ case =>
+ return n;
+ };
+ };
+};
+
+fn fd_write(fd: file, buf: const []u8) (size | error) = {
+ match (rt::write(fd, buf: *const [*]u8, len(buf))) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let n: size =>
+ return n;
+ };
+};
+
+fn fd_close(fd: file) (void | error) = {
+ match (rt::close(fd)) {
+ case void => void;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
+
+fn fd_seek(
+ fd: file,
+ offs: off,
+ whence: whence,
+) (off | error) = {
+ match (rt::lseek(fd, offs: i64, whence: int)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let n: i64 =>
+ return n: off;
+ };
+};
+
+fn fd_copy(to: file, from: file) (size | error) = errors::unsupported;
+
+fn fd_lock(fd: file, flags: int) (bool | error) = {
+ match (rt::flock(fd: int, flags)) {
+ case void => return true;
+ case let e: rt::errno =>
+ if (e == rt::EWOULDBLOCK: rt::errno) {
+ return false;
+ } else {
+ return errors::errno(e);
+ };
+ };
+};
+
+fn fd_trunc(fd: file, ln: size) (void | error) = {
+ match (rt::ftruncate(fd: int, ln: rt::off_t)) {
+ case void => void;
+ case let e: rt::errno => return errors::errno(e);
+ };
+};
diff --git a/io/+openbsd/vector.ha b/io/+openbsd/vector.ha
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use rt;
+use types;
+
+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.
+export fn readv(fd: file, vectors: vector...) (size | EOF | error) = {
+ if (len(vectors) > types::INT_MAX: size) {
+ return errors::invalid;
+ };
+ 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.
+export fn writev(fd: file, vectors: vector...) (size | error) = {
+ if (len(vectors) > types::INT_MAX: size) {
+ return errors::invalid;
+ };
+ 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/file.ha b/io/file.ha
@@ -13,8 +13,8 @@ export type lockop = enum int {
UNLOCK = rt::LOCK_UN,
};
-// Apply or remove an advisory lock on an open file. If block is true, the request will block while waiting
-// for the lock.
+// Apply or remove an advisory lock on an open file. If block is true, the
+// request will block while waiting for the lock.
export fn lock(fd: file, block: bool, op: lockop) (bool | error) = {
let flags = op: int;
if (!block) flags |= rt::LOCK_NB;