commit a3faae6f4b50c5b456a0be5ecc939f87f588ec95
parent ab69d42db3385e4af1e5e53f29daed2d1d95d694
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 1 Feb 2021 10:38:36 -0500
rt, os: rig up errno descriptions
Diffstat:
2 files changed, 283 insertions(+), 4 deletions(-)
diff --git a/os/+linux/errors.ha b/os/+linux/errors.ha
@@ -1,14 +1,16 @@
use io;
+use rt;
fn io_errstr(data: *void) str = {
- return "TODO: insert errno description here";
+ const errno = data: uintptr: int: rt::errno;
+ return rt::errstr(errno);
};
// TODO: Implement the inverse of this and make it public
fn errno_to_io(err: rt::errno) io::error = {
- let e: io::os_error = struct {
- string: *fn(data: *void) str = &io_errstr,
- data: *void = err: uintptr: *void,
+ let e = io::os_error {
+ string = &io_errstr,
+ data = err: uintptr: *void,
};
return e: io::error;
};
diff --git a/rt/+linux/errno.ha b/rt/+linux/errno.ha
@@ -13,6 +13,283 @@ export fn wrap_return(r: size) (errno | size) = {
return r;
};
+// Obtains a human-friendly reading of an [errno] (e.g. "Operation not
+// permitted").
+export fn errstr(err: errno) str = {
+ return switch (err: int) {
+ EPERM => "Operation not permitted",
+ ENOENT => "No such file or directory",
+ ESRCH => "No such process",
+ EINTR => "Interrupted system call",
+ EIO => "Input/output error",
+ ENXIO => "No such device or address",
+ E2BIG => "Argument list too long",
+ ENOEXEC => "Exec format error",
+ EBADF => "Bad file descriptor",
+ ECHILD => "No child processes",
+ EAGAIN => "Resource temporarily unavailable",
+ ENOMEM => "Cannot allocate memory",
+ EACCES => "Permission denied",
+ EFAULT => "Bad address",
+ ENOTBLK => "Block device required",
+ EBUSY => "Device or resource busy",
+ EEXIST => "File exists",
+ EXDEV => "Invalid cross-device link",
+ ENODEV => "No such device",
+ ENOTDIR => "Not a directory",
+ EISDIR => "Is a directory",
+ EINVAL => "Invalid argument",
+ ENFILE => "Too many open files in system",
+ EMFILE => "Too many open files",
+ ENOTTY => "Inappropriate ioctl for device",
+ ETXTBSY => "Text file busy",
+ EFBIG => "File too large",
+ ENOSPC => "No space left on device",
+ ESPIPE => "Illegal seek",
+ EROFS => "Read-only file system",
+ EMLINK => "Too many links",
+ EPIPE => "Broken pipe",
+ EDOM => "Numerical argument out of domain",
+ ERANGE => "Numerical result out of range",
+ EDEADLK => "Resource deadlock avoided",
+ ENAMETOOLONG => "File name too long",
+ ENOLCK => "No locks available",
+ ENOSYS => "Function not implemented",
+ ENOTEMPTY => "Directory not empty",
+ ELOOP => "Too many levels of symbolic links",
+ ENOMSG => "No message of desired type",
+ EIDRM => "Identifier removed",
+ ECHRNG => "Channel number out of range",
+ EL2NSYNC => "Level 2 not synchronized",
+ EL3HLT => "Level 3 halted",
+ EL3RST => "Level 3 reset",
+ ELNRNG => "Link number out of range",
+ EUNATCH => "Protocol driver not attached",
+ ENOCSI => "No CSI structure available",
+ EL2HLT => "Level 2 halted",
+ EBADE => "Invalid exchange",
+ EBADR => "Invalid request descriptor",
+ EXFULL => "Exchange full",
+ ENOANO => "No anode",
+ EBADRQC => "Invalid request code",
+ EBADSLT => "Invalid slot",
+ EBFONT => "Bad font file format",
+ ENOSTR => "Device not a stream",
+ ENODATA => "No data available",
+ ETIME => "Timer expired",
+ ENOSR => "Out of streams resources",
+ ENONET => "Machine is not on the network",
+ ENOPKG => "Package not installed",
+ EREMOTE => "Object is remote",
+ ENOLINK => "Link has been severed",
+ EADV => "Advertise error",
+ ESRMNT => "Srmount error",
+ ECOMM => "Communication error on send",
+ EPROTO => "Protocol error",
+ EMULTIHOP => "Multihop attempted",
+ EDOTDOT => "RFS specific error",
+ EBADMSG => "Bad message",
+ EOVERFLOW => "Value too large for defined data type",
+ ENOTUNIQ => "Name not unique on network",
+ EBADFD => "File descriptor in bad state",
+ EREMCHG => "Remote address changed",
+ ELIBACC => "Can not access a needed shared library",
+ ELIBBAD => "Accessing a corrupted shared library",
+ ELIBSCN => ".lib section in a.out corrupted",
+ ELIBMAX => "Attempting to link in too many shared libraries",
+ ELIBEXEC => "Cannot exec a shared library directly",
+ EILSEQ => "Invalid or incomplete multibyte or wide character",
+ ERESTART => "Interrupted system call should be restarted",
+ ESTRPIPE => "Streams pipe error",
+ EUSERS => "Too many users",
+ ENOTSOCK => "Socket operation on non-socket",
+ EDESTADDRREQ => "Destination address required",
+ EMSGSIZE => "Message too long",
+ EPROTOTYPE => "Protocol wrong type for socket",
+ ENOPROTOOPT => "Protocol not available",
+ EPROTONOSUPPORT => "Protocol not supported",
+ ESOCKTNOSUPPORT => "Socket type not supported",
+ EOPNOTSUPP => "Operation not supported",
+ EPFNOSUPPORT => "Protocol family not supported",
+ EAFNOSUPPORT => "Address family not supported by protocol",
+ EADDRINUSE => "Address already in use",
+ EADDRNOTAVAIL => "Cannot assign requested address",
+ ENETDOWN => "Network is down",
+ ENETUNREACH => "Network is unreachable",
+ ENETRESET => "Network dropped connection on reset",
+ ECONNABORTED => "Software caused connection abort",
+ ECONNRESET => "Connection reset by peer",
+ ENOBUFS => "No buffer space available",
+ EISCONN => "Transport endpoint is already connected",
+ ENOTCONN => "Transport endpoint is not connected",
+ ESHUTDOWN => "Cannot send after transport endpoint shutdown",
+ ETOOMANYREFS => "Too many references: cannot splice",
+ ETIMEDOUT => "Connection timed out",
+ ECONNREFUSED => "Connection refused",
+ EHOSTDOWN => "Host is down",
+ EHOSTUNREACH => "No route to host",
+ EALREADY => "Operation already in progress",
+ EINPROGRESS => "Operation now in progress",
+ ESTALE => "Stale file handle",
+ EUCLEAN => "Structure needs cleaning",
+ ENOTNAM => "Not a XENIX named type file",
+ ENAVAIL => "No XENIX semaphores available",
+ EISNAM => "Is a named type file",
+ EREMOTEIO => "Remote I/O error",
+ EDQUOT => "Disk quota exceeded",
+ ENOMEDIUM => "No medium found",
+ EMEDIUMTYPE => "Wrong medium type",
+ ECANCELED => "Operation canceled",
+ ENOKEY => "Required key not available",
+ EKEYEXPIRED => "Key has expired",
+ EKEYREVOKED => "Key has been revoked",
+ EKEYREJECTED => "Key was rejected by service",
+ EOWNERDEAD => "Owner died",
+ ENOTRECOVERABLE => "State not recoverable",
+ ERFKILL => "Operation not possible due to RF-kill",
+ EHWPOISON => "Memory page has hardware error",
+ * => "Unknown Linux error code", // TODO: snprintf to add errno?
+ };
+};
+
+// Gets the programmer-friendly name for an [errno] (e.g. EPERM).
+export fn errname(err: errno) str = {
+ return switch (err: int) {
+ EPERM => "EPERM",
+ ENOENT => "ENOENT",
+ ESRCH => "ESRCH",
+ EINTR => "EINTR",
+ EIO => "EIO",
+ ENXIO => "ENXIO",
+ E2BIG => "E2BIG",
+ ENOEXEC => "ENOEXEC",
+ EBADF => "EBADF",
+ ECHILD => "ECHILD",
+ EAGAIN => "EAGAIN",
+ ENOMEM => "ENOMEM",
+ EACCES => "EACCES",
+ EFAULT => "EFAULT",
+ ENOTBLK => "ENOTBLK",
+ EBUSY => "EBUSY",
+ EEXIST => "EEXIST",
+ EXDEV => "EXDEV",
+ ENODEV => "ENODEV",
+ ENOTDIR => "ENOTDIR",
+ EISDIR => "EISDIR",
+ EINVAL => "EINVAL",
+ ENFILE => "ENFILE",
+ EMFILE => "EMFILE",
+ ENOTTY => "ENOTTY",
+ ETXTBSY => "ETXTBSY",
+ EFBIG => "EFBIG",
+ ENOSPC => "ENOSPC",
+ ESPIPE => "ESPIPE",
+ EROFS => "EROFS",
+ EMLINK => "EMLINK",
+ EPIPE => "EPIPE",
+ EDOM => "EDOM",
+ ERANGE => "ERANGE",
+ EDEADLK => "EDEADLK",
+ ENAMETOOLONG => "ENAMETOOLONG",
+ ENOLCK => "ENOLCK",
+ ENOSYS => "ENOSYS",
+ ENOTEMPTY => "ENOTEMPTY",
+ ELOOP => "ELOOP",
+ ENOMSG => "ENOMSG",
+ EIDRM => "EIDRM",
+ ECHRNG => "ECHRNG",
+ EL2NSYNC => "EL2NSYNC",
+ EL3HLT => "EL3HLT",
+ EL3RST => "EL3RST",
+ ELNRNG => "ELNRNG",
+ EUNATCH => "EUNATCH",
+ ENOCSI => "ENOCSI",
+ EL2HLT => "EL2HLT",
+ EBADE => "EBADE",
+ EBADR => "EBADR",
+ EXFULL => "EXFULL",
+ ENOANO => "ENOANO",
+ EBADRQC => "EBADRQC",
+ EBADSLT => "EBADSLT",
+ EBFONT => "EBFONT",
+ ENOSTR => "ENOSTR",
+ ENODATA => "ENODATA",
+ ETIME => "ETIME",
+ ENOSR => "ENOSR",
+ ENONET => "ENONET",
+ ENOPKG => "ENOPKG",
+ EREMOTE => "EREMOTE",
+ ENOLINK => "ENOLINK",
+ EADV => "EADV",
+ ESRMNT => "ESRMNT",
+ ECOMM => "ECOMM",
+ EPROTO => "EPROTO",
+ EMULTIHOP => "EMULTIHOP",
+ EDOTDOT => "EDOTDOT",
+ EBADMSG => "EBADMSG",
+ EOVERFLOW => "EOVERFLOW",
+ ENOTUNIQ => "ENOTUNIQ",
+ EBADFD => "EBADFD",
+ EREMCHG => "EREMCHG",
+ ELIBACC => "ELIBACC",
+ ELIBBAD => "ELIBBAD",
+ ELIBSCN => "ELIBSCN",
+ ELIBMAX => "ELIBMAX",
+ ELIBEXEC => "ELIBEXEC",
+ EILSEQ => "EILSEQ",
+ ERESTART => "ERESTART",
+ ESTRPIPE => "ESTRPIPE",
+ EUSERS => "EUSERS",
+ ENOTSOCK => "ENOTSOCK",
+ EDESTADDRREQ => "EDESTADDRREQ",
+ EMSGSIZE => "EMSGSIZE",
+ EPROTOTYPE => "EPROTOTYPE",
+ ENOPROTOOPT => "ENOPROTOOPT",
+ EPROTONOSUPPORT => "EPROTONOSUPPORT",
+ ESOCKTNOSUPPORT => "ESOCKTNOSUPPORT",
+ EOPNOTSUPP => "EOPNOTSUPP",
+ EPFNOSUPPORT => "EPFNOSUPPORT",
+ EAFNOSUPPORT => "EAFNOSUPPORT",
+ EADDRINUSE => "EADDRINUSE",
+ EADDRNOTAVAIL => "EADDRNOTAVAIL",
+ ENETDOWN => "ENETDOWN",
+ ENETUNREACH => "ENETUNREACH",
+ ENETRESET => "ENETRESET",
+ ECONNABORTED => "ECONNABORTED",
+ ECONNRESET => "ECONNRESET",
+ ENOBUFS => "ENOBUFS",
+ EISCONN => "EISCONN",
+ ENOTCONN => "ENOTCONN",
+ ESHUTDOWN => "ESHUTDOWN",
+ ETOOMANYREFS => "ETOOMANYREFS",
+ ETIMEDOUT => "ETIMEDOUT",
+ ECONNREFUSED => "ECONNREFUSED",
+ EHOSTDOWN => "EHOSTDOWN",
+ EHOSTUNREACH => "EHOSTUNREACH",
+ EALREADY => "EALREADY",
+ EINPROGRESS => "EINPROGRESS",
+ ESTALE => "ESTALE",
+ EUCLEAN => "EUCLEAN",
+ ENOTNAM => "ENOTNAM",
+ ENAVAIL => "ENAVAIL",
+ EISNAM => "EISNAM",
+ EREMOTEIO => "EREMOTEIO",
+ EDQUOT => "EDQUOT",
+ ENOMEDIUM => "ENOMEDIUM",
+ EMEDIUMTYPE => "EMEDIUMTYPE",
+ ECANCELED => "ECANCELED",
+ ENOKEY => "ENOKEY",
+ EKEYEXPIRED => "EKEYEXPIRED",
+ EKEYREVOKED => "EKEYREVOKED",
+ EKEYREJECTED => "EKEYREJECTED",
+ EOWNERDEAD => "EOWNERDEAD",
+ ENOTRECOVERABLE => "ENOTRECOVERABLE",
+ ERFKILL => "ERFKILL",
+ EHWPOISON => "EHWPOISON",
+ * => "[unknown errno]", // TODO: snprintf to add errno?
+ };
+};
+
export def EPERM: int = 1;
export def ENOENT: int = 2;
export def ESRCH: int = 3;