commit 255d5f785bf75ede677d6c1e318f18619a975261
parent a96bd0449c2beb92590c7eea17046498e43853d2
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 10 Nov 2023 13:56:51 +0100
io: add dup, dup2 functions
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
8 files changed, 92 insertions(+), 6 deletions(-)
diff --git a/io/+freebsd/dup.ha b/io/+freebsd/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);
+ };
+};
diff --git a/io/+linux/dup.ha b/io/+linux/dup.ha
@@ -0,0 +1,42 @@
+// 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::dup(old)) {
+ 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);
+ };
+};
+
+// 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::dup3(old, new, flags)) {
+ case let fd: int =>
+ return fd;
+ case let e: rt::errno =>
+ return errors::errno(e);
+ };
+};
diff --git a/makefiles/freebsd.aarch64.mk b/makefiles/freebsd.aarch64.mk
@@ -57,7 +57,7 @@ $(HARECACHE)/errors.ssa: $(errors_ha) $(HARECACHE)/rt.td
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $(HARECACHE)/errors.ssa -t $(HARECACHE)/errors.td.tmp -N errors $(errors_ha)
-io_ha = io/+freebsd/mmap.ha io/+freebsd/platform_file.ha io/+freebsd/vector.ha io/arch+aarch64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
+io_ha = io/+freebsd/dup.ha io/+freebsd/mmap.ha io/+freebsd/platform_file.ha io/+freebsd/vector.ha io/arch+aarch64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
$(HARECACHE)/io.ssa: $(io_ha) $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/rt.td $(HARECACHE)/types.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/freebsd.riscv64.mk b/makefiles/freebsd.riscv64.mk
@@ -57,7 +57,7 @@ $(HARECACHE)/errors.ssa: $(errors_ha) $(HARECACHE)/rt.td
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $(HARECACHE)/errors.ssa -t $(HARECACHE)/errors.td.tmp -N errors $(errors_ha)
-io_ha = io/+freebsd/mmap.ha io/+freebsd/platform_file.ha io/+freebsd/vector.ha io/arch+riscv64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
+io_ha = io/+freebsd/dup.ha io/+freebsd/mmap.ha io/+freebsd/platform_file.ha io/+freebsd/vector.ha io/arch+riscv64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
$(HARECACHE)/io.ssa: $(io_ha) $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/rt.td $(HARECACHE)/types.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/freebsd.x86_64.mk b/makefiles/freebsd.x86_64.mk
@@ -57,7 +57,7 @@ $(HARECACHE)/errors.ssa: $(errors_ha) $(HARECACHE)/rt.td
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $(HARECACHE)/errors.ssa -t $(HARECACHE)/errors.td.tmp -N errors $(errors_ha)
-io_ha = io/+freebsd/mmap.ha io/+freebsd/platform_file.ha io/+freebsd/vector.ha io/arch+x86_64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
+io_ha = io/+freebsd/dup.ha io/+freebsd/mmap.ha io/+freebsd/platform_file.ha io/+freebsd/vector.ha io/arch+x86_64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
$(HARECACHE)/io.ssa: $(io_ha) $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/rt.td $(HARECACHE)/types.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/linux.aarch64.mk b/makefiles/linux.aarch64.mk
@@ -57,7 +57,7 @@ $(HARECACHE)/errors.ssa: $(errors_ha) $(HARECACHE)/rt.td
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $(HARECACHE)/errors.ssa -t $(HARECACHE)/errors.td.tmp -N errors $(errors_ha)
-io_ha = io/+linux/mmap.ha io/+linux/platform_file.ha io/+linux/vector.ha io/arch+aarch64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
+io_ha = io/+linux/dup.ha io/+linux/mmap.ha io/+linux/platform_file.ha io/+linux/vector.ha io/arch+aarch64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
$(HARECACHE)/io.ssa: $(io_ha) $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/rt.td $(HARECACHE)/types.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/linux.riscv64.mk b/makefiles/linux.riscv64.mk
@@ -57,7 +57,7 @@ $(HARECACHE)/errors.ssa: $(errors_ha) $(HARECACHE)/rt.td
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $(HARECACHE)/errors.ssa -t $(HARECACHE)/errors.td.tmp -N errors $(errors_ha)
-io_ha = io/+linux/mmap.ha io/+linux/platform_file.ha io/+linux/vector.ha io/arch+riscv64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
+io_ha = io/+linux/dup.ha io/+linux/mmap.ha io/+linux/platform_file.ha io/+linux/vector.ha io/arch+riscv64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
$(HARECACHE)/io.ssa: $(io_ha) $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/rt.td $(HARECACHE)/types.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
diff --git a/makefiles/linux.x86_64.mk b/makefiles/linux.x86_64.mk
@@ -57,7 +57,7 @@ $(HARECACHE)/errors.ssa: $(errors_ha) $(HARECACHE)/rt.td
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $(HARECACHE)/errors.ssa -t $(HARECACHE)/errors.td.tmp -N errors $(errors_ha)
-io_ha = io/+linux/mmap.ha io/+linux/platform_file.ha io/+linux/vector.ha io/arch+x86_64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
+io_ha = io/+linux/dup.ha io/+linux/mmap.ha io/+linux/platform_file.ha io/+linux/vector.ha io/arch+x86_64.ha io/copy.ha io/drain.ha io/empty.ha io/file.ha io/handle.ha io/limit.ha io/stream.ha io/tee.ha io/types.ha io/util.ha io/zero.ha
$(HARECACHE)/io.ssa: $(io_ha) $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/rt.td $(HARECACHE)/types.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"