~sircmpwn/hare-dev

hare: io: more appropriate fd errors v1 PROPOSED

Sebastian: 1
 io: more appropriate fd errors

 2 files changed, 93 insertions(+), 9 deletions(-)
#786656 alpine.yml success
#786657 freebsd.yml success
Some of these are already redundant with errors::errno, such as EAGAIN.
For errors which don't map as intelligently for a given syscall (such as
EISDIR in the first example), we can add an override like this, but
for others we should be improving errors::errno and being careful not to
duplicate branches between them.
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/hare-dev/patches/33239/mbox | git am -3
Learn more about email & git

[PATCH hare] io: more appropriate fd errors Export this patch

Signed-off-by: Sebastian <sebastian@sebsite.pw>
---
 io/+freebsd/file.ha | 46 +++++++++++++++++++++++++++++++++----
 io/+linux/file.ha   | 56 +++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/io/+freebsd/file.ha b/io/+freebsd/file.ha
index 81b2c93f..b2a66a6d 100644
--- a/io/+freebsd/file.ha
+++ b/io/+freebsd/file.ha
@@ -21,7 +21,18 @@ 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);
		switch (err) {
		case rt::EAGAIN =>
			return errors::again;
		case rt::EINTR =>
			return errors::interrupted;
		case rt::EINVAL =>
			return errors::invalid;
		case rt::EISDIR =>
			return errors::unsupported;
		case =>
			return errors::errno(err);
		};
	case let n: size =>
		switch (n) {
		case 0 =>
@@ -35,7 +46,20 @@ fn fd_read(fd: file, buf: []u8) (size | EOF | error) = {
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);
		switch (err) {
		case rt::EAGAIN =>
			return errors::again;
		case rt::EINTR =>
			return errors::interrupted;
		case rt::EINVAL =>
			return errors::invalid;
		case rt::EPERM =>
			return errors::noaccess;
		case rt::EPIPE =>
			return errors::unsupported;
		case =>
			return errors::errno(err);
		};
	case let n: size =>
		return n;
	};
@@ -45,7 +69,12 @@ fn fd_close(fd: file) (void | error) = {
	match (rt::close(fd)) {
	case void => void;
	case let err: rt::errno =>
		return errors::errno(err);
		switch (err) {
		case rt::EINTR =>
			return errors::interrupted;
		case =>
			return errors::errno(err);
		};
	};
};

@@ -56,7 +85,16 @@ fn fd_seek(
) (off | error) = {
	match (rt::lseek(fd, offs: i64, whence: uint)) {
	case let err: rt::errno =>
		return errors::errno(err);
		switch (err) {
		case rt::EINVAL =>
			return errors::invalid;
		case rt::EOVERFLOW =>
			return errors::overflow;
		case rt::ESPIPE =>
			return errors::unsupported;
		case =>
			return errors::errno(err);
		};
	case let n: i64 =>
		return n: off;
	};
diff --git a/io/+linux/file.ha b/io/+linux/file.ha
index f2564e17..399342a3 100644
--- a/io/+linux/file.ha
+++ b/io/+linux/file.ha
@@ -22,7 +22,18 @@ 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);
		switch (err) {
		case rt::EAGAIN =>
			return errors::again;
		case rt::EINTR =>
			return errors::interrupted;
		case rt::EINVAL =>
			return errors::invalid;
		case rt::EISDIR =>
			return errors::unsupported;
		case =>
			return errors::errno(err);
		};
	case let n: size =>
		switch (n) {
		case 0 =>
@@ -36,7 +47,20 @@ fn fd_read(fd: file, buf: []u8) (size | EOF | error) = {
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);
		switch (err) {
		case rt::EAGAIN =>
			return errors::again;
		case rt::EINTR =>
			return errors::interrupted;
		case rt::EINVAL =>
			return errors::invalid;
		case rt::EPERM =>
			return errors::noaccess;
		case rt::EPIPE =>
			return errors::unsupported;
		case =>
			return errors::errno(err);
		};
	case let n: size =>
		return n;
	};
@@ -46,7 +70,12 @@ fn fd_close(fd: file) (void | error) = {
	match (rt::close(fd)) {
	case void => void;
	case let err: rt::errno =>
		return errors::errno(err);
		switch (err) {
		case rt::EINTR =>
			return errors::interrupted;
		case =>
			return errors::errno(err);
		};
	};
};

@@ -57,7 +86,16 @@ fn fd_seek(
) (off | error) = {
	match (rt::lseek(fd, offs: i64, whence: uint)) {
	case let err: rt::errno =>
		return errors::errno(err);
		switch (err) {
		case rt::EINVAL =>
			return errors::invalid;
		case rt::EOVERFLOW =>
			return errors::overflow;
		case rt::ESPIPE =>
			return errors::unsupported;
		case =>
			return errors::errno(err);
		};
	case let n: i64 =>
		return n: off;
	};
@@ -71,11 +109,19 @@ fn fd_copy(to: file, from: file) (size | error) = {
		let n = match (rt::sendfile(to, from, null, SENDFILE_MAX)) {
		case let err: rt::errno =>
			switch (err) {
			case rt::EAGAIN =>
				return errors::again;
			case rt::EINVAL =>
				if (sum == 0) {
					return errors::unsupported;
				};
				return errors::errno(err);
				return errors::invalid;
			case rt::ENOMEM =>
				return errors::nomem;
			case rt::EOVERFLOW =>
				return errors::overflow;
			case rt::ESPIPE =>
				return errors::unsupported;
			case =>
				return errors::errno(err);
			};
-- 
2.36.1
This will probably make sense in other modules as well.  So it would
probably makes sense to factor this out into it's own function (say
errors::from_errno()) and just call this function instead (??)
hare/patches: SUCCESS in 1m32s

[io: more appropriate fd errors][0] from [Sebastian][1]

[0]: https://lists.sr.ht/~sircmpwn/hare-dev/patches/33239
[1]: mailto:sebastian@sebsite.pw

✓ #786657 SUCCESS hare/patches/freebsd.yml https://builds.sr.ht/~sircmpwn/job/786657
✓ #786656 SUCCESS hare/patches/alpine.yml  https://builds.sr.ht/~sircmpwn/job/786656