|
@@ -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,12 +506,13 @@ 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
|
|
|
+@(private, require_results)
|
|
|
_get_errno :: proc(res: int) -> Error {
|
|
|
if res < 0 && res > -4096 {
|
|
|
return Platform_Error(-res)
|
|
@@ -536,7 +537,7 @@ get_last_error :: proc "contextless" () -> Error {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
-personality :: proc(persona: u64) -> (Error) {
|
|
|
+personality :: proc(persona: u64) -> Error {
|
|
|
res := unix.sys_personality(persona)
|
|
|
if res == -1 {
|
|
|
return _get_errno(res)
|
|
@@ -544,6 +545,7 @@ personality :: proc(persona: u64) -> (Error) {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
fork :: proc() -> (Pid, Error) {
|
|
|
pid := unix.sys_fork()
|
|
|
if pid == -1 {
|
|
@@ -567,6 +569,7 @@ execvp :: proc(path: string, args: []string) -> Error {
|
|
|
}
|
|
|
|
|
|
|
|
|
+@(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)
|
|
@@ -659,6 +662,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
|
|
return i64(res), nil
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
file_size :: proc(fd: Handle) -> (i64, Error) {
|
|
|
// deliberately uninitialized; the syscall fills this buffer for us
|
|
|
s: OS_Stat = ---
|
|
@@ -694,6 +698,7 @@ remove_directory :: proc(path: string) -> Error {
|
|
|
return _get_errno(unix.sys_rmdir(path_cstr))
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
is_file_handle :: proc(fd: Handle) -> bool {
|
|
|
s, err := _fstat(fd)
|
|
|
if err != nil {
|
|
@@ -702,6 +707,7 @@ is_file_handle :: proc(fd: Handle) -> bool {
|
|
|
return S_ISREG(s.mode)
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
|
|
s: OS_Stat
|
|
|
err: Error
|
|
@@ -717,6 +723,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
|
|
}
|
|
|
|
|
|
|
|
|
+@(require_results)
|
|
|
is_dir_handle :: proc(fd: Handle) -> bool {
|
|
|
s, err := _fstat(fd)
|
|
|
if err != nil {
|
|
@@ -725,6 +732,7 @@ is_dir_handle :: proc(fd: Handle) -> bool {
|
|
|
return S_ISDIR(s.mode)
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
|
|
s: OS_Stat
|
|
|
err: Error
|
|
@@ -742,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)
|
|
@@ -759,19 +768,21 @@ stderr: Handle = 2
|
|
|
last_write_time :: proc(fd: Handle) -> File_Time {}
|
|
|
last_write_time_by_name :: proc(name: string) -> File_Time {}
|
|
|
*/
|
|
|
+@(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), nil
|
|
|
}
|
|
|
|
|
|
+@(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), nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(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)
|
|
@@ -785,7 +796,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) {
|
|
|
return s, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(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)
|
|
@@ -799,7 +810,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) {
|
|
|
return s, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(private, require_results)
|
|
|
_fstat :: proc(fd: Handle) -> (OS_Stat, Error) {
|
|
|
// deliberately uninitialized; the syscall fills this buffer for us
|
|
|
s: OS_Stat = ---
|
|
@@ -810,7 +821,7 @@ _fstat :: proc(fd: Handle) -> (OS_Stat, Error) {
|
|
|
return s, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(private, require_results)
|
|
|
_fdopendir :: proc(fd: Handle) -> (Dir, Error) {
|
|
|
dirp := _unix_fdopendir(fd)
|
|
|
if dirp == cast(Dir)nil {
|
|
@@ -819,7 +830,7 @@ _fdopendir :: proc(fd: Handle) -> (Dir, Error) {
|
|
|
return dirp, nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(private)
|
|
|
_closedir :: proc(dirp: Dir) -> Error {
|
|
|
rc := _unix_closedir(dirp)
|
|
|
if rc != 0 {
|
|
@@ -828,12 +839,12 @@ _closedir :: proc(dirp: Dir) -> Error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(private)
|
|
|
_rewinddir :: proc(dirp: Dir) {
|
|
|
_unix_rewinddir(dirp)
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(private, require_results)
|
|
|
_readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) {
|
|
|
result: ^Dirent
|
|
|
rc := _unix_readdir_r(dirp, &entry, &result)
|
|
@@ -853,7 +864,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-@private
|
|
|
+@(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)
|
|
@@ -876,6 +887,7 @@ _readlink :: proc(path: string) -> (string, Error) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
|
|
buf : [256]byte
|
|
|
fd_str := strconv.itoa( buf[:], cast(int)fd )
|
|
@@ -886,6 +898,7 @@ absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
|
|
return _readlink(procfs_path)
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
|
|
rel := rel
|
|
|
if rel == "" {
|
|
@@ -916,6 +929,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) {
|
|
|
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)
|
|
@@ -927,6 +941,7 @@ 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
|
|
@@ -954,6 +969,7 @@ unset_env :: proc(key: string) -> Error {
|
|
|
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.
|
|
@@ -990,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()
|
|
@@ -1015,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.
|
|
@@ -1027,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__ {
|
|
@@ -1040,6 +1061,7 @@ _alloc_command_line_arguments :: proc() -> []string {
|
|
|
return res
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) {
|
|
|
result := unix.sys_socket(domain, type, protocol)
|
|
|
if result < 0 {
|
|
@@ -1048,7 +1070,7 @@ socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) {
|
|
|
return Socket(result), nil
|
|
|
}
|
|
|
|
|
|
-bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) {
|
|
|
+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)
|
|
@@ -1057,7 +1079,7 @@ bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) {
|
|
|
+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)
|
|
@@ -1073,7 +1095,7 @@ accept :: proc(sd: Socket, addr: ^SOCKADDR, len: rawptr) -> (Socket, Error) {
|
|
|
return Socket(result), nil
|
|
|
}
|
|
|
|
|
|
-listen :: proc(sd: Socket, backlog: int) -> (Error) {
|
|
|
+listen :: proc(sd: Socket, backlog: int) -> Error {
|
|
|
result := unix.sys_listen(int(sd), backlog)
|
|
|
if result < 0 {
|
|
|
return _get_errno(result)
|
|
@@ -1081,7 +1103,7 @@ listen :: proc(sd: Socket, backlog: int) -> (Error) {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> (Error) {
|
|
|
+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)
|
|
@@ -1123,7 +1145,7 @@ send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Error) {
|
|
|
return u32(result), nil
|
|
|
}
|
|
|
|
|
|
-shutdown :: proc(sd: Socket, how: int) -> (Error) {
|
|
|
+shutdown :: proc(sd: Socket, how: int) -> Error {
|
|
|
result := unix.sys_shutdown(int(sd), how)
|
|
|
if result < 0 {
|
|
|
return _get_errno(result)
|
|
@@ -1139,6 +1161,7 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Error) {
|
|
|
return result, nil
|
|
|
}
|
|
|
|
|
|
+@(require_results)
|
|
|
poll :: proc(fds: []pollfd, timeout: int) -> (int, Error) {
|
|
|
result := unix.sys_poll(raw_data(fds), uint(len(fds)), timeout)
|
|
|
if result < 0 {
|
|
@@ -1147,6 +1170,7 @@ poll :: proc(fds: []pollfd, timeout: int) -> (int, Error) {
|
|
|
return result, nil
|
|
|
}
|
|
|
|
|
|
+@(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 {
|