commit 1cdd99f66b77962d5f6de841e2f7839bd918cf4b
parent 1c326effa6e64184a8b42eb9ec3e61c9cc2a839c
Author: Eyal Sawady <ecs@d2evs.net>
Date: Thu, 21 Oct 2021 05:26:11 +0000
unix: add pipe wrapper for Linux
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
6 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/rt/+linux/+aarch64.ha b/rt/+linux/+aarch64.ha
@@ -26,3 +26,4 @@ export fn clone(
};
export def O_DIRECTORY: int = 0o40000;
+export def O_DIRECT: int = 0o200000;
diff --git a/rt/+linux/+riscv64.ha b/rt/+linux/+riscv64.ha
@@ -24,3 +24,4 @@ export fn clone(
};
export def O_DIRECTORY: int = 0o200000;
+export def O_DIRECT: int = 0o40000;
diff --git a/rt/+linux/+x86_64.ha b/rt/+linux/+x86_64.ha
@@ -24,3 +24,4 @@ export fn clone(
};
export def O_DIRECTORY: int = 0o200000;
+export def O_DIRECT: int = 0o40000;
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -846,6 +846,7 @@ unix() {
# XXX: getuid and setuid are probably platform-specific too
gen_srcs unix \
'$(PLATFORM)/nice.ha' \
+ '$(PLATFORM)/pipe.ha' \
'$(PLATFORM)/umask.ha' \
getuid.ha \
setuid.ha
diff --git a/stdlib.mk b/stdlib.mk
@@ -1155,6 +1155,7 @@ $(HARECACHE)/types/types.ssa: $(stdlib_types_srcs) $(stdlib_rt)
# unix
stdlib_unix_srcs= \
$(STDLIB)/unix/$(PLATFORM)/nice.ha \
+ $(STDLIB)/unix/$(PLATFORM)/pipe.ha \
$(STDLIB)/unix/$(PLATFORM)/umask.ha \
$(STDLIB)/unix/getuid.ha \
$(STDLIB)/unix/setuid.ha
@@ -2417,6 +2418,7 @@ $(TESTCACHE)/types/types.ssa: $(testlib_types_srcs) $(testlib_rt)
# unix
testlib_unix_srcs= \
$(STDLIB)/unix/$(PLATFORM)/nice.ha \
+ $(STDLIB)/unix/$(PLATFORM)/pipe.ha \
$(STDLIB)/unix/$(PLATFORM)/umask.ha \
$(STDLIB)/unix/getuid.ha \
$(STDLIB)/unix/setuid.ha
diff --git a/unix/+linux/pipe.ha b/unix/+linux/pipe.ha
@@ -0,0 +1,29 @@
+use errors;
+use io;
+use rt;
+
+// Flags to use for the [[io::file]]s returned by [[pipe]]
+// Only CLOEXEC and NONBLOCK are guaranteed to be available.
+export type pipe_flag = enum {
+ CLOEXEC = rt::O_CLOEXEC,
+ DIRECT = rt::O_DIRECT,
+ NONBLOCK = rt::O_NONBLOCK,
+};
+
+// Create a pair of two linked [[io::file]]s, such that any data written to the
+// second [[io::file]] may be read from the first. If no [[pipe_flag]]s are
+// provided, [[pipe_flag::CLOEXEC]] is used. If you pass your own flags, it is
+// recommended that you add it unless you know that you don't want it.
+export fn pipe(flags: pipe_flag...) ((io::file, io::file) | errors::error) = {
+ let fds: [2]int = [0...];
+ let flag: pipe_flag = if (len(flags) == 0) pipe_flag::CLOEXEC else 0;
+ for (let i = 0z; i < len(flags); i += 1) {
+ flag |= flags[i];
+ };
+ match (rt::pipe2(&fds, flag)) {
+ case void => void;
+ case e: rt::errno =>
+ return errors::errno(e);
+ };
+ return (fds[0], fds[1]);
+};