aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2024-08-04 15:53:18 +0100
committerGitHub <noreply@github.com>2024-08-04 15:53:18 +0100
commitf427f040fd83f5db411396bd4d4eae6f39c26de7 (patch)
tree0ee1feef26570f195a8d0d00d0266edc028dbfec /core
parent71932628cc3c1957a98e998740b059df9b7dd392 (diff)
parentc078b2dd1be617e6687a3a5ffc919a45bbabb5bf (diff)
Merge pull request #4020 from odin-lang/bill/os-errno
`os.Error` to replace `os.Errno`
Diffstat (limited to 'core')
-rw-r--r--core/crypto/rand_windows.odin6
-rw-r--r--core/encoding/csv/example.odin6
-rw-r--r--core/flags/errors.odin2
-rw-r--r--core/flags/internal_rtti.odin4
-rw-r--r--core/image/general_os.odin2
-rw-r--r--core/image/png/example.odin2
-rw-r--r--core/image/png/helpers.odin2
-rw-r--r--core/mem/virtual/file.odin4
-rw-r--r--core/net/socket_darwin.odin64
-rw-r--r--core/os/dir_unix.odin27
-rw-r--r--core/os/dir_windows.odin21
-rw-r--r--core/os/env_windows.odin38
-rw-r--r--core/os/errors.odin322
-rw-r--r--core/os/file_windows.odin176
-rw-r--r--core/os/os.odin148
-rw-r--r--core/os/os2/errors.odin3
-rw-r--r--core/os/os2/errors_linux.odin10
-rw-r--r--core/os/os2/file_util.odin25
-rw-r--r--core/os/os2/path_linux.odin2
-rw-r--r--core/os/os2/stat_windows.odin13
-rw-r--r--core/os/os_darwin.odin689
-rw-r--r--core/os/os_essence.odin53
-rw-r--r--core/os/os_freebsd.odin530
-rw-r--r--core/os/os_haiku.odin170
-rw-r--r--core/os/os_js.odin167
-rw-r--r--core/os/os_linux.odin551
-rw-r--r--core/os/os_netbsd.odin609
-rw-r--r--core/os/os_openbsd.odin547
-rw-r--r--core/os/os_wasi.odin43
-rw-r--r--core/os/os_windows.odin158
-rw-r--r--core/os/stat_unix.odin56
-rw-r--r--core/os/stat_windows.odin72
-rw-r--r--core/os/stream.odin49
-rw-r--r--core/path/filepath/match.odin4
-rw-r--r--core/path/filepath/path_windows.odin10
-rw-r--r--core/path/filepath/walk.odin35
-rw-r--r--core/prof/spall/spall.odin4
-rw-r--r--core/prof/spall/spall_linux.odin15
-rw-r--r--core/prof/spall/spall_unix.odin13
-rw-r--r--core/prof/spall/spall_windows.odin9
-rw-r--r--core/sync/futex_haiku.odin11
-rw-r--r--core/sys/haiku/os.odin2
-rw-r--r--core/sys/wasm/wasi/wasi_api.odin1
-rw-r--r--core/testing/runner.odin4
44 files changed, 2876 insertions, 1803 deletions
diff --git a/core/crypto/rand_windows.odin b/core/crypto/rand_windows.odin
index 9cd647cc1..83a976e38 100644
--- a/core/crypto/rand_windows.odin
+++ b/core/crypto/rand_windows.odin
@@ -8,9 +8,9 @@ HAS_RAND_BYTES :: true
@(private)
_rand_bytes :: proc(dst: []byte) {
- ret := (os.Errno)(win32.BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG))
- if ret != os.ERROR_NONE {
- switch ret {
+ ret := os.Platform_Error(win32.BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG))
+ if ret != nil {
+ #partial switch ret {
case os.ERROR_INVALID_HANDLE:
// The handle to the first parameter is invalid.
// This should not happen here, since we explicitly pass nil to it
diff --git a/core/encoding/csv/example.odin b/core/encoding/csv/example.odin
index 24722589d..d791eb33b 100644
--- a/core/encoding/csv/example.odin
+++ b/core/encoding/csv/example.odin
@@ -38,9 +38,9 @@ iterate_csv_from_stream :: proc(filename: string) {
r.reuse_record_buffer = true // Without it you have to each of the fields within it
defer csv.reader_destroy(&r)
- handle, errno := os.open(filename)
- if errno != os.ERROR_NONE {
- fmt.printfln("Error opening file: %v", filename)
+ handle, err := os.open(filename)
+ if err != nil {
+ fmt.eprintfln("Error opening file: %v", filename)
return
}
defer os.close(handle)
diff --git a/core/flags/errors.odin b/core/flags/errors.odin
index 21ea05477..6e48f6ccf 100644
--- a/core/flags/errors.odin
+++ b/core/flags/errors.odin
@@ -28,7 +28,7 @@ Parse_Error :: struct {
// Provides more granular information than what just a string could hold.
Open_File_Error :: struct {
filename: string,
- errno: os.Errno,
+ errno: os.Error,
mode: int,
perms: int,
}
diff --git a/core/flags/internal_rtti.odin b/core/flags/internal_rtti.odin
index ac39eaa8b..4c1db5d0b 100644
--- a/core/flags/internal_rtti.odin
+++ b/core/flags/internal_rtti.odin
@@ -254,8 +254,8 @@ parse_and_set_pointer_by_named_type :: proc(ptr: rawptr, str: string, data_type:
}
handle, errno := os.open(str, mode, perms)
- if errno != 0 {
- // NOTE(Feoramund): os.Errno is system-dependent, and there's
+ if errno != nil {
+ // NOTE(Feoramund): os.Error is system-dependent, and there's
// currently no good way to translate them all into strings.
//
// The upcoming `os2` package will hopefully solve this.
diff --git a/core/image/general_os.odin b/core/image/general_os.odin
index 144a3470f..e1fe440a4 100644
--- a/core/image/general_os.odin
+++ b/core/image/general_os.odin
@@ -27,7 +27,7 @@ which :: proc{
which_file :: proc(path: string) -> Which_File_Type {
f, err := os.open(path)
- if err != 0 {
+ if err != nil {
return .Unknown
}
header: [128]byte
diff --git a/core/image/png/example.odin b/core/image/png/example.odin
index cd9788bd3..ce491978b 100644
--- a/core/image/png/example.odin
+++ b/core/image/png/example.odin
@@ -213,7 +213,7 @@ write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: b
}
fd, err := open(filename, flags, mode)
- if err != 0 {
+ if err != nil {
return false
}
defer close(fd)
diff --git a/core/image/png/helpers.odin b/core/image/png/helpers.odin
index ac61378da..7b6367694 100644
--- a/core/image/png/helpers.odin
+++ b/core/image/png/helpers.odin
@@ -450,7 +450,7 @@ when false {
}
fd, fderr := open(filename, flags, mode)
- if fderr != 0 {
+ if fderr != nil {
return .Cannot_Open_File
}
defer close(fd)
diff --git a/core/mem/virtual/file.odin b/core/mem/virtual/file.odin
index 5d7180588..2f852b40c 100644
--- a/core/mem/virtual/file.odin
+++ b/core/mem/virtual/file.odin
@@ -24,7 +24,7 @@ map_file :: proc{
map_file_from_path :: proc(filename: string, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
fd, err := os.open(filename, os.O_RDWR)
- if err != 0 {
+ if err != nil {
return nil, .Open_Failure
}
defer os.close(fd)
@@ -34,7 +34,7 @@ map_file_from_path :: proc(filename: string, flags: Map_File_Flags) -> (data: []
map_file_from_file_descriptor :: proc(fd: uintptr, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
size, os_err := os.file_size(os.Handle(fd))
- if os_err != 0 {
+ if os_err != nil {
return nil, .Stat_Failure
}
if size < 0 {
diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin
index fc422b3a9..10069963a 100644
--- a/core/net/socket_darwin.odin
+++ b/core/net/socket_darwin.odin
@@ -53,9 +53,9 @@ _create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (so
unreachable()
}
- sock, ok := os.socket(c_family, c_type, c_protocol)
- if ok != os.ERROR_NONE {
- err = Create_Socket_Error(ok)
+ sock, sock_err := os.socket(c_family, c_type, c_protocol)
+ if sock_err != nil {
+ err = Create_Socket_Error(os.is_platform_error(sock_err) or_else -1)
return
}
@@ -84,8 +84,8 @@ _dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_optio
sockaddr := _endpoint_to_sockaddr(endpoint)
res := os.connect(os.Socket(skt), (^os.SOCKADDR)(&sockaddr), i32(sockaddr.len))
- if res != os.ERROR_NONE {
- err = Dial_Error(res)
+ if res != nil {
+ err = Dial_Error(os.is_platform_error(res) or_else -1)
return
}
@@ -100,11 +100,11 @@ _bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Network_Error) {
sockaddr := _endpoint_to_sockaddr(ep)
s := any_socket_to_socket(skt)
res := os.bind(os.Socket(s), (^os.SOCKADDR)(&sockaddr), i32(sockaddr.len))
- if res != os.ERROR_NONE {
+ if res != nil {
if res == os.EACCES && ep.port <= MAX_PRIVILEGED_PORT {
err = .Privileged_Port_Without_Root
} else {
- err = Bind_Error(res)
+ err = Bind_Error(os.is_platform_error(res) or_else -1)
}
}
return
@@ -128,8 +128,8 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_
bind(sock, interface_endpoint) or_return
res := os.listen(os.Socket(skt), backlog)
- if res != os.ERROR_NONE {
- err = Listen_Error(res)
+ if res != nil {
+ err = Listen_Error(os.is_platform_error(res) or_else -1)
return
}
@@ -141,9 +141,9 @@ _accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (client
sockaddr: os.SOCKADDR_STORAGE_LH
sockaddrlen := c.int(size_of(sockaddr))
- client_sock, ok := os.accept(os.Socket(sock), cast(^os.SOCKADDR) &sockaddr, &sockaddrlen)
- if ok != os.ERROR_NONE {
- err = Accept_Error(ok)
+ client_sock, client_sock_err := os.accept(os.Socket(sock), cast(^os.SOCKADDR) &sockaddr, &sockaddrlen)
+ if client_sock_err != nil {
+ err = Accept_Error(os.is_platform_error(client_sock_err) or_else -1)
return
}
client = TCP_Socket(client_sock)
@@ -162,9 +162,9 @@ _recv_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_read: int, err: Networ
if len(buf) <= 0 {
return
}
- res, ok := os.recv(os.Socket(skt), buf, 0)
- if ok != os.ERROR_NONE {
- err = TCP_Recv_Error(ok)
+ res, res_err := os.recv(os.Socket(skt), buf, 0)
+ if res_err != nil {
+ err = TCP_Recv_Error(os.is_platform_error(res_err) or_else -1)
return
}
return int(res), nil
@@ -178,9 +178,9 @@ _recv_udp :: proc(skt: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_endp
from: os.SOCKADDR_STORAGE_LH
fromsize := c.int(size_of(from))
- res, ok := os.recvfrom(os.Socket(skt), buf, 0, cast(^os.SOCKADDR) &from, &fromsize)
- if ok != os.ERROR_NONE {
- err = UDP_Recv_Error(ok)
+ res, res_err := os.recvfrom(os.Socket(skt), buf, 0, cast(^os.SOCKADDR) &from, &fromsize)
+ if res_err != nil {
+ err = UDP_Recv_Error(os.is_platform_error(res_err) or_else -1)
return
}
@@ -194,9 +194,9 @@ _send_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_written: int, err: Net
for bytes_written < len(buf) {
limit := min(int(max(i32)), len(buf) - bytes_written)
remaining := buf[bytes_written:][:limit]
- res, ok := os.send(os.Socket(skt), remaining, 0)
- if ok != os.ERROR_NONE {
- err = TCP_Send_Error(ok)
+ res, res_err := os.send(os.Socket(skt), remaining, 0)
+ if res_err != nil {
+ err = TCP_Send_Error(os.is_platform_error(res_err) or_else -1)
return
}
bytes_written += int(res)
@@ -210,9 +210,9 @@ _send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written:
for bytes_written < len(buf) {
limit := min(1<<31, len(buf) - bytes_written)
remaining := buf[bytes_written:][:limit]
- res, ok := os.sendto(os.Socket(skt), remaining, 0, cast(^os.SOCKADDR)&toaddr, i32(toaddr.len))
- if ok != os.ERROR_NONE {
- err = UDP_Send_Error(ok)
+ res, res_err := os.sendto(os.Socket(skt), remaining, 0, cast(^os.SOCKADDR)&toaddr, i32(toaddr.len))
+ if res_err != nil {
+ err = UDP_Send_Error(os.is_platform_error(res_err) or_else -1)
return
}
bytes_written += int(res)
@@ -224,8 +224,8 @@ _send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written:
_shutdown :: proc(skt: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
s := any_socket_to_socket(skt)
res := os.shutdown(os.Socket(s), int(manner))
- if res != os.ERROR_NONE {
- return Shutdown_Error(res)
+ if res != nil {
+ return Shutdown_Error(os.is_platform_error(res) or_else -1)
}
return
}
@@ -302,8 +302,8 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
skt := any_socket_to_socket(s)
res := os.setsockopt(os.Socket(skt), int(level), int(option), ptr, len)
- if res != os.ERROR_NONE {
- return Socket_Option_Error(res)
+ if res != nil {
+ return Socket_Option_Error(os.is_platform_error(res) or_else -1)
}
return nil
@@ -314,8 +314,8 @@ _set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_E
socket := any_socket_to_socket(socket)
flags, getfl_err := os.fcntl(int(socket), os.F_GETFL, 0)
- if getfl_err != os.ERROR_NONE {
- return Set_Blocking_Error(getfl_err)
+ if getfl_err != nil {
+ return Set_Blocking_Error(os.is_platform_error(getfl_err) or_else -1)
}
if should_block {
@@ -325,8 +325,8 @@ _set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_E
}
_, setfl_err := os.fcntl(int(socket), os.F_SETFL, flags)
- if setfl_err != os.ERROR_NONE {
- return Set_Blocking_Error(setfl_err)
+ if setfl_err != nil {
+ return Set_Blocking_Error(os.is_platform_error(setfl_err) or_else -1)
}
return nil
diff --git a/core/os/dir_unix.odin b/core/os/dir_unix.odin
index 58cd873ae..6f6bed36d 100644
--- a/core/os/dir_unix.odin
+++ b/core/os/dir_unix.odin
@@ -3,21 +3,12 @@ package os
import "core:strings"
-read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
- dirp: Dir
- dirp, err = _fdopendir(fd)
- if err != ERROR_NONE {
- return
- }
-
+@(require_results)
+read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
+ dirp := _fdopendir(fd) or_return
defer _closedir(dirp)
- dirpath: string
- dirpath, err = absolute_path_from_handle(fd)
- if err != ERROR_NONE {
- return
- }
-
+ dirpath := absolute_path_from_handle(fd) or_return
defer delete(dirpath)
n := n
@@ -27,8 +18,8 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
size = 100
}
- dfi := make([dynamic]File_Info, 0, size, allocator)
- defer if err != ERROR_NONE {
+ dfi := make([dynamic]File_Info, 0, size, allocator) or_return
+ defer if err != nil {
for fi_ in dfi {
file_info_delete(fi_, allocator)
}
@@ -39,7 +30,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
entry: Dirent
end_of_stream: bool
entry, err, end_of_stream = _readdir(dirp)
- if err != ERROR_NONE {
+ if err != nil {
return
} else if end_of_stream {
break
@@ -56,7 +47,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
s: OS_Stat
s, err = _lstat(fullpath)
- if err != ERROR_NONE {
+ if err != nil {
delete(fullpath, allocator)
return
}
@@ -67,5 +58,5 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
append(&dfi, fi_)
}
- return dfi[:], ERROR_NONE
+ return dfi[:], nil
}
diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin
index 9ca78948e..ae3e6922c 100644
--- a/core/os/dir_windows.odin
+++ b/core/os/dir_windows.odin
@@ -4,7 +4,9 @@ import win32 "core:sys/windows"
import "core:strings"
import "base:runtime"
-read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
+@(require_results)
+read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
+ @(require_results)
find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) {
// Ignore "." and ".."
if d.cFileName[0] == '.' && d.cFileName[1] == 0 {
@@ -57,7 +59,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
dir_fi, _ := file_info_from_get_file_information_by_handle("", h)
if !dir_fi.is_dir {
- return nil, ERROR_FILE_IS_NOT_DIR
+ return nil, .Not_Dir
}
n := n
@@ -68,15 +70,14 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
}
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator)
- wpath: []u16
- wpath, err = cleanpath_from_handle_u16(fd, context.temp_allocator)
- if len(wpath) == 0 || err != ERROR_NONE {
+ wpath := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return
+ if len(wpath) == 0 {
return
}
- dfi := make([dynamic]File_Info, 0, size)
+ dfi := make([dynamic]File_Info, 0, size) or_return
- wpath_search := make([]u16, len(wpath)+3, context.temp_allocator)
+ wpath_search := make([]u16, len(wpath)+3, context.temp_allocator) or_return
copy(wpath_search, wpath)
wpath_search[len(wpath)+0] = '\\'
wpath_search[len(wpath)+1] = '*'
@@ -88,7 +89,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
find_data := &win32.WIN32_FIND_DATAW{}
find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data)
if find_handle == win32.INVALID_HANDLE_VALUE {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
return dfi[:], err
}
defer win32.FindClose(find_handle)
@@ -101,7 +102,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
}
if !win32.FindNextFileW(find_handle, find_data) {
- e := Errno(win32.GetLastError())
+ e := get_last_error()
if e == ERROR_NO_MORE_FILES {
break
}
@@ -109,5 +110,5 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
}
}
- return dfi[:], ERROR_NONE
+ return dfi[:], nil
}
diff --git a/core/os/env_windows.odin b/core/os/env_windows.odin
index 0e3c7f04a..efd002342 100644
--- a/core/os/env_windows.odin
+++ b/core/os/env_windows.odin
@@ -7,27 +7,22 @@ import "base:runtime"
// If the variable is found in the environment the value (which can be empty) is returned and the boolean is true
// Otherwise the returned value will be empty and the boolean will be false
// NOTE: the value will be allocated with the supplied allocator
+@(require_results)
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
if key == "" {
return
}
wkey := win32.utf8_to_wstring(key)
n := win32.GetEnvironmentVariableW(wkey, nil, 0)
- if n == 0 {
- err := win32.GetLastError()
- if err == u32(ERROR_ENVVAR_NOT_FOUND) {
- return "", false
- }
+ if n == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND {
+ return "", false
}
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator)
- b := make([dynamic]u16, n, context.temp_allocator)
+ b, _ := make([dynamic]u16, n, context.temp_allocator)
n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
- if n == 0 {
- err := win32.GetLastError()
- if err == u32(ERROR_ENVVAR_NOT_FOUND) {
- return "", false
- }
+ if n == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND {
+ return "", false
}
value, _ = win32.utf16_to_utf8(b[:n], allocator)
found = true
@@ -39,41 +34,46 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
// It returns the value, which will be empty if the variable is not present
// To distinguish between an empty value and an unset value, use lookup_env
// NOTE: the value will be allocated with the supplied allocator
+@(require_results)
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
value, _ = lookup_env(key, allocator)
return
}
// set_env sets the value of the environment variable named by the key
-set_env :: proc(key, value: string) -> Errno {
+set_env :: proc(key, value: string) -> Error {
k := win32.utf8_to_wstring(key)
v := win32.utf8_to_wstring(value)
if !win32.SetEnvironmentVariableW(k, v) {
- return Errno(win32.GetLastError())
+ return get_last_error()
}
- return 0
+ return nil
}
// unset_env unsets a single environment variable
-unset_env :: proc(key: string) -> Errno {
+unset_env :: proc(key: string) -> Error {
k := win32.utf8_to_wstring(key)
if !win32.SetEnvironmentVariableW(k, nil) {
- return Errno(win32.GetLastError())
+ return get_last_error()
}
- return 0
+ return nil
}
// environ returns a copy of strings representing the environment, in the form "key=value"
// NOTE: the slice of strings and the strings with be allocated using the supplied allocator
+@(require_results)
environ :: proc(allocator := context.allocator) -> []string {
- envs := cast([^]win32.WCHAR)(win32.GetEnvironmentStringsW())
+ envs := ([^]win32.WCHAR)(win32.GetEnvironmentStringsW())
if envs == nil {
return nil
}
defer win32.FreeEnvironmentStringsW(envs)
- r := make([dynamic]string, 0, 50, allocator)
+ r, err := make([dynamic]string, 0, 50, allocator)
+ if err != nil {
+ return nil
+ }
for from, i := 0, 0; true; i += 1 {
if c := envs[i]; c == 0 {
if i <= from {
diff --git a/core/os/errors.odin b/core/os/errors.odin
new file mode 100644
index 000000000..691397f4b
--- /dev/null
+++ b/core/os/errors.odin
@@ -0,0 +1,322 @@
+package os
+
+import "base:intrinsics"
+import "base:runtime"
+import "core:io"
+
+Platform_Error :: _Platform_Error
+#assert(size_of(Platform_Error) <= 4)
+#assert(intrinsics.type_has_nil(Platform_Error))
+
+General_Error :: enum u32 {
+ None,
+
+ Permission_Denied,
+ Exist,
+ Not_Exist,
+ Closed,
+
+ Timeout,
+
+ Broken_Pipe,
+
+ // Indicates that an attempt to retrieve a file's size was made, but the
+ // file doesn't have a size.
+ No_Size,
+
+ Invalid_File,
+ Invalid_Dir,
+ Invalid_Path,
+ Invalid_Callback,
+
+ Pattern_Has_Separator,
+
+ Unsupported,
+
+ File_Is_Pipe,
+ Not_Dir,
+}
+
+
+Errno :: Error // alias for legacy use
+
+Error :: union #shared_nil {
+ General_Error,
+ io.Error,
+ runtime.Allocator_Error,
+ Platform_Error,
+}
+#assert(size_of(Error) == 8)
+
+ERROR_NONE :: Error{}
+
+ERROR_EOF :: io.Error.EOF
+
+@(require_results)
+is_platform_error :: proc "contextless" (ferr: Error) -> (err: i32, ok: bool) {
+ v := ferr.(Platform_Error) or_else {}
+ return i32(v), i32(v) != 0
+}
+
+@(require_results)
+error_string :: proc "contextless" (ferr: Error) -> string {
+ if ferr == nil {
+ return ""
+ }
+ switch e in ferr {
+ case General_Error:
+ switch e {
+ case .None: return ""
+ case .Permission_Denied: return "permission denied"
+ case .Exist: return "file already exists"
+ case .Not_Exist: return "file does not exist"
+ case .Closed: return "file already closed"
+ case .Timeout: return "i/o timeout"
+ case .Broken_Pipe: return "Broken pipe"
+ case .No_Size: return "file has no definite size"
+ case .Invalid_File: return "invalid file"
+ case .Invalid_Dir: return "invalid directory"
+ case .Invalid_Path: return "invalid path"
+ case .Invalid_Callback: return "invalid callback"
+ case .Unsupported: return "unsupported"
+ case .Pattern_Has_Separator: return "pattern has separator"
+ case .File_Is_Pipe: return "file is pipe"
+ case .Not_Dir: return "file is not directory"
+ }
+ case io.Error:
+ switch e {
+ case .None: return ""
+ case .EOF: return "eof"
+ case .Unexpected_EOF: return "unexpected eof"
+ case .Short_Write: return "short write"
+ case .Invalid_Write: return "invalid write result"
+ case .Short_Buffer: return "short buffer"
+ case .No_Progress: return "multiple read calls return no data or error"
+ case .Invalid_Whence: return "invalid whence"
+ case .Invalid_Offset: return "invalid offset"
+ case .Invalid_Unread: return "invalid unread"
+ case .Negative_Read: return "negative read"
+ case .Negative_Write: return "negative write"
+ case .Negative_Count: return "negative count"
+ case .Buffer_Full: return "buffer full"
+ case .Unknown, .Empty: //
+ }
+ case runtime.Allocator_Error:
+ switch e {
+ case .None: return ""
+ case .Out_Of_Memory: return "out of memory"
+ case .Invalid_Pointer: return "invalid allocator pointer"
+ case .Invalid_Argument: return "invalid allocator argument"
+ case .Mode_Not_Implemented: return "allocator mode not implemented"
+ }
+ case Platform_Error:
+ return _error_string(e)
+ }
+
+ return "unknown error"
+}
+
+print_error :: proc(f: Handle, ferr: Error, msg: string) -> (n: int, err: Error) {
+ err_str := error_string(ferr)
+
+ // msg + ": " + err_str + '\n'
+ length := len(msg) + 2 + len(err_str) + 1
+ buf_ := intrinsics.alloca(length, 1)
+ buf := buf_[:length]
+
+ copy(buf, msg)
+ buf[len(msg)] = ':'
+ buf[len(msg) + 1] = ' '
+ copy(buf[len(msg) + 2:], err_str)
+ buf[length - 1] = '\n'
+ return write(f, buf)
+}
+
+
+@(require_results, private)
+_error_string :: proc "contextless" (e: Platform_Error) -> string where intrinsics.type_is_enum(Platform_Error) {
+ if e == nil {
+ return ""
+ }
+
+ when ODIN_OS == .Darwin {
+ if s := string(_darwin_string_error(i32(e))); s != "" {
+ return s
+ }
+ }
+
+ when ODIN_OS != .Linux {
+ @(require_results)
+ binary_search :: proc "contextless" (array: $A/[]$T, key: T) -> (index: int, found: bool) #no_bounds_check {
+ n := len(array)
+ left, right := 0, n
+ for left < right {
+ mid := int(uint(left+right) >> 1)
+ if array[mid] < key {
+ left = mid+1
+ } else {
+ // equal or greater
+ right = mid
+ }
+ }
+ return left, left < n && array[left] == key
+ }
+
+ err := runtime.Type_Info_Enum_Value(e)
+
+ ti := &runtime.type_info_base(type_info_of(Platform_Error)).variant.(runtime.Type_Info_Enum)
+ if idx, ok := binary_search(ti.values, err); ok {
+ return ti.names[idx]
+ }
+ } else {
+ @(rodata, static)
+ pe_strings := [Platform_Error]string{
+ .NONE = "",
+ .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",
+ .EUNKNOWN_41 = "Unknown Error (41)",
+ .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",
+ .EUNKNOWN_58 = "Unknown Error (58)",
+ .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",
+ }
+ if Platform_Error.NONE <= e && e <= max(Platform_Error) {
+ return pe_strings[e]
+ }
+ }
+ return "<unknown platform error>"
+}
+
+@(private, require_results)
+error_to_io_error :: proc(ferr: Error) -> io.Error {
+ if ferr == nil {
+ return .None
+ }
+ return ferr.(io.Error) or_else .Unknown
+}
diff --git a/core/os/file_windows.odin b/core/os/file_windows.odin
index d900c5e70..3f6f781aa 100644
--- a/core/os/file_windows.odin
+++ b/core/os/file_windows.odin
@@ -5,13 +5,15 @@ import "base:intrinsics"
import "base:runtime"
import "core:unicode/utf16"
+@(require_results)
is_path_separator :: proc(c: byte) -> bool {
return c == '/' || c == '\\'
}
-open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
+@(require_results)
+open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) {
if len(path) == 0 {
- return INVALID_HANDLE, ERROR_FILE_NOT_FOUND
+ return INVALID_HANDLE, General_Error.Not_Exist
}
access: u32
@@ -52,32 +54,31 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errn
wide_path := win32.utf8_to_wstring(path)
handle := Handle(win32.CreateFileW(wide_path, access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS, nil))
if handle != INVALID_HANDLE {
- return handle, ERROR_NONE
+ return handle, nil
}
- err := Errno(win32.GetLastError())
- return INVALID_HANDLE, err
+ return INVALID_HANDLE, get_last_error()
}
-close :: proc(fd: Handle) -> Errno {
+close :: proc(fd: Handle) -> Error {
if !win32.CloseHandle(win32.HANDLE(fd)) {
- return Errno(win32.GetLastError())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-flush :: proc(fd: Handle) -> (err: Errno) {
+flush :: proc(fd: Handle) -> (err: Error) {
if !win32.FlushFileBuffers(win32.HANDLE(fd)) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
return
}
-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
}
single_write_length: win32.DWORD
@@ -90,25 +91,24 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil)
if single_write_length <= 0 || !e {
- err := Errno(win32.GetLastError())
- return int(total_write), err
+ return int(total_write), get_last_error()
}
total_write += i64(single_write_length)
}
- return int(total_write), ERROR_NONE
+ return int(total_write), nil
}
-@(private="file")
-read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
+@(private="file", require_results)
+read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Error) {
if len(b) == 0 {
- return 0, 0
+ return 0, nil
}
BUF_SIZE :: 386
buf16: [BUF_SIZE]u16
buf8: [4*BUF_SIZE]u8
- for n < len(b) && err == 0 {
+ for n < len(b) && err == nil {
min_read := max(len(b)/4, 1 if len(b) > 0 else 0)
max_read := u32(min(BUF_SIZE, min_read))
if max_read == 0 {
@@ -118,7 +118,7 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
single_read_length: u32
ok := win32.ReadConsoleW(handle, &buf16[0], max_read, &single_read_length, nil)
if !ok {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
buf8_len := utf16.decode_to_utf8(buf8[:], buf16[:single_read_length])
@@ -149,9 +149,9 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
return
}
-read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Errno) {
+read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Error) {
if len(data) == 0 {
- return 0, ERROR_NONE
+ return 0, nil
}
handle := win32.HANDLE(fd)
@@ -165,7 +165,7 @@ read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Errno) {
if is_console {
total_read, err = read_console(handle, data[total_read:][:to_read])
- if err != 0 {
+ if err != nil {
return total_read, err
}
} else {
@@ -175,18 +175,18 @@ read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Errno) {
// Successful read can mean two things, including EOF, see:
// https://learn.microsoft.com/en-us/windows/win32/fileio/testing-for-the-end-of-a-file
if bytes_read == 0 {
- return 0, ERROR_HANDLE_EOF
+ return 0, .EOF
} else {
- return int(bytes_read), ERROR_NONE
+ return int(bytes_read), nil
}
} else {
- return 0, Errno(win32.GetLastError())
+ return 0, get_last_error()
}
}
- return total_read, ERROR_NONE
+ return total_read, nil
}
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
w: u32
switch whence {
case 0: w = win32.FILE_BEGIN
@@ -197,22 +197,23 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
lo := i32(offset)
ft := win32.GetFileType(win32.HANDLE(fd))
if ft == win32.FILE_TYPE_PIPE {
- return 0, ERROR_FILE_IS_PIPE
+ return 0, .File_Is_Pipe
}
dw_ptr := win32.SetFilePointer(win32.HANDLE(fd), lo, &hi, w)
if dw_ptr == win32.INVALID_SET_FILE_POINTER {
- err := Errno(win32.GetLastError())
+ err := get_last_error()
return 0, err
}
- return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE
+ return i64(hi)<<32 + i64(dw_ptr), nil
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
+@(require_results)
+file_size :: proc(fd: Handle) -> (i64, Error) {
length: win32.LARGE_INTEGER
- err: Errno
+ err: Error
if !win32.GetFileSizeEx(win32.HANDLE(fd), &length) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
return i64(length), err
}
@@ -220,10 +221,9 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
@(private)
MAX_RW :: 1<<30
-ERROR_EOF :: 38
@(private)
-pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
+pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
buf := data
if len(buf) > MAX_RW {
buf = buf[:MAX_RW]
@@ -239,15 +239,15 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
h := win32.HANDLE(fd)
done: win32.DWORD
- e: Errno
+ e: Error
if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
- e = Errno(win32.GetLastError())
+ e = get_last_error()
done = 0
}
return int(done), e
}
@(private)
-pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
+pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
buf := data
if len(buf) > MAX_RW {
buf = buf[:MAX_RW]
@@ -261,9 +261,9 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
h := win32.HANDLE(fd)
done: win32.DWORD
- e: Errno
+ e: Error
if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
- e = Errno(win32.GetLastError())
+ e = get_last_error()
done = 0
}
return int(done), e
@@ -279,19 +279,19 @@ on Windows, read_at changes the position of the file cursor, on *nix, it does no
will read from the location twice on *nix, and from two different locations on Windows
*/
-read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
+read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
if offset < 0 {
- return 0, ERROR_NEGATIVE_OFFSET
+ return 0, .Invalid_Offset
}
b, offset := data, offset
for len(b) > 0 {
m, e := pread(fd, b, offset)
if e == ERROR_EOF {
- err = 0
+ err = nil
break
}
- if e != 0 {
+ if e != nil {
err = e
break
}
@@ -311,18 +311,14 @@ on Windows, write_at changes the position of the file cursor, on *nix, it does n
will write to the location twice on *nix, and to two different locations on Windows
*/
-write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
+write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
if offset < 0 {
- return 0, ERROR_NEGATIVE_OFFSET
+ return 0, .Invalid_Offset
}
b, offset := data, offset
for len(b) > 0 {
- m, e := pwrite(fd, b, offset)
- if e != 0 {
- err = e
- break
- }
+ m := pwrite(fd, b, offset) or_return
n += m
b = b[m:]
offset += i64(m)
@@ -338,6 +334,7 @@ stdout := get_std_handle(uint(win32.STD_OUTPUT_HANDLE))
stderr := get_std_handle(uint(win32.STD_ERROR_HANDLE))
+@(require_results)
get_std_handle :: proc "contextless" (h: uint) -> Handle {
fd := win32.GetStdHandle(win32.DWORD(h))
return Handle(fd)
@@ -352,6 +349,7 @@ exists :: proc(path: string) -> bool {
return attribs != win32.INVALID_FILE_ATTRIBUTES
}
+@(require_results)
is_file :: proc(path: string) -> bool {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
@@ -363,6 +361,7 @@ is_file :: proc(path: string) -> bool {
return false
}
+@(require_results)
is_dir :: proc(path: string) -> bool {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
@@ -377,13 +376,14 @@ is_dir :: proc(path: string) -> bool {
// NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName
@private cwd_lock := win32.SRWLOCK{} // zero is initialized
+@(require_results)
get_current_directory :: proc(allocator := context.allocator) -> string {
win32.AcquireSRWLockExclusive(&cwd_lock)
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator)
sz_utf16 := win32.GetCurrentDirectoryW(0, nil)
- dir_buf_wstr := make([]u16, sz_utf16, context.temp_allocator) // the first time, it _includes_ the NUL.
+ dir_buf_wstr, _ := make([]u16, sz_utf16, context.temp_allocator) // the first time, it _includes_ the NUL.
sz_utf16 = win32.GetCurrentDirectoryW(win32.DWORD(len(dir_buf_wstr)), raw_data(dir_buf_wstr))
assert(int(sz_utf16)+1 == len(dir_buf_wstr)) // the second time, it _excludes_ the NUL.
@@ -393,14 +393,14 @@ get_current_directory :: proc(allocator := context.allocator) -> string {
return win32.utf16_to_utf8(dir_buf_wstr, allocator) or_else ""
}
-set_current_directory :: proc(path: string) -> (err: Errno) {
+set_current_directory :: proc(path: string) -> (err: Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
wstr := win32.utf8_to_wstring(path, context.temp_allocator)
win32.AcquireSRWLockExclusive(&cwd_lock)
if !win32.SetCurrentDirectoryW(wstr) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
win32.ReleaseSRWLockExclusive(&cwd_lock)
@@ -409,31 +409,31 @@ set_current_directory :: proc(path: string) -> (err: Errno) {
}
change_directory :: set_current_directory
-make_directory :: proc(path: string, mode: u32 = 0) -> (err: Errno) {
+make_directory :: proc(path: string, mode: u32 = 0) -> (err: Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
// Mode is unused on Windows, but is needed on *nix
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
if !win32.CreateDirectoryW(wpath, nil) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
return
}
-remove_directory :: proc(path: string) -> (err: Errno) {
+remove_directory :: proc(path: string) -> (err: Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
if !win32.RemoveDirectoryW(wpath) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
return
}
-@(private)
+@(private, require_results)
is_abs :: proc(path: string) -> bool {
if len(path) > 0 && path[0] == '/' {
return true
@@ -449,7 +449,7 @@ is_abs :: proc(path: string) -> bool {
return false
}
-@(private)
+@(private, require_results)
fix_long_path :: proc(path: string) -> string {
if len(path) < 248 {
return path
@@ -464,7 +464,7 @@ fix_long_path :: proc(path: string) -> string {
prefix :: `\\?`
- path_buf := make([]byte, len(prefix)+len(path)+len(`\`), context.temp_allocator)
+ path_buf, _ := make([]byte, len(prefix)+len(path)+len(`\`), context.temp_allocator)
copy(path_buf, prefix)
n := len(path)
r, w := 0, len(prefix)
@@ -494,80 +494,69 @@ fix_long_path :: proc(path: string) -> string {
}
-link :: proc(old_name, new_name: string) -> (err: Errno) {
+link :: proc(old_name, new_name: string) -> (err: Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
n := win32.utf8_to_wstring(fix_long_path(new_name))
o := win32.utf8_to_wstring(fix_long_path(old_name))
- return Errno(win32.CreateHardLinkW(n, o, nil))
+ return Platform_Error(win32.CreateHardLinkW(n, o, nil))
}
-unlink :: proc(path: string) -> (err: Errno) {
+unlink :: proc(path: string) -> (err: Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
if !win32.DeleteFileW(wpath) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
return
}
-rename :: proc(old_path, new_path: string) -> (err: Errno) {
+rename :: proc(old_path, new_path: string) -> (err: Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
from := win32.utf8_to_wstring(old_path, context.temp_allocator)
to := win32.utf8_to_wstring(new_path, context.temp_allocator)
if !win32.MoveFileExW(from, to, win32.MOVEFILE_REPLACE_EXISTING) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
return
}
-ftruncate :: proc(fd: Handle, length: i64) -> (err: Errno) {
- curr_off, e := seek(fd, 0, 1)
- if e != 0 {
- return e
- }
+ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
+ curr_off := seek(fd, 0, 1) or_return
defer seek(fd, curr_off, 0)
- _, e = seek(fd, length, 0)
- if e != 0 {
- return e
- }
+ _= seek(fd, length, 0) or_return
ok := win32.SetEndOfFile(win32.HANDLE(fd))
if !ok {
- return Errno(win32.GetLastError())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-truncate :: proc(path: string, length: i64) -> (err: Errno) {
- fd: Handle
- fd, err = open(path, O_WRONLY|O_CREATE, 0o666)
- if err != 0 {
- return
- }
+truncate :: proc(path: string, length: i64) -> (err: Error) {
+ fd := open(path, O_WRONLY|O_CREATE, 0o666) or_return
defer close(fd)
- err = ftruncate(fd, length)
- return
+ return ftruncate(fd, length)
}
-remove :: proc(name: string) -> Errno {
+remove :: proc(name: string) -> Error {
p := win32.utf8_to_wstring(fix_long_path(name))
err, err1: win32.DWORD
if !win32.DeleteFileW(p) {
err = win32.GetLastError()
}
if err == 0 {
- return 0
+ return nil
}
if !win32.RemoveDirectoryW(p) {
err1 = win32.GetLastError()
}
if err1 == 0 {
- return 0
+ return nil
}
if err != err1 {
@@ -588,16 +577,17 @@ remove :: proc(name: string) -> Errno {
}
}
- return Errno(err)
+ return Platform_Error(err)
}
-pipe :: proc() -> (r, w: Handle, err: Errno) {
+@(require_results)
+pipe :: proc() -> (r, w: Handle, err: Error) {
sa: win32.SECURITY_ATTRIBUTES
sa.nLength = size_of(win32.SECURITY_ATTRIBUTES)
sa.bInheritHandle = true
if !win32.CreatePipe((^win32.HANDLE)(&r), (^win32.HANDLE)(&w), &sa, 0) {
- err = Errno(win32.GetLastError())
+ err = get_last_error()
}
return
}
diff --git a/core/os/os.odin b/core/os/os.odin
index 51652a52b..568c0a2aa 100644
--- a/core/os/os.odin
+++ b/core/os/os.odin
@@ -1,6 +1,8 @@
package os
+import "base:intrinsics"
import "base:runtime"
+import "core:io"
import "core:strconv"
import "core:unicode/utf8"
@@ -13,15 +15,15 @@ SEEK_SET :: 0
SEEK_CUR :: 1
SEEK_END :: 2
-write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
+write_string :: proc(fd: Handle, str: string) -> (int, Error) {
return write(fd, transmute([]byte)str)
}
-write_byte :: proc(fd: Handle, b: byte) -> (int, Errno) {
+write_byte :: proc(fd: Handle, b: byte) -> (int, Error) {
return write(fd, []byte{b})
}
-write_rune :: proc(fd: Handle, r: rune) -> (int, Errno) {
+write_rune :: proc(fd: Handle, r: rune) -> (int, Error) {
if r < utf8.RUNE_SELF {
return write_byte(fd, byte(r))
}
@@ -30,113 +32,145 @@ write_rune :: proc(fd: Handle, r: rune) -> (int, Errno) {
return write(fd, b[:n])
}
-write_encoded_rune :: proc(fd: Handle, r: rune) {
- write_byte(fd, '\'')
+write_encoded_rune :: proc(f: Handle, r: rune) -> (n: int, err: Error) {
+ wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool {
+ n^ += m
+ if merr != nil {
+ err^ = merr
+ return true
+ }
+ return false
+ }
+
+ if wrap(write_byte(f, '\''), &n, &err) { return }
switch r {
- case '\a': write_string(fd, "\\a")
- case '\b': write_string(fd, "\\b")
- case '\e': write_string(fd, "\\e")
- case '\f': write_string(fd, "\\f")
- case '\n': write_string(fd, "\\n")
- case '\r': write_string(fd, "\\r")
- case '\t': write_string(fd, "\\t")
- case '\v': write_string(fd, "\\v")
+ case '\a': if wrap(write_string(f, "\\a"), &n, &err) { return }
+ case '\b': if wrap(write_string(f, "\\b"), &n, &err) { return }
+ case '\e': if wrap(write_string(f, "\\e"), &n, &err) { return }
+ case '\f': if wrap(write_string(f, "\\f"), &n, &err) { return }
+ case '\n': if wrap(write_string(f, "\\n"), &n, &err) { return }
+ case '\r': if wrap(write_string(f, "\\r"), &n, &err) { return }
+ case '\t': if wrap(write_string(f, "\\t"), &n, &err) { return }
+ case '\v': if wrap(write_string(f, "\\v"), &n, &err) { return }
case:
if r < 32 {
- write_string(fd, "\\x")
+ if wrap(write_string(f, "\\x"), &n, &err) { return }
b: [2]byte
s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil)
switch len(s) {
- case 0: write_string(fd, "00")
- case 1: write_rune(fd, '0')
- case 2: write_string(fd, s)
+ case 0: if wrap(write_string(f, "00"), &n, &err) { return }
+ case 1: if wrap(write_rune(f, '0'), &n, &err) { return }
+ case 2: if wrap(write_string(f, s), &n, &err) { return }
}
} else {
- write_rune(fd, r)
+ if wrap(write_rune(f, r), &n, &err) { return }
}
}
- write_byte(fd, '\'')
+ _ = wrap(write_byte(f, '\''), &n, &err)
+ return
}
-read_at_least :: proc(fd: Handle, buf: []byte, min: int) -> (n: int, err: Errno) {
+read_at_least :: proc(fd: Handle, buf: []byte, min: int) -> (n: int, err: Error) {
if len(buf) < min {
- return 0, -1
+ return 0, io.Error.Short_Buffer
}
nn := max(int)
- for nn > 0 && n < min && err == 0 {
+ for nn > 0 && n < min && err == nil {
nn, err = read(fd, buf[n:])
n += nn
}
if n >= min {
- err = 0
+ err = nil
}
return
}
-read_full :: proc(fd: Handle, buf: []byte) -> (n: int, err: Errno) {
+read_full :: proc(fd: Handle, buf: []byte) -> (n: int, err: Error) {
return read_at_least(fd, buf, len(buf))
}
+@(require_results)
file_size_from_path :: proc(path: string) -> i64 {
fd, err := open(path, O_RDONLY, 0)
- if err != 0 {
+ if err != nil {
return -1
}
defer close(fd)
length: i64
- if length, err = file_size(fd); err != 0 {
+ if length, err = file_size(fd); err != nil {
return -1
}
return length
}
+@(require_results)
read_entire_file_from_filename :: proc(name: string, allocator := context.allocator, loc := #caller_location) -> (data: []byte, success: bool) {
+ err: Error
+ data, err = read_entire_file_from_filename_or_err(name, allocator, loc)
+ success = err == nil
+ return
+}
+
+@(require_results)
+read_entire_file_from_handle :: proc(fd: Handle, allocator := context.allocator, loc := #caller_location) -> (data: []byte, success: bool) {
+ err: Error
+ data, err = read_entire_file_from_handle_or_err(fd, allocator, loc)
+ success = err == nil
+ return
+}
+
+read_entire_file :: proc {
+ read_entire_file_from_filename,
+ read_entire_file_from_handle,
+}
+
+@(require_results)
+read_entire_file_from_filename_or_err :: proc(name: string, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Error) {
context.allocator = allocator
- fd, err := open(name, O_RDONLY, 0)
- if err != 0 {
- return nil, false
- }
+ fd := open(name, O_RDONLY, 0) or_return
defer close(fd)
- return read_entire_file_from_handle(fd, allocator, loc)
+ return read_entire_file_from_handle_or_err(fd, allocator, loc)
}
-read_entire_file_from_handle :: proc(fd: Handle, allocator := context.allocator, loc := #caller_location) -> (data: []byte, success: bool) {
+@(require_results)
+read_entire_file_from_handle_or_err :: proc(fd: Handle, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Error) {
context.allocator = allocator
- length: i64
- err: Errno
- if length, err = file_size(fd); err != 0 {
- return nil, false
- }
-
+ length := file_size(fd) or_return
if length <= 0 {
- return nil, true
+ return nil, nil
}
- data = make([]byte, int(length), allocator, loc)
+ data = make([]byte, int(length), allocator, loc) or_return
if data == nil {
- return nil, false
+ return nil, nil
}
-
- bytes_read, read_err := read_full(fd, data)
- if read_err != ERROR_NONE {
- delete(data)
- return nil, false
+ defer if err != nil {
+ delete(data, allocator)
}
- return data[:bytes_read], true
+
+ bytes_read := read_full(fd, data) or_return
+ data = data[:bytes_read]
+ return
}
-read_entire_file :: proc {
- read_entire_file_from_filename,
- read_entire_file_from_handle,
+read_entire_file_or_err :: proc {
+ read_entire_file_from_filename_or_err,
+ read_entire_file_from_handle_or_err,
}
+
write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (success: bool) {
+ return write_entire_file_or_err(name, data, truncate) == nil
+}
+
+@(require_results)
+write_entire_file_or_err :: proc(name: string, data: []byte, truncate := true) -> Error {
flags: int = O_WRONLY|O_CREATE
if truncate {
flags |= O_TRUNC
@@ -148,21 +182,18 @@ write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (succ
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
}
- fd, err := open(name, flags, mode)
- if err != 0 {
- return false
- }
+ fd := open(name, flags, mode) or_return
defer close(fd)
- _, write_err := write(fd, data)
- return write_err == 0
+ _ = write(fd, data) or_return
+ return nil
}
-write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
+write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Error) {
return write(fd, ([^]byte)(data)[:len])
}
-read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
+read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Error) {
return read(fd, ([^]byte)(data)[:len])
}
@@ -173,6 +204,7 @@ heap_alloc :: runtime.heap_alloc
heap_resize :: runtime.heap_resize
heap_free :: runtime.heap_free
+@(require_results)
processor_core_count :: proc() -> int {
return _processor_core_count()
}
diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin
index 2b9b3528e..bc51bb1e8 100644
--- a/core/os/os2/errors.odin
+++ b/core/os/os2/errors.odin
@@ -42,13 +42,14 @@ Error :: union #shared_nil {
ERROR_NONE :: Error{}
-
+@(require_results)
is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
v := ferr.(Platform_Error) or_else {}
return i32(v), i32(v) != 0
}
+@(require_results)
error_string :: proc(ferr: Error) -> string {
if ferr == nil {
return ""
diff --git a/core/os/os2/errors_linux.odin b/core/os/os2/errors_linux.odin
index d7234ce8b..28c93cfae 100644
--- a/core/os/os2/errors_linux.odin
+++ b/core/os/os2/errors_linux.odin
@@ -4,8 +4,8 @@ package os2
import "core:sys/linux"
@(rodata)
-_errno_strings : [linux.Errno]string = {
- .NONE = "Success",
+_errno_strings := [linux.Error]string{
+ .NONE = "",
.EPERM = "Operation not permitted",
.ENOENT = "No such file or directory",
.ESRCH = "No such process",
@@ -142,7 +142,7 @@ _errno_strings : [linux.Errno]string = {
}
-_get_platform_error :: proc(errno: linux.Errno) -> Error {
+_get_platform_error :: proc(errno: linux.Error) -> Error {
#partial switch errno {
case .NONE:
return nil
@@ -158,8 +158,8 @@ _get_platform_error :: proc(errno: linux.Errno) -> Error {
}
_error_string :: proc(errno: i32) -> string {
- if errno >= 0 && errno <= i32(max(linux.Errno)) {
- return _errno_strings[linux.Errno(errno)]
+ if errno >= 0 && errno <= i32(max(linux.Error)) {
+ return _errno_strings[linux.Error(errno)]
}
return "Unknown Error"
}
diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin
index 2011d1cc4..b982afb3e 100644
--- a/core/os/os2/file_util.odin
+++ b/core/os/os2/file_util.odin
@@ -73,6 +73,24 @@ write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
return
}
+read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) {
+ if len(buf) < min {
+ return 0, .Short_Buffer
+ }
+ nn := max(int)
+ for nn > 0 && n < min && err == nil {
+ nn, err = read(f, buf[n:])
+ n += nn
+ }
+ if n >= min {
+ err = nil
+ }
+ return
+}
+
+read_full :: proc(f: ^File, buf: []byte) -> (n: int, err: Error) {
+ return read_at_least(f, buf, len(buf))
+}
write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
return write(f, ([^]byte)(data)[:len])
@@ -155,11 +173,8 @@ write_entire_file :: proc(name: string, data: []byte, perm: int, truncate := tru
if truncate {
flags |= O_TRUNC
}
- f, err := open(name, flags, perm)
- if err != nil {
- return err
- }
- _, err = write(f, data)
+ f := open(name, flags, perm) or_return
+ _, err := write(f, data)
if cerr := close(f); cerr != nil && err == nil {
err = cerr
}
diff --git a/core/os/os2/path_linux.odin b/core/os/os2/path_linux.odin
index be60f9b86..62386675d 100644
--- a/core/os/os2/path_linux.odin
+++ b/core/os/os2/path_linux.odin
@@ -59,7 +59,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error {
path_bytes[len(path)] = 0
dfd: linux.Fd
- errno: linux.Errno
+ errno: linux.Error
if path_bytes[0] == '/' {
dfd, errno = linux.open("/", _OPENDIR_FLAGS)
path_bytes = path_bytes[1:]
diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin
index 3a3a3b1b4..5e66507be 100644
--- a/core/os/os2/stat_windows.odin
+++ b/core/os/os2/stat_windows.odin
@@ -6,25 +6,22 @@ import "core:time"
import "core:strings"
import win32 "core:sys/windows"
-_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
+_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) {
if f == nil || (^File_Impl)(f.impl).fd == nil {
- return {}, nil
+ return
}
- path, err := _cleanpath_from_handle(f, allocator)
- if err != nil {
- return {}, err
- }
+ path := _cleanpath_from_handle(f, allocator) or_return
h := _handle(f)
switch win32.GetFileType(h) {
case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR:
- fi := File_Info {
+ fi = File_Info {
fullpath = path,
name = basename(path),
type = file_type(h),
}
- return fi, nil
+ return
}
return _file_info_from_get_file_information_by_handle(path, h, allocator)
diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin
index e3748cce4..09cdd84d0 100644
--- a/core/os/os_darwin.odin
+++ b/core/os/os_darwin.odin
@@ -10,146 +10,284 @@ import "core:c"
Handle :: distinct i32
File_Time :: distinct u64
-Errno :: distinct int
INVALID_HANDLE :: ~Handle(0)
-ERROR_NONE: Errno : 0
-EPERM: Errno : 1 /* Operation not permitted */
-ENOENT: Errno : 2 /* No such file or directory */
-ESRCH: Errno : 3 /* No such process */
-EINTR: Errno : 4 /* Interrupted system call */
-EIO: Errno : 5 /* Input/output error */
-ENXIO: Errno : 6 /* Device not configured */
-E2BIG: Errno : 7 /* Argument list too long */
-ENOEXEC: Errno : 8 /* Exec format error */
-EBADF: Errno : 9 /* Bad file descriptor */
-ECHILD: Errno : 10 /* No child processes */
-EDEADLK: Errno : 11 /* Resource deadlock avoided */
-ENOMEM: Errno : 12 /* Cannot allocate memory */
-EACCES: Errno : 13 /* Permission denied */
-EFAULT: Errno : 14 /* Bad address */
-ENOTBLK: Errno : 15 /* Block device required */
-EBUSY: Errno : 16 /* Device / Resource busy */
-EEXIST: Errno : 17 /* File exists */
-EXDEV: Errno : 18 /* Cross-device link */
-ENODEV: Errno : 19 /* Operation not supported by device */
-ENOTDIR: Errno : 20 /* Not a directory */
-EISDIR: Errno : 21 /* Is a directory */
-EINVAL: Errno : 22 /* Invalid argument */
-ENFILE: Errno : 23 /* Too many open files in system */
-EMFILE: Errno : 24 /* Too many open files */
-ENOTTY: Errno : 25 /* Inappropriate ioctl for device */
-ETXTBSY: Errno : 26 /* Text file busy */
-EFBIG: Errno : 27 /* File too large */
-ENOSPC: Errno : 28 /* No space left on device */
-ESPIPE: Errno : 29 /* Illegal seek */
-EROFS: Errno : 30 /* Read-only file system */
-EMLINK: Errno : 31 /* Too many links */
-EPIPE: Errno : 32 /* Broken pipe */
+_Platform_Error :: enum i32 {
+ NONE = 0,
+ EPERM = 1, /* Operation not permitted */
+ ENOENT = 2, /* No such file or directory */
+ ESRCH = 3, /* No such process */
+ EINTR = 4, /* Interrupted system call */
+ EIO = 5, /* Input/output error */
+ ENXIO = 6, /* Device not configured */
+ E2BIG = 7, /* Argument list too long */
+ ENOEXEC = 8, /* Exec format error */
+ EBADF = 9, /* Bad file descriptor */
+ ECHILD = 10, /* No child processes */
+ EDEADLK = 11, /* Resource deadlock avoided */
+ ENOMEM = 12, /* Cannot allocate memory */
+ EACCES = 13, /* Permission denied */
+ EFAULT = 14, /* Bad address */
+ ENOTBLK = 15, /* Block device required */
+ EBUSY = 16, /* Device / Resource busy */
+ EEXIST = 17, /* File exists */
+ EXDEV = 18, /* Cross-device link */
+ ENODEV = 19, /* Operation not supported by device */
+ ENOTDIR = 20, /* Not a directory */
+ EISDIR = 21, /* Is a directory */
+ EINVAL = 22, /* Invalid argument */
+ ENFILE = 23, /* Too many open files in system */
+ EMFILE = 24, /* Too many open files */
+ ENOTTY = 25, /* Inappropriate ioctl for device */
+ ETXTBSY = 26, /* Text file busy */
+ EFBIG = 27, /* File too large */
+ ENOSPC = 28, /* No space left on device */
+ ESPIPE = 29, /* Illegal seek */
+ EROFS = 30, /* Read-only file system */
+ EMLINK = 31, /* Too many links */
+ EPIPE = 32, /* Broken pipe */
+
+ /* math software */
+ EDOM = 33, /* Numerical argument out of domain */
+ ERANGE = 34, /* Result too large */
+
+ /* non-blocking and interrupt i/o */
+ EAGAIN = 35, /* Resource temporarily unavailable */
+ EWOULDBLOCK = EAGAIN, /* Operation would block */
+ EINPROGRESS = 36, /* Operation now in progress */
+ EALREADY = 37, /* Operation already in progress */
+
+ /* ipc/network software -- argument errors */
+ ENOTSOCK = 38, /* Socket operation on non-socket */
+ EDESTADDRREQ = 39, /* Destination address required */
+ EMSGSIZE = 40, /* Message too long */
+ EPROTOTYPE = 41, /* Protocol wrong type for socket */
+ ENOPROTOOPT = 42, /* Protocol not available */
+ EPROTONOSUPPORT = 43, /* Protocol not supported */
+ ESOCKTNOSUPPORT = 44, /* Socket type not supported */
+ ENOTSUP = 45, /* Operation not supported */
+ EOPNOTSUPP = ENOTSUP,
+ EPFNOSUPPORT = 46, /* Protocol family not supported */
+ EAFNOSUPPORT = 47, /* Address family not supported by protocol family */
+ EADDRINUSE = 48, /* Address already in use */
+ EADDRNOTAVAIL = 49, /* Can't assign requested address */
+
+ /* ipc/network software -- operational errors */
+ ENETDOWN = 50, /* Network is down */
+ ENETUNREACH = 51, /* Network is unreachable */
+ ENETRESET = 52, /* Network dropped connection on reset */
+ ECONNABORTED = 53, /* Software caused connection abort */
+ ECONNRESET = 54, /* Connection reset by peer */
+ ENOBUFS = 55, /* No buffer space available */
+ EISCONN = 56, /* Socket is already connected */
+ ENOTCONN = 57, /* Socket is not connected */
+ ESHUTDOWN = 58, /* Can't send after socket shutdown */
+ ETOOMANYREFS = 59, /* Too many references: can't splice */
+ ETIMEDOUT = 60, /* Operation timed out */
+ ECONNREFUSED = 61, /* Connection refused */
+
+ ELOOP = 62, /* Too many levels of symbolic links */
+ ENAMETOOLONG = 63, /* File name too long */
+
+ /* should be rearranged */
+ EHOSTDOWN = 64, /* Host is down */
+ EHOSTUNREACH = 65, /* No route to host */
+ ENOTEMPTY = 66, /* Directory not empty */
+
+ /* quotas & mush */
+ EPROCLIM = 67, /* Too many processes */
+ EUSERS = 68, /* Too many users */
+ EDQUOT = 69, /* Disc quota exceeded */
+
+ /* Network File System */
+ ESTALE = 70, /* Stale NFS file handle */
+ EREMOTE = 71, /* Too many levels of remote in path */
+ EBADRPC = 72, /* RPC struct is bad */
+ ERPCMISMATCH = 73, /* RPC version wrong */
+ EPROGUNAVAIL = 74, /* RPC prog. not avail */
+ EPROGMISMATCH = 75, /* Program version wrong */
+ EPROCUNAVAIL = 76, /* Bad procedure for program */
+
+ ENOLCK = 77, /* No locks available */
+ ENOSYS = 78, /* Function not implemented */
+
+ EFTYPE = 79, /* Inappropriate file type or format */
+ EAUTH = 80, /* Authentication error */
+ ENEEDAUTH = 81, /* Need authenticator */
+
+ /* Intelligent device errors */
+ EPWROFF = 82, /* Device power is off */
+ EDEVERR = 83, /* Device error, e.g. paper out */
+ EOVERFLOW = 84, /* Value too large to be stored in data type */
+
+ /* Program loading errors */
+ EBADEXEC = 85, /* Bad executable */
+ EBADARCH = 86, /* Bad CPU type in executable */
+ ESHLIBVERS = 87, /* Shared library version mismatch */
+ EBADMACHO = 88, /* Malformed Macho file */
+
+ ECANCELED = 89, /* Operation canceled */
+
+ EIDRM = 90, /* Identifier removed */
+ ENOMSG = 91, /* No message of desired type */
+ EILSEQ = 92, /* Illegal byte sequence */
+ ENOATTR = 93, /* Attribute not found */
+
+ EBADMSG = 94, /* Bad message */
+ EMULTIHOP = 95, /* Reserved */
+ ENODATA = 96, /* No message available on STREAM */
+ ENOLINK = 97, /* Reserved */
+ ENOSR = 98, /* No STREAM resources */
+ ENOSTR = 99, /* Not a STREAM */
+ EPROTO = 100, /* Protocol error */
+ ETIME = 101, /* STREAM ioctl timeout */
+
+ ENOPOLICY = 103, /* No such policy registered */
+
+ ENOTRECOVERABLE = 104, /* State not recoverable */
+ EOWNERDEAD = 105, /* Previous owner died */
+
+ EQFULL = 106, /* Interface output queue is full */
+ ELAST = 106, /* Must be equal largest 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
+E2BIG :: _Platform_Error.E2BIG
+ENOEXEC :: _Platform_Error.ENOEXEC
+EBADF :: _Platform_Error.EBADF
+ECHILD :: _Platform_Error.ECHILD
+EDEADLK :: _Platform_Error.EDEADLK
+ENOMEM :: _Platform_Error.ENOMEM
+EACCES :: _Platform_Error.EACCES
+EFAULT :: _Platform_Error.EFAULT
+ENOTBLK :: _Platform_Error.ENOTBLK
+EBUSY :: _Platform_Error.EBUSY
+EEXIST :: _Platform_Error.EEXIST
+EXDEV :: _Platform_Error.EXDEV
+ENODEV :: _Platform_Error.ENODEV
+ENOTDIR :: _Platform_Error.ENOTDIR
+EISDIR :: _Platform_Error.EISDIR
+EINVAL :: _Platform_Error.EINVAL
+ENFILE :: _Platform_Error.ENFILE
+EMFILE :: _Platform_Error.EMFILE
+ENOTTY :: _Platform_Error.ENOTTY
+ETXTBSY :: _Platform_Error.ETXTBSY
+EFBIG :: _Platform_Error.EFBIG
+ENOSPC :: _Platform_Error.ENOSPC
+ESPIPE :: _Platform_Error.ESPIPE
+EROFS :: _Platform_Error.EROFS
+EMLINK :: _Platform_Error.EMLINK
+EPIPE :: _Platform_Error.EPIPE
/* math software */
-EDOM: Errno : 33 /* Numerical argument out of domain */
-ERANGE: Errno : 34 /* Result too large */
+EDOM :: _Platform_Error.EDOM
+ERANGE :: _Platform_Error.ERANGE
/* non-blocking and interrupt i/o */
-EAGAIN: Errno : 35 /* Resource temporarily unavailable */
-EWOULDBLOCK: Errno : EAGAIN /* Operation would block */
-EINPROGRESS: Errno : 36 /* Operation now in progress */
-EALREADY: Errno : 37 /* Operation already in progress */
+EAGAIN :: _Platform_Error.EAGAIN
+EWOULDBLOCK :: _Platform_Error.EWOULDBLOCK
+EINPROGRESS :: _Platform_Error.EINPROGRESS
+EALREADY :: _Platform_Error.EALREADY
/* ipc/network software -- argument errors */
-ENOTSOCK: Errno : 38 /* Socket operation on non-socket */
-EDESTADDRREQ: Errno : 39 /* Destination address required */
-EMSGSIZE: Errno : 40 /* Message too long */
-EPROTOTYPE: Errno : 41 /* Protocol wrong type for socket */
-ENOPROTOOPT: Errno : 42 /* Protocol not available */
-EPROTONOSUPPORT: Errno : 43 /* Protocol not supported */
-ESOCKTNOSUPPORT: Errno : 44 /* Socket type not supported */
-ENOTSUP: Errno : 45 /* Operation not supported */
-EOPNOTSUPP:: ENOTSUP
-EPFNOSUPPORT: Errno : 46 /* Protocol family not supported */
-EAFNOSUPPORT: Errno : 47 /* Address family not supported by protocol family */
-EADDRINUSE: Errno : 48 /* Address already in use */
-EADDRNOTAVAIL: Errno : 49 /* Can't assign requested address */
+ENOTSOCK :: _Platform_Error.ENOTSOCK
+EDESTADDRREQ :: _Platform_Error.EDESTADDRREQ
+EMSGSIZE :: _Platform_Error.EMSGSIZE
+EPROTOTYPE :: _Platform_Error.EPROTOTYPE
+ENOPROTOOPT :: _Platform_Error.ENOPROTOOPT
+EPROTONOSUPPORT :: _Platform_Error.EPROTONOSUPPORT
+ESOCKTNOSUPPORT :: _Platform_Error.ESOCKTNOSUPPORT
+ENOTSUP :: _Platform_Error.ENOTSUP
+EOPNOTSUPP :: _Platform_Error.EOPNOTSUPP
+EPFNOSUPPORT :: _Platform_Error.EPFNOSUPPORT
+EAFNOSUPPORT :: _Platform_Error.EAFNOSUPPORT
+EADDRINUSE :: _Platform_Error.EADDRINUSE
+EADDRNOTAVAIL :: _Platform_Error.EADDRNOTAVAIL
/* ipc/network software -- operational errors */
-ENETDOWN: Errno : 50 /* Network is down */
-ENETUNREACH: Errno : 51 /* Network is unreachable */
-ENETRESET: Errno : 52 /* Network dropped connection on reset */
-ECONNABORTED: Errno : 53 /* Software caused connection abort */
-ECONNRESET: Errno : 54 /* Connection reset by peer */
-ENOBUFS: Errno : 55 /* No buffer space available */
-EISCONN: Errno : 56 /* Socket is already connected */
-ENOTCONN: Errno : 57 /* Socket is not connected */
-ESHUTDOWN: Errno : 58 /* Can't send after socket shutdown */
-ETOOMANYREFS: Errno : 59 /* Too many references: can't splice */
-ETIMEDOUT: Errno : 60 /* Operation timed out */
-ECONNREFUSED: Errno : 61 /* Connection refused */
-
-ELOOP: Errno : 62 /* Too many levels of symbolic links */
-ENAMETOOLONG: Errno : 63 /* File name too long */
+ENETDOWN :: _Platform_Error.ENETDOWN
+ENETUNREACH :: _Platform_Error.ENETUNREACH
+ENETRESET :: _Platform_Error.ENETRESET
+ECONNABORTED :: _Platform_Error.ECONNABORTED
+ECONNRESET :: _Platform_Error.ECONNRESET
+ENOBUFS :: _Platform_Error.ENOBUFS
+EISCONN :: _Platform_Error.EISCONN
+ENOTCONN :: _Platform_Error.ENOTCONN
+ESHUTDOWN :: _Platform_Error.ESHUTDOWN
+ETOOMANYREFS :: _Platform_Error.ETOOMANYREFS
+ETIMEDOUT :: _Platform_Error.ETIMEDOUT
+ECONNREFUSED :: _Platform_Error.ECONNREFUSED
+
+ELOOP :: _Platform_Error.ELOOP
+ENAMETOOLONG :: _Platform_Error.ENAMETOOLONG
/* should be rearranged */
-EHOSTDOWN: Errno : 64 /* Host is down */
-EHOSTUNREACH: Errno : 65 /* No route to host */
-ENOTEMPTY: Errno : 66 /* Directory not empty */
+EHOSTDOWN :: _Platform_Error.EHOSTDOWN
+EHOSTUNREACH :: _Platform_Error.EHOSTUNREACH
+ENOTEMPTY :: _Platform_Error.ENOTEMPTY
/* quotas & mush */
-EPROCLIM: Errno : 67 /* Too many processes */
-EUSERS: Errno : 68 /* Too many users */
-EDQUOT: Errno : 69 /* Disc quota exceeded */
+EPROCLIM :: _Platform_Error.EPROCLIM
+EUSERS :: _Platform_Error.EUSERS
+EDQUOT :: _Platform_Error.EDQUOT
/* Network File System */
-ESTALE: Errno : 70 /* Stale NFS file handle */
-EREMOTE: Errno : 71 /* Too many levels of remote in path */
-EBADRPC: Errno : 72 /* RPC struct is bad */
-ERPCMISMATCH: Errno : 73 /* RPC version wrong */
-EPROGUNAVAIL: Errno : 74 /* RPC prog. not avail */
-EPROGMISMATCH: Errno : 75 /* Program version wrong */
-EPROCUNAVAIL: Errno : 76 /* Bad procedure for program */
+ESTALE :: _Platform_Error.ESTALE
+EREMOTE :: _Platform_Error.EREMOTE
+EBADRPC :: _Platform_Error.EBADRPC
+ERPCMISMATCH :: _Platform_Error.ERPCMISMATCH
+EPROGUNAVAIL :: _Platform_Error.EPROGUNAVAIL
+EPROGMISMATCH :: _Platform_Error.EPROGMISMATCH
+EPROCUNAVAIL :: _Platform_Error.EPROCUNAVAIL
-ENOLCK: Errno : 77 /* No locks available */
-ENOSYS: Errno : 78 /* Function not implemented */
+ENOLCK :: _Platform_Error.ENOLCK
+ENOSYS :: _Platform_Error.ENOSYS
-EFTYPE: Errno : 79 /* Inappropriate file type or format */
-EAUTH: Errno : 80 /* Authentication error */
-ENEEDAUTH: Errno : 81 /* Need authenticator */
+EFTYPE :: _Platform_Error.EFTYPE
+EAUTH :: _Platform_Error.EAUTH
+ENEEDAUTH :: _Platform_Error.ENEEDAUTH
/* Intelligent device errors */
-EPWROFF: Errno : 82 /* Device power is off */
-EDEVERR: Errno : 83 /* Device error, e.g. paper out */
-EOVERFLOW: Errno : 84 /* Value too large to be stored in data type */
+EPWROFF :: _Platform_Error.EPWROFF
+EDEVERR :: _Platform_Error.EDEVERR
+EOVERFLOW :: _Platform_Error.EOVERFLOW
/* Program loading errors */
-EBADEXEC: Errno : 85 /* Bad executable */
-EBADARCH: Errno : 86 /* Bad CPU type in executable */
-ESHLIBVERS: Errno : 87 /* Shared library version mismatch */
-EBADMACHO: Errno : 88 /* Malformed Macho file */
+EBADEXEC :: _Platform_Error.EBADEXEC
+EBADARCH :: _Platform_Error.EBADARCH
+ESHLIBVERS :: _Platform_Error.ESHLIBVERS
+EBADMACHO :: _Platform_Error.EBADMACHO
-ECANCELED: Errno : 89 /* Operation canceled */
+ECANCELED :: _Platform_Error.ECANCELED
-EIDRM: Errno : 90 /* Identifier removed */
-ENOMSG: Errno : 91 /* No message of desired type */
-EILSEQ: Errno : 92 /* Illegal byte sequence */
-ENOATTR: Errno : 93 /* Attribute not found */
+EIDRM :: _Platform_Error.EIDRM
+ENOMSG :: _Platform_Error.ENOMSG
+EILSEQ :: _Platform_Error.EILSEQ
+ENOATTR :: _Platform_Error.ENOATTR
-EBADMSG: Errno : 94 /* Bad message */
-EMULTIHOP: Errno : 95 /* Reserved */
-ENODATA: Errno : 96 /* No message available on STREAM */
-ENOLINK: Errno : 97 /* Reserved */
-ENOSR: Errno : 98 /* No STREAM resources */
-ENOSTR: Errno : 99 /* Not a STREAM */
-EPROTO: Errno : 100 /* Protocol error */
-ETIME: Errno : 101 /* STREAM ioctl timeout */
+EBADMSG :: _Platform_Error.EBADMSG
+EMULTIHOP :: _Platform_Error.EMULTIHOP
+ENODATA :: _Platform_Error.ENODATA
+ENOLINK :: _Platform_Error.ENOLINK
+ENOSR :: _Platform_Error.ENOSR
+ENOSTR :: _Platform_Error.ENOSTR
+EPROTO :: _Platform_Error.EPROTO
+ETIME :: _Platform_Error.ETIME
-ENOPOLICY: Errno : 103 /* No such policy registered */
+ENOPOLICY :: _Platform_Error.ENOPOLICY
-ENOTRECOVERABLE: Errno : 104 /* State not recoverable */
-EOWNERDEAD: Errno : 105 /* Previous owner died */
+ENOTRECOVERABLE :: _Platform_Error.ENOTRECOVERABLE
+EOWNERDEAD :: _Platform_Error.EOWNERDEAD
+
+EQFULL :: _Platform_Error.EQFULL
+ELAST :: _Platform_Error.ELAST
-EQFULL: Errno : 106 /* Interface output queue is full */
-ELAST: Errno : 106 /* Must be equal largest errno */
O_RDONLY :: 0x0000
O_WRONLY :: 0x0001
@@ -424,13 +562,13 @@ S_ISUID :: 0o4000 // Set user id on execution
S_ISGID :: 0o2000 // Set group id on execution
S_ISVTX :: 0o1000 // Directory restrcted delete
-S_ISLNK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFLNK }
-S_ISREG :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFREG }
-S_ISDIR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFDIR }
-S_ISCHR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFCHR }
-S_ISBLK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFBLK }
-S_ISFIFO :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFIFO }
-S_ISSOCK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFSOCK }
+@(require_results) S_ISLNK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFLNK }
+@(require_results) S_ISREG :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFREG }
+@(require_results) S_ISDIR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFDIR }
+@(require_results) S_ISCHR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFCHR }
+@(require_results) S_ISBLK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFBLK }
+@(require_results) S_ISFIFO :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFIFO }
+@(require_results) S_ISSOCK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFSOCK }
R_OK :: 4 // Test for read permission
W_OK :: 2 // Test for write permission
@@ -524,16 +662,19 @@ foreign dl {
@(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---
}
-get_last_error :: proc "contextless" () -> int {
- return int(__error()^)
+@(require_results, no_instrumentation)
+get_last_error :: proc "contextless" () -> Error {
+ return Platform_Error(__error()^)
}
+@(require_results)
get_last_error_string :: proc() -> string {
- return cast(string)_darwin_string_error(cast(c.int)get_last_error())
+ return string(_darwin_string_error(__error()^))
}
-open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno) {
+@(require_results)
+open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (handle: Handle, err: Error) {
isDir := is_dir_path(path)
flags := flags
if isDir {
@@ -546,9 +687,10 @@ open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
- handle := _unix_open(cstr, i32(flags), u16(mode))
- if handle == -1 {
- return INVALID_HANDLE, cast(Errno)get_last_error()
+ handle = _unix_open(cstr, i32(flags), u16(mode))
+ if handle == INVALID_HANDLE {
+ err = get_last_error()
+ return
}
/*
@@ -556,22 +698,22 @@ open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno
should not happen if the handle is a directory
*/
if mode != 0 && !isDir {
- err := fchmod(handle, cast(u16)mode)
- if err != 0 {
+ err = fchmod(handle, cast(u16)mode)
+ if err != nil {
_unix_close(handle)
- return INVALID_HANDLE, err
+ handle = INVALID_HANDLE
}
}
- return handle, 0
+ return
}
-fchmod :: proc(fd: Handle, mode: u16) -> Errno {
- return cast(Errno)_unix_fchmod(fd, mode)
+fchmod :: proc(fd: Handle, mode: u16) -> Error {
+ return cast(Platform_Error)_unix_fchmod(fd, mode)
}
-close :: proc(fd: Handle) -> Errno {
- return cast(Errno)_unix_close(fd)
+close :: proc(fd: Handle) -> Error {
+ return cast(Platform_Error)_unix_close(fd)
}
// If you read or write more than `SSIZE_MAX` bytes, most darwin implementations will return `EINVAL`
@@ -584,73 +726,74 @@ close :: proc(fd: Handle) -> Errno {
@(private)
MAX_RW :: 1 << 30
-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(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, raw_data(data), to_write)
if bytes_written < 0 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return bytes_written, ERROR_NONE
+ return bytes_written, nil
}
-read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
+read :: proc(fd: Handle, data: []u8) -> (int, Error) {
if len(data) == 0 {
- return 0, ERROR_NONE
+ return 0, nil
}
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, raw_data(data), to_read)
if bytes_read < 0 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return bytes_read, ERROR_NONE
+ return bytes_read, 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(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_pread(fd, raw_data(data), to_read, offset)
if bytes_read < 0 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- 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(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_pwrite(fd, raw_data(data), to_write, offset)
if bytes_written < 0 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- 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) {
assert(fd != -1)
final_offset := i64(_unix_lseek(fd, int(offset), c.int(whence)))
if final_offset == -1 {
- return 0, 1
+ return 0, get_last_error()
}
- return final_offset, 0
+ return final_offset, nil
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
+@(require_results)
+file_size :: proc(fd: Handle) -> (i64, Error) {
prev, _ := seek(fd, 0, SEEK_CUR)
size, err := seek(fd, 0, SEEK_END)
seek(fd, prev, SEEK_SET)
@@ -664,69 +807,70 @@ stdin: Handle = 0 // get_std_handle(win32.STD_INPUT_HANDLE);
stdout: Handle = 1 // get_std_handle(win32.STD_OUTPUT_HANDLE);
stderr: Handle = 2 // get_std_handle(win32.STD_ERROR_HANDLE);
-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
}
+@(require_results)
is_path_separator :: proc(r: rune) -> bool {
return r == '/'
}
+@(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)
@@ -735,6 +879,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)
@@ -749,85 +894,84 @@ rename :: proc(old: string, new: string) -> bool {
return _unix_rename(old_cstr, new_cstr) != -1
}
-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)
res := _unix_remove(path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return 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)
s: OS_Stat
result := _unix_stat(cstr, &s)
if result == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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)
s: OS_Stat
result := _unix_lstat(cstr, &s)
if result == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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) {
s: OS_Stat
result := _unix_fstat(fd, &s)
if result == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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
if result == nil {
end_of_stream = true
@@ -838,8 +982,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)
@@ -849,30 +993,27 @@ _readlink :: proc(path: string) -> (string, Errno) {
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
if rc == -1 {
delete(buf)
- return "", Errno(get_last_error())
+ return "", get_last_error()
} else if rc == int(bufsz) {
// NOTE(laleksic, 2021-01-21): Any cleaner way to resize the slice?
bufsz *= 2
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) -> (path: string, err: Error) {
buf: [DARWIN_MAXPATHLEN]byte
- _, err := fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0])))
- if err != ERROR_NONE {
- return "", err
- }
-
- path := strings.clone_from_cstring(cstring(&buf[0]))
- return path, err
+ _ = fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0]))) or_return
+ return strings.clone_from_cstring(cstring(&buf[0]))
}
-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 = "."
@@ -883,14 +1024,14 @@ 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_cstr := cast(cstring)path_ptr
path = strings.clone(string(path_cstr))
- return path, ERROR_NONE
+ return path, nil
}
access :: proc(path: string, mask: int) -> bool {
@@ -899,10 +1040,11 @@ access :: proc(path: string, mask: int) -> bool {
return _unix_access(cstr, c.int(mask)) == 0
}
-flush :: proc(fd: Handle) -> Errno {
- return cast(Errno)_unix_fsync(fd)
+flush :: proc(fd: Handle) -> Error {
+ return cast(Platform_Error)_unix_fsync(fd)
}
+@(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)
@@ -913,32 +1055,34 @@ 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)
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_unsetenv(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 {
page_size := get_page_size() // NOTE(tetra): See note in os_linux.odin/get_current_directory.
buf := make([dynamic]u8, page_size)
@@ -947,7 +1091,7 @@ get_current_directory :: proc() -> string {
if cwd != nil {
return string(cwd)
}
- if Errno(get_last_error()) != ERANGE {
+ if get_last_error() != ERANGE {
delete(buf)
return ""
}
@@ -956,24 +1100,24 @@ 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_chdir(cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-make_directory :: proc(path: string, mode: u16 = 0o775) -> Errno {
+make_directory :: proc(path: string, mode: u16 = 0o775) -> Error {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_mkdir(path_cstr, mode)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
exit :: proc "contextless" (code: int) -> ! {
@@ -981,6 +1125,7 @@ exit :: proc "contextless" (code: int) -> ! {
_unix_exit(i32(code))
}
+@(require_results)
current_thread_id :: proc "contextless" () -> int {
tid: u64
// NOTE(Oskar): available from OSX 10.6 and iOS 3.2.
@@ -991,12 +1136,14 @@ current_thread_id :: proc "contextless" () -> int {
return int(tid)
}
+@(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, flags)
return handle
}
+@(require_results)
dlsym :: proc(handle: rawptr, symbol: string) -> rawptr {
assert(handle != nil)
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
@@ -1012,6 +1159,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.
@@ -1024,7 +1172,7 @@ get_page_size :: proc() -> int {
return page_size
}
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
count : int = 0
count_size := size_of(count)
@@ -1037,6 +1185,7 @@ _processor_core_count :: proc() -> int {
return 1
}
+@(require_results)
_alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__))
for _, i in res {
@@ -1045,106 +1194,108 @@ _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_socket(domain, type, protocol)
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- return Socket(result), ERROR_NONE
+ return Socket(result), nil
}
-connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
+@(require_results)
+connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error {
result := _unix_connect(int(sd), addr, len)
if result < 0 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
+bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error {
result := _unix_bind(int(sd), addr, len)
if result < 0 {
- return Errno(get_last_error())
+ return get_last_error()
}
- 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_accept(int(sd), rawptr(addr), len)
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- 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_listen(int(sd), backlog)
if result < 0 {
- return Errno(get_last_error())
+ return get_last_error()
}
- 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_setsockopt(int(sd), level, optname, optval, optlen)
if result < 0 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-getsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> Errno {
+getsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> Error {
result := _unix_getsockopt(int(sd), level, optname, optval, optlen)
if result < 0 {
- return Errno(get_last_error())
+ return get_last_error()
}
- 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_recvfrom(int(sd), raw_data(data), len(data), flags, addr, addr_size)
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- 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_recv(int(sd), raw_data(data), len(data), flags)
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- 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_sendto(int(sd), raw_data(data), len(data), flags, addr, addrlen)
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- 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_send(int(sd), raw_data(data), len(data), 0)
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- 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_shutdown(int(sd), how)
if result < 0 {
- return Errno(get_last_error())
+ return get_last_error()
}
- 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__fcntl(Handle(fd), c.int(cmd), uintptr(arg))
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- return int(result), ERROR_NONE
+ return int(result), nil
}
diff --git a/core/os/os_essence.odin b/core/os/os_essence.odin
index e4281f6c9..75c4c1156 100644
--- a/core/os/os_essence.odin
+++ b/core/os/os_essence.odin
@@ -2,54 +2,59 @@ package os
import "core:sys/es"
-Handle :: distinct int;
-Errno :: distinct int;
+Handle :: distinct int
+_Platform_Error :: enum i32 {NONE}
-ERROR_NONE :: (Errno) (es.SUCCESS);
+// ERROR_NONE :: Error(es.SUCCESS)
-O_RDONLY :: 0x1;
-O_WRONLY :: 0x2;
-O_CREATE :: 0x4;
-O_TRUNC :: 0x8;
+O_RDONLY :: 0x1
+O_WRONLY :: 0x2
+O_CREATE :: 0x4
+O_TRUNC :: 0x8
-stderr : Handle = 0;
+stderr : Handle = 0
current_thread_id :: proc "contextless" () -> int {
- return (int) (es.ThreadGetID(es.CURRENT_THREAD));
+ return (int) (es.ThreadGetID(es.CURRENT_THREAD))
}
heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
- return es.HeapAllocate(size, zero_memory);
+ return es.HeapAllocate(size, zero_memory)
}
heap_free :: proc(ptr: rawptr) {
- es.HeapFree(ptr);
+ es.HeapFree(ptr)
}
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
- return es.HeapReallocate(ptr, new_size, false);
+ return es.HeapReallocate(ptr, new_size, false)
}
-open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
- return (Handle) (0), (Errno) (1);
+open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
+ return (Handle) (0), (Error) (1)
}
-close :: proc(fd: Handle) -> Errno {
- return (Errno) (1);
+close :: proc(fd: Handle) -> Error {
+ return (Error) (1)
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
- return (i64) (0), (Errno) (1);
+file_size :: proc(fd: Handle) -> (i64, Error) {
+ return (i64) (0), (Error) (1)
}
-read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
- return (int) (0), (Errno) (1);
+read :: proc(fd: Handle, data: []byte) -> (int, Error) {
+ return (int) (0), (Error) (1)
}
-write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
- return (int) (0), (Errno) (1);
+write :: proc(fd: Handle, data: []u8) -> (int, Error) {
+ return (int) (0), (Error) (1)
}
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
- return (i64) (0), (Errno) (1);
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
+ return (i64) (0), (Error) (1)
}
+
+flush :: proc(fd: Handle) -> Error {
+ // do nothing
+ return nil
+} \ No newline at end of file
diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin
index 36ada0948..c7955368e 100644
--- a/core/os/os_freebsd.odin
+++ b/core/os/os_freebsd.odin
@@ -9,105 +9,200 @@ import "core:c"
Handle :: distinct i32
File_Time :: distinct u64
-Errno :: distinct i32
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
-E2BIG: Errno : 7
-ENOEXEC: Errno : 8
-EBADF: Errno : 9
-ECHILD: Errno : 10
-EBEADLK: Errno : 11
-ENOMEM: Errno : 12
-EACCESS: Errno : 13
-EFAULT: Errno : 14
-ENOTBLK: Errno : 15
-EBUSY: Errno : 16
-EEXIST: Errno : 17
-EXDEV: Errno : 18
-ENODEV: Errno : 19
-ENOTDIR: Errno : 20
-EISDIR: Errno : 21
-EINVAL: Errno : 22
-ENFILE: Errno : 23
-EMFILE: Errno : 24
-ENOTTY: Errno : 25
-ETXTBSY: Errno : 26
-EFBIG: Errno : 27
-ENOSPC: Errno : 28
-ESPIPE: Errno : 29
-EROFS: Errno : 30
-EMLINK: Errno : 31
-EPIPE: Errno : 32
-EDOM: Errno : 33
-ERANGE: Errno : 34 /* Result too large */
-EAGAIN: Errno : 35
-EINPROGRESS: Errno : 36
-EALREADY: Errno : 37
-ENOTSOCK: Errno : 38
-EDESTADDRREQ: Errno : 39
-EMSGSIZE: Errno : 40
-EPROTOTYPE: Errno : 41
-ENOPROTOOPT: Errno : 42
-EPROTONOSUPPORT: Errno : 43
-ESOCKTNOSUPPORT: Errno : 44
-EOPNOTSUPP: Errno : 45
-EPFNOSUPPORT: Errno : 46
-EAFNOSUPPORT: Errno : 47
-EADDRINUSE: Errno : 48
-EADDRNOTAVAIL: Errno : 49
-ENETDOWN: Errno : 50
-ENETUNREACH: Errno : 51
-ENETRESET: Errno : 52
-ECONNABORTED: Errno : 53
-ECONNRESET: Errno : 54
-ENOBUFS: Errno : 55
-EISCONN: Errno : 56
-ENOTCONN: Errno : 57
-ESHUTDOWN: Errno : 58
-ETIMEDOUT: Errno : 60
-ECONNREFUSED: Errno : 61
-ELOOP: Errno : 62
-ENAMETOOLING: Errno : 63
-EHOSTDOWN: Errno : 64
-EHOSTUNREACH: Errno : 65
-ENOTEMPTY: Errno : 66
-EPROCLIM: Errno : 67
-EUSERS: Errno : 68
-EDQUOT: Errno : 69
-ESTALE: Errno : 70
-EBADRPC: Errno : 72
-ERPCMISMATCH: Errno : 73
-EPROGUNAVAIL: Errno : 74
-EPROGMISMATCH: Errno : 75
-EPROCUNAVAIL: Errno : 76
-ENOLCK: Errno : 77
-ENOSYS: Errno : 78
-EFTYPE: Errno : 79
-EAUTH: Errno : 80
-ENEEDAUTH: Errno : 81
-EIDRM: Errno : 82
-ENOMSG: Errno : 83
-EOVERFLOW: Errno : 84
-ECANCELED: Errno : 85
-EILSEQ: Errno : 86
-ENOATTR: Errno : 87
-EDOOFUS: Errno : 88
-EBADMSG: Errno : 89
-EMULTIHOP: Errno : 90
-ENOLINK: Errno : 91
-EPROTO: Errno : 92
-ENOTCAPABLE: Errno : 93
-ECAPMODE: Errno : 94
-ENOTRECOVERABLE: Errno : 95
-EOWNERDEAD: Errno : 96
+_Platform_Error :: enum i32 {
+ NONE = 0,
+ EPERM = 1,
+ ENOENT = 2,
+ ESRCH = 3,
+ EINTR = 4,
+ EIO = 5,
+ ENXIO = 6,
+ E2BIG = 7,
+ ENOEXEC = 8,
+ EBADF = 9,
+ ECHILD = 10,
+ EBEADLK = 11,
+ ENOMEM = 12,
+ EACCESS = 13,
+ EFAULT = 14,
+ ENOTBLK = 15,
+ EBUSY = 16,
+ EEXIST = 17,
+ EXDEV = 18,
+ ENODEV = 19,
+ ENOTDIR = 20,
+ EISDIR = 21,
+ EINVAL = 22,
+ ENFILE = 23,
+ EMFILE = 24,
+ ENOTTY = 25,
+ ETXTBSY = 26,
+ EFBIG = 27,
+ ENOSPC = 28,
+ ESPIPE = 29,
+ EROFS = 30,
+ EMLINK = 31,
+ EPIPE = 32,
+ EDOM = 33,
+ ERANGE = 34, /* Result too large */
+ EAGAIN = 35,
+ EINPROGRESS = 36,
+ EALREADY = 37,
+ ENOTSOCK = 38,
+ EDESTADDRREQ = 39,
+ EMSGSIZE = 40,
+ EPROTOTYPE = 41,
+ ENOPROTOOPT = 42,
+ EPROTONOSUPPORT = 43,
+ ESOCKTNOSUPPORT = 44,
+ EOPNOTSUPP = 45,
+ EPFNOSUPPORT = 46,
+ EAFNOSUPPORT = 47,
+ EADDRINUSE = 48,
+ EADDRNOTAVAIL = 49,
+ ENETDOWN = 50,
+ ENETUNREACH = 51,
+ ENETRESET = 52,
+ ECONNABORTED = 53,
+ ECONNRESET = 54,
+ ENOBUFS = 55,
+ EISCONN = 56,
+ ENOTCONN = 57,
+ ESHUTDOWN = 58,
+ ETIMEDOUT = 60,
+ ECONNREFUSED = 61,
+ ELOOP = 62,
+ ENAMETOOLING = 63,
+ EHOSTDOWN = 64,
+ EHOSTUNREACH = 65,
+ ENOTEMPTY = 66,
+ EPROCLIM = 67,
+ EUSERS = 68,
+ EDQUOT = 69,
+ ESTALE = 70,
+ EBADRPC = 72,
+ ERPCMISMATCH = 73,
+ EPROGUNAVAIL = 74,
+ EPROGMISMATCH = 75,
+ EPROCUNAVAIL = 76,
+ ENOLCK = 77,
+ ENOSYS = 78,
+ EFTYPE = 79,
+ EAUTH = 80,
+ ENEEDAUTH = 81,
+ EIDRM = 82,
+ ENOMSG = 83,
+ EOVERFLOW = 84,
+ ECANCELED = 85,
+ EILSEQ = 86,
+ ENOATTR = 87,
+ EDOOFUS = 88,
+ EBADMSG = 89,
+ EMULTIHOP = 90,
+ ENOLINK = 91,
+ EPROTO = 92,
+ ENOTCAPABLE = 93,
+ ECAPMODE = 94,
+ ENOTRECOVERABLE = 95,
+ EOWNERDEAD = 96,
+}
+EPERM :: Platform_Error.EPERM
+ENOENT :: Platform_Error.ENOENT
+ESRCH :: Platform_Error.ESRCH
+EINTR :: Platform_Error.EINTR
+EIO :: Platform_Error.EIO
+ENXIO :: Platform_Error.ENXIO
+E2BIG :: Platform_Error.E2BIG
+ENOEXEC :: Platform_Error.ENOEXEC
+EBADF :: Platform_Error.EBADF
+ECHILD :: Platform_Error.ECHILD
+EBEADLK :: Platform_Error.EBEADLK
+ENOMEM :: Platform_Error.ENOMEM
+EACCESS :: Platform_Error.EACCESS
+EFAULT :: Platform_Error.EFAULT
+ENOTBLK :: Platform_Error.ENOTBLK
+EBUSY :: Platform_Error.EBUSY
+EEXIST :: Platform_Error.EEXIST
+EXDEV :: Platform_Error.EXDEV
+ENODEV :: Platform_Error.ENODEV
+ENOTDIR :: Platform_Error.ENOTDIR
+EISDIR :: Platform_Error.EISDIR
+EINVAL :: Platform_Error.EINVAL
+ENFILE :: Platform_Error.ENFILE
+EMFILE :: Platform_Error.EMFILE
+ENOTTY :: Platform_Error.ENOTTY
+ETXTBSY :: Platform_Error.ETXTBSY
+EFBIG :: Platform_Error.EFBIG
+ENOSPC :: Platform_Error.ENOSPC
+ESPIPE :: Platform_Error.ESPIPE
+EROFS :: Platform_Error.EROFS
+EMLINK :: Platform_Error.EMLINK
+EPIPE :: Platform_Error.EPIPE
+EDOM :: Platform_Error.EDOM
+ERANGE :: Platform_Error.ERANGE
+EAGAIN :: Platform_Error.EAGAIN
+EINPROGRESS :: Platform_Error.EINPROGRESS
+EALREADY :: Platform_Error.EALREADY
+ENOTSOCK :: Platform_Error.ENOTSOCK
+EDESTADDRREQ :: Platform_Error.EDESTADDRREQ
+EMSGSIZE :: Platform_Error.EMSGSIZE
+EPROTOTYPE :: Platform_Error.EPROTOTYPE
+ENOPROTOOPT :: Platform_Error.ENOPROTOOPT
+EPROTONOSUPPORT :: Platform_Error.EPROTONOSUPPORT
+ESOCKTNOSUPPORT :: Platform_Error.ESOCKTNOSUPPORT
+EOPNOTSUPP :: Platform_Error.EOPNOTSUPP
+EPFNOSUPPORT :: Platform_Error.EPFNOSUPPORT
+EAFNOSUPPORT :: Platform_Error.EAFNOSUPPORT
+EADDRINUSE :: Platform_Error.EADDRINUSE
+EADDRNOTAVAIL :: Platform_Error.EADDRNOTAVAIL
+ENETDOWN :: Platform_Error.ENETDOWN
+ENETUNREACH :: Platform_Error.ENETUNREACH
+ENETRESET :: Platform_Error.ENETRESET
+ECONNABORTED :: Platform_Error.ECONNABORTED
+ECONNRESET :: Platform_Error.ECONNRESET
+ENOBUFS :: Platform_Error.ENOBUFS
+EISCONN :: Platform_Error.EISCONN
+ENOTCONN :: Platform_Error.ENOTCONN
+ESHUTDOWN :: Platform_Error.ESHUTDOWN
+ETIMEDOUT :: Platform_Error.ETIMEDOUT
+ECONNREFUSED :: Platform_Error.ECONNREFUSED
+ELOOP :: Platform_Error.ELOOP
+ENAMETOOLING :: Platform_Error.ENAMETOOLING
+EHOSTDOWN :: Platform_Error.EHOSTDOWN
+EHOSTUNREACH :: Platform_Error.EHOSTUNREACH
+ENOTEMPTY :: Platform_Error.ENOTEMPTY
+EPROCLIM :: Platform_Error.EPROCLIM
+EUSERS :: Platform_Error.EUSERS
+EDQUOT :: Platform_Error.EDQUOT
+ESTALE :: Platform_Error.ESTALE
+EBADRPC :: Platform_Error.EBADRPC
+ERPCMISMATCH :: Platform_Error.ERPCMISMATCH
+EPROGUNAVAIL :: Platform_Error.EPROGUNAVAIL
+EPROGMISMATCH :: Platform_Error.EPROGMISMATCH
+EPROCUNAVAIL :: Platform_Error.EPROCUNAVAIL
+ENOLCK :: Platform_Error.ENOLCK
+ENOSYS :: Platform_Error.ENOSYS
+EFTYPE :: Platform_Error.EFTYPE
+EAUTH :: Platform_Error.EAUTH
+ENEEDAUTH :: Platform_Error.ENEEDAUTH
+EIDRM :: Platform_Error.EIDRM
+ENOMSG :: Platform_Error.ENOMSG
+EOVERFLOW :: Platform_Error.EOVERFLOW
+ECANCELED :: Platform_Error.ECANCELED
+EILSEQ :: Platform_Error.EILSEQ
+ENOATTR :: Platform_Error.ENOATTR
+EDOOFUS :: Platform_Error.EDOOFUS
+EBADMSG :: Platform_Error.EBADMSG
+EMULTIHOP :: Platform_Error.EMULTIHOP
+ENOLINK :: Platform_Error.ENOLINK
+EPROTO :: Platform_Error.EPROTO
+ENOTCAPABLE :: Platform_Error.ENOTCAPABLE
+ECAPMODE :: Platform_Error.ECAPMODE
+ENOTRECOVERABLE :: Platform_Error.ENOTRECOVERABLE
+EOWNERDEAD :: Platform_Error.EOWNERDEAD
O_RDONLY :: 0x00000
O_WRONLY :: 0x00001
@@ -258,13 +353,13 @@ S_ISGID :: 0o2000 // Set group id on execution
S_ISVTX :: 0o1000 // Directory restrcted delete
-S_ISLNK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK }
-S_ISREG :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG }
-S_ISDIR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR }
-S_ISCHR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR }
-S_ISBLK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK }
-S_ISFIFO :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO }
-S_ISSOCK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK }
+@(require_results) S_ISLNK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK }
+@(require_results) S_ISREG :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG }
+@(require_results) S_ISDIR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR }
+@(require_results) S_ISCHR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR }
+@(require_results) S_ISBLK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK }
+@(require_results) S_ISFIFO :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO }
+@(require_results) S_ISSOCK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK }
F_OK :: 0 // Test for file existance
X_OK :: 1 // Test for execute permission
@@ -274,7 +369,7 @@ R_OK :: 4 // Test for read permission
F_KINFO :: 22
foreign libc {
- @(link_name="__error") __errno_location :: proc() -> ^c.int ---
+ @(link_name="__error") __Error_location :: proc() -> ^c.int ---
@(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
@(link_name="close") _unix_close :: proc(fd: Handle) -> c.int ---
@@ -320,30 +415,38 @@ foreign dl {
@(link_name="pthread_getthreadid_np") pthread_getthreadid_np :: proc() -> c.int ---
}
+@(require_results)
is_path_separator :: proc(r: rune) -> bool {
return r == '/'
}
-get_last_error :: proc "contextless" () -> int {
- return int(__errno_location()^)
+@(require_results, no_instrumentation)
+get_last_error :: proc "contextless" () -> Error {
+ return Platform_Error(__Error_location()^)
}
-open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
+@(require_results)
+open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, c.int(flags), c.int(mode))
if handle == -1 {
- return INVALID_HANDLE, Errno(get_last_error())
+ return INVALID_HANDLE, get_last_error()
}
- return handle, ERROR_NONE
+ return handle, nil
}
-close :: proc(fd: Handle) -> Errno {
+close :: proc(fd: Handle) -> Error {
result := _unix_close(fd)
if result == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
+}
+
+flush :: proc(fd: Handle) -> Error {
+ // do nothing
+ return nil
}
// If you read or write more than `INT_MAX` bytes, FreeBSD returns `EINVAL`.
@@ -354,124 +457,148 @@ 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) {
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, &data[0], to_read)
if bytes_read == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return int(bytes_read), ERROR_NONE
+ return int(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(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, &data[0], to_write)
if bytes_written == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
+ }
+ return int(bytes_written), nil
+}
+
+read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = read(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
+ }
+ return
+}
+
+write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = write(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
}
- return int(bytes_written), ERROR_NONE
+ return
}
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
res := _unix_seek(fd, offset, c.int(whence))
if res == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return res, ERROR_NONE
+ return res, nil
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
- s, err := _fstat(fd)
- if err != ERROR_NONE {
- return -1, err
- }
- return s.size, ERROR_NONE
+@(require_results)
+file_size :: proc(fd: Handle) -> (size: i64, err: Error) {
+ size = -1
+ s := _fstat(fd) or_return
+ size = s.size
+ return
}
-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)
res := _unix_rename(old_path_cstr, new_path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-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)
res := _unix_unlink(path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-make_directory :: proc(path: string, mode: mode_t = 0o775) -> Errno {
+make_directory :: proc(path: string, mode: mode_t = 0o775) -> Error {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_mkdir(path_cstr, mode)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-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)
res := _unix_rmdir(path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
+@(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)
@@ -490,38 +617,40 @@ 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) {
+@(require_results)
+last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
s, err := _fstat(fd)
- if err != ERROR_NONE {
+ if err != nil {
return 0, err
}
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) {
+@(require_results)
+last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
s, err := _stat(name)
- if err != ERROR_NONE {
+ if err != nil {
return 0, err
}
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)
s: OS_Stat = ---
result := _unix_lstat(cstr, &s)
if result == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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)
@@ -529,54 +658,53 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat = ---
res := _unix_lstat(cstr, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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) {
s: OS_Stat = ---
result := _unix_fstat(fd, &s)
if result == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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
if result == nil {
end_of_stream = true
@@ -586,8 +714,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)
@@ -598,20 +726,21 @@ _readlink :: proc(path: string) -> (string, Errno) {
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
if rc == -1 {
delete(buf)
- return "", Errno(get_last_error())
+ return "", get_last_error()
} else if rc == int(bufsz) {
bufsz += MAX_PATH
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
}
}
- return "", Errno{}
+ return "", Error{}
}
-absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
+@(require_results)
+absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
// NOTE(Feoramund): The situation isn't ideal, but this was the best way I
// could find to implement this. There are a couple outstanding bug reports
// regarding the desire to retrieve an absolute path from a handle, but to
@@ -626,14 +755,15 @@ absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
res := _unix_fcntl(fd, F_KINFO, cast(uintptr)&kinfo)
if res == -1 {
- return "", Errno(get_last_error())
+ return "", get_last_error()
}
path := strings.clone_from_cstring_bounded(cast(cstring)&kinfo.path[0], len(kinfo.path))
- return path, ERROR_NONE
+ return path, nil
}
-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 = "."
@@ -644,27 +774,28 @@ 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_access(cstr, c.int(mask))
if result == -1 {
- return false, Errno(get_last_error())
+ return false, get_last_error()
}
- 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)
@@ -676,11 +807,13 @@ 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
}
+@(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.
@@ -692,7 +825,7 @@ get_current_directory :: proc() -> string {
if cwd != nil {
return string(cwd)
}
- if Errno(get_last_error()) != ERANGE {
+ if get_last_error() != ERANGE {
delete(buf)
return ""
}
@@ -701,14 +834,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_chdir(cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
exit :: proc "contextless" (code: int) -> ! {
@@ -716,16 +849,19 @@ exit :: proc "contextless" (code: int) -> ! {
_unix_exit(c.int(code))
}
+@(require_results)
current_thread_id :: proc "contextless" () -> int {
return cast(int) pthread_getthreadid_np()
}
+@(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()
@@ -741,6 +877,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.
@@ -753,7 +890,7 @@ get_page_size :: proc() -> int {
return page_size
}
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
count : int = 0
count_size := size_of(count)
@@ -767,6 +904,7 @@ _processor_core_count :: proc() -> int {
}
+@(require_results)
_alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ {
diff --git a/core/os/os_haiku.odin b/core/os/os_haiku.odin
index 06052fc42..7f1ec7089 100644
--- a/core/os/os_haiku.odin
+++ b/core/os/os_haiku.odin
@@ -10,16 +10,14 @@ import "core:sys/haiku"
Handle :: i32
Pid :: i32
File_Time :: i64
-Errno :: i32
+_Platform_Error :: haiku.Errno
MAX_PATH :: haiku.PATH_MAX
-ENOSYS :: int(haiku.Errno.POSIX_ERROR_BASE) + 9
+ENOSYS :: _Platform_Error(i32(haiku.Errno.POSIX_ERROR_BASE) + 9)
INVALID_HANDLE :: ~Handle(0)
-ERROR_NONE: Errno: 0
-
stdin: Handle = 0
stdout: Handle = 1
stderr: Handle = 2
@@ -121,7 +119,7 @@ S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK
foreign libc {
- @(link_name="_errnop") __error :: proc() -> ^c.int ---
+ @(link_name="_errorp") __error :: proc() -> ^c.int ---
@(link_name="fork") _unix_fork :: proc() -> pid_t ---
@(link_name="getthrid") _unix_getthrid :: proc() -> int ---
@@ -179,38 +177,47 @@ Dirent :: struct {
Dir :: distinct rawptr // DIR*
+@(require_results)
is_path_separator :: proc(r: rune) -> bool {
return r == '/'
}
-get_last_error :: proc "contextless" () -> int {
- return int(__error()^)
+@(require_results, no_instrumentation)
+get_last_error :: proc "contextless" () -> Error {
+ return Platform_Error(__error()^)
}
-fork :: proc() -> (Pid, Errno) {
+@(require_results)
+fork :: proc() -> (Pid, Error) {
pid := _unix_fork()
if pid == -1 {
- return Pid(-1), Errno(get_last_error())
+ return Pid(-1), get_last_error()
}
- return Pid(pid), ERROR_NONE
+ return Pid(pid), nil
}
-open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
+@(require_results)
+open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, c.int(flags), c.int(mode))
if handle == -1 {
- return INVALID_HANDLE, Errno(get_last_error())
+ return INVALID_HANDLE, get_last_error()
}
- return handle, ERROR_NONE
+ return handle, nil
}
-close :: proc(fd: Handle) -> Errno {
+close :: proc(fd: Handle) -> Error {
result := _unix_close(fd)
if result == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
+}
+
+flush :: proc(fd: Handle) -> Error {
+ // do nothing
+ return nil
}
// In practice a read/write call would probably never read/write these big buffers all at once,
@@ -220,47 +227,69 @@ 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) {
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, &data[0], to_read)
if bytes_read == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return int(bytes_read), ERROR_NONE
+ return int(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(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, &data[0], to_write)
if bytes_written == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
+ }
+ return int(bytes_written), nil
+}
+
+read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = read(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
}
- return int(bytes_written), ERROR_NONE
+ return
}
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = write(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
+ }
+ return
+}
+
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
res := _unix_seek(fd, offset, c.int(whence))
if res == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return res, ERROR_NONE
+ return res, nil
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
+@(require_results)
+file_size :: proc(fd: Handle) -> (i64, Error) {
s, err := _fstat(fd)
- if err != ERROR_NONE {
+ if err != nil {
return -1, err
}
- return s.size, ERROR_NONE
+ return s.size, nil
}
// "Argv" arguments converted to Odin strings
args := _alloc_command_line_arguments()
+@(require_results)
_alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ {
@@ -269,8 +298,8 @@ _alloc_command_line_arguments :: proc() -> []string {
return res
}
-@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)
@@ -278,13 +307,13 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat = ---
res := _unix_stat(cstr, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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)
@@ -292,55 +321,54 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat = ---
res := _unix_lstat(cstr, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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
s: OS_Stat = ---
res := _unix_fstat(fd, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- return s, ERROR_NONE
+ return s, nil
}
-@private
-_fdopendir :: proc(fd: Handle) -> (Dir, Errno) {
+@(private)
+_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
if result == nil {
end_of_stream = true
@@ -350,8 +378,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)
@@ -361,22 +389,24 @@ _readlink :: proc(path: string) -> (string, Errno) {
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
if rc == -1 {
delete(buf)
- return "", Errno(get_last_error())
+ return "", get_last_error()
} else if rc == int(bufsz) {
bufsz += MAX_PATH
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) {
- return "", Errno(ENOSYS)
+@(require_results)
+absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
+ return "", Error(ENOSYS)
}
-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 = "."
@@ -387,26 +417,27 @@ 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_cstr := transmute(cstring)path_ptr
- path = strings.clone( string(path_cstr) )
+ path_cstr := cstring(path_ptr)
+ path = strings.clone(string(path_cstr))
- 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)
res := _unix_access(cstr, c.int(mask))
if res == -1 {
- return false, Errno(get_last_error())
+ return false, get_last_error()
}
- 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)
@@ -417,12 +448,13 @@ 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
}
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
info: haiku.system_info
haiku.get_system_info(&info)
diff --git a/core/os/os_js.odin b/core/os/os_js.odin
index 8b61cb7ed..eb434c727 100644
--- a/core/os/os_js.odin
+++ b/core/os/os_js.odin
@@ -3,42 +3,45 @@ package os
import "base:runtime"
+@(require_results)
is_path_separator :: proc(c: byte) -> bool {
return c == '/' || c == '\\'
}
-open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
+@(require_results)
+open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) {
unimplemented("core:os procedure not supported on JS target")
}
-close :: proc(fd: Handle) -> Errno {
+close :: proc(fd: Handle) -> Error {
unimplemented("core:os procedure not supported on JS target")
}
-flush :: proc(fd: Handle) -> (err: Errno) {
+flush :: proc(fd: Handle) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
+write :: proc(fd: Handle, data: []byte) -> (int, Error) {
unimplemented("core:os procedure not supported on JS target")
}
@(private="file")
-read_console :: proc(handle: Handle, b: []byte) -> (n: int, err: Errno) {
+read_console :: proc(handle: Handle, b: []byte) -> (n: int, err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
+read :: proc(fd: Handle, data: []byte) -> (int, Error) {
unimplemented("core:os procedure not supported on JS target")
}
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
unimplemented("core:os procedure not supported on JS target")
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
+@(require_results)
+file_size :: proc(fd: Handle) -> (i64, Error) {
unimplemented("core:os procedure not supported on JS target")
}
@@ -47,38 +50,42 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
MAX_RW :: 1<<30
@(private)
-pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
+pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
unimplemented("core:os procedure not supported on JS target")
}
@(private)
-pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
+pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
unimplemented("core:os procedure not supported on JS target")
}
-read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
+read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
+write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
stdout: Handle = 1
stderr: Handle = 2
+@(require_results)
get_std_handle :: proc "contextless" (h: uint) -> Handle {
context = runtime.default_context()
unimplemented("core:os procedure not supported on JS target")
}
+@(require_results)
exists :: proc(path: string) -> bool {
unimplemented("core:os procedure not supported on JS target")
}
+@(require_results)
is_file :: proc(path: string) -> bool {
unimplemented("core:os procedure not supported on JS target")
}
+@(require_results)
is_dir :: proc(path: string) -> bool {
unimplemented("core:os procedure not supported on JS target")
}
@@ -86,82 +93,118 @@ is_dir :: proc(path: string) -> bool {
// NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName
//@private cwd_lock := win32.SRWLOCK{} // zero is initialized
+@(require_results)
get_current_directory :: proc(allocator := context.allocator) -> string {
unimplemented("core:os procedure not supported on JS target")
}
-set_current_directory :: proc(path: string) -> (err: Errno) {
+set_current_directory :: proc(path: string) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-change_directory :: proc(path: string) -> (err: Errno) {
+change_directory :: proc(path: string) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-make_directory :: proc(path: string, mode: u32 = 0) -> (err: Errno) {
+make_directory :: proc(path: string, mode: u32 = 0) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-remove_directory :: proc(path: string) -> (err: Errno) {
+remove_directory :: proc(path: string) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-@(private)
+@(private, require_results)
is_abs :: proc(path: string) -> bool {
unimplemented("core:os procedure not supported on JS target")
}
-@(private)
+@(private, require_results)
fix_long_path :: proc(path: string) -> string {
unimplemented("core:os procedure not supported on JS target")
}
-link :: proc(old_name, new_name: string) -> (err: Errno) {
+link :: proc(old_name, new_name: string) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-unlink :: proc(path: string) -> (err: Errno) {
+unlink :: proc(path: string) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-rename :: proc(old_path, new_path: string) -> (err: Errno) {
+rename :: proc(old_path, new_path: string) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-ftruncate :: proc(fd: Handle, length: i64) -> (err: Errno) {
+ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-truncate :: proc(path: string, length: i64) -> (err: Errno) {
+truncate :: proc(path: string, length: i64) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-remove :: proc(name: string) -> Errno {
+remove :: proc(name: string) -> Error {
unimplemented("core:os procedure not supported on JS target")
}
-pipe :: proc() -> (r, w: Handle, err: Errno) {
+@(require_results)
+pipe :: proc() -> (r, w: Handle, err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
-read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
+@(require_results)
+read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
Handle :: distinct uintptr
File_Time :: distinct u64
-Errno :: distinct int
+
+_Platform_Error :: enum i32 {
+ NONE = 0,
+ FILE_NOT_FOUND = 2,
+ PATH_NOT_FOUND = 3,
+ ACCESS_DENIED = 5,
+ INVALID_HANDLE = 6,
+ NOT_ENOUGH_MEMORY = 8,
+ NO_MORE_FILES = 18,
+ HANDLE_EOF = 38,
+ NETNAME_DELETED = 64,
+ FILE_EXISTS = 80,
+ INVALID_PARAMETER = 87,
+ BROKEN_PIPE = 109,
+ BUFFER_OVERFLOW = 111,
+ INSUFFICIENT_BUFFER = 122,
+ MOD_NOT_FOUND = 126,
+ PROC_NOT_FOUND = 127,
+ DIR_NOT_EMPTY = 145,
+ ALREADY_EXISTS = 183,
+ ENVVAR_NOT_FOUND = 203,
+ MORE_DATA = 234,
+ OPERATION_ABORTED = 995,
+ IO_PENDING = 997,
+ NOT_FOUND = 1168,
+ PRIVILEGE_NOT_HELD = 1314,
+ WSAEACCES = 10013,
+ WSAECONNRESET = 10054,
+
+ // Windows reserves errors >= 1<<29 for application use
+ FILE_IS_PIPE = 1<<29 + 0,
+ FILE_IS_NOT_DIR = 1<<29 + 1,
+ NEGATIVE_OFFSET = 1<<29 + 2,
+}
INVALID_HANDLE :: ~Handle(0)
@@ -182,37 +225,34 @@ O_ASYNC :: 0x02000
O_CLOEXEC :: 0x80000
-ERROR_NONE: Errno : 0
-ERROR_FILE_NOT_FOUND: Errno : 2
-ERROR_PATH_NOT_FOUND: Errno : 3
-ERROR_ACCESS_DENIED: Errno : 5
-ERROR_INVALID_HANDLE: Errno : 6
-ERROR_NOT_ENOUGH_MEMORY: Errno : 8
-ERROR_NO_MORE_FILES: Errno : 18
-ERROR_HANDLE_EOF: Errno : 38
-ERROR_NETNAME_DELETED: Errno : 64
-ERROR_FILE_EXISTS: Errno : 80
-ERROR_INVALID_PARAMETER: Errno : 87
-ERROR_BROKEN_PIPE: Errno : 109
-ERROR_BUFFER_OVERFLOW: Errno : 111
-ERROR_INSUFFICIENT_BUFFER: Errno : 122
-ERROR_MOD_NOT_FOUND: Errno : 126
-ERROR_PROC_NOT_FOUND: Errno : 127
-ERROR_DIR_NOT_EMPTY: Errno : 145
-ERROR_ALREADY_EXISTS: Errno : 183
-ERROR_ENVVAR_NOT_FOUND: Errno : 203
-ERROR_MORE_DATA: Errno : 234
-ERROR_OPERATION_ABORTED: Errno : 995
-ERROR_IO_PENDING: Errno : 997
-ERROR_NOT_FOUND: Errno : 1168
-ERROR_PRIVILEGE_NOT_HELD: Errno : 1314
-WSAEACCES: Errno : 10013
-WSAECONNRESET: Errno : 10054
-
-// Windows reserves errors >= 1<<29 for application use
-ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0
-ERROR_FILE_IS_NOT_DIR: Errno : 1<<29 + 1
-ERROR_NEGATIVE_OFFSET: Errno : 1<<29 + 2
+ERROR_FILE_NOT_FOUND :: Platform_Error.FILE_NOT_FOUND
+ERROR_PATH_NOT_FOUND :: Platform_Error.PATH_NOT_FOUND
+ERROR_ACCESS_DENIED :: Platform_Error.ACCESS_DENIED
+ERROR_INVALID_HANDLE :: Platform_Error.INVALID_HANDLE
+ERROR_NOT_ENOUGH_MEMORY :: Platform_Error.NOT_ENOUGH_MEMORY
+ERROR_NO_MORE_FILES :: Platform_Error.NO_MORE_FILES
+ERROR_HANDLE_EOF :: Platform_Error.HANDLE_EOF
+ERROR_NETNAME_DELETED :: Platform_Error.NETNAME_DELETED
+ERROR_FILE_EXISTS :: Platform_Error.FILE_EXISTS
+ERROR_INVALID_PARAMETER :: Platform_Error.INVALID_PARAMETER
+ERROR_BROKEN_PIPE :: Platform_Error.BROKEN_PIPE
+ERROR_BUFFER_OVERFLOW :: Platform_Error.BUFFER_OVERFLOW
+ERROR_INSUFFICIENT_BUFFER :: Platform_Error.INSUFFICIENT_BUFFER
+ERROR_MOD_NOT_FOUND :: Platform_Error.MOD_NOT_FOUND
+ERROR_PROC_NOT_FOUND :: Platform_Error.PROC_NOT_FOUND
+ERROR_DIR_NOT_EMPTY :: Platform_Error.DIR_NOT_EMPTY
+ERROR_ALREADY_EXISTS :: Platform_Error.ALREADY_EXISTS
+ERROR_ENVVAR_NOT_FOUND :: Platform_Error.ENVVAR_NOT_FOUND
+ERROR_MORE_DATA :: Platform_Error.MORE_DATA
+ERROR_OPERATION_ABORTED :: Platform_Error.OPERATION_ABORTED
+ERROR_IO_PENDING :: Platform_Error.IO_PENDING
+ERROR_NOT_FOUND :: Platform_Error.NOT_FOUND
+ERROR_PRIVILEGE_NOT_HELD :: Platform_Error.PRIVILEGE_NOT_HELD
+WSAEACCES :: Platform_Error.WSAEACCES
+WSAECONNRESET :: Platform_Error.WSAECONNRESET
+
+ERROR_FILE_IS_PIPE :: General_Error.File_Is_Pipe
+ERROR_FILE_IS_NOT_DIR :: General_Error.Not_Dir
// "Argv" arguments converted to Odin strings
args := _alloc_command_line_arguments()
@@ -221,20 +261,23 @@ args := _alloc_command_line_arguments()
-last_write_time :: proc(fd: Handle) -> (File_Time, Errno) {
+@(require_results)
+last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
unimplemented("core:os procedure not supported on JS target")
}
-last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
+@(require_results)
+last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
unimplemented("core:os procedure not supported on JS target")
}
+@(require_results)
get_page_size :: proc() -> int {
unimplemented("core:os procedure not supported on JS target")
}
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
unimplemented("core:os procedure not supported on JS target")
}
@@ -246,6 +289,7 @@ exit :: proc "contextless" (code: int) -> ! {
+@(require_results)
current_thread_id :: proc "contextless" () -> int {
context = runtime.default_context()
unimplemented("core:os procedure not supported on JS target")
@@ -253,6 +297,7 @@ current_thread_id :: proc "contextless" () -> int {
+@(require_results)
_alloc_command_line_arguments :: proc() -> []string {
return nil
}
diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin
index ebc1b3600..1e110d18f 100644
--- a/core/os/os_linux.odin
+++ b/core/os/os_linux.odin
@@ -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
}
diff --git a/core/os/os_netbsd.odin b/core/os/os_netbsd.odin
index da34a4168..c41dc6aa6 100644
--- a/core/os/os_netbsd.odin
+++ b/core/os/os_netbsd.odin
@@ -9,150 +9,289 @@ import "core:c"
Handle :: distinct i32
File_Time :: distinct u64
-Errno :: distinct i32
INVALID_HANDLE :: ~Handle(0)
-ERROR_NONE: Errno : 0 /* No error */
-EPERM: Errno : 1 /* Operation not permitted */
-ENOENT: Errno : 2 /* No such file or directory */
-EINTR: Errno : 4 /* Interrupted system call */
-ESRCH: Errno : 3 /* No such process */
-EIO: Errno : 5 /* Input/output error */
-ENXIO: Errno : 6 /* Device not configured */
-E2BIG: Errno : 7 /* Argument list too long */
-ENOEXEC: Errno : 8 /* Exec format error */
-EBADF: Errno : 9 /* Bad file descriptor */
-ECHILD: Errno : 10 /* No child processes */
-EDEADLK: Errno : 11 /* Resource deadlock avoided. 11 was EAGAIN */
-ENOMEM: Errno : 12 /* Cannot allocate memory */
-EACCES: Errno : 13 /* Permission denied */
-EFAULT: Errno : 14 /* Bad address */
-ENOTBLK: Errno : 15 /* Block device required */
-EBUSY: Errno : 16 /* Device busy */
-EEXIST: Errno : 17 /* File exists */
-EXDEV: Errno : 18 /* Cross-device link */
-ENODEV: Errno : 19 /* Operation not supported by device */
-ENOTDIR: Errno : 20 /* Not a directory */
-EISDIR: Errno : 21 /* Is a directory */
-EINVAL: Errno : 22 /* Invalid argument */
-ENFILE: Errno : 23 /* Too many open files in system */
-EMFILE: Errno : 24 /* Too many open files */
-ENOTTY: Errno : 25 /* Inappropriate ioctl for device */
-ETXTBSY: Errno : 26 /* Text file busy */
-EFBIG: Errno : 27 /* File too large */
-ENOSPC: Errno : 28 /* No space left on device */
-ESPIPE: Errno : 29 /* Illegal seek */
-EROFS: Errno : 30 /* Read-only file system */
-EMLINK: Errno : 31 /* Too many links */
-EPIPE: Errno : 32 /* Broken pipe */
+_Platform_Error :: enum i32 {
+ NONE = 0,
+ EPERM = 1, /* Operation not permitted */
+ ENOENT = 2, /* No such file or directory */
+ EINTR = 4, /* Interrupted system call */
+ ESRCH = 3, /* No such process */
+ EIO = 5, /* Input/output error */
+ ENXIO = 6, /* Device not configured */
+ E2BIG = 7, /* Argument list too long */
+ ENOEXEC = 8, /* Exec format error */
+ EBADF = 9, /* Bad file descriptor */
+ ECHILD = 10, /* No child processes */
+ EDEADLK = 11, /* Resource deadlock avoided. 11 was EAGAIN */
+ ENOMEM = 12, /* Cannot allocate memory */
+ EACCES = 13, /* Permission denied */
+ EFAULT = 14, /* Bad address */
+ ENOTBLK = 15, /* Block device required */
+ EBUSY = 16, /* Device busy */
+ EEXIST = 17, /* File exists */
+ EXDEV = 18, /* Cross-device link */
+ ENODEV = 19, /* Operation not supported by device */
+ ENOTDIR = 20, /* Not a directory */
+ EISDIR = 21, /* Is a directory */
+ EINVAL = 22, /* Invalid argument */
+ ENFILE = 23, /* Too many open files in system */
+ EMFILE = 24, /* Too many open files */
+ ENOTTY = 25, /* Inappropriate ioctl for device */
+ ETXTBSY = 26, /* Text file busy */
+ EFBIG = 27, /* File too large */
+ ENOSPC = 28, /* No space left on device */
+ ESPIPE = 29, /* Illegal seek */
+ EROFS = 30, /* Read-only file system */
+ EMLINK = 31, /* Too many links */
+ EPIPE = 32, /* Broken pipe */
+
+ /* math software */
+ EDOM = 33, /* Numerical argument out of domain */
+ ERANGE = 34, /* Result too large or too small */
+
+ /* non-blocking and interrupt i/o */
+ EAGAIN = 35, /* Resource temporarily unavailable */
+ EWOULDBLOCK = EAGAIN, /* Operation would block */
+ EINPROGRESS = 36, /* Operation now in progress */
+ EALREADY = 37, /* Operation already in progress */
+
+ /* ipc/network software -- argument errors */
+ ENOTSOCK = 38, /* Socket operation on non-socket */
+ EDESTADDRREQ = 39, /* Destination address required */
+ EMSGSIZE = 40, /* Message too long */
+ EPROTOTYPE = 41, /* Protocol wrong type for socket */
+ ENOPROTOOPT = 42, /* Protocol option not available */
+ EPROTONOSUPPORT = 43, /* Protocol not supported */
+ ESOCKTNOSUPPORT = 44, /* Socket type not supported */
+ EOPNOTSUPP = 45, /* Operation not supported */
+ EPFNOSUPPORT = 46, /* Protocol family not supported */
+ EAFNOSUPPORT = 47, /* Address family not supported by protocol family */
+ EADDRINUSE = 48, /* Address already in use */
+ EADDRNOTAVAIL = 49, /* Can't assign requested address */
+
+ /* ipc/network software -- operational errors */
+ ENETDOWN = 50, /* Network is down */
+ ENETUNREACH = 51, /* Network is unreachable */
+ ENETRESET = 52, /* Network dropped connection on reset */
+ ECONNABORTED = 53, /* Software caused connection abort */
+ ECONNRESET = 54, /* Connection reset by peer */
+ ENOBUFS = 55, /* No buffer space available */
+ EISCONN = 56, /* Socket is already connected */
+ ENOTCONN = 57, /* Socket is not connected */
+ ESHUTDOWN = 58, /* Can't send after socket shutdown */
+ ETOOMANYREFS = 59, /* Too many references: can't splice */
+ ETIMEDOUT = 60, /* Operation timed out */
+ ECONNREFUSED = 61, /* Connection refused */
+
+ ELOOP = 62, /* Too many levels of symbolic links */
+ ENAMETOOLONG = 63, /* File name too long */
+
+ /* should be rearranged */
+ EHOSTDOWN = 64, /* Host is down */
+ EHOSTUNREACH = 65, /* No route to host */
+ ENOTEMPTY = 66, /* Directory not empty */
+
+ /* quotas & mush */
+ EPROCLIM = 67, /* Too many processes */
+ EUSERS = 68, /* Too many users */
+ EDQUOT = 69, /* Disc quota exceeded */
+
+ /* Network File System */
+ ESTALE = 70, /* Stale NFS file handle */
+ EREMOTE = 71, /* Too many levels of remote in path */
+ EBADRPC = 72, /* RPC struct is bad */
+ ERPCMISMATCH = 73, /* RPC version wrong */
+ EPROGUNAVAIL = 74, /* RPC prog. not avail */
+ EPROGMISMATCH = 75, /* Program version wrong */
+ EPROCUNAVAIL = 76, /* Bad procedure for program */
+
+ ENOLCK = 77, /* No locks available */
+ ENOSYS = 78, /* Function not implemented */
+
+ EFTYPE = 79, /* Inappropriate file type or format */
+ EAUTH = 80, /* Authentication error */
+ ENEEDAUTH = 81, /* Need authenticator */
+
+ /* SystemV IPC */
+ EIDRM = 82, /* Identifier removed */
+ ENOMSG = 83, /* No message of desired type */
+ EOVERFLOW = 84, /* Value too large to be stored in data type */
+
+ /* Wide/multibyte-character handling, ISO/IEC 9899/AMD1:1995 */
+ EILSEQ = 85, /* Illegal byte sequence */
+
+ /* From IEEE Std 1003.1-2001 */
+ /* Base, Realtime, Threads or Thread Priority Scheduling option errors */
+ ENOTSUP = 86, /* Not supported */
+
+ /* Realtime option errors */
+ ECANCELED = 87, /* Operation canceled */
+
+ /* Realtime, XSI STREAMS option errors */
+ EBADMSG = 88, /* Bad or Corrupt message */
+
+ /* XSI STREAMS option errors */
+ ENODATA = 89, /* No message available */
+ ENOSR = 90, /* No STREAM resources */
+ ENOSTR = 91, /* Not a STREAM */
+ ETIME = 92, /* STREAM ioctl timeout */
+
+ /* File system extended attribute errors */
+ ENOATTR = 93, /* Attribute not found */
+
+ /* Realtime, XSI STREAMS option errors */
+ EMULTIHOP = 94, /* Multihop attempted */
+ ENOLINK = 95, /* Link has been severed */
+ EPROTO = 96, /* Protocol error */
+
+ /* Robust mutexes */
+ EOWNERDEAD = 97, /* Previous owner died */
+ ENOTRECOVERABLE = 98, /* State not recoverable */
+
+ ELAST = 98, /* Must equal largest Error */
+}
+
+EPERM :: Platform_Error.EPERM /* Operation not permitted */
+ENOENT :: Platform_Error.ENOENT /* No such file or directory */
+EINTR :: Platform_Error.EINTR /* Interrupted system call */
+ESRCH :: Platform_Error.ESRCH /* No such process */
+EIO :: Platform_Error.EIO /* Input/output error */
+ENXIO :: Platform_Error.ENXIO /* Device not configured */
+E2BIG :: Platform_Error.E2BIG /* Argument list too long */
+ENOEXEC :: Platform_Error.ENOEXEC /* Exec format error */
+EBADF :: Platform_Error.EBADF /* Bad file descriptor */
+ECHILD :: Platform_Error.ECHILD /* No child processes */
+EDEADLK :: Platform_Error.EDEADLK /* Resource deadlock avoided. 11 was EAGAIN */
+ENOMEM :: Platform_Error.ENOMEM /* Cannot allocate memory */
+EACCES :: Platform_Error.EACCES /* Permission denied */
+EFAULT :: Platform_Error.EFAULT /* Bad address */
+ENOTBLK :: Platform_Error.ENOTBLK /* Block device required */
+EBUSY :: Platform_Error.EBUSY /* Device busy */
+EEXIST :: Platform_Error.EEXIST /* File exists */
+EXDEV :: Platform_Error.EXDEV /* Cross-device link */
+ENODEV :: Platform_Error.ENODEV /* Operation not supported by device */
+ENOTDIR :: Platform_Error.ENOTDIR /* Not a directory */
+EISDIR :: Platform_Error.EISDIR /* Is a directory */
+EINVAL :: Platform_Error.EINVAL /* Invalid argument */
+ENFILE :: Platform_Error.ENFILE /* Too many open files in system */
+EMFILE :: Platform_Error.EMFILE /* Too many open files */
+ENOTTY :: Platform_Error.ENOTTY /* Inappropriate ioctl for device */
+ETXTBSY :: Platform_Error.ETXTBSY /* Text file busy */
+EFBIG :: Platform_Error.EFBIG /* File too large */
+ENOSPC :: Platform_Error.ENOSPC /* No space left on device */
+ESPIPE :: Platform_Error.ESPIPE /* Illegal seek */
+EROFS :: Platform_Error.EROFS /* Read-only file system */
+EMLINK :: Platform_Error.EMLINK /* Too many links */
+EPIPE :: Platform_Error.EPIPE /* Broken pipe */
/* math software */
-EDOM: Errno : 33 /* Numerical argument out of domain */
-ERANGE: Errno : 34 /* Result too large or too small */
+EDOM :: Platform_Error.EDOM /* Numerical argument out of domain */
+ERANGE :: Platform_Error.ERANGE /* Result too large or too small */
/* non-blocking and interrupt i/o */
-EAGAIN: Errno : 35 /* Resource temporarily unavailable */
-EWOULDBLOCK: Errno : EAGAIN /* Operation would block */
-EINPROGRESS: Errno : 36 /* Operation now in progress */
-EALREADY: Errno : 37 /* Operation already in progress */
+EAGAIN :: Platform_Error.EAGAIN /* Resource temporarily unavailable */
+EWOULDBLOCK :: EAGAIN /* Operation would block */
+EINPROGRESS :: Platform_Error.EINPROGRESS /* Operation now in progress */
+EALREADY :: Platform_Error.EALREADY /* Operation already in progress */
/* ipc/network software -- argument errors */
-ENOTSOCK: Errno : 38 /* Socket operation on non-socket */
-EDESTADDRREQ: Errno : 39 /* Destination address required */
-EMSGSIZE: Errno : 40 /* Message too long */
-EPROTOTYPE: Errno : 41 /* Protocol wrong type for socket */
-ENOPROTOOPT: Errno : 42 /* Protocol option not available */
-EPROTONOSUPPORT: Errno : 43 /* Protocol not supported */
-ESOCKTNOSUPPORT: Errno : 44 /* Socket type not supported */
-EOPNOTSUPP: Errno : 45 /* Operation not supported */
-EPFNOSUPPORT: Errno : 46 /* Protocol family not supported */
-EAFNOSUPPORT: Errno : 47 /* Address family not supported by protocol family */
-EADDRINUSE: Errno : 48 /* Address already in use */
-EADDRNOTAVAIL: Errno : 49 /* Can't assign requested address */
+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 option not available */
+EPROTONOSUPPORT :: Platform_Error.EPROTONOSUPPORT /* Protocol not supported */
+ESOCKTNOSUPPORT :: Platform_Error.ESOCKTNOSUPPORT /* Socket type not supported */
+EOPNOTSUPP :: Platform_Error.EOPNOTSUPP /* Operation not supported */
+EPFNOSUPPORT :: Platform_Error.EPFNOSUPPORT /* Protocol family not supported */
+EAFNOSUPPORT :: Platform_Error.EAFNOSUPPORT /* Address family not supported by protocol family */
+EADDRINUSE :: Platform_Error.EADDRINUSE /* Address already in use */
+EADDRNOTAVAIL :: Platform_Error.EADDRNOTAVAIL /* Can't assign requested address */
/* ipc/network software -- operational errors */
-ENETDOWN: Errno : 50 /* Network is down */
-ENETUNREACH: Errno : 51 /* Network is unreachable */
-ENETRESET: Errno : 52 /* Network dropped connection on reset */
-ECONNABORTED: Errno : 53 /* Software caused connection abort */
-ECONNRESET: Errno : 54 /* Connection reset by peer */
-ENOBUFS: Errno : 55 /* No buffer space available */
-EISCONN: Errno : 56 /* Socket is already connected */
-ENOTCONN: Errno : 57 /* Socket is not connected */
-ESHUTDOWN: Errno : 58 /* Can't send after socket shutdown */
-ETOOMANYREFS: Errno : 59 /* Too many references: can't splice */
-ETIMEDOUT: Errno : 60 /* Operation timed out */
-ECONNREFUSED: Errno : 61 /* Connection refused */
-
-ELOOP: Errno : 62 /* Too many levels of symbolic links */
-ENAMETOOLONG: Errno : 63 /* File name too long */
+ENETDOWN :: Platform_Error.ENETDOWN /* Network is down */
+ENETUNREACH :: Platform_Error.ENETUNREACH /* Network is unreachable */
+ENETRESET :: Platform_Error.ENETRESET /* Network dropped connection on 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 /* Socket is already connected */
+ENOTCONN :: Platform_Error.ENOTCONN /* Socket is not connected */
+ESHUTDOWN :: Platform_Error.ESHUTDOWN /* Can't send after socket shutdown */
+ETOOMANYREFS :: Platform_Error.ETOOMANYREFS /* Too many references: can't splice */
+ETIMEDOUT :: Platform_Error.ETIMEDOUT /* Operation timed out */
+ECONNREFUSED :: Platform_Error.ECONNREFUSED /* Connection refused */
+
+ELOOP :: Platform_Error.ELOOP /* Too many levels of symbolic links */
+ENAMETOOLONG :: Platform_Error.ENAMETOOLONG /* File name too long */
/* should be rearranged */
-EHOSTDOWN: Errno : 64 /* Host is down */
-EHOSTUNREACH: Errno : 65 /* No route to host */
-ENOTEMPTY: Errno : 66 /* Directory not empty */
+EHOSTDOWN :: Platform_Error.EHOSTDOWN /* Host is down */
+EHOSTUNREACH :: Platform_Error.EHOSTUNREACH /* No route to host */
+ENOTEMPTY :: Platform_Error.ENOTEMPTY /* Directory not empty */
/* quotas & mush */
-EPROCLIM: Errno : 67 /* Too many processes */
-EUSERS: Errno : 68 /* Too many users */
-EDQUOT: Errno : 69 /* Disc quota exceeded */
+EPROCLIM :: Platform_Error.EPROCLIM /* Too many processes */
+EUSERS :: Platform_Error.EUSERS /* Too many users */
+EDQUOT :: Platform_Error.EDQUOT /* Disc quota exceeded */
/* Network File System */
-ESTALE: Errno : 70 /* Stale NFS file handle */
-EREMOTE: Errno : 71 /* Too many levels of remote in path */
-EBADRPC: Errno : 72 /* RPC struct is bad */
-ERPCMISMATCH: Errno : 73 /* RPC version wrong */
-EPROGUNAVAIL: Errno : 74 /* RPC prog. not avail */
-EPROGMISMATCH: Errno : 75 /* Program version wrong */
-EPROCUNAVAIL: Errno : 76 /* Bad procedure for program */
+ESTALE :: Platform_Error.ESTALE /* Stale NFS file handle */
+EREMOTE :: Platform_Error.EREMOTE /* Too many levels of remote in path */
+EBADRPC :: Platform_Error.EBADRPC /* RPC struct is bad */
+ERPCMISMATCH :: Platform_Error.ERPCMISMATCH /* RPC version wrong */
+EPROGUNAVAIL :: Platform_Error.EPROGUNAVAIL /* RPC prog. not avail */
+EPROGMISMATCH :: Platform_Error.EPROGMISMATCH /* Program version wrong */
+EPROCUNAVAIL :: Platform_Error.EPROCUNAVAIL /* Bad procedure for program */
-ENOLCK: Errno : 77 /* No locks available */
-ENOSYS: Errno : 78 /* Function not implemented */
+ENOLCK :: Platform_Error.ENOLCK /* No locks available */
+ENOSYS :: Platform_Error.ENOSYS /* Function not implemented */
-EFTYPE: Errno : 79 /* Inappropriate file type or format */
-EAUTH: Errno : 80 /* Authentication error */
-ENEEDAUTH: Errno : 81 /* Need authenticator */
+EFTYPE :: Platform_Error.EFTYPE /* Inappropriate file type or format */
+EAUTH :: Platform_Error.EAUTH /* Authentication error */
+ENEEDAUTH :: Platform_Error.ENEEDAUTH /* Need authenticator */
/* SystemV IPC */
-EIDRM: Errno : 82 /* Identifier removed */
-ENOMSG: Errno : 83 /* No message of desired type */
-EOVERFLOW: Errno : 84 /* Value too large to be stored in data type */
+EIDRM :: Platform_Error.EIDRM /* Identifier removed */
+ENOMSG :: Platform_Error.ENOMSG /* No message of desired type */
+EOVERFLOW :: Platform_Error.EOVERFLOW /* Value too large to be stored in data type */
/* Wide/multibyte-character handling, ISO/IEC 9899/AMD1:1995 */
-EILSEQ: Errno : 85 /* Illegal byte sequence */
+EILSEQ :: Platform_Error.EILSEQ /* Illegal byte sequence */
/* From IEEE Std 1003.1-2001 */
/* Base, Realtime, Threads or Thread Priority Scheduling option errors */
-ENOTSUP: Errno : 86 /* Not supported */
+ENOTSUP :: Platform_Error.ENOTSUP /* Not supported */
/* Realtime option errors */
-ECANCELED: Errno : 87 /* Operation canceled */
+ECANCELED :: Platform_Error.ECANCELED /* Operation canceled */
/* Realtime, XSI STREAMS option errors */
-EBADMSG: Errno : 88 /* Bad or Corrupt message */
+EBADMSG :: Platform_Error.EBADMSG /* Bad or Corrupt message */
/* XSI STREAMS option errors */
-ENODATA: Errno : 89 /* No message available */
-ENOSR: Errno : 90 /* No STREAM resources */
-ENOSTR: Errno : 91 /* Not a STREAM */
-ETIME: Errno : 92 /* STREAM ioctl timeout */
+ENODATA :: Platform_Error.ENODATA /* No message available */
+ENOSR :: Platform_Error.ENOSR /* No STREAM resources */
+ENOSTR :: Platform_Error.ENOSTR /* Not a STREAM */
+ETIME :: Platform_Error.ETIME /* STREAM ioctl timeout */
/* File system extended attribute errors */
-ENOATTR: Errno : 93 /* Attribute not found */
+ENOATTR :: Platform_Error.ENOATTR /* Attribute not found */
/* Realtime, XSI STREAMS option errors */
-EMULTIHOP: Errno : 94 /* Multihop attempted */
-ENOLINK: Errno : 95 /* Link has been severed */
-EPROTO: Errno : 96 /* Protocol error */
+EMULTIHOP :: Platform_Error.EMULTIHOP /* Multihop attempted */
+ENOLINK :: Platform_Error.ENOLINK /* Link has been severed */
+EPROTO :: Platform_Error.EPROTO /* Protocol error */
/* Robust mutexes */
-EOWNERDEAD: Errno : 97 /* Previous owner died */
-ENOTRECOVERABLE: Errno : 98 /* State not recoverable */
+EOWNERDEAD :: Platform_Error.EOWNERDEAD /* Previous owner died */
+ENOTRECOVERABLE :: Platform_Error.ENOTRECOVERABLE /* State not recoverable */
-ELAST: Errno : 98 /* Must equal largest errno */
+ELAST :: Platform_Error.ELAST /* Must equal largest Error */
-/* end of errno */
+/* end of Error */
O_RDONLY :: 0x000000000
O_WRONLY :: 0x000000001
@@ -268,13 +407,13 @@ S_ISUID :: 0o4000 // Set user id on execution
S_ISGID :: 0o2000 // Set group id on execution
S_ISVTX :: 0o1000 // Directory restrcted delete
-S_ISLNK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK }
-S_ISREG :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG }
-S_ISDIR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR }
-S_ISCHR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR }
-S_ISBLK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK }
-S_ISFIFO :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO }
-S_ISSOCK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK }
+@(require_results) S_ISLNK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK }
+@(require_results) S_ISREG :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG }
+@(require_results) S_ISDIR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR }
+@(require_results) S_ISCHR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR }
+@(require_results) S_ISBLK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK }
+@(require_results) S_ISFIFO :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO }
+@(require_results) S_ISSOCK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK }
F_OK :: 0 // Test for file existance
X_OK :: 1 // Test for execute permission
@@ -334,154 +473,186 @@ foreign libc {
// NOTE(phix): Perhaps share the following functions with FreeBSD if they turn out to be the same in the end.
+@(require_results)
is_path_separator :: proc(r: rune) -> bool {
return r == '/'
}
-get_last_error :: proc "contextless" () -> int {
- return int(__errno_location()^)
+@(require_results, no_instrumentation)
+get_last_error :: proc "contextless" () -> Error {
+ return Platform_Error(__errno_location()^)
}
-open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
+@(require_results)
+open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, c.int(flags), c.int(mode))
if handle == -1 {
- return INVALID_HANDLE, Errno(get_last_error())
+ return INVALID_HANDLE, get_last_error()
}
- return handle, ERROR_NONE
+ return handle, nil
}
-close :: proc(fd: Handle) -> Errno {
+close :: proc(fd: Handle) -> Error {
result := _unix_close(fd)
if result == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
+}
+
+flush :: proc(fd: Handle) -> Error {
+ // do nothing
+ return nil
}
// We set a max of 1GB to keep alignment and to be safe.
@(private)
MAX_RW :: 1 << 30
-read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
+read :: proc(fd: Handle, data: []byte) -> (int, Error) {
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, &data[0], to_read)
if bytes_read == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return int(bytes_read), ERROR_NONE
+ return int(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(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, &data[0], to_write)
if bytes_written == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
+ }
+ return int(bytes_written), nil
+}
+
+read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = read(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
}
- return int(bytes_written), ERROR_NONE
+ return
}
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = write(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
+ }
+ return
+}
+
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
res := _unix_seek(fd, offset, c.int(whence))
if res == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return res, ERROR_NONE
+ return res, nil
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
- s, err := _fstat(fd)
- if err != ERROR_NONE {
- return -1, err
- }
- return s.size, ERROR_NONE
+@(require_results)
+file_size :: proc(fd: Handle) -> (size: i64, err: Error) {
+ size = -1
+ s := _fstat(fd) or_return
+ size = s.size
+ return
}
-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)
res := _unix_rename(old_path_cstr, new_path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-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)
res := _unix_unlink(path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-make_directory :: proc(path: string, mode: mode_t = 0o775) -> Errno {
+make_directory :: proc(path: string, mode: mode_t = 0o775) -> Error {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_mkdir(path_cstr, mode)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-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)
res := _unix_rmdir(path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
+@(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)
@@ -490,6 +661,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)
@@ -497,12 +669,13 @@ exists :: proc(path: string) -> bool {
return res == 0
}
-fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) {
+@(require_results)
+fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Error) {
result := _unix_fcntl(Handle(fd), c.int(cmd), uintptr(arg))
if result < 0 {
- return 0, Errno(get_last_error())
+ return 0, get_last_error()
}
- return int(result), ERROR_NONE
+ return int(result), nil
}
// NOTE(bill): Uses startup to initialize it
@@ -511,38 +684,34 @@ stdin: Handle = 0
stdout: Handle = 1
stderr: Handle = 2
-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)
s: OS_Stat = ---
result := _unix_lstat(cstr, &s)
if result == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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)
@@ -550,54 +719,54 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat = ---
res := _unix_lstat(cstr, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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) {
s: OS_Stat = ---
result := _unix_fstat(fd, &s)
if result == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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
@@ -607,8 +776,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)
@@ -619,31 +788,28 @@ _readlink :: proc(path: string) -> (string, Errno) {
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
if rc == -1 {
delete(buf)
- return "", Errno(get_last_error())
+ return "", get_last_error()
} else if rc == int(bufsz) {
bufsz += MAX_PATH
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
}
}
- return "", Errno{}
+ return "", Error{}
}
-absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
+@(require_results)
+absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
buf: [MAX_PATH]byte
- _, err := fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0])))
- if err != ERROR_NONE {
- return "", err
- }
-
- path := strings.clone_from_cstring(cstring(&buf[0]))
- return path, err
+ _ = fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0]))) or_return
+ return strings.clone_from_cstring(cstring(&buf[0]))
}
-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 = "."
@@ -654,26 +820,27 @@ 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_access(cstr, c.int(mask))
if result == -1 {
- return false, Errno(get_last_error())
+ return false, get_last_error()
}
- 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)
@@ -685,11 +852,13 @@ 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
}
+@(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.
@@ -701,7 +870,7 @@ get_current_directory :: proc() -> string {
if cwd != nil {
return string(cwd)
}
- if Errno(get_last_error()) != ERANGE {
+ if get_last_error() != ERANGE {
delete(buf)
return ""
}
@@ -710,14 +879,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_chdir(cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
exit :: proc "contextless" (code: int) -> ! {
@@ -725,10 +894,12 @@ exit :: proc "contextless" (code: int) -> ! {
_unix_exit(c.int(code))
}
+@(require_results)
current_thread_id :: proc "contextless" () -> int {
return int(_lwp_self())
}
+@(require_results)
dlopen :: proc(filename: string, flags: int) -> rawptr {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(filename, context.temp_allocator)
@@ -736,6 +907,7 @@ dlopen :: proc(filename: string, flags: int) -> rawptr {
return handle
}
+@(require_results)
dlsym :: proc(handle: rawptr, symbol: string) -> rawptr {
assert(handle != nil)
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
@@ -749,10 +921,12 @@ dlclose :: proc(handle: rawptr) -> bool {
return _unix_dlclose(handle) == 0
}
+@(require_results)
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.
@@ -765,7 +939,7 @@ get_page_size :: proc() -> int {
return page_size
}
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
count : int = 0
count_size := size_of(count)
@@ -778,6 +952,7 @@ _processor_core_count :: proc() -> int {
return 1
}
+@(require_results)
_alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ {
diff --git a/core/os/os_openbsd.odin b/core/os/os_openbsd.odin
index a3b74a524..1cd26211e 100644
--- a/core/os/os_openbsd.odin
+++ b/core/os/os_openbsd.odin
@@ -9,108 +9,205 @@ import "base:runtime"
Handle :: distinct i32
Pid :: distinct i32
File_Time :: distinct u64
-Errno :: distinct i32
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
-E2BIG: Errno: 7
-ENOEXEC: Errno: 8
-EBADF: Errno: 9
-ECHILD: Errno: 10
-EDEADLK: Errno: 11
-ENOMEM: Errno: 12
-EACCES: Errno: 13
-EFAULT: Errno: 14
-ENOTBLK: Errno: 15
-EBUSY: Errno: 16
-EEXIST: Errno: 17
-EXDEV: Errno: 18
-ENODEV: Errno: 19
-ENOTDIR: Errno: 20
-EISDIR: Errno: 21
-EINVAL: Errno: 22
-ENFILE: Errno: 23
-EMFILE: Errno: 24
-ENOTTY: Errno: 25
-ETXTBSY: Errno: 26
-EFBIG: Errno: 27
-ENOSPC: Errno: 28
-ESPIPE: Errno: 29
-EROFS: Errno: 30
-EMLINK: Errno: 31
-EPIPE: Errno: 32
-EDOM: Errno: 33
-ERANGE: Errno: 34
-EAGAIN: Errno: 35
-EWOULDBLOCK: Errno: EAGAIN
-EINPROGRESS: Errno: 36
-EALREADY: Errno: 37
-ENOTSOCK: Errno: 38
-EDESTADDRREQ: Errno: 39
-EMSGSIZE: Errno: 40
-EPROTOTYPE: Errno: 41
-ENOPROTOOPT: Errno: 42
-EPROTONOSUPPORT: Errno: 43
-ESOCKTNOSUPPORT: Errno: 44
-EOPNOTSUPP: Errno: 45
-EPFNOSUPPORT: Errno: 46
-EAFNOSUPPORT: Errno: 47
-EADDRINUSE: Errno: 48
-EADDRNOTAVAIL: Errno: 49
-ENETDOWN: Errno: 50
-ENETUNREACH: Errno: 51
-ENETRESET: Errno: 52
-ECONNABORTED: Errno: 53
-ECONNRESET: Errno: 54
-ENOBUFS: Errno: 55
-EISCONN: Errno: 56
-ENOTCONN: Errno: 57
-ESHUTDOWN: Errno: 58
-ETOOMANYREFS: Errno: 59
-ETIMEDOUT: Errno: 60
-ECONNREFUSED: Errno: 61
-ELOOP: Errno: 62
-ENAMETOOLONG: Errno: 63
-EHOSTDOWN: Errno: 64
-EHOSTUNREACH: Errno: 65
-ENOTEMPTY: Errno: 66
-EPROCLIM: Errno: 67
-EUSERS: Errno: 68
-EDQUOT: Errno: 69
-ESTALE: Errno: 70
-EREMOTE: Errno: 71
-EBADRPC: Errno: 72
-ERPCMISMATCH: Errno: 73
-EPROGUNAVAIL: Errno: 74
-EPROGMISMATCH: Errno: 75
-EPROCUNAVAIL: Errno: 76
-ENOLCK: Errno: 77
-ENOSYS: Errno: 78
-EFTYPE: Errno: 79
-EAUTH: Errno: 80
-ENEEDAUTH: Errno: 81
-EIPSEC: Errno: 82
-ENOATTR: Errno: 83
-EILSEQ: Errno: 84
-ENOMEDIUM: Errno: 85
-EMEDIUMTYPE: Errno: 86
-EOVERFLOW: Errno: 87
-ECANCELED: Errno: 88
-EIDRM: Errno: 89
-ENOMSG: Errno: 90
-ENOTSUP: Errno: 91
-EBADMSG: Errno: 92
-ENOTRECOVERABLE: Errno: 93
-EOWNERDEAD: Errno: 94
-EPROTO: Errno: 95
+_Platform_Error :: enum i32 {
+ NONE = 0,
+ EPERM = 1,
+ ENOENT = 2,
+ ESRCH = 3,
+ EINTR = 4,
+ EIO = 5,
+ ENXIO = 6,
+ E2BIG = 7,
+ ENOEXEC = 8,
+ EBADF = 9,
+ ECHILD = 10,
+ EDEADLK = 11,
+ ENOMEM = 12,
+ EACCES = 13,
+ EFAULT = 14,
+ ENOTBLK = 15,
+ EBUSY = 16,
+ EEXIST = 17,
+ EXDEV = 18,
+ ENODEV = 19,
+ ENOTDIR = 20,
+ EISDIR = 21,
+ EINVAL = 22,
+ ENFILE = 23,
+ EMFILE = 24,
+ ENOTTY = 25,
+ ETXTBSY = 26,
+ EFBIG = 27,
+ ENOSPC = 28,
+ ESPIPE = 29,
+ EROFS = 30,
+ EMLINK = 31,
+ EPIPE = 32,
+ EDOM = 33,
+ ERANGE = 34,
+ EAGAIN = 35,
+ EWOULDBLOCK = EAGAIN,
+ EINPROGRESS = 36,
+ EALREADY = 37,
+ ENOTSOCK = 38,
+ EDESTADDRREQ = 39,
+ EMSGSIZE = 40,
+ EPROTOTYPE = 41,
+ ENOPROTOOPT = 42,
+ EPROTONOSUPPORT = 43,
+ ESOCKTNOSUPPORT = 44,
+ EOPNOTSUPP = 45,
+ EPFNOSUPPORT = 46,
+ EAFNOSUPPORT = 47,
+ EADDRINUSE = 48,
+ EADDRNOTAVAIL = 49,
+ ENETDOWN = 50,
+ ENETUNREACH = 51,
+ ENETRESET = 52,
+ ECONNABORTED = 53,
+ ECONNRESET = 54,
+ ENOBUFS = 55,
+ EISCONN = 56,
+ ENOTCONN = 57,
+ ESHUTDOWN = 58,
+ ETOOMANYREFS = 59,
+ ETIMEDOUT = 60,
+ ECONNREFUSED = 61,
+ ELOOP = 62,
+ ENAMETOOLONG = 63,
+ EHOSTDOWN = 64,
+ EHOSTUNREACH = 65,
+ ENOTEMPTY = 66,
+ EPROCLIM = 67,
+ EUSERS = 68,
+ EDQUOT = 69,
+ ESTALE = 70,
+ EREMOTE = 71,
+ EBADRPC = 72,
+ ERPCMISMATCH = 73,
+ EPROGUNAVAIL = 74,
+ EPROGMISMATCH = 75,
+ EPROCUNAVAIL = 76,
+ ENOLCK = 77,
+ ENOSYS = 78,
+ EFTYPE = 79,
+ EAUTH = 80,
+ ENEEDAUTH = 81,
+ EIPSEC = 82,
+ ENOATTR = 83,
+ EILSEQ = 84,
+ ENOMEDIUM = 85,
+ EMEDIUMTYPE = 86,
+ EOVERFLOW = 87,
+ ECANCELED = 88,
+ EIDRM = 89,
+ ENOMSG = 90,
+ ENOTSUP = 91,
+ EBADMSG = 92,
+ ENOTRECOVERABLE = 93,
+ EOWNERDEAD = 94,
+ EPROTO = 95,
+}
+
+EPERM :: Platform_Error.EPERM
+ENOENT :: Platform_Error.ENOENT
+ESRCH :: Platform_Error.ESRCH
+EINTR :: Platform_Error.EINTR
+EIO :: Platform_Error.EIO
+ENXIO :: Platform_Error.ENXIO
+E2BIG :: Platform_Error.E2BIG
+ENOEXEC :: Platform_Error.ENOEXEC
+EBADF :: Platform_Error.EBADF
+ECHILD :: Platform_Error.ECHILD
+EDEADLK :: Platform_Error.EDEADLK
+ENOMEM :: Platform_Error.ENOMEM
+EACCES :: Platform_Error.EACCES
+EFAULT :: Platform_Error.EFAULT
+ENOTBLK :: Platform_Error.ENOTBLK
+EBUSY :: Platform_Error.EBUSY
+EEXIST :: Platform_Error.EEXIST
+EXDEV :: Platform_Error.EXDEV
+ENODEV :: Platform_Error.ENODEV
+ENOTDIR :: Platform_Error.ENOTDIR
+EISDIR :: Platform_Error.EISDIR
+EINVAL :: Platform_Error.EINVAL
+ENFILE :: Platform_Error.ENFILE
+EMFILE :: Platform_Error.EMFILE
+ENOTTY :: Platform_Error.ENOTTY
+ETXTBSY :: Platform_Error.ETXTBSY
+EFBIG :: Platform_Error.EFBIG
+ENOSPC :: Platform_Error.ENOSPC
+ESPIPE :: Platform_Error.ESPIPE
+EROFS :: Platform_Error.EROFS
+EMLINK :: Platform_Error.EMLINK
+EPIPE :: Platform_Error.EPIPE
+EDOM :: Platform_Error.EDOM
+ERANGE :: Platform_Error.ERANGE
+EAGAIN :: Platform_Error.EAGAIN
+EWOULDBLOCK :: Platform_Error.EWOULDBLOCK
+EINPROGRESS :: Platform_Error.EINPROGRESS
+EALREADY :: Platform_Error.EALREADY
+ENOTSOCK :: Platform_Error.ENOTSOCK
+EDESTADDRREQ :: Platform_Error.EDESTADDRREQ
+EMSGSIZE :: Platform_Error.EMSGSIZE
+EPROTOTYPE :: Platform_Error.EPROTOTYPE
+ENOPROTOOPT :: Platform_Error.ENOPROTOOPT
+EPROTONOSUPPORT :: Platform_Error.EPROTONOSUPPORT
+ESOCKTNOSUPPORT :: Platform_Error.ESOCKTNOSUPPORT
+EOPNOTSUPP :: Platform_Error.EOPNOTSUPP
+EPFNOSUPPORT :: Platform_Error.EPFNOSUPPORT
+EAFNOSUPPORT :: Platform_Error.EAFNOSUPPORT
+EADDRINUSE :: Platform_Error.EADDRINUSE
+EADDRNOTAVAIL :: Platform_Error.EADDRNOTAVAIL
+ENETDOWN :: Platform_Error.ENETDOWN
+ENETUNREACH :: Platform_Error.ENETUNREACH
+ENETRESET :: Platform_Error.ENETRESET
+ECONNABORTED :: Platform_Error.ECONNABORTED
+ECONNRESET :: Platform_Error.ECONNRESET
+ENOBUFS :: Platform_Error.ENOBUFS
+EISCONN :: Platform_Error.EISCONN
+ENOTCONN :: Platform_Error.ENOTCONN
+ESHUTDOWN :: Platform_Error.ESHUTDOWN
+ETOOMANYREFS :: Platform_Error.ETOOMANYREFS
+ETIMEDOUT :: Platform_Error.ETIMEDOUT
+ECONNREFUSED :: Platform_Error.ECONNREFUSED
+ELOOP :: Platform_Error.ELOOP
+ENAMETOOLONG :: Platform_Error.ENAMETOOLONG
+EHOSTDOWN :: Platform_Error.EHOSTDOWN
+EHOSTUNREACH :: Platform_Error.EHOSTUNREACH
+ENOTEMPTY :: Platform_Error.ENOTEMPTY
+EPROCLIM :: Platform_Error.EPROCLIM
+EUSERS :: Platform_Error.EUSERS
+EDQUOT :: Platform_Error.EDQUOT
+ESTALE :: Platform_Error.ESTALE
+EREMOTE :: Platform_Error.EREMOTE
+EBADRPC :: Platform_Error.EBADRPC
+ERPCMISMATCH :: Platform_Error.ERPCMISMATCH
+EPROGUNAVAIL :: Platform_Error.EPROGUNAVAIL
+EPROGMISMATCH :: Platform_Error.EPROGMISMATCH
+EPROCUNAVAIL :: Platform_Error.EPROCUNAVAIL
+ENOLCK :: Platform_Error.ENOLCK
+ENOSYS :: Platform_Error.ENOSYS
+EFTYPE :: Platform_Error.EFTYPE
+EAUTH :: Platform_Error.EAUTH
+ENEEDAUTH :: Platform_Error.ENEEDAUTH
+EIPSEC :: Platform_Error.EIPSEC
+ENOATTR :: Platform_Error.ENOATTR
+EILSEQ :: Platform_Error.EILSEQ
+ENOMEDIUM :: Platform_Error.ENOMEDIUM
+EMEDIUMTYPE :: Platform_Error.EMEDIUMTYPE
+EOVERFLOW :: Platform_Error.EOVERFLOW
+ECANCELED :: Platform_Error.ECANCELED
+EIDRM :: Platform_Error.EIDRM
+ENOMSG :: Platform_Error.ENOMSG
+ENOTSUP :: Platform_Error.ENOTSUP
+EBADMSG :: Platform_Error.EBADMSG
+ENOTRECOVERABLE :: Platform_Error.ENOTRECOVERABLE
+EOWNERDEAD :: Platform_Error.EOWNERDEAD
+EPROTO :: Platform_Error.EPROTO
O_RDONLY :: 0x00000
O_WRONLY :: 0x00001
@@ -225,13 +322,13 @@ S_ISUID :: 0o4000 // Set user id on execution
S_ISGID :: 0o2000 // Set group id on execution
S_ISTXT :: 0o1000 // Sticky bit
-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 :: 0x00 // Test for file existance
X_OK :: 0x01 // Test for execute permission
@@ -291,38 +388,47 @@ foreign libc {
@(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---
}
+@(require_results)
is_path_separator :: proc(r: rune) -> bool {
return r == '/'
}
-get_last_error :: proc "contextless" () -> int {
- return int(__error()^)
+@(require_results, no_instrumentation)
+get_last_error :: proc "contextless" () -> Error {
+ return Platform_Error(__error()^)
}
-fork :: proc() -> (Pid, Errno) {
+@(require_results)
+fork :: proc() -> (Pid, Error) {
pid := _unix_fork()
if pid == -1 {
- return Pid(-1), Errno(get_last_error())
+ return Pid(-1), get_last_error()
}
- return Pid(pid), ERROR_NONE
+ return Pid(pid), nil
}
-open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
+@(require_results)
+open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, c.int(flags), c.int(mode))
if handle == -1 {
- return INVALID_HANDLE, Errno(get_last_error())
+ return INVALID_HANDLE, get_last_error()
}
- return handle, ERROR_NONE
+ return handle, nil
}
-close :: proc(fd: Handle) -> Errno {
+close :: proc(fd: Handle) -> Error {
result := _unix_close(fd)
if result == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
+}
+
+flush :: proc(fd: Handle) -> Error {
+ // do nothing
+ return nil
}
// If you read or write more than `SSIZE_MAX` bytes, OpenBSD returns `EINVAL`.
@@ -333,124 +439,148 @@ 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) {
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, &data[0], to_read)
if bytes_read == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return int(bytes_read), ERROR_NONE
+ return int(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(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, &data[0], to_write)
if bytes_written == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
+ }
+ return int(bytes_written), nil
+}
+
+read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = read(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
}
- return int(bytes_written), ERROR_NONE
+ return
+}
+
+write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
+ curr := seek(fd, offset, SEEK_CUR) or_return
+ n, err = write(fd, data)
+ _, err1 := seek(fd, curr, SEEK_SET)
+ if err1 != nil && err == nil {
+ err = err1
+ }
+ return
}
-seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
res := _unix_seek(fd, offset, c.int(whence))
if res == -1 {
- return -1, Errno(get_last_error())
+ return -1, get_last_error()
}
- return res, ERROR_NONE
+ return res, nil
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
- s, err := _fstat(fd)
- if err != ERROR_NONE {
- return -1, err
- }
- return s.size, ERROR_NONE
+@(require_results)
+file_size :: proc(fd: Handle) -> (size: i64, err: Error) {
+ size = -1
+ s := _fstat(fd) or_return
+ size = s.size
+ return
}
-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)
res := _unix_rename(old_path_cstr, new_path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-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)
res := _unix_unlink(path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-make_directory :: proc(path: string, mode: mode_t = 0o775) -> Errno {
+make_directory :: proc(path: string, mode: mode_t = 0o775) -> Error {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_mkdir(path_cstr, mode)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
-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)
res := _unix_rmdir(path_cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
+@(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)
@@ -469,26 +599,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)
@@ -496,13 +622,13 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat = ---
res := _unix_stat(cstr, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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)
@@ -510,55 +636,55 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat = ---
res := _unix_lstat(cstr, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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
s: OS_Stat = ---
res := _unix_fstat(fd, &s)
if res == -1 {
- return s, Errno(get_last_error())
+ return s, get_last_error()
}
- 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
@@ -568,8 +694,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)
@@ -579,23 +705,25 @@ _readlink :: proc(path: string) -> (string, Errno) {
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
if rc == -1 {
delete(buf)
- return "", Errno(get_last_error())
+ return "", get_last_error()
} else if rc == int(bufsz) {
bufsz += MAX_PATH
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
}
}
}
// XXX OpenBSD
-absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
- return "", Errno(ENOSYS)
+@(require_results)
+absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
+ return "", Error(ENOSYS)
}
-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 = "."
@@ -606,25 +734,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)
res := _unix_access(cstr, c.int(mask))
if res == -1 {
- return false, Errno(get_last_error())
+ return false, get_last_error()
}
- 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)
@@ -635,11 +764,13 @@ 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
}
+@(require_results)
get_current_directory :: proc() -> string {
buf := make([dynamic]u8, MAX_PATH)
for {
@@ -647,7 +778,7 @@ get_current_directory :: proc() -> string {
if cwd != nil {
return string(cwd)
}
- if Errno(get_last_error()) != ERANGE {
+ if get_last_error() != ERANGE {
delete(buf)
return ""
}
@@ -656,14 +787,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_chdir(cstr)
if res == -1 {
- return Errno(get_last_error())
+ return get_last_error()
}
- return ERROR_NONE
+ return nil
}
exit :: proc "contextless" (code: int) -> ! {
@@ -671,16 +802,19 @@ exit :: proc "contextless" (code: int) -> ! {
_unix_exit(c.int(code))
}
+@(require_results)
current_thread_id :: proc "contextless" () -> int {
return _unix_getthrid()
}
+@(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()
@@ -692,10 +826,12 @@ dlclose :: proc(handle: rawptr) -> bool {
assert(handle != nil)
return _unix_dlclose(handle) == 0
}
+@(require_results)
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.
@@ -710,11 +846,12 @@ get_page_size :: proc() -> int {
_SC_NPROCESSORS_ONLN :: 503
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
return int(_sysconf(_SC_NPROCESSORS_ONLN))
}
+@(require_results)
_alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ {
diff --git a/core/os/os_wasi.odin b/core/os/os_wasi.odin
index 7b7fb4686..28f470357 100644
--- a/core/os/os_wasi.odin
+++ b/core/os/os_wasi.odin
@@ -4,12 +4,10 @@ import "core:sys/wasm/wasi"
import "base:runtime"
Handle :: distinct i32
-Errno :: distinct i32
+_Platform_Error :: wasi.errno_t
INVALID_HANDLE :: -1
-ERROR_NONE :: Errno(wasi.errno_t.SUCCESS)
-
O_RDONLY :: 0x00000
O_WRONLY :: 0x00001
O_RDWR :: 0x00002
@@ -29,6 +27,7 @@ stderr: Handle = 2
args := _alloc_command_line_arguments()
+@(require_results)
_alloc_command_line_arguments :: proc() -> (args: []string) {
args = make([]string, len(runtime.args__))
for &arg, i in args {
@@ -93,8 +92,9 @@ init_preopens :: proc() {
preopens = dyn_preopens[:]
}
+@(require_results)
wasi_match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) {
-
+ @(require_results)
prefix_matches :: proc(prefix, path: string) -> bool {
// Empty is valid for any relative path.
if len(prefix) == 0 && len(path) > 0 && path[0] != '/' {
@@ -148,23 +148,24 @@ wasi_match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) {
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
iovs := wasi.ciovec_t(data)
n, err := wasi.fd_write(wasi.fd_t(fd), {iovs})
- return int(n), Errno(err)
+ return int(n), Platform_Error(err)
}
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
iovs := wasi.iovec_t(data)
n, err := wasi.fd_read(wasi.fd_t(fd), {iovs})
- return int(n), Errno(err)
+ return int(n), Platform_Error(err)
}
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
iovs := wasi.ciovec_t(data)
n, err := wasi.fd_pwrite(wasi.fd_t(fd), {iovs}, wasi.filesize_t(offset))
- return int(n), Errno(err)
+ return int(n), Platform_Error(err)
}
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
iovs := wasi.iovec_t(data)
n, err := wasi.fd_pread(wasi.fd_t(fd), {iovs}, wasi.filesize_t(offset))
- return int(n), Errno(err)
+ return int(n), Platform_Error(err)
}
+@(require_results)
open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
oflags: wasi.oflags_t
if mode & O_CREATE == O_CREATE {
@@ -201,30 +202,36 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errn
}
fd, err := wasi.path_open(dir_fd, {.SYMLINK_FOLLOW}, relative, oflags, rights, {}, fdflags)
- return Handle(fd), Errno(err)
+ return Handle(fd), Platform_Error(err)
}
close :: proc(fd: Handle) -> Errno {
err := wasi.fd_close(wasi.fd_t(fd))
- return Errno(err)
+ return Platform_Error(err)
+}
+
+flush :: proc(fd: Handle) -> Error {
+ // do nothing
+ return nil
}
+
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
n, err := wasi.fd_seek(wasi.fd_t(fd), wasi.filedelta_t(offset), wasi.whence_t(whence))
- return i64(n), Errno(err)
+ return i64(n), Platform_Error(err)
}
+@(require_results)
current_thread_id :: proc "contextless" () -> int {
return 0
}
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
return 1
}
-file_size :: proc(fd: Handle) -> (i64, Errno) {
- stat, err := wasi.fd_filestat_get(wasi.fd_t(fd))
- if err != nil {
- return 0, Errno(err)
- }
- return i64(stat.size), 0
+@(require_results)
+file_size :: proc(fd: Handle) -> (size: i64, err: Errno) {
+ stat := wasi.fd_filestat_get(wasi.fd_t(fd)) or_return
+ size = i64(stat.size)
+ return
}
diff --git a/core/os/os_windows.odin b/core/os/os_windows.odin
index ecfb0b419..273fe5af0 100644
--- a/core/os/os_windows.odin
+++ b/core/os/os_windows.odin
@@ -7,7 +7,6 @@ import "base:intrinsics"
Handle :: distinct uintptr
File_Time :: distinct u64
-Errno :: distinct int
INVALID_HANDLE :: ~Handle(0)
@@ -27,70 +26,119 @@ O_SYNC :: 0x01000
O_ASYNC :: 0x02000
O_CLOEXEC :: 0x80000
-
-ERROR_NONE: Errno : 0
-ERROR_FILE_NOT_FOUND: Errno : 2
-ERROR_PATH_NOT_FOUND: Errno : 3
-ERROR_ACCESS_DENIED: Errno : 5
-ERROR_INVALID_HANDLE: Errno : 6
-ERROR_NOT_ENOUGH_MEMORY: Errno : 8
-ERROR_NO_MORE_FILES: Errno : 18
-ERROR_HANDLE_EOF: Errno : 38
-ERROR_NETNAME_DELETED: Errno : 64
-ERROR_FILE_EXISTS: Errno : 80
-ERROR_INVALID_PARAMETER: Errno : 87
-ERROR_BROKEN_PIPE: Errno : 109
-ERROR_BUFFER_OVERFLOW: Errno : 111
-ERROR_INSUFFICIENT_BUFFER: Errno : 122
-ERROR_MOD_NOT_FOUND: Errno : 126
-ERROR_PROC_NOT_FOUND: Errno : 127
-ERROR_DIR_NOT_EMPTY: Errno : 145
-ERROR_ALREADY_EXISTS: Errno : 183
-ERROR_ENVVAR_NOT_FOUND: Errno : 203
-ERROR_MORE_DATA: Errno : 234
-ERROR_OPERATION_ABORTED: Errno : 995
-ERROR_IO_PENDING: Errno : 997
-ERROR_NOT_FOUND: Errno : 1168
-ERROR_PRIVILEGE_NOT_HELD: Errno : 1314
-WSAEACCES: Errno : 10013
-WSAECONNRESET: Errno : 10054
-
-// Windows reserves errors >= 1<<29 for application use
-ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0
-ERROR_FILE_IS_NOT_DIR: Errno : 1<<29 + 1
-ERROR_NEGATIVE_OFFSET: Errno : 1<<29 + 2
+_Platform_Error :: win32.System_Error
+
+ERROR_FILE_NOT_FOUND :: _Platform_Error(2)
+ERROR_PATH_NOT_FOUND :: _Platform_Error(3)
+ERROR_ACCESS_DENIED :: _Platform_Error(5)
+ERROR_INVALID_HANDLE :: _Platform_Error(6)
+ERROR_NOT_ENOUGH_MEMORY :: _Platform_Error(8)
+ERROR_NO_MORE_FILES :: _Platform_Error(18)
+ERROR_HANDLE_EOF :: _Platform_Error(38)
+ERROR_NETNAME_DELETED :: _Platform_Error(64)
+ERROR_FILE_EXISTS :: _Platform_Error(80)
+ERROR_INVALID_PARAMETER :: _Platform_Error(87)
+ERROR_BROKEN_PIPE :: _Platform_Error(109)
+ERROR_BUFFER_OVERFLOW :: _Platform_Error(111)
+ERROR_INSUFFICIENT_BUFFER :: _Platform_Error(122)
+ERROR_MOD_NOT_FOUND :: _Platform_Error(126)
+ERROR_PROC_NOT_FOUND :: _Platform_Error(127)
+ERROR_DIR_NOT_EMPTY :: _Platform_Error(145)
+ERROR_ALREADY_EXISTS :: _Platform_Error(183)
+ERROR_ENVVAR_NOT_FOUND :: _Platform_Error(203)
+ERROR_MORE_DATA :: _Platform_Error(234)
+ERROR_OPERATION_ABORTED :: _Platform_Error(995)
+ERROR_IO_PENDING :: _Platform_Error(997)
+ERROR_NOT_FOUND :: _Platform_Error(1168)
+ERROR_PRIVILEGE_NOT_HELD :: _Platform_Error(1314)
+WSAEACCES :: _Platform_Error(10013)
+WSAECONNRESET :: _Platform_Error(10054)
+
+ERROR_FILE_IS_PIPE :: General_Error.File_Is_Pipe
+ERROR_FILE_IS_NOT_DIR :: General_Error.Not_Dir
// "Argv" arguments converted to Odin strings
args := _alloc_command_line_arguments()
+@(require_results, no_instrumentation)
+get_last_error :: proc "contextless" () -> Error {
+ err := win32.GetLastError()
+ if err == 0 {
+ return nil
+ }
+ switch err {
+ case win32.ERROR_ACCESS_DENIED, win32.ERROR_SHARING_VIOLATION:
+ return .Permission_Denied
+
+ case win32.ERROR_FILE_EXISTS, win32.ERROR_ALREADY_EXISTS:
+ return .Exist
+
+ case win32.ERROR_FILE_NOT_FOUND, win32.ERROR_PATH_NOT_FOUND:
+ return .Not_Exist
+
+ case win32.ERROR_NO_DATA:
+ return .Closed
+
+ case win32.ERROR_TIMEOUT, win32.WAIT_TIMEOUT:
+ return .Timeout
+
+ case win32.ERROR_NOT_SUPPORTED:
+ return .Unsupported
+
+ case win32.ERROR_HANDLE_EOF:
+ return .EOF
+
+ case win32.ERROR_INVALID_HANDLE:
+ return .Invalid_File
+
+ case
+ win32.ERROR_BAD_ARGUMENTS,
+ win32.ERROR_INVALID_PARAMETER,
+ win32.ERROR_NOT_ENOUGH_MEMORY,
+ win32.ERROR_NO_MORE_FILES,
+ win32.ERROR_LOCK_VIOLATION,
+ win32.ERROR_BROKEN_PIPE,
+ win32.ERROR_CALL_NOT_IMPLEMENTED,
+ win32.ERROR_INSUFFICIENT_BUFFER,
+ win32.ERROR_INVALID_NAME,
+ win32.ERROR_LOCK_FAILED,
+ win32.ERROR_ENVVAR_NOT_FOUND,
+ win32.ERROR_OPERATION_ABORTED,
+ win32.ERROR_IO_PENDING,
+ win32.ERROR_NO_UNICODE_TRANSLATION:
+ // fallthrough
+ }
+ return Platform_Error(err)
+}
-
-
-last_write_time :: proc(fd: Handle) -> (File_Time, Errno) {
+@(require_results)
+last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
file_info: win32.BY_HANDLE_FILE_INFORMATION
if !win32.GetFileInformationByHandle(win32.HANDLE(fd), &file_info) {
- return 0, Errno(win32.GetLastError())
+ return 0, get_last_error()
}
lo := File_Time(file_info.ftLastWriteTime.dwLowDateTime)
hi := File_Time(file_info.ftLastWriteTime.dwHighDateTime)
- return lo | hi << 32, ERROR_NONE
+ return lo | hi << 32, nil
}
-last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
+@(require_results)
+last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
data: win32.WIN32_FILE_ATTRIBUTE_DATA
wide_path := win32.utf8_to_wstring(name)
if !win32.GetFileAttributesExW(wide_path, win32.GetFileExInfoStandard, &data) {
- return 0, Errno(win32.GetLastError())
+ return 0, get_last_error()
}
l := File_Time(data.ftLastWriteTime.dwLowDateTime)
h := File_Time(data.ftLastWriteTime.dwHighDateTime)
- return l | h << 32, ERROR_NONE
+ return l | h << 32, nil
}
+@(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.
@@ -105,7 +153,7 @@ get_page_size :: proc() -> int {
return page_size
}
-@(private)
+@(private, require_results)
_processor_core_count :: proc() -> int {
length : win32.DWORD = 0
result := win32.GetLogicalProcessorInformation(nil, &length)
@@ -136,12 +184,14 @@ exit :: proc "contextless" (code: int) -> ! {
+@(require_results)
current_thread_id :: proc "contextless" () -> int {
return int(win32.GetCurrentThreadId())
}
+@(require_results)
_alloc_command_line_arguments :: proc() -> []string {
arg_count: i32
arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count)
@@ -175,44 +225,52 @@ _alloc_command_line_arguments :: proc() -> []string {
*/
WINDOWS_11_BUILD_CUTOFF :: 22_000
-get_windows_version_w :: proc() -> win32.OSVERSIONINFOEXW {
+@(require_results)
+get_windows_version_w :: proc "contextless" () -> win32.OSVERSIONINFOEXW {
osvi : win32.OSVERSIONINFOEXW
osvi.dwOSVersionInfoSize = size_of(win32.OSVERSIONINFOEXW)
win32.RtlGetVersion(&osvi)
return osvi
}
-is_windows_xp :: proc() -> bool {
+@(require_results)
+is_windows_xp :: proc "contextless" () -> bool {
osvi := get_windows_version_w()
return (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
}
-is_windows_vista :: proc() -> bool {
+@(require_results)
+is_windows_vista :: proc "contextless" () -> bool {
osvi := get_windows_version_w()
return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
}
-is_windows_7 :: proc() -> bool {
+@(require_results)
+is_windows_7 :: proc "contextless" () -> bool {
osvi := get_windows_version_w()
return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
}
-is_windows_8 :: proc() -> bool {
+@(require_results)
+is_windows_8 :: proc "contextless" () -> bool {
osvi := get_windows_version_w()
return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2)
}
-is_windows_8_1 :: proc() -> bool {
+@(require_results)
+is_windows_8_1 :: proc "contextless" () -> bool {
osvi := get_windows_version_w()
return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3)
}
-is_windows_10 :: proc() -> bool {
+@(require_results)
+is_windows_10 :: proc "contextless" () -> bool {
osvi := get_windows_version_w()
return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber < WINDOWS_11_BUILD_CUTOFF)
}
-is_windows_11 :: proc() -> bool {
+@(require_results)
+is_windows_11 :: proc "contextless" () -> bool {
osvi := get_windows_version_w()
return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber >= WINDOWS_11_BUILD_CUTOFF)
}
diff --git a/core/os/stat_unix.odin b/core/os/stat_unix.odin
index 3bd62dfc7..8e89bee4f 100644
--- a/core/os/stat_unix.odin
+++ b/core/os/stat_unix.odin
@@ -50,14 +50,14 @@ File_Info :: struct {
}
*/
-@private
+@(private, require_results)
_make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time {
return time.Time{
_nsec = uft.nanoseconds + uft.seconds * 1_000_000_000,
}
}
-@private
+@(private)
_fill_file_info_from_stat :: proc(fi: ^File_Info, s: OS_Stat) {
fi.size = s.size
fi.mode = cast(File_Mode)s.mode
@@ -71,7 +71,7 @@ _fill_file_info_from_stat :: proc(fi: ^File_Info, s: OS_Stat) {
}
-@private
+@(private, require_results)
path_base :: proc(path: string) -> string {
is_separator :: proc(c: byte) -> bool {
return c == '/'
@@ -100,55 +100,35 @@ path_base :: proc(path: string) -> string {
}
-lstat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Errno) {
-
+@(require_results)
+lstat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Error) {
context.allocator = allocator
- s: OS_Stat
- s, err = _lstat(name)
- if err != ERROR_NONE {
- return fi, err
- }
+ s := _lstat(name) or_return
_fill_file_info_from_stat(&fi, s)
- fi.fullpath, err = absolute_path_from_relative(name)
- if err != ERROR_NONE {
- return
- }
+ fi.fullpath = absolute_path_from_relative(name) or_return
fi.name = path_base(fi.fullpath)
- return fi, ERROR_NONE
+ return
}
-stat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Errno) {
+@(require_results)
+stat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Error) {
context.allocator = allocator
- s: OS_Stat
- s, err = _stat(name)
- if err != ERROR_NONE {
- return fi, err
- }
+ s := _stat(name) or_return
_fill_file_info_from_stat(&fi, s)
- fi.fullpath, err = absolute_path_from_relative(name)
- if err != ERROR_NONE {
- return
- }
+ fi.fullpath = absolute_path_from_relative(name) or_return
fi.name = path_base(fi.fullpath)
- return fi, ERROR_NONE
+ return
}
-fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Errno) {
-
+@(require_results)
+fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Error) {
context.allocator = allocator
- s: OS_Stat
- s, err = _fstat(fd)
- if err != ERROR_NONE {
- return fi, err
- }
+ s := _fstat(fd) or_return
_fill_file_info_from_stat(&fi, s)
- fi.fullpath, err = absolute_path_from_handle(fd)
- if err != ERROR_NONE {
- return
- }
+ fi.fullpath = absolute_path_from_handle(fd) or_return
fi.name = path_base(fi.fullpath)
- return fi, ERROR_NONE
+ return
}
diff --git a/core/os/stat_windows.odin b/core/os/stat_windows.odin
index 4bb3bd4c4..ca4f87668 100644
--- a/core/os/stat_windows.odin
+++ b/core/os/stat_windows.odin
@@ -4,7 +4,7 @@ import "core:time"
import "base:runtime"
import win32 "core:sys/windows"
-@(private)
+@(private, require_results)
full_path_from_name :: proc(name: string, allocator := context.allocator) -> (path: string, err: Errno) {
context.allocator = allocator
@@ -19,10 +19,10 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa
for {
n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil)
if n == 0 {
- return "", Errno(win32.GetLastError())
+ return "", get_last_error()
}
if n <= u32(len(buf)) {
- return win32.utf16_to_utf8(buf[:n], allocator) or_else "", ERROR_NONE
+ return win32.utf16_to_utf8(buf[:n], allocator) or_else "", nil
}
resize(&buf, len(buf)*2)
}
@@ -30,7 +30,7 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa
return
}
-@(private)
+@(private, require_results)
_stat :: proc(name: string, create_file_attributes: u32, allocator := context.allocator) -> (fi: File_Info, e: Errno) {
if len(name) == 0 {
return {}, ERROR_PATH_NOT_FOUND
@@ -54,7 +54,7 @@ _stat :: proc(name: string, create_file_attributes: u32, allocator := context.al
fd: win32.WIN32_FIND_DATAW
sh := win32.FindFirstFileW(wname, &fd)
if sh == win32.INVALID_HANDLE_VALUE {
- e = Errno(win32.GetLastError())
+ e = get_last_error()
return
}
win32.FindClose(sh)
@@ -64,7 +64,7 @@ _stat :: proc(name: string, create_file_attributes: u32, allocator := context.al
h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil)
if h == win32.INVALID_HANDLE_VALUE {
- e = Errno(win32.GetLastError())
+ e = get_last_error()
return
}
defer win32.CloseHandle(h)
@@ -72,26 +72,29 @@ _stat :: proc(name: string, create_file_attributes: u32, allocator := context.al
}
+@(require_results)
lstat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) {
attrs := win32.FILE_FLAG_BACKUP_SEMANTICS
attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT
return _stat(name, attrs, allocator)
}
+@(require_results)
stat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) {
attrs := win32.FILE_FLAG_BACKUP_SEMANTICS
return _stat(name, attrs, allocator)
}
-fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, errno: Errno) {
+@(require_results)
+fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Errno) {
if fd == 0 {
- return {}, ERROR_INVALID_HANDLE
+ err = ERROR_INVALID_HANDLE
}
context.allocator = allocator
- path, err := cleanpath_from_handle(fd)
- if err != ERROR_NONE {
- return {}, err
+ path := cleanpath_from_handle(fd) or_return
+ defer if err != nil {
+ delete(path)
}
h := win32.HANDLE(fd)
@@ -99,16 +102,16 @@ fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err
case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR:
fi.name = basename(path)
fi.mode |= file_type_mode(h)
- errno = ERROR_NONE
+ err = nil
case:
- fi, errno = file_info_from_get_file_information_by_handle(path, h)
+ fi = file_info_from_get_file_information_by_handle(path, h) or_return
}
fi.fullpath = path
return
}
-@(private)
+@(private, require_results)
cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 {
buf := buf
N := 0
@@ -133,16 +136,13 @@ cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 {
return buf
}
-@(private)
-cleanpath_from_handle :: proc(fd: Handle) -> (string, Errno) {
+@(private, require_results)
+cleanpath_from_handle :: proc(fd: Handle) -> (s: string, err: Errno) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
- buf, err := cleanpath_from_handle_u16(fd, context.temp_allocator)
- if err != 0 {
- return "", err
- }
- return win32.utf16_to_utf8(buf, context.allocator) or_else "", err
+ buf := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return
+ return win32.utf16_to_utf8(buf, context.allocator)
}
-@(private)
+@(private, require_results)
cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> ([]u16, Errno) {
if fd == 0 {
return nil, ERROR_INVALID_HANDLE
@@ -151,20 +151,20 @@ cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> (
n := win32.GetFinalPathNameByHandleW(h, nil, 0, 0)
if n == 0 {
- return nil, Errno(win32.GetLastError())
+ return nil, get_last_error()
}
buf := make([]u16, max(n, win32.DWORD(260))+1, allocator)
buf_len := win32.GetFinalPathNameByHandleW(h, raw_data(buf), n, 0)
- return buf[:buf_len], ERROR_NONE
+ return buf[:buf_len], nil
}
-@(private)
+@(private, require_results)
cleanpath_from_buf :: proc(buf: []u16) -> string {
buf := buf
buf = cleanpath_strip_prefix(buf)
return win32.utf16_to_utf8(buf, context.allocator) or_else ""
}
-@(private)
+@(private, require_results)
basename :: proc(name: string) -> (base: string) {
name := name
if len(name) > 3 && name[:3] == `\\?` {
@@ -190,7 +190,7 @@ basename :: proc(name: string) -> (base: string) {
return name
}
-@(private)
+@(private, require_results)
file_type_mode :: proc(h: win32.HANDLE) -> File_Mode {
switch win32.GetFileType(h) {
case win32.FILE_TYPE_PIPE:
@@ -202,7 +202,7 @@ file_type_mode :: proc(h: win32.HANDLE) -> File_Mode {
}
-@(private)
+@(private, require_results)
file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (mode: File_Mode) {
if FileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
mode |= 0o444
@@ -239,7 +239,7 @@ windows_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) {
fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
}
-@(private)
+@(private, require_results)
file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) {
fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
@@ -254,7 +254,7 @@ file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_
return
}
-@(private)
+@(private, require_results)
file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) -> (fi: File_Info, e: Errno) {
fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
@@ -269,20 +269,20 @@ file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string)
return
}
-@(private)
+@(private, require_results)
file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE) -> (File_Info, Errno) {
d: win32.BY_HANDLE_FILE_INFORMATION
if !win32.GetFileInformationByHandle(h, &d) {
- err := Errno(win32.GetLastError())
+ err := get_last_error()
return {}, err
}
ti: win32.FILE_ATTRIBUTE_TAG_INFO
if !win32.GetFileInformationByHandleEx(h, .FileAttributeTagInfo, &ti, size_of(ti)) {
- err := win32.GetLastError()
- if err != u32(ERROR_INVALID_PARAMETER) {
- return {}, Errno(err)
+ err := get_last_error()
+ if err != ERROR_INVALID_PARAMETER {
+ return {}, err
}
// Indicate this is a symlink on FAT file systems
ti.ReparseTag = 0
@@ -299,5 +299,5 @@ file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HAN
windows_set_file_info_times(&fi, &d)
- return fi, ERROR_NONE
+ return fi, nil
}
diff --git a/core/os/stream.odin b/core/os/stream.odin
index 9a168b95c..8acbee489 100644
--- a/core/os/stream.odin
+++ b/core/os/stream.odin
@@ -14,44 +14,36 @@ stream_from_handle :: proc(fd: Handle) -> io.Stream {
_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
fd := Handle(uintptr(stream_data))
n_int: int
- os_err: Errno
+ os_err: Error
switch mode {
case .Close:
- close(fd)
+ os_err = close(fd)
case .Flush:
- when ODIN_OS == .Windows {
- flush(fd)
- } else {
- // TOOD(bill): other operating systems
- }
+ os_err = flush(fd)
case .Read:
n_int, os_err = read(fd, p)
n = i64(n_int)
- if n == 0 && os_err == 0 {
+ if n == 0 && os_err == nil {
err = .EOF
}
case .Read_At:
- when !(ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku) {
- n_int, os_err = read_at(fd, p, offset)
- n = i64(n_int)
- if n == 0 && os_err == 0 {
- err = .EOF
- }
+ n_int, os_err = read_at(fd, p, offset)
+ n = i64(n_int)
+ if n == 0 && os_err == nil {
+ err = .EOF
}
case .Write:
n_int, os_err = write(fd, p)
n = i64(n_int)
- if n == 0 && os_err == 0 {
+ if n == 0 && os_err == nil {
err = .EOF
}
case .Write_At:
- when !(ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku) {
- n_int, os_err = write_at(fd, p, offset)
- n = i64(n_int)
- if n == 0 && os_err == 0 {
- err = .EOF
- }
+ n_int, os_err = write_at(fd, p, offset)
+ n = i64(n_int)
+ if n == 0 && os_err == nil {
+ err = .EOF
}
case .Seek:
n, os_err = seek(fd, offset, int(whence))
@@ -60,20 +52,11 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte,
case .Destroy:
err = .Empty
case .Query:
- when ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
- return io.query_utility({.Close, .Flush, .Read, .Write, .Seek, .Size, .Query})
- } else {
- return io.query_utility({.Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query})
- }
+ return io.query_utility({.Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query})
}
- if err == nil && os_err != 0 {
- when ODIN_OS == .Windows {
- if os_err == ERROR_HANDLE_EOF {
- return n, .EOF
- }
- }
- err = .Unknown
+ if err == nil && os_err != nil {
+ err = error_to_io_error(os_err)
}
return
}
diff --git a/core/path/filepath/match.odin b/core/path/filepath/match.odin
index 1279bdd84..7eb72b9a7 100644
--- a/core/path/filepath/match.odin
+++ b/core/path/filepath/match.odin
@@ -271,7 +271,7 @@ _glob :: proc(dir, pattern: string, matches: ^[dynamic]string, allocator := cont
d, derr := os.open(dir, os.O_RDONLY)
- if derr != 0 {
+ if derr != nil {
return
}
defer os.close(d)
@@ -280,7 +280,7 @@ _glob :: proc(dir, pattern: string, matches: ^[dynamic]string, allocator := cont
file_info, ferr := os.fstat(d)
defer os.file_info_delete(file_info)
- if ferr != 0 {
+ if ferr != nil {
return
}
if !file_info.is_dir {
diff --git a/core/path/filepath/path_windows.odin b/core/path/filepath/path_windows.odin
index 5ebd2cdc2..0dcb28cf8 100644
--- a/core/path/filepath/path_windows.odin
+++ b/core/path/filepath/path_windows.odin
@@ -52,7 +52,7 @@ is_abs :: proc(path: string) -> bool {
@(private)
-temp_full_path :: proc(name: string) -> (path: string, err: os.Errno) {
+temp_full_path :: proc(name: string) -> (path: string, err: os.Error) {
ta := context.temp_allocator
name := name
@@ -63,17 +63,17 @@ temp_full_path :: proc(name: string) -> (path: string, err: os.Errno) {
p := win32.utf8_to_utf16(name, ta)
n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil)
if n == 0 {
- return "", os.Errno(win32.GetLastError())
+ return "", os.get_last_error()
}
buf := make([]u16, n, ta)
n = win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil)
if n == 0 {
delete(buf)
- return "", os.Errno(win32.GetLastError())
+ return "", os.get_last_error()
}
- return win32.utf16_to_utf8(buf[:n], ta) or_else "", os.ERROR_NONE
+ return win32.utf16_to_utf8(buf[:n], ta)
}
@@ -81,7 +81,7 @@ temp_full_path :: proc(name: string) -> (path: string, err: os.Errno) {
abs :: proc(path: string, allocator := context.allocator) -> (string, bool) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = allocator == context.temp_allocator)
full_path, err := temp_full_path(path)
- if err != 0 {
+ if err != nil {
return "", false
}
p := clean(full_path, allocator)
diff --git a/core/path/filepath/walk.odin b/core/path/filepath/walk.odin
index 9ba3165dc..51dfa71d2 100644
--- a/core/path/filepath/walk.odin
+++ b/core/path/filepath/walk.odin
@@ -14,7 +14,7 @@ import "core:slice"
// The sole exception is if 'skip_dir' is returned as true:
// when 'skip_dir' is invoked on a directory. 'walk' skips directory contents
// when 'skip_dir' is invoked on a non-directory. 'walk' skips the remaining files in the containing directory
-Walk_Proc :: #type proc(info: os.File_Info, in_err: os.Errno, user_data: rawptr) -> (err: os.Errno, skip_dir: bool)
+Walk_Proc :: #type proc(info: os.File_Info, in_err: os.Error, user_data: rawptr) -> (err: os.Error, skip_dir: bool)
// walk walks the file tree rooted at 'root', calling 'walk_proc' for each file or directory in the tree, including 'root'
// All errors that happen visiting files and directories are filtered by walk_proc
@@ -22,44 +22,44 @@ Walk_Proc :: #type proc(info: os.File_Info, in_err: os.Errno, user_data: rawptr)
// NOTE: Walking large directories can be inefficient due to the lexical sort
// NOTE: walk does not follow symbolic links
// NOTE: os.File_Info uses the 'context.temp_allocator' to allocate, and will delete when it is done
-walk :: proc(root: string, walk_proc: Walk_Proc, user_data: rawptr) -> os.Errno {
+walk :: proc(root: string, walk_proc: Walk_Proc, user_data: rawptr) -> os.Error {
info, err := os.lstat(root, context.temp_allocator)
defer os.file_info_delete(info, context.temp_allocator)
skip_dir: bool
- if err != 0 {
+ if err != nil {
err, skip_dir = walk_proc(info, err, user_data)
} else {
err, skip_dir = _walk(info, walk_proc, user_data)
}
- return 0 if skip_dir else err
+ return nil if skip_dir else err
}
@(private)
-_walk :: proc(info: os.File_Info, walk_proc: Walk_Proc, user_data: rawptr) -> (err: os.Errno, skip_dir: bool) {
+_walk :: proc(info: os.File_Info, walk_proc: Walk_Proc, user_data: rawptr) -> (err: os.Error, skip_dir: bool) {
if !info.is_dir {
if info.fullpath == "" && info.name == "" {
// ignore empty things
return
}
- return walk_proc(info, 0, user_data)
+ return walk_proc(info, nil, user_data)
}
fis: []os.File_Info
- err1: os.Errno
+ err1: os.Error
fis, err = read_dir(info.fullpath, context.temp_allocator)
defer os.file_info_slice_delete(fis, context.temp_allocator)
err1, skip_dir = walk_proc(info, err, user_data)
- if err != 0 || err1 != 0 || skip_dir {
+ if err != nil || err1 != nil || skip_dir {
err = err1
return
}
for fi in fis {
err, skip_dir = _walk(fi, walk_proc, user_data)
- if err != 0 || skip_dir {
+ if err != nil || skip_dir {
if !fi.is_dir || !skip_dir {
return
}
@@ -70,19 +70,12 @@ _walk :: proc(info: os.File_Info, walk_proc: Walk_Proc, user_data: rawptr) -> (e
}
@(private)
-read_dir :: proc(dir_name: string, allocator := context.temp_allocator) -> ([]os.File_Info, os.Errno) {
- f, err := os.open(dir_name, os.O_RDONLY)
- if err != 0 {
- return nil, err
- }
- fis: []os.File_Info
- fis, err = os.read_dir(f, -1, allocator)
- os.close(f)
- if err != 0 {
- return nil, err
- }
+read_dir :: proc(dir_name: string, allocator := context.temp_allocator) -> (fis: []os.File_Info, err: os.Error) {
+ f := os.open(dir_name, os.O_RDONLY) or_return
+ defer os.close(f)
+ fis = os.read_dir(f, -1, allocator) or_return
slice.sort_by(fis, proc(a, b: os.File_Info) -> bool {
return a.name < b.name
})
- return fis, 0
+ return
}
diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin
index a6fc59e74..12f082b2c 100644
--- a/core/prof/spall/spall.odin
+++ b/core/prof/spall/spall.odin
@@ -68,7 +68,7 @@ BUFFER_DEFAULT_SIZE :: 0x10_0000
context_create_with_scale :: proc(filename: string, precise_time: bool, timestamp_scale: f64) -> (ctx: Context, ok: bool) #optional_ok {
fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600)
- if err != os.ERROR_NONE {
+ if err != nil {
return
}
@@ -227,7 +227,7 @@ _buffer_end :: proc "contextless" (ctx: ^Context, buffer: ^Buffer) #no_bounds_ch
}
@(no_instrumentation)
-write :: proc "contextless" (fd: os.Handle, buf: []byte) -> (n: int, err: os.Errno) {
+write :: proc "contextless" (fd: os.Handle, buf: []byte) -> (n: int, err: os.Error) {
return _write(fd, buf)
}
diff --git a/core/prof/spall/spall_linux.odin b/core/prof/spall/spall_linux.odin
index 3f475c5e0..b25d2b336 100644
--- a/core/prof/spall/spall_linux.odin
+++ b/core/prof/spall/spall_linux.odin
@@ -10,21 +10,12 @@ import "core:sys/linux"
MAX_RW :: 0x7fffffff
@(no_instrumentation)
-_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (n: int, err: os.Errno) #no_bounds_check /* bounds check would segfault instrumentation */ {
- if len(data) == 0 {
- return 0, os.ERROR_NONE
- }
-
+_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (n: int, err: os.Error) #no_bounds_check /* bounds check would segfault instrumentation */ {
for n < len(data) {
chunk := data[:min(len(data), MAX_RW)]
- written, errno := linux.write(linux.Fd(fd), chunk)
- if errno != .NONE {
- return n, os.Errno(errno)
- }
- n += written
+ n += linux.write(linux.Fd(fd), chunk) or_return
}
-
- return n, os.ERROR_NONE
+ return
}
CLOCK_MONOTONIC_RAW :: 4 // NOTE(tetra): "RAW" means: Not adjusted by NTP.
diff --git a/core/prof/spall/spall_unix.odin b/core/prof/spall/spall_unix.odin
index e6199d86b..174b3a11b 100644
--- a/core/prof/spall/spall_unix.odin
+++ b/core/prof/spall/spall_unix.odin
@@ -22,29 +22,24 @@ foreign libc {
@(link_name="clock_gettime") _unix_clock_gettime :: proc(clock_id: u64, timespec: ^timespec) -> i32 ---
}
-@(no_instrumentation)
-get_last_error :: proc "contextless" () -> int {
- return int(__error()^)
-}
-
MAX_RW :: 0x7fffffff
@(no_instrumentation)
-_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (n: int, err: os.Errno) #no_bounds_check /* bounds check would segfault instrumentation */ {
+_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (n: int, err: os.Error) #no_bounds_check /* bounds check would segfault instrumentation */ {
if len(data) == 0 {
- return 0, os.ERROR_NONE
+ return 0, nil
}
for n < len(data) {
chunk := data[:min(len(data), MAX_RW)]
written := _unix_write(fd, raw_data(chunk), len(chunk))
if written < 0 {
- return n, os.Errno(get_last_error())
+ return n, os.get_last_error()
}
n += written
}
- return n, os.ERROR_NONE
+ return n, nil
}
CLOCK_MONOTONIC_RAW :: 4 // NOTE(tetra): "RAW" means: Not adjusted by NTP.
diff --git a/core/prof/spall/spall_windows.odin b/core/prof/spall/spall_windows.odin
index 4d96c111a..c8b044963 100644
--- a/core/prof/spall/spall_windows.odin
+++ b/core/prof/spall/spall_windows.odin
@@ -10,9 +10,9 @@ import win32 "core:sys/windows"
MAX_RW :: 1<<30
@(no_instrumentation)
-_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (int, os.Errno) #no_bounds_check /* bounds check would segfault instrumentation */ {
+_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (int, os.Error) #no_bounds_check /* bounds check would segfault instrumentation */ {
if len(data) == 0 {
- return 0, os.ERROR_NONE
+ return 0, nil
}
single_write_length: win32.DWORD
@@ -25,12 +25,11 @@ _write :: proc "contextless" (fd: os.Handle, data: []byte) -> (int, os.Errno) #n
e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil)
if single_write_length <= 0 || !e {
- err := os.Errno(win32.GetLastError())
- return int(total_write), err
+ return int(total_write), os.get_last_error()
}
total_write += i64(single_write_length)
}
- return int(total_write), os.ERROR_NONE
+ return int(total_write), nil
}
@(no_instrumentation)
diff --git a/core/sync/futex_haiku.odin b/core/sync/futex_haiku.odin
index b81743cad..6fe5894a0 100644
--- a/core/sync/futex_haiku.odin
+++ b/core/sync/futex_haiku.odin
@@ -2,7 +2,6 @@
package sync
import "core:c"
-import "base:runtime"
import "core:sys/haiku"
import "core:sys/unix"
import "core:time"
@@ -86,10 +85,10 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) {
waiter.prev.next = waiter.next
waiter.next.prev = waiter.prev
- unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
+ _ = unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
// FIXME: Add error handling!
- return
+ return
}
_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration: time.Duration) -> (ok: bool) {
@@ -133,10 +132,10 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration
waiter.prev.next = waiter.next
waiter.next.prev = waiter.prev
- unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
+ unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
- // FIXME: Add error handling!
- return
+ // FIXME: Add error handling!
+ return
}
_futex_signal :: proc "contextless" (f: ^Futex) {
diff --git a/core/sys/haiku/os.odin b/core/sys/haiku/os.odin
index 1e00145eb..883072c2d 100644
--- a/core/sys/haiku/os.odin
+++ b/core/sys/haiku/os.odin
@@ -399,7 +399,7 @@ cpu_topology_node_info :: struct {
},
_package: struct {
vendor: cpu_vendor,
- cache_line_size: u32
+ cache_line_size: u32,
},
_core: struct {
model: u32,
diff --git a/core/sys/wasm/wasi/wasi_api.odin b/core/sys/wasm/wasi/wasi_api.odin
index 22abd8dc4..6ae6c9151 100644
--- a/core/sys/wasm/wasi/wasi_api.odin
+++ b/core/sys/wasm/wasi/wasi_api.odin
@@ -16,6 +16,7 @@ CLOCK_REALTIME :: clockid_t(2)
CLOCK_THREAD_CPUTIME_ID :: clockid_t(3)
errno_t :: enum u16 {
+ NONE = 0,
// No error occurred. System call completed successfully.
SUCCESS = 0,
// Argument list too long.
diff --git a/core/testing/runner.odin b/core/testing/runner.odin
index da0328f91..16967e3c7 100644
--- a/core/testing/runner.odin
+++ b/core/testing/runner.odin
@@ -868,8 +868,8 @@ To partly mitigate this, redirect STDERR to a file or use the -define:ODIN_TEST_
when ODIN_OS != .Windows {
mode = os.S_IRUSR|os.S_IWUSR|os.S_IRGRP|os.S_IROTH
}
- json_fd, errno := os.open(JSON_REPORT, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
- fmt.assertf(errno == os.ERROR_NONE, "unable to open file %q for writing of JSON report, error: %v", JSON_REPORT, errno)
+ json_fd, err := os.open(JSON_REPORT, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
+ fmt.assertf(err == nil, "unable to open file %q for writing of JSON report, error: %v", JSON_REPORT, err)
defer os.close(json_fd)
for test, i in report.all_tests {