|
@@ -20,148 +20,148 @@ import "base:intrinsics"
|
|
|
// all that about compatibility. But we don't want to push experimental changes
|
|
|
// and have people's code break while it's still work in progress.
|
|
|
import unix "core:sys/unix"
|
|
|
+import linux "core:sys/linux"
|
|
|
|
|
|
Handle :: distinct i32
|
|
|
Pid :: distinct i32
|
|
|
File_Time :: distinct u64
|
|
|
-Errno :: distinct i32
|
|
|
Socket :: distinct int
|
|
|
|
|
|
INVALID_HANDLE :: ~Handle(0)
|
|
|
|
|
|
-ERROR_NONE: Errno : 0
|
|
|
-EPERM: Errno : 1
|
|
|
-ENOENT: Errno : 2
|
|
|
-ESRCH: Errno : 3
|
|
|
-EINTR: Errno : 4
|
|
|
-EIO: Errno : 5
|
|
|
-ENXIO: Errno : 6
|
|
|
-EBADF: Errno : 9
|
|
|
-EAGAIN: Errno : 11
|
|
|
-ENOMEM: Errno : 12
|
|
|
-EACCES: Errno : 13
|
|
|
-EFAULT: Errno : 14
|
|
|
-EEXIST: Errno : 17
|
|
|
-ENODEV: Errno : 19
|
|
|
-ENOTDIR: Errno : 20
|
|
|
-EISDIR: Errno : 21
|
|
|
-EINVAL: Errno : 22
|
|
|
-ENFILE: Errno : 23
|
|
|
-EMFILE: Errno : 24
|
|
|
-ETXTBSY: Errno : 26
|
|
|
-EFBIG: Errno : 27
|
|
|
-ENOSPC: Errno : 28
|
|
|
-ESPIPE: Errno : 29
|
|
|
-EROFS: Errno : 30
|
|
|
-EPIPE: Errno : 32
|
|
|
-
|
|
|
-ERANGE: Errno : 34 /* Result too large */
|
|
|
-EDEADLK: Errno : 35 /* Resource deadlock would occur */
|
|
|
-ENAMETOOLONG: Errno : 36 /* File name too long */
|
|
|
-ENOLCK: Errno : 37 /* No record locks available */
|
|
|
-
|
|
|
-ENOSYS: Errno : 38 /* Invalid system call number */
|
|
|
-
|
|
|
-ENOTEMPTY: Errno : 39 /* Directory not empty */
|
|
|
-ELOOP: Errno : 40 /* Too many symbolic links encountered */
|
|
|
-EWOULDBLOCK: Errno : EAGAIN /* Operation would block */
|
|
|
-ENOMSG: Errno : 42 /* No message of desired type */
|
|
|
-EIDRM: Errno : 43 /* Identifier removed */
|
|
|
-ECHRNG: Errno : 44 /* Channel number out of range */
|
|
|
-EL2NSYNC: Errno : 45 /* Level 2 not synchronized */
|
|
|
-EL3HLT: Errno : 46 /* Level 3 halted */
|
|
|
-EL3RST: Errno : 47 /* Level 3 reset */
|
|
|
-ELNRNG: Errno : 48 /* Link number out of range */
|
|
|
-EUNATCH: Errno : 49 /* Protocol driver not attached */
|
|
|
-ENOCSI: Errno : 50 /* No CSI structure available */
|
|
|
-EL2HLT: Errno : 51 /* Level 2 halted */
|
|
|
-EBADE: Errno : 52 /* Invalid exchange */
|
|
|
-EBADR: Errno : 53 /* Invalid request descriptor */
|
|
|
-EXFULL: Errno : 54 /* Exchange full */
|
|
|
-ENOANO: Errno : 55 /* No anode */
|
|
|
-EBADRQC: Errno : 56 /* Invalid request code */
|
|
|
-EBADSLT: Errno : 57 /* Invalid slot */
|
|
|
-EDEADLOCK: Errno : EDEADLK
|
|
|
-EBFONT: Errno : 59 /* Bad font file format */
|
|
|
-ENOSTR: Errno : 60 /* Device not a stream */
|
|
|
-ENODATA: Errno : 61 /* No data available */
|
|
|
-ETIME: Errno : 62 /* Timer expired */
|
|
|
-ENOSR: Errno : 63 /* Out of streams resources */
|
|
|
-ENONET: Errno : 64 /* Machine is not on the network */
|
|
|
-ENOPKG: Errno : 65 /* Package not installed */
|
|
|
-EREMOTE: Errno : 66 /* Object is remote */
|
|
|
-ENOLINK: Errno : 67 /* Link has been severed */
|
|
|
-EADV: Errno : 68 /* Advertise error */
|
|
|
-ESRMNT: Errno : 69 /* Srmount error */
|
|
|
-ECOMM: Errno : 70 /* Communication error on send */
|
|
|
-EPROTO: Errno : 71 /* Protocol error */
|
|
|
-EMULTIHOP: Errno : 72 /* Multihop attempted */
|
|
|
-EDOTDOT: Errno : 73 /* RFS specific error */
|
|
|
-EBADMSG: Errno : 74 /* Not a data message */
|
|
|
-EOVERFLOW: Errno : 75 /* Value too large for defined data type */
|
|
|
-ENOTUNIQ: Errno : 76 /* Name not unique on network */
|
|
|
-EBADFD: Errno : 77 /* File descriptor in bad state */
|
|
|
-EREMCHG: Errno : 78 /* Remote address changed */
|
|
|
-ELIBACC: Errno : 79 /* Can not access a needed shared library */
|
|
|
-ELIBBAD: Errno : 80 /* Accessing a corrupted shared library */
|
|
|
-ELIBSCN: Errno : 81 /* .lib section in a.out corrupted */
|
|
|
-ELIBMAX: Errno : 82 /* Attempting to link in too many shared libraries */
|
|
|
-ELIBEXEC: Errno : 83 /* Cannot exec a shared library directly */
|
|
|
-EILSEQ: Errno : 84 /* Illegal byte sequence */
|
|
|
-ERESTART: Errno : 85 /* Interrupted system call should be restarted */
|
|
|
-ESTRPIPE: Errno : 86 /* Streams pipe error */
|
|
|
-EUSERS: Errno : 87 /* Too many users */
|
|
|
-ENOTSOCK: Errno : 88 /* Socket operation on non-socket */
|
|
|
-EDESTADDRREQ: Errno : 89 /* Destination address required */
|
|
|
-EMSGSIZE: Errno : 90 /* Message too long */
|
|
|
-EPROTOTYPE: Errno : 91 /* Protocol wrong type for socket */
|
|
|
-ENOPROTOOPT: Errno : 92 /* Protocol not available */
|
|
|
-EPROTONOSUPPORT:Errno : 93 /* Protocol not supported */
|
|
|
-ESOCKTNOSUPPORT:Errno : 94 /* Socket type not supported */
|
|
|
-EOPNOTSUPP: Errno : 95 /* Operation not supported on transport endpoint */
|
|
|
-EPFNOSUPPORT: Errno : 96 /* Protocol family not supported */
|
|
|
-EAFNOSUPPORT: Errno : 97 /* Address family not supported by protocol */
|
|
|
-EADDRINUSE: Errno : 98 /* Address already in use */
|
|
|
-EADDRNOTAVAIL: Errno : 99 /* Cannot assign requested address */
|
|
|
-ENETDOWN: Errno : 100 /* Network is down */
|
|
|
-ENETUNREACH: Errno : 101 /* Network is unreachable */
|
|
|
-ENETRESET: Errno : 102 /* Network dropped connection because of reset */
|
|
|
-ECONNABORTED: Errno : 103 /* Software caused connection abort */
|
|
|
-ECONNRESET: Errno : 104 /* Connection reset by peer */
|
|
|
-ENOBUFS: Errno : 105 /* No buffer space available */
|
|
|
-EISCONN: Errno : 106 /* Transport endpoint is already connected */
|
|
|
-ENOTCONN: Errno : 107 /* Transport endpoint is not connected */
|
|
|
-ESHUTDOWN: Errno : 108 /* Cannot send after transport endpoint shutdown */
|
|
|
-ETOOMANYREFS: Errno : 109 /* Too many references: cannot splice */
|
|
|
-ETIMEDOUT: Errno : 110 /* Connection timed out */
|
|
|
-ECONNREFUSED: Errno : 111 /* Connection refused */
|
|
|
-EHOSTDOWN: Errno : 112 /* Host is down */
|
|
|
-EHOSTUNREACH: Errno : 113 /* No route to host */
|
|
|
-EALREADY: Errno : 114 /* Operation already in progress */
|
|
|
-EINPROGRESS: Errno : 115 /* Operation now in progress */
|
|
|
-ESTALE: Errno : 116 /* Stale file handle */
|
|
|
-EUCLEAN: Errno : 117 /* Structure needs cleaning */
|
|
|
-ENOTNAM: Errno : 118 /* Not a XENIX named type file */
|
|
|
-ENAVAIL: Errno : 119 /* No XENIX semaphores available */
|
|
|
-EISNAM: Errno : 120 /* Is a named type file */
|
|
|
-EREMOTEIO: Errno : 121 /* Remote I/O error */
|
|
|
-EDQUOT: Errno : 122 /* Quota exceeded */
|
|
|
-
|
|
|
-ENOMEDIUM: Errno : 123 /* No medium found */
|
|
|
-EMEDIUMTYPE: Errno : 124 /* Wrong medium type */
|
|
|
-ECANCELED: Errno : 125 /* Operation Canceled */
|
|
|
-ENOKEY: Errno : 126 /* Required key not available */
|
|
|
-EKEYEXPIRED: Errno : 127 /* Key has expired */
|
|
|
-EKEYREVOKED: Errno : 128 /* Key has been revoked */
|
|
|
-EKEYREJECTED: Errno : 129 /* Key was rejected by service */
|
|
|
+_Platform_Error :: linux.Errno
|
|
|
+EPERM :: Platform_Error.EPERM
|
|
|
+ENOENT :: Platform_Error.ENOENT
|
|
|
+ESRCH :: Platform_Error.ESRCH
|
|
|
+EINTR :: Platform_Error.EINTR
|
|
|
+EIO :: Platform_Error.EIO
|
|
|
+ENXIO :: Platform_Error.ENXIO
|
|
|
+EBADF :: Platform_Error.EBADF
|
|
|
+EAGAIN :: Platform_Error.EAGAIN
|
|
|
+ENOMEM :: Platform_Error.ENOMEM
|
|
|
+EACCES :: Platform_Error.EACCES
|
|
|
+EFAULT :: Platform_Error.EFAULT
|
|
|
+EEXIST :: Platform_Error.EEXIST
|
|
|
+ENODEV :: Platform_Error.ENODEV
|
|
|
+ENOTDIR :: Platform_Error.ENOTDIR
|
|
|
+EISDIR :: Platform_Error.EISDIR
|
|
|
+EINVAL :: Platform_Error.EINVAL
|
|
|
+ENFILE :: Platform_Error.ENFILE
|
|
|
+EMFILE :: Platform_Error.EMFILE
|
|
|
+ETXTBSY :: Platform_Error.ETXTBSY
|
|
|
+EFBIG :: Platform_Error.EFBIG
|
|
|
+ENOSPC :: Platform_Error.ENOSPC
|
|
|
+ESPIPE :: Platform_Error.ESPIPE
|
|
|
+EROFS :: Platform_Error.EROFS
|
|
|
+EPIPE :: Platform_Error.EPIPE
|
|
|
+
|
|
|
+ERANGE :: Platform_Error.ERANGE /* Result too large */
|
|
|
+EDEADLK :: Platform_Error.EDEADLK /* Resource deadlock would occur */
|
|
|
+ENAMETOOLONG :: Platform_Error.ENAMETOOLONG /* File name too long */
|
|
|
+ENOLCK :: Platform_Error.ENOLCK /* No record locks available */
|
|
|
+
|
|
|
+ENOSYS :: Platform_Error.ENOSYS /* Invalid system call number */
|
|
|
+
|
|
|
+ENOTEMPTY :: Platform_Error.ENOTEMPTY /* Directory not empty */
|
|
|
+ELOOP :: Platform_Error.ELOOP /* Too many symbolic links encountered */
|
|
|
+EWOULDBLOCK :: Platform_Error.EWOULDBLOCK /* Operation would block */
|
|
|
+ENOMSG :: Platform_Error.ENOMSG /* No message of desired type */
|
|
|
+EIDRM :: Platform_Error.EIDRM /* Identifier removed */
|
|
|
+ECHRNG :: Platform_Error.ECHRNG /* Channel number out of range */
|
|
|
+EL2NSYNC :: Platform_Error.EL2NSYNC /* Level 2 not synchronized */
|
|
|
+EL3HLT :: Platform_Error.EL3HLT /* Level 3 halted */
|
|
|
+EL3RST :: Platform_Error.EL3RST /* Level 3 reset */
|
|
|
+ELNRNG :: Platform_Error.ELNRNG /* Link number out of range */
|
|
|
+EUNATCH :: Platform_Error.EUNATCH /* Protocol driver not attached */
|
|
|
+ENOCSI :: Platform_Error.ENOCSI /* No CSI structure available */
|
|
|
+EL2HLT :: Platform_Error.EL2HLT /* Level 2 halted */
|
|
|
+EBADE :: Platform_Error.EBADE /* Invalid exchange */
|
|
|
+EBADR :: Platform_Error.EBADR /* Invalid request descriptor */
|
|
|
+EXFULL :: Platform_Error.EXFULL /* Exchange full */
|
|
|
+ENOANO :: Platform_Error.ENOANO /* No anode */
|
|
|
+EBADRQC :: Platform_Error.EBADRQC /* Invalid request code */
|
|
|
+EBADSLT :: Platform_Error.EBADSLT /* Invalid slot */
|
|
|
+EDEADLOCK :: Platform_Error.EDEADLOCK
|
|
|
+EBFONT :: Platform_Error.EBFONT /* Bad font file format */
|
|
|
+ENOSTR :: Platform_Error.ENOSTR /* Device not a stream */
|
|
|
+ENODATA :: Platform_Error.ENODATA /* No data available */
|
|
|
+ETIME :: Platform_Error.ETIME /* Timer expired */
|
|
|
+ENOSR :: Platform_Error.ENOSR /* Out of streams resources */
|
|
|
+ENONET :: Platform_Error.ENONET /* Machine is not on the network */
|
|
|
+ENOPKG :: Platform_Error.ENOPKG /* Package not installed */
|
|
|
+EREMOTE :: Platform_Error.EREMOTE /* Object is remote */
|
|
|
+ENOLINK :: Platform_Error.ENOLINK /* Link has been severed */
|
|
|
+EADV :: Platform_Error.EADV /* Advertise error */
|
|
|
+ESRMNT :: Platform_Error.ESRMNT /* Srmount error */
|
|
|
+ECOMM :: Platform_Error.ECOMM /* Communication error on send */
|
|
|
+EPROTO :: Platform_Error.EPROTO /* Protocol error */
|
|
|
+EMULTIHOP :: Platform_Error.EMULTIHOP /* Multihop attempted */
|
|
|
+EDOTDOT :: Platform_Error.EDOTDOT /* RFS specific error */
|
|
|
+EBADMSG :: Platform_Error.EBADMSG /* Not a data message */
|
|
|
+EOVERFLOW :: Platform_Error.EOVERFLOW /* Value too large for defined data type */
|
|
|
+ENOTUNIQ :: Platform_Error.ENOTUNIQ /* Name not unique on network */
|
|
|
+EBADFD :: Platform_Error.EBADFD /* File descriptor in bad state */
|
|
|
+EREMCHG :: Platform_Error.EREMCHG /* Remote address changed */
|
|
|
+ELIBACC :: Platform_Error.ELIBACC /* Can not access a needed shared library */
|
|
|
+ELIBBAD :: Platform_Error.ELIBBAD /* Accessing a corrupted shared library */
|
|
|
+ELIBSCN :: Platform_Error.ELIBSCN /* .lib section in a.out corrupted */
|
|
|
+ELIBMAX :: Platform_Error.ELIBMAX /* Attempting to link in too many shared libraries */
|
|
|
+ELIBEXEC :: Platform_Error.ELIBEXEC /* Cannot exec a shared library directly */
|
|
|
+EILSEQ :: Platform_Error.EILSEQ /* Illegal byte sequence */
|
|
|
+ERESTART :: Platform_Error.ERESTART /* Interrupted system call should be restarted */
|
|
|
+ESTRPIPE :: Platform_Error.ESTRPIPE /* Streams pipe error */
|
|
|
+EUSERS :: Platform_Error.EUSERS /* Too many users */
|
|
|
+ENOTSOCK :: Platform_Error.ENOTSOCK /* Socket operation on non-socket */
|
|
|
+EDESTADDRREQ :: Platform_Error.EDESTADDRREQ /* Destination address required */
|
|
|
+EMSGSIZE :: Platform_Error.EMSGSIZE /* Message too long */
|
|
|
+EPROTOTYPE :: Platform_Error.EPROTOTYPE /* Protocol wrong type for socket */
|
|
|
+ENOPROTOOPT :: Platform_Error.ENOPROTOOPT /* Protocol not available */
|
|
|
+EPROTONOSUPPOR :: Platform_Error.EPROTONOSUPPORT /* Protocol not supported */
|
|
|
+ESOCKTNOSUPPOR :: Platform_Error.ESOCKTNOSUPPORT /* Socket type not supported */
|
|
|
+EOPNOTSUPP :: Platform_Error.EOPNOTSUPP /* Operation not supported on transport endpoint */
|
|
|
+EPFNOSUPPORT :: Platform_Error.EPFNOSUPPORT /* Protocol family not supported */
|
|
|
+EAFNOSUPPORT :: Platform_Error.EAFNOSUPPORT /* Address family not supported by protocol */
|
|
|
+EADDRINUSE :: Platform_Error.EADDRINUSE /* Address already in use */
|
|
|
+EADDRNOTAVAIL :: Platform_Error.EADDRNOTAVAIL /* Cannot assign requested address */
|
|
|
+ENETDOWN :: Platform_Error.ENETDOWN /* Network is down */
|
|
|
+ENETUNREACH :: Platform_Error.ENETUNREACH /* Network is unreachable */
|
|
|
+ENETRESET :: Platform_Error.ENETRESET /* Network dropped connection because of reset */
|
|
|
+ECONNABORTED :: Platform_Error.ECONNABORTED /* Software caused connection abort */
|
|
|
+ECONNRESET :: Platform_Error.ECONNRESET /* Connection reset by peer */
|
|
|
+ENOBUFS :: Platform_Error.ENOBUFS /* No buffer space available */
|
|
|
+EISCONN :: Platform_Error.EISCONN /* Transport endpoint is already connected */
|
|
|
+ENOTCONN :: Platform_Error.ENOTCONN /* Transport endpoint is not connected */
|
|
|
+ESHUTDOWN :: Platform_Error.ESHUTDOWN /* Cannot send after transport endpoint shutdown */
|
|
|
+ETOOMANYREFS :: Platform_Error.ETOOMANYREFS /* Too many references: cannot splice */
|
|
|
+ETIMEDOUT :: Platform_Error.ETIMEDOUT /* Connection timed out */
|
|
|
+ECONNREFUSED :: Platform_Error.ECONNREFUSED /* Connection refused */
|
|
|
+EHOSTDOWN :: Platform_Error.EHOSTDOWN /* Host is down */
|
|
|
+EHOSTUNREACH :: Platform_Error.EHOSTUNREACH /* No route to host */
|
|
|
+EALREADY :: Platform_Error.EALREADY /* Operation already in progress */
|
|
|
+EINPROGRESS :: Platform_Error.EINPROGRESS /* Operation now in progress */
|
|
|
+ESTALE :: Platform_Error.ESTALE /* Stale file handle */
|
|
|
+EUCLEAN :: Platform_Error.EUCLEAN /* Structure needs cleaning */
|
|
|
+ENOTNAM :: Platform_Error.ENOTNAM /* Not a XENIX named type file */
|
|
|
+ENAVAIL :: Platform_Error.ENAVAIL /* No XENIX semaphores available */
|
|
|
+EISNAM :: Platform_Error.EISNAM /* Is a named type file */
|
|
|
+EREMOTEIO :: Platform_Error.EREMOTEIO /* Remote I/O error */
|
|
|
+EDQUOT :: Platform_Error.EDQUOT /* Quota exceeded */
|
|
|
+
|
|
|
+ENOMEDIUM :: Platform_Error.ENOMEDIUM /* No medium found */
|
|
|
+EMEDIUMTYPE :: Platform_Error.EMEDIUMTYPE /* Wrong medium type */
|
|
|
+ECANCELED :: Platform_Error.ECANCELED /* Operation Canceled */
|
|
|
+ENOKEY :: Platform_Error.ENOKEY /* Required key not available */
|
|
|
+EKEYEXPIRED :: Platform_Error.EKEYEXPIRED /* Key has expired */
|
|
|
+EKEYREVOKED :: Platform_Error.EKEYREVOKED /* Key has been revoked */
|
|
|
+EKEYREJECTED :: Platform_Error.EKEYREJECTED /* Key was rejected by service */
|
|
|
|
|
|
/* for robust mutexes */
|
|
|
-EOWNERDEAD: Errno : 130 /* Owner died */
|
|
|
-ENOTRECOVERABLE: Errno : 131 /* State not recoverable */
|
|
|
+EOWNERDEAD :: Platform_Error.EOWNERDEAD /* Owner died */
|
|
|
+ENOTRECOVERABLE :: Platform_Error.ENOTRECOVERABLE /* State not recoverable */
|
|
|
|
|
|
-ERFKILL: Errno : 132 /* Operation not possible due to RF-kill */
|
|
|
+ERFKILL :: Platform_Error.ERFKILL /* Operation not possible due to RF-kill */
|
|
|
|
|
|
-EHWPOISON: Errno : 133 /* Memory page has hardware error */
|
|
|
+EHWPOISON :: Platform_Error.EHWPOISON /* Memory page has hardware error */
|
|
|
|
|
|
ADDR_NO_RANDOMIZE :: 0x40000
|
|
|
|
|
@@ -448,13 +448,13 @@ S_ISGID :: 0o2000 // Set group id on execution
|
|
|
S_ISVTX :: 0o1000 // Directory restrcted delete
|
|
|
|
|
|
|
|
|
-S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK }
|
|
|
-S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG }
|
|
|
-S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR }
|
|
|
-S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR }
|
|
|
-S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK }
|
|
|
-S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO }
|
|
|
-S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK }
|
|
|
+@(require_results) S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK }
|
|
|
+@(require_results) S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG }
|
|
|
+@(require_results) S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR }
|
|
|
+@(require_results) S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR }
|
|
|
+@(require_results) S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK }
|
|
|
+@(require_results) S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO }
|
|
|
+@(require_results) S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK }
|
|
|
|
|
|
F_OK :: 0 // Test for file existance
|
|
|
X_OK :: 1 // Test for execute permission
|
|
@@ -506,41 +506,55 @@ foreign dl {
|
|
|
@(link_name="freeifaddrs") _freeifaddrs :: proc(ifa: ^ifaddrs) ---
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
is_path_separator :: proc(r: rune) -> bool {
|
|
|
return r == '/'
|
|
|
}
|
|
|
|
|
|
// determine errno from syscall return value
|
|
|
-@private
|
|
|
-_get_errno :: proc(res: int) -> Errno {
|
|
|
+@(private, require_results)
|
|
|
+_get_errno :: proc(res: int) -> Error {
|
|
|
if res < 0 && res > -4096 {
|
|
|
- return Errno(-res)
|
|
|
+ return Platform_Error(-res)
|
|
|
}
|
|
|
- return 0
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
// get errno from libc
|
|
|
-get_last_error :: proc "contextless" () -> int {
|
|
|
- return int(__errno_location()^)
|
|
|
+@(require_results, no_instrumentation)
|
|
|
+get_last_error :: proc "contextless" () -> Error {
|
|
|
+ err := Platform_Error(__errno_location()^)
|
|
|
+ #partial switch err {
|
|
|
+ case .NONE:
|
|
|
+ return nil
|
|
|
+ case .EPERM:
|
|
|
+ return .Permission_Denied
|
|
|
+ case .EEXIST:
|
|
|
+ return .Exist
|
|
|
+ case .ENOENT:
|
|
|
+ return .Not_Exist
|
|
|
+ }
|
|
|
+ return err
|
|
|
}
|
|
|
|
|
|
-personality :: proc(persona: u64) -> (Errno) {
|
|
|
+personality :: proc(persona: u64) -> Error {
|
|
|
res := unix.sys_personality(persona)
|
|
|
if res == -1 {
|
|
|
return _get_errno(res)
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-fork :: proc() -> (Pid, Errno) {
|
|
|
+@(require_results)
|
|
|
+fork :: proc() -> (Pid, Error) {
|
|
|
pid := unix.sys_fork()
|
|
|
if pid == -1 {
|
|
|
return -1, _get_errno(pid)
|
|
|
}
|
|
|
- return Pid(pid), ERROR_NONE
|
|
|
+ return Pid(pid), nil
|
|
|
}
|
|
|
|
|
|
-execvp :: proc(path: string, args: []string) -> Errno {
|
|
|
+execvp :: proc(path: string, args: []string) -> Error {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
|
|
@@ -551,24 +565,30 @@ execvp :: proc(path: string, args: []string) -> Errno {
|
|
|
}
|
|
|
|
|
|
_unix_execvp(path_cstr, raw_data(args_cstrs))
|
|
|
- return Errno(get_last_error())
|
|
|
+ return get_last_error()
|
|
|
}
|
|
|
|
|
|
|
|
|
-open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0o000) -> (Handle, Errno) {
|
|
|
+@(require_results)
|
|
|
+open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0o000) -> (Handle, Error) {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
handle := unix.sys_open(cstr, flags, uint(mode))
|
|
|
if handle < 0 {
|
|
|
return INVALID_HANDLE, _get_errno(handle)
|
|
|
}
|
|
|
- return Handle(handle), ERROR_NONE
|
|
|
+ return Handle(handle), nil
|
|
|
}
|
|
|
|
|
|
-close :: proc(fd: Handle) -> Errno {
|
|
|
+close :: proc(fd: Handle) -> Error {
|
|
|
return _get_errno(unix.sys_close(int(fd)))
|
|
|
}
|
|
|
|
|
|
+flush :: proc(fd: Handle) -> Error {
|
|
|
+ // do nothing
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
// If you read or write more than `SSIZE_MAX` bytes, result is implementation defined (probably an error).
|
|
|
// `SSIZE_MAX` is also implementation defined but usually the max of a `ssize_t` which is `max(int)` in Odin.
|
|
|
// In practice a read/write call would probably never read/write these big buffers all at once,
|
|
@@ -578,9 +598,9 @@ close :: proc(fd: Handle) -> Errno {
|
|
|
@(private)
|
|
|
MAX_RW :: 1 << 30
|
|
|
|
|
|
-read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|
|
+read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
|
|
if len(data) == 0 {
|
|
|
- return 0, ERROR_NONE
|
|
|
+ return 0, nil
|
|
|
}
|
|
|
|
|
|
to_read := min(uint(len(data)), MAX_RW)
|
|
@@ -589,12 +609,12 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|
|
if bytes_read < 0 {
|
|
|
return -1, _get_errno(bytes_read)
|
|
|
}
|
|
|
- return bytes_read, ERROR_NONE
|
|
|
+ return bytes_read, nil
|
|
|
}
|
|
|
|
|
|
-write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|
|
+write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
|
|
if len(data) == 0 {
|
|
|
- return 0, ERROR_NONE
|
|
|
+ return 0, nil
|
|
|
}
|
|
|
|
|
|
to_write := min(uint(len(data)), MAX_RW)
|
|
@@ -603,12 +623,12 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|
|
if bytes_written < 0 {
|
|
|
return -1, _get_errno(bytes_written)
|
|
|
}
|
|
|
- return bytes_written, ERROR_NONE
|
|
|
+ return bytes_written, nil
|
|
|
}
|
|
|
|
|
|
-read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
|
|
+read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
|
|
if len(data) == 0 {
|
|
|
- return 0, ERROR_NONE
|
|
|
+ return 0, nil
|
|
|
}
|
|
|
|
|
|
to_read := min(uint(len(data)), MAX_RW)
|
|
@@ -617,12 +637,12 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
|
|
if bytes_read < 0 {
|
|
|
return -1, _get_errno(bytes_read)
|
|
|
}
|
|
|
- return bytes_read, ERROR_NONE
|
|
|
+ return bytes_read, nil
|
|
|
}
|
|
|
|
|
|
-write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
|
|
+write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
|
|
if len(data) == 0 {
|
|
|
- return 0, ERROR_NONE
|
|
|
+ return 0, nil
|
|
|
}
|
|
|
|
|
|
to_write := min(uint(len(data)), MAX_RW)
|
|
@@ -631,92 +651,97 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
|
|
if bytes_written < 0 {
|
|
|
return -1, _get_errno(bytes_written)
|
|
|
}
|
|
|
- return bytes_written, ERROR_NONE
|
|
|
+ return bytes_written, nil
|
|
|
}
|
|
|
|
|
|
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
|
|
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
|
|
res := unix.sys_lseek(int(fd), offset, whence)
|
|
|
if res < 0 {
|
|
|
return -1, _get_errno(int(res))
|
|
|
}
|
|
|
- return i64(res), ERROR_NONE
|
|
|
+ return i64(res), nil
|
|
|
}
|
|
|
|
|
|
-file_size :: proc(fd: Handle) -> (i64, Errno) {
|
|
|
+@(require_results)
|
|
|
+file_size :: proc(fd: Handle) -> (i64, Error) {
|
|
|
// deliberately uninitialized; the syscall fills this buffer for us
|
|
|
s: OS_Stat = ---
|
|
|
result := unix.sys_fstat(int(fd), rawptr(&s))
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(result)
|
|
|
}
|
|
|
- return max(s.size, 0), ERROR_NONE
|
|
|
+ return max(s.size, 0), nil
|
|
|
}
|
|
|
|
|
|
-rename :: proc(old_path, new_path: string) -> Errno {
|
|
|
+rename :: proc(old_path, new_path: string) -> Error {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator)
|
|
|
new_path_cstr := strings.clone_to_cstring(new_path, context.temp_allocator)
|
|
|
return _get_errno(unix.sys_rename(old_path_cstr, new_path_cstr))
|
|
|
}
|
|
|
|
|
|
-remove :: proc(path: string) -> Errno {
|
|
|
+remove :: proc(path: string) -> Error {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
return _get_errno(unix.sys_unlink(path_cstr))
|
|
|
}
|
|
|
|
|
|
-make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
|
|
|
+make_directory :: proc(path: string, mode: u32 = 0o775) -> Error {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
return _get_errno(unix.sys_mkdir(path_cstr, uint(mode)))
|
|
|
}
|
|
|
|
|
|
-remove_directory :: proc(path: string) -> Errno {
|
|
|
+remove_directory :: proc(path: string) -> Error {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
return _get_errno(unix.sys_rmdir(path_cstr))
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
is_file_handle :: proc(fd: Handle) -> bool {
|
|
|
s, err := _fstat(fd)
|
|
|
- if err != ERROR_NONE {
|
|
|
+ if err != nil {
|
|
|
return false
|
|
|
}
|
|
|
return S_ISREG(s.mode)
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
|
|
s: OS_Stat
|
|
|
- err: Errno
|
|
|
+ err: Error
|
|
|
if follow_links {
|
|
|
s, err = _stat(path)
|
|
|
} else {
|
|
|
s, err = _lstat(path)
|
|
|
}
|
|
|
- if err != ERROR_NONE {
|
|
|
+ if err != nil {
|
|
|
return false
|
|
|
}
|
|
|
return S_ISREG(s.mode)
|
|
|
}
|
|
|
|
|
|
|
|
|
+@(require_results)
|
|
|
is_dir_handle :: proc(fd: Handle) -> bool {
|
|
|
s, err := _fstat(fd)
|
|
|
- if err != ERROR_NONE {
|
|
|
+ if err != nil {
|
|
|
return false
|
|
|
}
|
|
|
return S_ISDIR(s.mode)
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
|
|
s: OS_Stat
|
|
|
- err: Errno
|
|
|
+ err: Error
|
|
|
if follow_links {
|
|
|
s, err = _stat(path)
|
|
|
} else {
|
|
|
s, err = _lstat(path)
|
|
|
}
|
|
|
- if err != ERROR_NONE {
|
|
|
+ if err != nil {
|
|
|
return false
|
|
|
}
|
|
|
return S_ISDIR(s.mode)
|
|
@@ -725,6 +750,7 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
|
|
is_file :: proc {is_file_path, is_file_handle}
|
|
|
is_dir :: proc {is_dir_path, is_dir_handle}
|
|
|
|
|
|
+@(require_results)
|
|
|
exists :: proc(path: string) -> bool {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
cpath := strings.clone_to_cstring(path, context.temp_allocator)
|
|
@@ -742,26 +768,22 @@ stderr: Handle = 2
|
|
|
last_write_time :: proc(fd: Handle) -> File_Time {}
|
|
|
last_write_time_by_name :: proc(name: string) -> File_Time {}
|
|
|
*/
|
|
|
-last_write_time :: proc(fd: Handle) -> (File_Time, Errno) {
|
|
|
- s, err := _fstat(fd)
|
|
|
- if err != ERROR_NONE {
|
|
|
- return 0, err
|
|
|
- }
|
|
|
+@(require_results)
|
|
|
+last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) {
|
|
|
+ s := _fstat(fd) or_return
|
|
|
modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds
|
|
|
- return File_Time(modified), ERROR_NONE
|
|
|
+ return File_Time(modified), nil
|
|
|
}
|
|
|
|
|
|
-last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
|
|
|
- s, err := _stat(name)
|
|
|
- if err != ERROR_NONE {
|
|
|
- return 0, err
|
|
|
- }
|
|
|
+@(require_results)
|
|
|
+last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) {
|
|
|
+ s := _stat(name) or_return
|
|
|
modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds
|
|
|
- return File_Time(modified), ERROR_NONE
|
|
|
+ return File_Time(modified), nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
-_stat :: proc(path: string) -> (OS_Stat, Errno) {
|
|
|
+@(private, require_results)
|
|
|
+_stat :: proc(path: string) -> (OS_Stat, Error) {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
|
|
@@ -771,11 +793,11 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
|
|
|
if result < 0 {
|
|
|
return s, _get_errno(result)
|
|
|
}
|
|
|
- return s, ERROR_NONE
|
|
|
+ return s, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
-_lstat :: proc(path: string) -> (OS_Stat, Errno) {
|
|
|
+@(private, require_results)
|
|
|
+_lstat :: proc(path: string) -> (OS_Stat, Error) {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
|
|
@@ -785,53 +807,53 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
|
|
|
if result < 0 {
|
|
|
return s, _get_errno(result)
|
|
|
}
|
|
|
- return s, ERROR_NONE
|
|
|
+ return s, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
-_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
|
|
|
+@(private, require_results)
|
|
|
+_fstat :: proc(fd: Handle) -> (OS_Stat, Error) {
|
|
|
// deliberately uninitialized; the syscall fills this buffer for us
|
|
|
s: OS_Stat = ---
|
|
|
result := unix.sys_fstat(int(fd), rawptr(&s))
|
|
|
if result < 0 {
|
|
|
return s, _get_errno(result)
|
|
|
}
|
|
|
- return s, ERROR_NONE
|
|
|
+ return s, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
-_fdopendir :: proc(fd: Handle) -> (Dir, Errno) {
|
|
|
+@(private, require_results)
|
|
|
+_fdopendir :: proc(fd: Handle) -> (Dir, Error) {
|
|
|
dirp := _unix_fdopendir(fd)
|
|
|
if dirp == cast(Dir)nil {
|
|
|
- return nil, Errno(get_last_error())
|
|
|
+ return nil, get_last_error()
|
|
|
}
|
|
|
- return dirp, ERROR_NONE
|
|
|
+ return dirp, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
-_closedir :: proc(dirp: Dir) -> Errno {
|
|
|
+@(private)
|
|
|
+_closedir :: proc(dirp: Dir) -> Error {
|
|
|
rc := _unix_closedir(dirp)
|
|
|
if rc != 0 {
|
|
|
- return Errno(get_last_error())
|
|
|
+ return get_last_error()
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(private)
|
|
|
_rewinddir :: proc(dirp: Dir) {
|
|
|
_unix_rewinddir(dirp)
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
-_readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Errno, end_of_stream: bool) {
|
|
|
+@(private, require_results)
|
|
|
+_readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) {
|
|
|
result: ^Dirent
|
|
|
rc := _unix_readdir_r(dirp, &entry, &result)
|
|
|
|
|
|
if rc != 0 {
|
|
|
- err = Errno(get_last_error())
|
|
|
+ err = get_last_error()
|
|
|
return
|
|
|
}
|
|
|
- err = ERROR_NONE
|
|
|
+ err = nil
|
|
|
|
|
|
if result == nil {
|
|
|
end_of_stream = true
|
|
@@ -842,8 +864,8 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Errno, end_of_stream: bool)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
-_readlink :: proc(path: string) -> (string, Errno) {
|
|
|
+@(private, require_results)
|
|
|
+_readlink :: proc(path: string) -> (string, Error) {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
|
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
|
|
@@ -860,12 +882,13 @@ _readlink :: proc(path: string) -> (string, Errno) {
|
|
|
delete(buf)
|
|
|
buf = make([]byte, bufsz)
|
|
|
} else {
|
|
|
- return strings.string_from_ptr(&buf[0], rc), ERROR_NONE
|
|
|
+ return strings.string_from_ptr(&buf[0], rc), nil
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
|
|
|
+@(require_results)
|
|
|
+absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
|
|
buf : [256]byte
|
|
|
fd_str := strconv.itoa( buf[:], cast(int)fd )
|
|
|
|
|
@@ -875,7 +898,8 @@ absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
|
|
|
return _readlink(procfs_path)
|
|
|
}
|
|
|
|
|
|
-absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
|
|
|
+@(require_results)
|
|
|
+absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
|
|
rel := rel
|
|
|
if rel == "" {
|
|
|
rel = "."
|
|
@@ -886,25 +910,26 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
|
|
|
|
|
|
path_ptr := _unix_realpath(rel_cstr, nil)
|
|
|
if path_ptr == nil {
|
|
|
- return "", Errno(get_last_error())
|
|
|
+ return "", get_last_error()
|
|
|
}
|
|
|
defer _unix_free(path_ptr)
|
|
|
|
|
|
path = strings.clone(string(cstring(path_ptr)))
|
|
|
|
|
|
- return path, ERROR_NONE
|
|
|
+ return path, nil
|
|
|
}
|
|
|
|
|
|
-access :: proc(path: string, mask: int) -> (bool, Errno) {
|
|
|
+access :: proc(path: string, mask: int) -> (bool, Error) {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
result := unix.sys_access(cstr, mask)
|
|
|
if result < 0 {
|
|
|
return false, _get_errno(result)
|
|
|
}
|
|
|
- return true, ERROR_NONE
|
|
|
+ return true, nil
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator)
|
|
|
path_str := strings.clone_to_cstring(key, context.temp_allocator)
|
|
@@ -916,33 +941,35 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
|
|
|
return strings.clone(string(cstr), allocator), true
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
|
|
value, _ = lookup_env(key, allocator)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-set_env :: proc(key, value: string) -> Errno {
|
|
|
+set_env :: proc(key, value: string) -> Error {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
key_cstring := strings.clone_to_cstring(key, context.temp_allocator)
|
|
|
value_cstring := strings.clone_to_cstring(value, context.temp_allocator)
|
|
|
// NOTE(GoNZooo): `setenv` instead of `putenv` because it copies both key and value more commonly
|
|
|
res := _unix_setenv(key_cstring, value_cstring, 1)
|
|
|
if res < 0 {
|
|
|
- return Errno(get_last_error())
|
|
|
+ return get_last_error()
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-unset_env :: proc(key: string) -> Errno {
|
|
|
+unset_env :: proc(key: string) -> Error {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
s := strings.clone_to_cstring(key, context.temp_allocator)
|
|
|
res := _unix_putenv(s)
|
|
|
if res < 0 {
|
|
|
- return Errno(get_last_error())
|
|
|
+ return get_last_error()
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
get_current_directory :: proc() -> string {
|
|
|
// NOTE(tetra): I would use PATH_MAX here, but I was not able to find
|
|
|
// an authoritative value for it across all systems.
|
|
@@ -964,14 +991,14 @@ get_current_directory :: proc() -> string {
|
|
|
unreachable()
|
|
|
}
|
|
|
|
|
|
-set_current_directory :: proc(path: string) -> (err: Errno) {
|
|
|
+set_current_directory :: proc(path: string) -> (err: Error) {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
|
|
res := unix.sys_chdir(cstr)
|
|
|
if res < 0 {
|
|
|
return _get_errno(res)
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
exit :: proc "contextless" (code: int) -> ! {
|
|
@@ -979,16 +1006,19 @@ exit :: proc "contextless" (code: int) -> ! {
|
|
|
_unix_exit(c.int(code))
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
current_thread_id :: proc "contextless" () -> int {
|
|
|
return unix.sys_gettid()
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
dlopen :: proc(filename: string, flags: int) -> rawptr {
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
|
cstr := strings.clone_to_cstring(filename, context.temp_allocator)
|
|
|
handle := _unix_dlopen(cstr, c.int(flags))
|
|
|
return handle
|
|
|
}
|
|
|
+@(require_results)
|
|
|
dlsym :: proc(handle: rawptr, symbol: string) -> rawptr {
|
|
|
assert(handle != nil)
|
|
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
@@ -1004,6 +1034,7 @@ dlerror :: proc() -> string {
|
|
|
return string(_unix_dlerror())
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
get_page_size :: proc() -> int {
|
|
|
// NOTE(tetra): The page size never changes, so why do anything complicated
|
|
|
// if we don't have to.
|
|
@@ -1016,11 +1047,12 @@ get_page_size :: proc() -> int {
|
|
|
return page_size
|
|
|
}
|
|
|
|
|
|
-@(private)
|
|
|
+@(private, require_results)
|
|
|
_processor_core_count :: proc() -> int {
|
|
|
return int(_unix_get_nprocs())
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
_alloc_command_line_arguments :: proc() -> []string {
|
|
|
res := make([]string, len(runtime.args__))
|
|
|
for arg, i in runtime.args__ {
|
|
@@ -1029,117 +1061,120 @@ _alloc_command_line_arguments :: proc() -> []string {
|
|
|
return res
|
|
|
}
|
|
|
|
|
|
-socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Errno) {
|
|
|
+@(require_results)
|
|
|
+socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) {
|
|
|
result := unix.sys_socket(domain, type, protocol)
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(result)
|
|
|
}
|
|
|
- return Socket(result), ERROR_NONE
|
|
|
+ return Socket(result), nil
|
|
|
}
|
|
|
|
|
|
-bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
|
|
|
+bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error {
|
|
|
result := unix.sys_bind(int(sd), addr, len)
|
|
|
if result < 0 {
|
|
|
return _get_errno(result)
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
|
|
|
-connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
|
|
|
+connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error {
|
|
|
result := unix.sys_connect(int(sd), addr, len)
|
|
|
if result < 0 {
|
|
|
return _get_errno(result)
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-accept :: proc(sd: Socket, addr: ^SOCKADDR, len: rawptr) -> (Socket, Errno) {
|
|
|
+accept :: proc(sd: Socket, addr: ^SOCKADDR, len: rawptr) -> (Socket, Error) {
|
|
|
result := unix.sys_accept(int(sd), rawptr(addr), len)
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(result)
|
|
|
}
|
|
|
- return Socket(result), ERROR_NONE
|
|
|
+ return Socket(result), nil
|
|
|
}
|
|
|
|
|
|
-listen :: proc(sd: Socket, backlog: int) -> (Errno) {
|
|
|
+listen :: proc(sd: Socket, backlog: int) -> Error {
|
|
|
result := unix.sys_listen(int(sd), backlog)
|
|
|
if result < 0 {
|
|
|
return _get_errno(result)
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> (Errno) {
|
|
|
+setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> Error {
|
|
|
result := unix.sys_setsockopt(int(sd), level, optname, optval, optlen)
|
|
|
if result < 0 {
|
|
|
return _get_errno(result)
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
|
|
|
-recvfrom :: proc(sd: Socket, data: []byte, flags: int, addr: ^SOCKADDR, addr_size: ^socklen_t) -> (u32, Errno) {
|
|
|
+recvfrom :: proc(sd: Socket, data: []byte, flags: int, addr: ^SOCKADDR, addr_size: ^socklen_t) -> (u32, Error) {
|
|
|
result := unix.sys_recvfrom(int(sd), raw_data(data), len(data), flags, addr, uintptr(addr_size))
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(int(result))
|
|
|
}
|
|
|
- return u32(result), ERROR_NONE
|
|
|
+ return u32(result), nil
|
|
|
}
|
|
|
|
|
|
-recv :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Errno) {
|
|
|
+recv :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Error) {
|
|
|
result := unix.sys_recvfrom(int(sd), raw_data(data), len(data), flags, nil, 0)
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(int(result))
|
|
|
}
|
|
|
- return u32(result), ERROR_NONE
|
|
|
+ return u32(result), nil
|
|
|
}
|
|
|
|
|
|
|
|
|
-sendto :: proc(sd: Socket, data: []u8, flags: int, addr: ^SOCKADDR, addrlen: socklen_t) -> (u32, Errno) {
|
|
|
+sendto :: proc(sd: Socket, data: []u8, flags: int, addr: ^SOCKADDR, addrlen: socklen_t) -> (u32, Error) {
|
|
|
result := unix.sys_sendto(int(sd), raw_data(data), len(data), flags, addr, addrlen)
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(int(result))
|
|
|
}
|
|
|
- return u32(result), ERROR_NONE
|
|
|
+ return u32(result), nil
|
|
|
}
|
|
|
|
|
|
-send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Errno) {
|
|
|
+send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Error) {
|
|
|
result := unix.sys_sendto(int(sd), raw_data(data), len(data), 0, nil, 0)
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(int(result))
|
|
|
}
|
|
|
- return u32(result), ERROR_NONE
|
|
|
+ return u32(result), nil
|
|
|
}
|
|
|
|
|
|
-shutdown :: proc(sd: Socket, how: int) -> (Errno) {
|
|
|
+shutdown :: proc(sd: Socket, how: int) -> Error {
|
|
|
result := unix.sys_shutdown(int(sd), how)
|
|
|
if result < 0 {
|
|
|
return _get_errno(result)
|
|
|
}
|
|
|
- return ERROR_NONE
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) {
|
|
|
+fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Error) {
|
|
|
result := unix.sys_fcntl(fd, cmd, arg)
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(result)
|
|
|
}
|
|
|
- return result, ERROR_NONE
|
|
|
+ return result, nil
|
|
|
}
|
|
|
|
|
|
-poll :: proc(fds: []pollfd, timeout: int) -> (int, Errno) {
|
|
|
+@(require_results)
|
|
|
+poll :: proc(fds: []pollfd, timeout: int) -> (int, Error) {
|
|
|
result := unix.sys_poll(raw_data(fds), uint(len(fds)), timeout)
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(result)
|
|
|
}
|
|
|
- return result, ERROR_NONE
|
|
|
+ return result, nil
|
|
|
}
|
|
|
|
|
|
-ppoll :: proc(fds: []pollfd, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Errno) {
|
|
|
+@(require_results)
|
|
|
+ppoll :: proc(fds: []pollfd, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Error) {
|
|
|
result := unix.sys_ppoll(raw_data(fds), uint(len(fds)), timeout, sigmask, size_of(sigset_t))
|
|
|
if result < 0 {
|
|
|
return 0, _get_errno(result)
|
|
|
}
|
|
|
- return result, ERROR_NONE
|
|
|
+ return result, nil
|
|
|
}
|