commit 91bcdbeb4858cf39875b95b4b3c2be029e16dcfc
parent 4df0fba8b05fcf175805f7bb41aa7fd6333e2ad9
Author: Autumn! <autumnull@posteo.net>
Date: Sat, 13 May 2023 15:32:31 +0000
io: move fd-related functions into one file
Signed-off-by: Autumn! <autumnull@posteo.net>
Diffstat:
13 files changed, 219 insertions(+), 250 deletions(-)
diff --git a/io/+freebsd/file.ha b/io/+freebsd/file.ha
@@ -1,65 +0,0 @@
-// License: MPL-2.0
-// (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
-// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use errors;
-use rt;
-use strings;
-
-// 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 FreeBSD, [[io::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;
diff --git a/io/+freebsd/platform_file.ha b/io/+freebsd/platform_file.ha
@@ -0,0 +1,84 @@
+// License: MPL-2.0
+// (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
+// (c) 2021 Ember Sawady <ecs@d2evs.net>
+use errors;
+use rt;
+use strings;
+
+// 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 FreeBSD, [[io::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/+freebsd/platform_lock.ha b/io/+freebsd/platform_lock.ha
@@ -1,15 +0,0 @@
-// License: MPL-2.0
-use errors;
-use rt;
-
-fn platform_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);
- };
- };
-};
diff --git a/io/+freebsd/platform_trunc.ha b/io/+freebsd/platform_trunc.ha
@@ -1,10 +0,0 @@
-// License: MPL-2.0
-use errors;
-use rt;
-
- fn platform_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/+linux/file.ha b/io/+linux/file.ha
@@ -1,81 +0,0 @@
-// License: MPL-2.0
-// (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
-// (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
-// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use errors;
-use rt;
-use strings;
-
-// 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 Linux, [[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;
- };
-};
-
-def SENDFILE_MAX: size = 2147479552z;
-
-fn fd_copy(to: file, from: file) (size | error) = {
- let sum = 0z;
- for (true) match (rt::sendfile(to, from, null, SENDFILE_MAX)) {
- case let err: rt::errno =>
- if (err == rt::EINVAL && sum == 0) {
- return errors::unsupported;
- };
- return errors::errno(err);
- case let n: size =>
- if (n == 0) break;
- sum += n;
- };
- return sum;
-};
diff --git a/io/+linux/platform_file.ha b/io/+linux/platform_file.ha
@@ -0,0 +1,100 @@
+// License: MPL-2.0
+// (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
+// (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
+// (c) 2021 Ember Sawady <ecs@d2evs.net>
+use errors;
+use rt;
+use strings;
+
+// 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 Linux, [[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;
+ };
+};
+
+def SENDFILE_MAX: size = 2147479552z;
+
+fn fd_copy(to: file, from: file) (size | error) = {
+ let sum = 0z;
+ for (true) match (rt::sendfile(to, from, null, SENDFILE_MAX)) {
+ case let err: rt::errno =>
+ if (err == rt::EINVAL && sum == 0) {
+ return errors::unsupported;
+ };
+ return errors::errno(err);
+ case let n: size =>
+ if (n == 0) break;
+ sum += n;
+ };
+ return sum;
+};
+
+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/+linux/platform_lock.ha b/io/+linux/platform_lock.ha
@@ -1,15 +0,0 @@
-// License: MPL-2.0
-use errors;
-use rt;
-
-fn platform_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);
- };
- };
-};
diff --git a/io/+linux/platform_trunc.ha b/io/+linux/platform_trunc.ha
@@ -1,10 +0,0 @@
-// License: MPL-2.0
-use errors;
-use rt;
-
- fn platform_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/file.ha b/io/file.ha
@@ -0,0 +1,23 @@
+// License: MPL-2.0
+use rt;
+
+// Lock operation to use with [[lock]].
+export type lockop = enum int {
+ // shared file lock
+ SHARED = rt::LOCK_SH,
+ // exclusive file lock
+ EXCLUSIVE = rt::LOCK_EX,
+ // unlock file
+ 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.
+export fn lock(fd: file, block: bool, op: lockop) (bool | error) = {
+ let flags = op: int;
+ if (!block) flags |= rt::LOCK_NB;
+ return fd_lock(fd, flags);
+};
+
+// Truncate a file to a specified length. The file must be open for writing.
+export fn trunc(fd: file, ln: size) (void | error) = fd_trunc(fd, ln);
diff --git a/io/lock.ha b/io/lock.ha
@@ -1,20 +0,0 @@
-// License: MPL-2.0
-use rt;
-
-// Lock operation to use with [[lock]].
-export type lockop = enum int {
- // shared file lock
- SHARED = rt::LOCK_SH,
- // exclusive file lock
- EXCLUSIVE = rt::LOCK_EX,
- // unlock file
- 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.
-export fn lock(fd: file, block: bool, op: lockop) (bool | error) = {
- let flags = op: int;
- if (!block) flags |= rt::LOCK_NB;
- return platform_lock(fd, flags);
-};
diff --git a/io/trunc.ha b/io/trunc.ha
@@ -1,4 +0,0 @@
-// License: MPL-2.0
-
-// Truncate a file to a specified length. The file must be open for writing.
-export fn trunc(fd: file, ln: size) (void | error) = platform_trunc(fd, ln);
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -867,40 +867,34 @@ hash_siphash() {
gensrcs_io() {
gen_srcs -plinux io \
'arch+$(ARCH).ha' \
- +linux/file.ha \
+linux/mmap.ha \
- +linux/platform_lock.ha \
- +linux/platform_trunc.ha \
+ +linux/platform_file.ha \
+linux/vector.ha \
copy.ha \
drain.ha \
empty.ha \
+ file.ha \
handle.ha \
limit.ha \
- lock.ha \
stream.ha \
tee.ha \
- trunc.ha \
types.ha \
util.ha \
zero.ha \
$*
gen_srcs -pfreebsd io \
'arch+$(ARCH).ha' \
- +freebsd/file.ha \
+freebsd/mmap.ha \
- +freebsd/platform_lock.ha \
- +freebsd/platform_trunc.ha \
+ +freebsd/platform_file.ha \
+freebsd/vector.ha \
copy.ha \
drain.ha \
empty.ha \
+ file.ha \
handle.ha \
limit.ha \
- lock.ha \
stream.ha \
tee.ha \
- trunc.ha \
types.ha \
util.ha \
zero.ha \
diff --git a/stdlib.mk b/stdlib.mk
@@ -1556,20 +1556,17 @@ $(HARECACHE)/hash/siphash/hash_siphash-any.ssa: $(stdlib_hash_siphash_any_srcs)
# io (+linux)
stdlib_io_linux_srcs = \
$(STDLIB)/io/arch+$(ARCH).ha \
- $(STDLIB)/io/+linux/file.ha \
$(STDLIB)/io/+linux/mmap.ha \
- $(STDLIB)/io/+linux/platform_lock.ha \
- $(STDLIB)/io/+linux/platform_trunc.ha \
+ $(STDLIB)/io/+linux/platform_file.ha \
$(STDLIB)/io/+linux/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \
+ $(STDLIB)/io/file.ha \
$(STDLIB)/io/handle.ha \
$(STDLIB)/io/limit.ha \
- $(STDLIB)/io/lock.ha \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
- $(STDLIB)/io/trunc.ha \
$(STDLIB)/io/types.ha \
$(STDLIB)/io/util.ha \
$(STDLIB)/io/zero.ha
@@ -1577,20 +1574,17 @@ stdlib_io_linux_srcs = \
# io (+freebsd)
stdlib_io_freebsd_srcs = \
$(STDLIB)/io/arch+$(ARCH).ha \
- $(STDLIB)/io/+freebsd/file.ha \
$(STDLIB)/io/+freebsd/mmap.ha \
- $(STDLIB)/io/+freebsd/platform_lock.ha \
- $(STDLIB)/io/+freebsd/platform_trunc.ha \
+ $(STDLIB)/io/+freebsd/platform_file.ha \
$(STDLIB)/io/+freebsd/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \
+ $(STDLIB)/io/file.ha \
$(STDLIB)/io/handle.ha \
$(STDLIB)/io/limit.ha \
- $(STDLIB)/io/lock.ha \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
- $(STDLIB)/io/trunc.ha \
$(STDLIB)/io/types.ha \
$(STDLIB)/io/util.ha \
$(STDLIB)/io/zero.ha
@@ -3997,20 +3991,17 @@ $(TESTCACHE)/hash/siphash/hash_siphash-any.ssa: $(testlib_hash_siphash_any_srcs)
# io (+linux)
testlib_io_linux_srcs = \
$(STDLIB)/io/arch+$(ARCH).ha \
- $(STDLIB)/io/+linux/file.ha \
$(STDLIB)/io/+linux/mmap.ha \
- $(STDLIB)/io/+linux/platform_lock.ha \
- $(STDLIB)/io/+linux/platform_trunc.ha \
+ $(STDLIB)/io/+linux/platform_file.ha \
$(STDLIB)/io/+linux/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \
+ $(STDLIB)/io/file.ha \
$(STDLIB)/io/handle.ha \
$(STDLIB)/io/limit.ha \
- $(STDLIB)/io/lock.ha \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
- $(STDLIB)/io/trunc.ha \
$(STDLIB)/io/types.ha \
$(STDLIB)/io/util.ha \
$(STDLIB)/io/zero.ha \
@@ -4020,20 +4011,17 @@ testlib_io_linux_srcs = \
# io (+freebsd)
testlib_io_freebsd_srcs = \
$(STDLIB)/io/arch+$(ARCH).ha \
- $(STDLIB)/io/+freebsd/file.ha \
$(STDLIB)/io/+freebsd/mmap.ha \
- $(STDLIB)/io/+freebsd/platform_lock.ha \
- $(STDLIB)/io/+freebsd/platform_trunc.ha \
+ $(STDLIB)/io/+freebsd/platform_file.ha \
$(STDLIB)/io/+freebsd/vector.ha \
$(STDLIB)/io/copy.ha \
$(STDLIB)/io/drain.ha \
$(STDLIB)/io/empty.ha \
+ $(STDLIB)/io/file.ha \
$(STDLIB)/io/handle.ha \
$(STDLIB)/io/limit.ha \
- $(STDLIB)/io/lock.ha \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
- $(STDLIB)/io/trunc.ha \
$(STDLIB)/io/types.ha \
$(STDLIB)/io/util.ha \
$(STDLIB)/io/zero.ha \