commit 1acd233098dcb406b457ee55b8ddc81c0eff942b
parent e6b59a2ce3a9a835ac598d57844ec87d070fe40a
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 20 Nov 2024 09:37:33 +0100
os: add fcntl F_GETFL/F_SETFL wrappers
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
19 files changed, 258 insertions(+), 12 deletions(-)
diff --git a/makefiles/freebsd.aarch64.mk b/makefiles/freebsd.aarch64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+freebsd/dirfdfs.ha os/+freebsd/exit.ha os/+freebsd/fs.ha os/+freebsd/memfd.ha os/+freebsd/platform_environ.ha os/+freebsd/shm.ha os/+freebsd/status.ha os/+freebsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+freebsd/dirfdfs.ha os/+freebsd/exit.ha os/+freebsd/fcntl.ha os/+freebsd/fs.ha os/+freebsd/memfd.ha os/+freebsd/platform_environ.ha os/+freebsd/shm.ha os/+freebsd/status.ha os/+freebsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/freebsd.riscv64.mk b/makefiles/freebsd.riscv64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+freebsd/dirfdfs.ha os/+freebsd/exit.ha os/+freebsd/fs.ha os/+freebsd/memfd.ha os/+freebsd/platform_environ.ha os/+freebsd/shm.ha os/+freebsd/status.ha os/+freebsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+freebsd/dirfdfs.ha os/+freebsd/exit.ha os/+freebsd/fcntl.ha os/+freebsd/fs.ha os/+freebsd/memfd.ha os/+freebsd/platform_environ.ha os/+freebsd/shm.ha os/+freebsd/status.ha os/+freebsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/freebsd.x86_64.mk b/makefiles/freebsd.x86_64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+freebsd/dirfdfs.ha os/+freebsd/exit.ha os/+freebsd/fs.ha os/+freebsd/memfd.ha os/+freebsd/platform_environ.ha os/+freebsd/shm.ha os/+freebsd/status.ha os/+freebsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+freebsd/dirfdfs.ha os/+freebsd/exit.ha os/+freebsd/fcntl.ha os/+freebsd/fs.ha os/+freebsd/memfd.ha os/+freebsd/platform_environ.ha os/+freebsd/shm.ha os/+freebsd/status.ha os/+freebsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/linux.aarch64.mk b/makefiles/linux.aarch64.mk
@@ -147,7 +147,7 @@ $(HARECACHE)/fs.ssa: $(fs_ha) $(HARECACHE)/encoding_utf8.td $(HARECACHE)/errors.
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/fs.td.tmp -N fs $(fs_ha)
-os_ha = os/+linux/dirfdfs.ha os/+linux/exit.ha os/+linux/fs.ha os/+linux/memfd.ha os/+linux/memory.ha os/+linux/platform_environ.ha os/+linux/shm.ha os/+linux/status.ha os/+linux/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+linux/dirfdfs.ha os/+linux/exit.ha os/+linux/fcntl.ha os/+linux/fs.ha os/+linux/memfd.ha os/+linux/memory.ha os/+linux/platform_environ.ha os/+linux/shm.ha os/+linux/status.ha os/+linux/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/math.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/linux.riscv64.mk b/makefiles/linux.riscv64.mk
@@ -147,7 +147,7 @@ $(HARECACHE)/fs.ssa: $(fs_ha) $(HARECACHE)/encoding_utf8.td $(HARECACHE)/errors.
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/fs.td.tmp -N fs $(fs_ha)
-os_ha = os/+linux/dirfdfs.ha os/+linux/exit.ha os/+linux/fs.ha os/+linux/memfd.ha os/+linux/memory.ha os/+linux/platform_environ.ha os/+linux/shm.ha os/+linux/status.ha os/+linux/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+linux/dirfdfs.ha os/+linux/exit.ha os/+linux/fcntl.ha os/+linux/fs.ha os/+linux/memfd.ha os/+linux/memory.ha os/+linux/platform_environ.ha os/+linux/shm.ha os/+linux/status.ha os/+linux/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/math.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/linux.x86_64.mk b/makefiles/linux.x86_64.mk
@@ -147,7 +147,7 @@ $(HARECACHE)/fs.ssa: $(fs_ha) $(HARECACHE)/encoding_utf8.td $(HARECACHE)/errors.
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/fs.td.tmp -N fs $(fs_ha)
-os_ha = os/+linux/dirfdfs.ha os/+linux/exit.ha os/+linux/fs.ha os/+linux/memfd.ha os/+linux/memory.ha os/+linux/platform_environ.ha os/+linux/shm.ha os/+linux/status.ha os/+linux/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+linux/dirfdfs.ha os/+linux/exit.ha os/+linux/fcntl.ha os/+linux/fs.ha os/+linux/memfd.ha os/+linux/memory.ha os/+linux/platform_environ.ha os/+linux/shm.ha os/+linux/status.ha os/+linux/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/math.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/netbsd.aarch64.mk b/makefiles/netbsd.aarch64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fcntl.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/netbsd.riscv64.mk b/makefiles/netbsd.riscv64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fcntl.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/netbsd.x86_64.mk b/makefiles/netbsd.x86_64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fcntl.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/openbsd.aarch64.mk b/makefiles/openbsd.aarch64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+openbsd/dirfdfs.ha os/+openbsd/exit.ha os/+openbsd/fs.ha os/+openbsd/platform_environ.ha os/+openbsd/shm.ha os/+openbsd/status.ha os/+openbsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+openbsd/dirfdfs.ha os/+openbsd/exit.ha os/+openbsd/fcntl.ha os/+openbsd/fs.ha os/+openbsd/platform_environ.ha os/+openbsd/shm.ha os/+openbsd/status.ha os/+openbsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/openbsd.riscv64.mk b/makefiles/openbsd.riscv64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+openbsd/dirfdfs.ha os/+openbsd/exit.ha os/+openbsd/fs.ha os/+openbsd/platform_environ.ha os/+openbsd/shm.ha os/+openbsd/status.ha os/+openbsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+openbsd/dirfdfs.ha os/+openbsd/exit.ha os/+openbsd/fcntl.ha os/+openbsd/fs.ha os/+openbsd/platform_environ.ha os/+openbsd/shm.ha os/+openbsd/status.ha os/+openbsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/openbsd.x86_64.mk b/makefiles/openbsd.x86_64.mk
@@ -129,7 +129,7 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+openbsd/dirfdfs.ha os/+openbsd/exit.ha os/+openbsd/fs.ha os/+openbsd/platform_environ.ha os/+openbsd/shm.ha os/+openbsd/status.ha os/+openbsd/stdfd.ha os/environ.ha os/os.ha
+os_ha = os/+openbsd/dirfdfs.ha os/+openbsd/exit.ha os/+openbsd/fcntl.ha os/+openbsd/fs.ha os/+openbsd/platform_environ.ha os/+openbsd/shm.ha os/+openbsd/status.ha os/+openbsd/stdfd.ha os/environ.ha os/os.ha
$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/os/+freebsd/dirfdfs.ha b/os/+freebsd/dirfdfs.ha
@@ -161,6 +161,50 @@ fn fsflags_to_bsd(flags: fs::flag) (int | errors::unsupported) = {
return out;
};
+fn bsd_to_fsflags(flags: int) fs::flag = {
+ let out: fs::flag = 0;
+ if (flags & rt::O_WRONLY == rt::O_WRONLY) {
+ out |= fs::flag::WRONLY;
+ };
+ if (flags & rt::O_RDWR == rt::O_RDWR) {
+ out |= fs::flag::RDWR;
+ };
+ if (flags & rt::O_CREAT == rt::O_CREAT) {
+ out |= fs::flag::CREATE;
+ };
+ if (flags & rt::O_EXCL == rt::O_EXCL) {
+ out |= fs::flag::EXCL;
+ };
+ if (flags & rt::O_NOCTTY == 0) {
+ out |= fs::flag::CTTY;
+ };
+ if (flags & rt::O_TRUNC == rt::O_TRUNC) {
+ out |= fs::flag::TRUNC;
+ };
+ if (flags & rt::O_APPEND == rt::O_APPEND) {
+ out |= fs::flag::APPEND;
+ };
+ if (flags & rt::O_NONBLOCK == rt::O_NONBLOCK) {
+ out |= fs::flag::NONBLOCK;
+ };
+ if (flags & rt::O_DSYNC == rt::O_DSYNC) {
+ out |= fs::flag::DSYNC;
+ };
+ if (flags & rt::O_SYNC == rt::O_SYNC) {
+ out |= fs::flag::SYNC;
+ };
+ if (flags & rt::O_DIRECTORY == rt::O_DIRECTORY) {
+ out |= fs::flag::DIRECTORY;
+ };
+ if (flags & rt::O_NOFOLLOW == rt::O_NOFOLLOW) {
+ out |= fs::flag::NOFOLLOW;
+ };
+ if (flags & rt::O_CLOEXEC == 0) {
+ out |= fs::flag::NOCLOEXEC;
+ };
+ return out;
+};
+
fn fs_open_file(
fs: *fs::fs,
path: str,
diff --git a/os/+freebsd/fcntl.ha b/os/+freebsd/fcntl.ha
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use fs;
+use io;
+use rt;
+
+// Returns the [[fs::flag]]s associated with a file descriptor. See fcntl(2).
+export fn getfl(file: io::file) (fs::flag | errors::error) = {
+ match (rt::fcntl(file, rt::F_GETFL, void)) {
+ case let i: int =>
+ return bsd_to_fsflags(i);
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
+
+// Sets the [[fs::flag]]s associated with a file descriptor. Changes to the
+// access mode (e.g. [[fs::flag::RDWR]] and file creation flags (e.g.
+// [[fs::flag::CREATE]]) are ignored. See fcntl(2).
+export fn setfl(file: io::file, flags: fs::flag) (void | errors::error) = {
+ const flags = fsflags_to_bsd(flags)?;
+ match (rt::fcntl(file, rt::F_SETFL, flags)) {
+ case int =>
+ return;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
diff --git a/os/+linux/fcntl.ha b/os/+linux/fcntl.ha
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use fs;
+use io;
+use rt;
+
+// Returns the [[fs::flag]]s associated with a file descriptor. See fcntl(2),
+// ref F_GETFL.
+export fn getflags(file: io::file) (fs::flag | errors::error) = {
+ match (rt::fcntl(file, rt::F_GETFL, void)) {
+ case let i: int =>
+ return i: fs::flag;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
+
+// Sets the [[fs::flag]]s associated with a file descriptor. Changes to the
+// access mode (e.g. [[fs::flag::RDWR]] and file creation flags (e.g.
+// [[fs::flag::CREATE]]) are ignored. See fcntl(2), ref F_SETFL.
+export fn setflags(file: io::file, flags: fs::flag) (void | errors::error) = {
+ match (rt::fcntl(file, rt::F_SETFL, flags)) {
+ case int =>
+ return;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
diff --git a/os/+netbsd/dirfdfs.ha b/os/+netbsd/dirfdfs.ha
@@ -161,6 +161,50 @@ fn fsflags_to_bsd(flags: fs::flag) (int | errors::unsupported) = {
return out;
};
+fn bsd_to_fsflags(flags: int) fs::flag = {
+ let out: fs::flag = 0;
+ if (flags & rt::O_WRONLY == rt::O_WRONLY) {
+ out |= fs::flag::WRONLY;
+ };
+ if (flags & rt::O_RDWR == rt::O_RDWR) {
+ out |= fs::flag::RDWR;
+ };
+ if (flags & rt::O_CREAT == rt::O_CREAT) {
+ out |= fs::flag::CREATE;
+ };
+ if (flags & rt::O_EXCL == rt::O_EXCL) {
+ out |= fs::flag::EXCL;
+ };
+ if (flags & rt::O_NOCTTY == 0) {
+ out |= fs::flag::CTTY;
+ };
+ if (flags & rt::O_TRUNC == rt::O_TRUNC) {
+ out |= fs::flag::TRUNC;
+ };
+ if (flags & rt::O_APPEND == rt::O_APPEND) {
+ out |= fs::flag::APPEND;
+ };
+ if (flags & rt::O_NONBLOCK == rt::O_NONBLOCK) {
+ out |= fs::flag::NONBLOCK;
+ };
+ if (flags & rt::O_DSYNC == rt::O_DSYNC) {
+ out |= fs::flag::DSYNC;
+ };
+ if (flags & rt::O_SYNC == rt::O_SYNC) {
+ out |= fs::flag::SYNC;
+ };
+ if (flags & rt::O_DIRECTORY == rt::O_DIRECTORY) {
+ out |= fs::flag::DIRECTORY;
+ };
+ if (flags & rt::O_NOFOLLOW == rt::O_NOFOLLOW) {
+ out |= fs::flag::NOFOLLOW;
+ };
+ if (flags & rt::O_CLOEXEC == 0) {
+ out |= fs::flag::NOCLOEXEC;
+ };
+ return out;
+};
+
fn fs_open_file(
fs: *fs::fs,
path: str,
diff --git a/os/+netbsd/fcntl.ha b/os/+netbsd/fcntl.ha
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use fs;
+use io;
+use rt;
+
+// Returns the [[fs::flag]]s associated with a file descriptor. See fcntl(2).
+export fn getfl(file: io::file) (fs::flag | errors::error) = {
+ match (rt::fcntl(file, rt::F_GETFL, void)) {
+ case let i: int =>
+ return bsd_to_fsflags(i);
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
+
+// Sets the [[fs::flag]]s associated with a file descriptor. Changes to the
+// access mode (e.g. [[fs::flag::RDWR]] and file creation flags (e.g.
+// [[fs::flag::CREATE]]) are ignored. See fcntl(2).
+export fn setfl(file: io::file, flags: fs::flag) (void | errors::error) = {
+ const flags = fsflags_to_bsd(flags)?;
+ match (rt::fcntl(file, rt::F_SETFL, flags)) {
+ case int =>
+ return;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
diff --git a/os/+openbsd/dirfdfs.ha b/os/+openbsd/dirfdfs.ha
@@ -65,6 +65,44 @@ fn fsflags_to_bsd(flags: fs::flag) (int | errors::unsupported) = {
return out;
};
+fn bsd_to_fsflags(flags: int) fs::flag = {
+ let out: fs::flag = 0;
+ if (flags & rt::O_WRONLY == rt::O_WRONLY) {
+ out |= fs::flag::WRONLY;
+ };
+ if (flags & rt::O_RDWR == rt::O_RDWR) {
+ out |= fs::flag::RDWR;
+ };
+ if (flags & rt::O_CREAT == rt::O_CREAT) {
+ out |= fs::flag::CREATE;
+ };
+ if (flags & rt::O_EXCL == rt::O_EXCL) {
+ out |= fs::flag::EXCL;
+ };
+ if (flags & rt::O_TRUNC == rt::O_TRUNC) {
+ out |= fs::flag::TRUNC;
+ };
+ if (flags & rt::O_APPEND == rt::O_APPEND) {
+ out |= fs::flag::APPEND;
+ };
+ if (flags & rt::O_NONBLOCK == rt::O_NONBLOCK) {
+ out |= fs::flag::NONBLOCK;
+ };
+ if (flags & rt::O_SYNC == rt::O_SYNC) {
+ out |= fs::flag::SYNC;
+ };
+ if (flags & rt::O_DIRECTORY == rt::O_DIRECTORY) {
+ out |= fs::flag::DIRECTORY;
+ };
+ if (flags & rt::O_NOFOLLOW == rt::O_NOFOLLOW) {
+ out |= fs::flag::NOFOLLOW;
+ };
+ if (flags & rt::O_CLOEXEC == 0) {
+ out |= fs::flag::NOCLOEXEC;
+ };
+ return out;
+};
+
fn _fs_open(
fs: *fs::fs,
path: str,
diff --git a/os/+openbsd/fcntl.ha b/os/+openbsd/fcntl.ha
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use fs;
+use io;
+use rt;
+
+// Returns the [[fs::flag]]s associated with a file descriptor. See fcntl(2).
+export fn getfl(file: io::file) (fs::flag | errors::error) = {
+ match (rt::fcntl(file, rt::F_GETFL, void)) {
+ case let i: int =>
+ return bsd_to_fsflags(i);
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};
+
+// Sets the [[fs::flag]]s associated with a file descriptor. Changes to the
+// access mode (e.g. [[fs::flag::RDWR]] and file creation flags (e.g.
+// [[fs::flag::CREATE]]) are ignored. See fcntl(2).
+export fn setfl(file: io::file, flags: fs::flag) (void | errors::error) = {
+ const flags = fsflags_to_bsd(flags)?;
+ match (rt::fcntl(file, rt::F_SETFL, flags)) {
+ case int =>
+ return;
+ case let err: rt::errno =>
+ return errors::errno(err);
+ };
+};