mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
Try to keep the interface for most of the common procedures the same
This entire package is a mess, and even though it will be replaced, it does need to be cleaned up.
This commit is contained in:
@@ -4,7 +4,7 @@ package os
|
||||
import "core:strings"
|
||||
|
||||
@(require_results)
|
||||
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
_read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
dirp := _fdopendir(fd) or_return
|
||||
defer _closedir(dirp)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import "core:strings"
|
||||
import "base:runtime"
|
||||
|
||||
@(require_results)
|
||||
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
_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 ".."
|
||||
|
||||
@@ -8,7 +8,7 @@ import "base:runtime"
|
||||
// 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) {
|
||||
_lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
if key == "" {
|
||||
return
|
||||
}
|
||||
@@ -35,13 +35,13 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
|
||||
// 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) {
|
||||
_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) -> Error {
|
||||
_set_env :: proc(key, value: string) -> Error {
|
||||
k := win32.utf8_to_wstring(key)
|
||||
v := win32.utf8_to_wstring(value)
|
||||
|
||||
@@ -52,7 +52,7 @@ set_env :: proc(key, value: string) -> Error {
|
||||
}
|
||||
|
||||
// unset_env unsets a single environment variable
|
||||
unset_env :: proc(key: string) -> Error {
|
||||
_unset_env :: proc(key: string) -> Error {
|
||||
k := win32.utf8_to_wstring(key)
|
||||
if !win32.SetEnvironmentVariableW(k, nil) {
|
||||
return get_last_error()
|
||||
@@ -63,7 +63,7 @@ unset_env :: proc(key: string) -> Error {
|
||||
// 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 {
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
envs := ([^]win32.WCHAR)(win32.GetEnvironmentStringsW())
|
||||
if envs == nil {
|
||||
return nil
|
||||
@@ -89,7 +89,7 @@ environ :: proc(allocator := context.allocator) -> []string {
|
||||
|
||||
|
||||
// clear_env deletes all environment variables
|
||||
clear_env :: proc() {
|
||||
_clear_env :: proc() {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
envs := environ(context.temp_allocator)
|
||||
for env in envs {
|
||||
|
||||
@@ -6,12 +6,12 @@ import "base:runtime"
|
||||
import "core:unicode/utf16"
|
||||
|
||||
@(require_results)
|
||||
is_path_separator :: proc(c: byte) -> bool {
|
||||
_is_path_separator :: proc "contextless" (c: rune) -> bool {
|
||||
return c == '/' || c == '\\'
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) {
|
||||
_open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) {
|
||||
if len(path) == 0 {
|
||||
return INVALID_HANDLE, General_Error.Not_Exist
|
||||
}
|
||||
@@ -60,14 +60,14 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Erro
|
||||
return INVALID_HANDLE, get_last_error()
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
if !win32.CloseHandle(win32.HANDLE(fd)) {
|
||||
return get_last_error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> (err: Error) {
|
||||
_flush :: proc(fd: Handle) -> (err: Error) {
|
||||
if !win32.FlushFileBuffers(win32.HANDLE(fd)) {
|
||||
err = get_last_error()
|
||||
}
|
||||
@@ -76,7 +76,7 @@ flush :: proc(fd: Handle) -> (err: Error) {
|
||||
|
||||
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -149,7 +149,7 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Error) {
|
||||
_read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -186,7 +186,7 @@ read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Error) {
|
||||
return total_read, nil
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
w: u32
|
||||
switch whence {
|
||||
case 0: w = win32.FILE_BEGIN
|
||||
@@ -209,7 +209,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
_file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
length: win32.LARGE_INTEGER
|
||||
err: Error
|
||||
if !win32.GetFileSizeEx(win32.HANDLE(fd), &length) {
|
||||
@@ -279,7 +279,7 @@ 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: Error) {
|
||||
_read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
if offset < 0 {
|
||||
return 0, .Invalid_Offset
|
||||
}
|
||||
@@ -311,7 +311,7 @@ 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: Error) {
|
||||
_write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
if offset < 0 {
|
||||
return 0, .Invalid_Offset
|
||||
}
|
||||
@@ -341,7 +341,7 @@ get_std_handle :: proc "contextless" (h: uint) -> Handle {
|
||||
}
|
||||
|
||||
|
||||
exists :: proc(path: string) -> bool {
|
||||
_exists :: proc(path: string) -> bool {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
@@ -350,7 +350,7 @@ exists :: proc(path: string) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file :: proc(path: string) -> bool {
|
||||
_is_file_path :: proc(path: string, _: bool) -> bool {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
@@ -362,7 +362,7 @@ is_file :: proc(path: string) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir :: proc(path: string) -> bool {
|
||||
_is_dir_path :: proc(path: string, _: bool) -> bool {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
@@ -373,11 +373,21 @@ is_dir :: proc(path: string) -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 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 {
|
||||
_get_current_directory :: proc(allocator := context.allocator) -> string {
|
||||
win32.AcquireSRWLockExclusive(&cwd_lock)
|
||||
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator)
|
||||
@@ -393,7 +403,7 @@ 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: Error) {
|
||||
_set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
wstr := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
|
||||
@@ -407,9 +417,8 @@ set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
|
||||
return
|
||||
}
|
||||
change_directory :: set_current_directory
|
||||
|
||||
make_directory :: proc(path: string, mode: u32 = 0) -> (err: Error) {
|
||||
_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)
|
||||
@@ -421,7 +430,7 @@ make_directory :: proc(path: string, mode: u32 = 0) -> (err: Error) {
|
||||
}
|
||||
|
||||
|
||||
remove_directory :: proc(path: string) -> (err: Error) {
|
||||
_remove_directory :: proc(path: string) -> (err: Error) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
|
||||
@@ -494,14 +503,14 @@ fix_long_path :: proc(path: string) -> string {
|
||||
}
|
||||
|
||||
|
||||
link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
_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 Platform_Error(win32.CreateHardLinkW(n, o, nil))
|
||||
}
|
||||
|
||||
unlink :: proc(path: string) -> (err: Error) {
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
|
||||
@@ -513,7 +522,7 @@ unlink :: proc(path: string) -> (err: Error) {
|
||||
|
||||
|
||||
|
||||
rename :: proc(old_path, new_path: string) -> (err: Error) {
|
||||
_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)
|
||||
@@ -525,7 +534,7 @@ rename :: proc(old_path, new_path: string) -> (err: Error) {
|
||||
}
|
||||
|
||||
|
||||
ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
curr_off := seek(fd, 0, 1) or_return
|
||||
defer seek(fd, curr_off, 0)
|
||||
_= seek(fd, length, 0) or_return
|
||||
@@ -536,14 +545,14 @@ ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
fd := open(path, O_WRONLY|O_CREATE, 0o666) or_return
|
||||
defer close(fd)
|
||||
return ftruncate(fd, length)
|
||||
}
|
||||
|
||||
|
||||
remove :: proc(name: string) -> Error {
|
||||
_remove :: proc(name: string) -> Error {
|
||||
p := win32.utf8_to_wstring(fix_long_path(name))
|
||||
err, err1: win32.DWORD
|
||||
if !win32.DeleteFileW(p) {
|
||||
@@ -582,7 +591,7 @@ remove :: proc(name: string) -> Error {
|
||||
|
||||
|
||||
@(require_results)
|
||||
pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
sa: win32.SECURITY_ATTRIBUTES
|
||||
sa.nLength = size_of(win32.SECURITY_ATTRIBUTES)
|
||||
sa.bInheritHandle = true
|
||||
|
||||
204
core/os/os.odin
204
core/os/os.odin
@@ -15,6 +15,210 @@ SEEK_SET :: 0
|
||||
SEEK_CUR :: 1
|
||||
SEEK_END :: 2
|
||||
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
return _get_last_error()
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (handle: Handle, err: Error) {
|
||||
return _open(path, flags, mode)
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
return _close(fd)
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
return _flush(fd)
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return _write(fd, data)
|
||||
}
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return _read(fd, data)
|
||||
}
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
return _read_at(fd, data, offset)
|
||||
}
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
return _write_at(fd, data, offset)
|
||||
}
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
return _seek(fd, offset, whence)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) {
|
||||
return _last_write_time(fd)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) {
|
||||
return _last_write_time_by_name(name)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_path_separator_rune :: proc "contextless" (r: rune) -> bool {
|
||||
return _is_path_separator(r)
|
||||
}
|
||||
@(require_results)
|
||||
is_path_separator_byte :: proc "contextless" (b: byte) -> bool {
|
||||
return _is_path_separator(rune(b))
|
||||
}
|
||||
|
||||
is_path_separator :: proc{
|
||||
is_path_separator_rune,
|
||||
is_path_separator_byte,
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
return _is_file_handle(fd)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
return _is_file_path(path, follow_links)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
return _is_dir_handle(fd)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
return _is_dir_path(path, follow_links)
|
||||
}
|
||||
|
||||
is_file :: proc {is_file_path, is_file_handle}
|
||||
is_dir :: proc {is_dir_path, is_dir_handle}
|
||||
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
return _file_size(fd)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
exists :: proc(path: string) -> bool {
|
||||
return _exists(path)
|
||||
}
|
||||
|
||||
rename :: proc(old, new: string) -> Error {
|
||||
return _rename(old, new)
|
||||
}
|
||||
|
||||
remove :: proc(path: string) -> Error {
|
||||
return _remove(path)
|
||||
}
|
||||
|
||||
link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
return _link(old_name, new_name)
|
||||
}
|
||||
unlink :: proc(path: string) -> (err: Error) {
|
||||
return _unlink(path)
|
||||
}
|
||||
ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
return _ftruncate(fd, length)
|
||||
}
|
||||
|
||||
truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
return _truncate(path, length)
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
return _pipe()
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
return _read_dir(fd, n, allocator)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
return _absolute_path_from_handle(fd)
|
||||
}
|
||||
@(require_results)
|
||||
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
return _absolute_path_from_relative(rel)
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
return _access(path, mask)
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
environ :: proc(allocator := context.allocator) -> []string {
|
||||
return _environ(allocator)
|
||||
}
|
||||
@(require_results)
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
return _lookup_env(key, allocator)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
return _get_env(key, allocator)
|
||||
}
|
||||
|
||||
set_env :: proc(key, value: string) -> Error {
|
||||
return _set_env(key, value)
|
||||
}
|
||||
unset_env :: proc(key: string) -> Error {
|
||||
return _unset_env(key)
|
||||
}
|
||||
|
||||
clear_env :: proc() {
|
||||
_clear_env()
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
get_current_directory :: proc() -> string {
|
||||
return _get_current_directory()
|
||||
}
|
||||
|
||||
|
||||
set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
return _set_current_directory(path)
|
||||
}
|
||||
|
||||
change_directory :: set_current_directory
|
||||
|
||||
|
||||
make_directory :: proc(path: string, mode: u32 = 0o775) -> Error {
|
||||
return _make_directory(path, mode)
|
||||
}
|
||||
|
||||
remove_directory :: proc(path: string) -> Error {
|
||||
return _remove_directory(path)
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit(code)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
return _current_thread_id()
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_page_size :: proc() -> int {
|
||||
return _get_page_size()
|
||||
}
|
||||
|
||||
|
||||
write_string :: proc(fd: Handle, str: string) -> (int, Error) {
|
||||
return write(fd, transmute([]byte)str)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ _Path_List_Separator :: ':'
|
||||
|
||||
_OPENDIR_FLAGS : linux.Open_Flags : {.NONBLOCK, .DIRECTORY, .LARGEFILE, .CLOEXEC}
|
||||
|
||||
_is_path_separator :: proc(c: byte) -> bool {
|
||||
_is_path_separator :: proc(c: rune) -> bool {
|
||||
return c == '/'
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ _Path_Separator :: '\\'
|
||||
_Path_Separator_String :: "\\"
|
||||
_Path_List_Separator :: ';'
|
||||
|
||||
_is_path_separator :: proc(c: byte) -> bool {
|
||||
_is_path_separator :: proc "contextless" (c: rune) -> bool {
|
||||
return c == '\\' || c == '/'
|
||||
}
|
||||
|
||||
|
||||
@@ -663,7 +663,7 @@ foreign dl {
|
||||
}
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
return Platform_Error(__error()^)
|
||||
}
|
||||
|
||||
@@ -673,8 +673,8 @@ get_last_error_string :: proc() -> string {
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (handle: Handle, err: Error) {
|
||||
@(private, 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 {
|
||||
@@ -712,7 +712,8 @@ fchmod :: proc(fd: Handle, mode: u16) -> Error {
|
||||
return cast(Platform_Error)_unix_fchmod(fd, mode)
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
@(private)
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
return cast(Platform_Error)_unix_close(fd)
|
||||
}
|
||||
|
||||
@@ -726,7 +727,8 @@ close :: proc(fd: Handle) -> Error {
|
||||
@(private)
|
||||
MAX_RW :: 1 << 30
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
@(private, require_results)
|
||||
_write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -740,7 +742,8 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return bytes_written, nil
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []u8) -> (int, Error) {
|
||||
@(private, require_results)
|
||||
_read :: proc(fd: Handle, data: []u8) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -754,7 +757,8 @@ read :: proc(fd: Handle, data: []u8) -> (int, Error) {
|
||||
return bytes_read, nil
|
||||
}
|
||||
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
@(private, require_results)
|
||||
_read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -768,7 +772,8 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
return bytes_read, nil
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
@(private, require_results)
|
||||
_write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -782,7 +787,8 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
return bytes_written, nil
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
@(private, require_results)
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
assert(fd != -1)
|
||||
|
||||
final_offset := i64(_unix_lseek(fd, int(offset), c.int(whence)))
|
||||
@@ -792,8 +798,8 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
return final_offset, nil
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
@(private, 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)
|
||||
@@ -808,14 +814,14 @@ stdout: Handle = 1 // get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||
stderr: Handle = 2 // get_std_handle(win32.STD_ERROR_HANDLE);
|
||||
|
||||
@(require_results)
|
||||
last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) {
|
||||
_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) {
|
||||
_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
|
||||
@@ -823,12 +829,12 @@ last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) {
|
||||
|
||||
|
||||
@(require_results)
|
||||
is_path_separator :: proc(r: rune) -> bool {
|
||||
_is_path_separator :: proc "contextless" (r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -837,7 +843,7 @@ is_file_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -853,7 +859,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
|
||||
|
||||
@(require_results)
|
||||
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -862,7 +868,7 @@ is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -876,25 +882,26 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
return S_ISDIR(s.mode)
|
||||
}
|
||||
|
||||
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 {
|
||||
_exists :: proc(path: string) -> bool {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cpath := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
res := _unix_access(cpath, O_RDONLY)
|
||||
return res == 0
|
||||
}
|
||||
|
||||
rename :: proc(old: string, new: string) -> bool {
|
||||
_rename :: proc(old, new: string) -> Error {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
old_cstr := strings.clone_to_cstring(old, context.temp_allocator)
|
||||
new_cstr := strings.clone_to_cstring(new, context.temp_allocator)
|
||||
return _unix_rename(old_cstr, new_cstr) != -1
|
||||
res := _unix_rename(old_cstr, new_cstr)
|
||||
if res == -1 {
|
||||
return get_last_error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
remove :: proc(path: string) -> Error {
|
||||
_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)
|
||||
@@ -1005,15 +1012,15 @@ _readlink :: proc(path: string) -> (string, Error) {
|
||||
}
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
@(private, require_results)
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
buf: [DARWIN_MAXPATHLEN]byte
|
||||
_ = fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0]))) or_return
|
||||
return strings.clone_from_cstring(cstring(&buf[0]))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
@(private, require_results)
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
rel := rel
|
||||
if rel == "" {
|
||||
rel = "."
|
||||
@@ -1034,18 +1041,40 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> bool {
|
||||
@(private)
|
||||
_access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
return _unix_access(cstr, c.int(mask)) == 0
|
||||
res := _unix_access(cstr, c.int(mask))
|
||||
if res == 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, get_last_error()
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("TODO: _link")
|
||||
}
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _unlink")
|
||||
}
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _ftruncate")
|
||||
}
|
||||
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _truncate")
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(private)
|
||||
_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) {
|
||||
@(private, 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)
|
||||
cstr := _unix_getenv(path_str)
|
||||
@@ -1055,13 +1084,14 @@ 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) {
|
||||
@(private, require_results)
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
value, _ = lookup_env(key, allocator)
|
||||
return
|
||||
}
|
||||
|
||||
set_env :: proc(key, value: string) -> Error {
|
||||
@(private)
|
||||
_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)
|
||||
@@ -1072,7 +1102,8 @@ set_env :: proc(key, value: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
unset_env :: proc(key: string) -> Error {
|
||||
@(private)
|
||||
_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)
|
||||
@@ -1083,7 +1114,15 @@ unset_env :: proc(key: string) -> Error {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_current_directory :: proc() -> string {
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
return nil
|
||||
}
|
||||
_clear_env :: proc() {
|
||||
}
|
||||
|
||||
|
||||
@(private, 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)
|
||||
for {
|
||||
@@ -1100,7 +1139,8 @@ get_current_directory :: proc() -> string {
|
||||
unreachable()
|
||||
}
|
||||
|
||||
set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
@(private)
|
||||
_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)
|
||||
@@ -1110,23 +1150,29 @@ set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
make_directory :: proc(path: string, mode: u16 = 0o775) -> Error {
|
||||
@(private)
|
||||
_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)
|
||||
res := _unix_mkdir(path_cstr, mode)
|
||||
res := _unix_mkdir(path_cstr, u16(mode))
|
||||
if res == -1 {
|
||||
return get_last_error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_remove_directory :: proc(path: string) -> Error {
|
||||
unimplemented("TODO: _remove_directory")
|
||||
}
|
||||
|
||||
@(private)
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(i32(code))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
@(private, require_results)
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
tid: u64
|
||||
// NOTE(Oskar): available from OSX 10.6 and iOS 3.2.
|
||||
// For older versions there is `syscall(SYS_thread_selfid)`, but not really
|
||||
@@ -1160,7 +1206,13 @@ dlerror :: proc() -> string {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_page_size :: proc() -> int {
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
|
||||
@(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.
|
||||
@static page_size := -1
|
||||
|
||||
@@ -30,31 +30,31 @@ heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
return es.HeapReallocate(ptr, new_size, false)
|
||||
}
|
||||
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
|
||||
_open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
|
||||
return (Handle) (0), (Error) (1)
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
return (Error) (1)
|
||||
}
|
||||
|
||||
file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
_file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
return (i64) (0), (Error) (1)
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return (int) (0), (Error) (1)
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []u8) -> (int, Error) {
|
||||
_write :: proc(fd: Handle, data: []u8) -> (int, Error) {
|
||||
return (int) (0), (Error) (1)
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
return (i64) (0), (Error) (1)
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_flush :: proc(fd: Handle) -> Error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
@@ -416,17 +416,17 @@ foreign dl {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_path_separator :: proc(r: rune) -> bool {
|
||||
_is_path_separator :: proc "contextless" (r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
return Platform_Error(__Error_location()^)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
|
||||
_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))
|
||||
@@ -436,7 +436,7 @@ open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Err
|
||||
return handle, nil
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
result := _unix_close(fd)
|
||||
if result == -1 {
|
||||
return get_last_error()
|
||||
@@ -444,7 +444,7 @@ close :: proc(fd: Handle) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_flush :: proc(fd: Handle) -> Error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
@@ -457,7 +457,7 @@ flush :: proc(fd: Handle) -> Error {
|
||||
@(private)
|
||||
MAX_RW :: 1 << 30
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_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 {
|
||||
@@ -466,7 +466,7 @@ read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_read), nil
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -479,7 +479,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_written), nil
|
||||
}
|
||||
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -489,7 +489,7 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -499,7 +499,7 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error)
|
||||
return
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
res := _unix_seek(fd, offset, c.int(whence))
|
||||
if res == -1 {
|
||||
return -1, get_last_error()
|
||||
@@ -508,14 +508,24 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (size: i64, err: Error) {
|
||||
_file_size :: proc(fd: Handle) -> (size: i64, err: Error) {
|
||||
size = -1
|
||||
s := _fstat(fd) or_return
|
||||
size = s.size
|
||||
return
|
||||
}
|
||||
@(require_results)
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
|
||||
rename :: proc(old_path, new_path: string) -> Error {
|
||||
@(require_results)
|
||||
_exists :: proc(path: string) -> bool {
|
||||
unimplemented("TODO: _exists")
|
||||
}
|
||||
|
||||
_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)
|
||||
@@ -526,7 +536,7 @@ rename :: proc(old_path, new_path: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
remove :: proc(path: string) -> Error {
|
||||
_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)
|
||||
@@ -536,17 +546,17 @@ remove :: proc(path: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
make_directory :: proc(path: string, mode: mode_t = 0o775) -> Error {
|
||||
_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)
|
||||
res := _unix_mkdir(path_cstr, mode)
|
||||
res := _unix_mkdir(path_cstr, mode_t(mode))
|
||||
if res == -1 {
|
||||
return get_last_error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
remove_directory :: proc(path: string) -> Error {
|
||||
_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)
|
||||
@@ -556,8 +566,23 @@ remove_directory :: proc(path: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("TODO: _link")
|
||||
}
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _unlink")
|
||||
}
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _ftruncate")
|
||||
}
|
||||
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _truncate")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -566,7 +591,7 @@ is_file_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -581,7 +606,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -590,7 +615,7 @@ is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -604,8 +629,6 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
return S_ISDIR(s.mode)
|
||||
}
|
||||
|
||||
is_file :: proc {is_file_path, is_file_handle}
|
||||
is_dir :: proc {is_dir_path, is_dir_handle}
|
||||
|
||||
// NOTE(bill): Uses startup to initialize it
|
||||
|
||||
@@ -618,7 +641,7 @@ 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) -> (File_Time, Error) {
|
||||
_last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -628,7 +651,7 @@ last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
|
||||
_last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
|
||||
s, err := _stat(name)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -740,7 +763,7 @@ _readlink :: proc(path: string) -> (string, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
_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
|
||||
@@ -763,7 +786,7 @@ absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
rel := rel
|
||||
if rel == "" {
|
||||
rel = "."
|
||||
@@ -784,7 +807,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
_access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
|
||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
@@ -796,7 +819,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
_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)
|
||||
@@ -808,13 +831,29 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
value, _ = lookup_env(key, allocator)
|
||||
return
|
||||
}
|
||||
|
||||
_set_env :: proc(key, value: string) -> Error {
|
||||
unimplemented("TODO: _set_env")
|
||||
}
|
||||
_unset_env :: proc(key: string) -> Error {
|
||||
unimplemented("TODO: _unset_env")
|
||||
}
|
||||
|
||||
_clear_env :: proc() {
|
||||
unimplemented("TODO: _clear_env")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_current_directory :: proc() -> string {
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
unimplemented("TODO: _environ")
|
||||
}
|
||||
|
||||
@(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.
|
||||
// The largest value I could find was 4096, so might as well use the page size.
|
||||
@@ -834,7 +873,7 @@ get_current_directory :: proc() -> string {
|
||||
unreachable()
|
||||
}
|
||||
|
||||
set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
_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)
|
||||
@@ -844,13 +883,13 @@ set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(c.int(code))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
return cast(int) pthread_getthreadid_np()
|
||||
}
|
||||
|
||||
@@ -878,7 +917,7 @@ dlerror :: proc() -> string {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_page_size :: proc() -> int {
|
||||
_get_page_size :: proc() -> int {
|
||||
// NOTE(tetra): The page size never changes, so why do anything complicated
|
||||
// if we don't have to.
|
||||
@static page_size := -1
|
||||
|
||||
@@ -4,6 +4,7 @@ foreign import libc "system:c"
|
||||
|
||||
import "base:runtime"
|
||||
import "core:c"
|
||||
import "core:time"
|
||||
import "core:strings"
|
||||
import "core:sys/haiku"
|
||||
|
||||
@@ -178,17 +179,17 @@ Dirent :: struct {
|
||||
Dir :: distinct rawptr // DIR*
|
||||
|
||||
@(require_results)
|
||||
is_path_separator :: proc(r: rune) -> bool {
|
||||
_is_path_separator :: proc "contextless" (r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
return Platform_Error(__error()^)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
fork :: proc() -> (Pid, Error) {
|
||||
_fork :: proc() -> (Pid, Error) {
|
||||
pid := _unix_fork()
|
||||
if pid == -1 {
|
||||
return Pid(-1), get_last_error()
|
||||
@@ -197,7 +198,7 @@ fork :: proc() -> (Pid, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
|
||||
_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))
|
||||
@@ -207,7 +208,7 @@ open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Err
|
||||
return handle, nil
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
result := _unix_close(fd)
|
||||
if result == -1 {
|
||||
return get_last_error()
|
||||
@@ -215,7 +216,7 @@ close :: proc(fd: Handle) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_flush :: proc(fd: Handle) -> Error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
@@ -227,7 +228,7 @@ flush :: proc(fd: Handle) -> Error {
|
||||
@(private)
|
||||
MAX_RW :: 1 << 30
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_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 {
|
||||
@@ -236,7 +237,7 @@ read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_read), nil
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -249,7 +250,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_written), nil
|
||||
}
|
||||
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -259,7 +260,7 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -269,7 +270,7 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error)
|
||||
return
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
res := _unix_seek(fd, offset, c.int(whence))
|
||||
if res == -1 {
|
||||
return -1, get_last_error()
|
||||
@@ -278,7 +279,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
_file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
@@ -401,12 +402,12 @@ _readlink :: proc(path: string) -> (string, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
return "", Error(ENOSYS)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
rel := rel
|
||||
if rel == "" {
|
||||
rel = "."
|
||||
@@ -427,7 +428,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
_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))
|
||||
@@ -438,7 +439,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
_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)
|
||||
cstr := _unix_getenv(path_str)
|
||||
@@ -449,11 +450,59 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
value, _ = lookup_env(key, allocator)
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
unimplemented("TODO: _environ")
|
||||
}
|
||||
|
||||
|
||||
_set_env :: proc(key, value: string) -> Error {
|
||||
unimplemented("TODO: _set_env")
|
||||
}
|
||||
_unset_env :: proc(key: string) -> Error {
|
||||
unimplemented("TODO: _unset_env")
|
||||
}
|
||||
|
||||
_clear_env :: proc() {
|
||||
unimplemented("TODO: _clear_env")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_get_current_directory :: proc() -> string {
|
||||
unimplemented("TODO: _get_current_directory")
|
||||
}
|
||||
|
||||
|
||||
_set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _set_current_directory")
|
||||
}
|
||||
|
||||
_make_directory :: proc(path: string, mode: u32 = 0o775) -> Error {
|
||||
unimplemented("TODO: _make_directory")
|
||||
}
|
||||
|
||||
_remove_directory :: proc(path: string) -> Error {
|
||||
unimplemented("TODO: _remove_directory")
|
||||
}
|
||||
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
context = runtime.default_context()
|
||||
unimplemented("TODO: _current_thread_id")
|
||||
}
|
||||
|
||||
_get_page_size :: proc() -> int {
|
||||
unimplemented("TODO: _get_page_size")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@(private, require_results)
|
||||
_processor_core_count :: proc() -> int {
|
||||
info: haiku.system_info
|
||||
@@ -461,7 +510,107 @@ _processor_core_count :: proc() -> int {
|
||||
return int(info.cpu_count)
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(i32(code))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
_last_write_time :: proc(fd: Handle) -> (ft: File_Time, err: Error) {
|
||||
s := fstat(fd) or_return
|
||||
defer file_info_delete(s)
|
||||
ft = File_Time(time.time_to_unix(s.modification_time)) // TODO: is this correct?
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_last_write_time_by_name :: proc(name: string) -> (ft: File_Time, err: Error) {
|
||||
s := stat(name) or_return
|
||||
defer file_info_delete(s)
|
||||
ft = File_Time(time.time_to_unix(s.modification_time)) // TODO: is this correct?
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := fstat(fd)
|
||||
defer file_info_delete(s)
|
||||
return err != nil && !s.is_dir
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
if follow_links {
|
||||
s, err := lstat(path)
|
||||
defer file_info_delete(s)
|
||||
return err != nil && !s.is_dir
|
||||
}
|
||||
s, err := stat(path)
|
||||
defer file_info_delete(s)
|
||||
return err != nil && !s.is_dir
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := fstat(fd)
|
||||
defer file_info_delete(s)
|
||||
return err != nil && s.is_dir
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
if follow_links {
|
||||
s, err := lstat(path)
|
||||
defer file_info_delete(s)
|
||||
return err != nil && s.is_dir
|
||||
}
|
||||
s, err := stat(path)
|
||||
defer file_info_delete(s)
|
||||
return err != nil && s.is_dir
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_exists :: proc(path: string) -> bool {
|
||||
fi, err := stat(path)
|
||||
file_info_delete(fi)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
_rename :: proc(old, new: string) -> Error {
|
||||
unimplemented("TODO: _rename")
|
||||
}
|
||||
|
||||
_remove :: proc(path: string) -> Error {
|
||||
unimplemented("TODO: _remove")
|
||||
}
|
||||
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("TODO: _link")
|
||||
}
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _unlink")
|
||||
}
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _ftruncate")
|
||||
}
|
||||
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _truncate")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
unimplemented("TODO: _pipe")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
unimplemented("TODO: _read_dir")
|
||||
}
|
||||
|
||||
|
||||
@@ -3,45 +3,51 @@ package os
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_path_separator :: proc(c: byte) -> bool {
|
||||
_is_path_separator :: proc "contextless" (c: rune) -> bool {
|
||||
return c == '/' || c == '\\'
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) {
|
||||
_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) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> (err: Error) {
|
||||
_flush :: proc(fd: Handle) -> (err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_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: Error) {
|
||||
_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, Error) {
|
||||
_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, Error) {
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
_file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@@ -58,10 +64,10 @@ 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: Error) {
|
||||
_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: Error) {
|
||||
_write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@@ -76,17 +82,27 @@ get_std_handle :: proc "contextless" (h: uint) -> Handle {
|
||||
|
||||
|
||||
@(require_results)
|
||||
exists :: proc(path: string) -> bool {
|
||||
_exists :: proc(path: string) -> bool {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file :: proc(path: string) -> bool {
|
||||
_is_file_path :: proc(path: string, _: bool) -> bool {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir :: proc(path: string) -> bool {
|
||||
_is_dir_path :: proc(path: string, _: bool) -> bool {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_file_handle :: proc(handle: Handle) -> bool {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_dir_handle :: proc(handle: Handle) -> bool {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@@ -94,26 +110,26 @@ is_dir :: proc(path: string) -> bool {
|
||||
//@private cwd_lock := win32.SRWLOCK{} // zero is initialized
|
||||
|
||||
@(require_results)
|
||||
get_current_directory :: proc(allocator := context.allocator) -> string {
|
||||
_get_current_directory :: proc(allocator := context.allocator) -> string {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
_set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
|
||||
|
||||
change_directory :: proc(path: string) -> (err: Error) {
|
||||
_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: Error) {
|
||||
_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: Error) {
|
||||
_remove_directory :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@@ -130,42 +146,42 @@ fix_long_path :: proc(path: string) -> string {
|
||||
}
|
||||
|
||||
|
||||
link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
unlink :: proc(path: string) -> (err: Error) {
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
|
||||
|
||||
rename :: proc(old_path, new_path: string) -> (err: Error) {
|
||||
_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: Error) {
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
|
||||
remove :: proc(name: string) -> Error {
|
||||
_remove :: proc(name: string) -> Error {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
_read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@@ -262,19 +278,19 @@ args := _alloc_command_line_arguments()
|
||||
|
||||
|
||||
@(require_results)
|
||||
last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
|
||||
_last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
|
||||
_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")
|
||||
_get_page_size :: proc() -> int {
|
||||
return 1<<16
|
||||
}
|
||||
|
||||
@(private, require_results)
|
||||
@@ -282,7 +298,7 @@ _processor_core_count :: proc() -> int {
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
context = runtime.default_context()
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
@@ -290,7 +306,7 @@ exit :: proc "contextless" (code: int) -> ! {
|
||||
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
context = runtime.default_context()
|
||||
unimplemented("core:os procedure not supported on JS target")
|
||||
}
|
||||
@@ -302,3 +318,41 @@ _alloc_command_line_arguments :: proc() -> []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
unimplemented("TODO: _absolute_path_from_handle")
|
||||
}
|
||||
@(require_results)
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
unimplemented("TODO: _absolute_path_from_relative")
|
||||
}
|
||||
|
||||
_access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
unimplemented("TODO: _access")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
unimplemented("TODO: _environ")
|
||||
}
|
||||
@(require_results)
|
||||
_lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
unimplemented("TODO: _lookup_env")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
unimplemented("TODO: _get_env")
|
||||
}
|
||||
|
||||
_set_env :: proc(key, value: string) -> Error {
|
||||
unimplemented("TODO: _set_env")
|
||||
}
|
||||
_unset_env :: proc(key: string) -> Error {
|
||||
unimplemented("TODO: _unset_env")
|
||||
}
|
||||
|
||||
_clear_env :: proc() {
|
||||
unimplemented("TODO: _clear_env")
|
||||
}
|
||||
|
||||
@@ -507,7 +507,7 @@ foreign dl {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_path_separator :: proc(r: rune) -> bool {
|
||||
_is_path_separator :: proc "contextless" (r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
@@ -522,7 +522,7 @@ _get_errno :: proc(res: int) -> Error {
|
||||
|
||||
// get errno from libc
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
err := Platform_Error(__errno_location()^)
|
||||
#partial switch err {
|
||||
case .NONE:
|
||||
@@ -570,7 +570,7 @@ execvp :: proc(path: string, args: []string) -> Error {
|
||||
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0o000) -> (Handle, Error) {
|
||||
_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))
|
||||
@@ -580,11 +580,11 @@ open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0o000) -> (Handle,
|
||||
return Handle(handle), nil
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
return _get_errno(unix.sys_close(int(fd)))
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_flush :: proc(fd: Handle) -> Error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
@@ -598,7 +598,7 @@ flush :: proc(fd: Handle) -> Error {
|
||||
@(private)
|
||||
MAX_RW :: 1 << 30
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -612,7 +612,7 @@ read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return bytes_read, nil
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -626,7 +626,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return bytes_written, nil
|
||||
}
|
||||
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
_read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -640,7 +640,7 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
return bytes_read, nil
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
_write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -654,7 +654,7 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
|
||||
return bytes_written, nil
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
_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))
|
||||
@@ -663,7 +663,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
_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))
|
||||
@@ -673,33 +673,53 @@ file_size :: proc(fd: Handle) -> (i64, Error) {
|
||||
return max(s.size, 0), nil
|
||||
}
|
||||
|
||||
rename :: proc(old_path, new_path: string) -> Error {
|
||||
_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) -> Error {
|
||||
_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) -> Error {
|
||||
_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) -> Error {
|
||||
_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))
|
||||
}
|
||||
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("TODO: _link")
|
||||
}
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _unlink")
|
||||
}
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _ftruncate")
|
||||
}
|
||||
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _truncate")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -708,7 +728,7 @@ is_file_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -724,7 +744,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
|
||||
|
||||
@(require_results)
|
||||
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -733,7 +753,7 @@ is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -747,11 +767,9 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
return S_ISDIR(s.mode)
|
||||
}
|
||||
|
||||
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 {
|
||||
_exists :: proc(path: string) -> bool {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cpath := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
res := unix.sys_access(cpath, O_RDONLY)
|
||||
@@ -769,14 +787,14 @@ 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) {
|
||||
_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) {
|
||||
_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
|
||||
@@ -888,7 +906,7 @@ _readlink :: proc(path: string) -> (string, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
buf : [256]byte
|
||||
fd_str := strconv.itoa( buf[:], cast(int)fd )
|
||||
|
||||
@@ -899,7 +917,7 @@ absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
rel := rel
|
||||
if rel == "" {
|
||||
rel = "."
|
||||
@@ -919,7 +937,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
_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)
|
||||
@@ -930,7 +948,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
_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)
|
||||
// NOTE(tetra): Lifetime of 'cstr' is unclear, but _unix_free(cstr) segfaults.
|
||||
@@ -942,12 +960,12 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
value, _ = lookup_env(key, allocator)
|
||||
return
|
||||
}
|
||||
|
||||
set_env :: proc(key, value: string) -> Error {
|
||||
_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)
|
||||
@@ -959,7 +977,7 @@ set_env :: proc(key, value: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
unset_env :: proc(key: string) -> Error {
|
||||
_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)
|
||||
@@ -968,9 +986,17 @@ unset_env :: proc(key: string) -> Error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@(require_results)
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
return nil
|
||||
}
|
||||
_clear_env :: proc() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
get_current_directory :: proc() -> string {
|
||||
_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.
|
||||
// The largest value I could find was 4096, so might as well use the page size.
|
||||
@@ -991,7 +1017,7 @@ get_current_directory :: proc() -> string {
|
||||
unreachable()
|
||||
}
|
||||
|
||||
set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
_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)
|
||||
@@ -1001,13 +1027,13 @@ set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(c.int(code))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
return unix.sys_gettid()
|
||||
}
|
||||
|
||||
@@ -1035,7 +1061,7 @@ dlerror :: proc() -> string {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_page_size :: proc() -> int {
|
||||
_get_page_size :: proc() -> int {
|
||||
// NOTE(tetra): The page size never changes, so why do anything complicated
|
||||
// if we don't have to.
|
||||
@static page_size := -1
|
||||
|
||||
@@ -474,17 +474,17 @@ 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 {
|
||||
_is_path_separator :: proc "contextless" (r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
return Platform_Error(__errno_location()^)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
|
||||
_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))
|
||||
@@ -494,7 +494,7 @@ open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Err
|
||||
return handle, nil
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
result := _unix_close(fd)
|
||||
if result == -1 {
|
||||
return get_last_error()
|
||||
@@ -502,7 +502,7 @@ close :: proc(fd: Handle) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_flush :: proc(fd: Handle) -> Error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
@@ -511,7 +511,7 @@ flush :: proc(fd: Handle) -> Error {
|
||||
@(private)
|
||||
MAX_RW :: 1 << 30
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_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 {
|
||||
@@ -520,7 +520,7 @@ read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_read), nil
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -533,7 +533,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_written), nil
|
||||
}
|
||||
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -543,7 +543,7 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -553,7 +553,7 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error)
|
||||
return
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
res := _unix_seek(fd, offset, c.int(whence))
|
||||
if res == -1 {
|
||||
return -1, get_last_error()
|
||||
@@ -562,14 +562,14 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (size: i64, err: Error) {
|
||||
_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) -> Error {
|
||||
_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)
|
||||
@@ -580,7 +580,7 @@ rename :: proc(old_path, new_path: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
remove :: proc(path: string) -> Error {
|
||||
_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)
|
||||
@@ -590,17 +590,32 @@ remove :: proc(path: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
make_directory :: proc(path: string, mode: mode_t = 0o775) -> Error {
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("TODO: _link")
|
||||
}
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _unlink")
|
||||
}
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _ftruncate")
|
||||
}
|
||||
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _truncate")
|
||||
}
|
||||
|
||||
|
||||
_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)
|
||||
res := _unix_mkdir(path_cstr, mode)
|
||||
res := _unix_mkdir(path_cstr, mode_t(mode))
|
||||
if res == -1 {
|
||||
return get_last_error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
remove_directory :: proc(path: string) -> Error {
|
||||
_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)
|
||||
@@ -611,7 +626,7 @@ remove_directory :: proc(path: string) -> Error {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -620,7 +635,7 @@ is_file_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -635,7 +650,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -644,7 +659,7 @@ is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -658,11 +673,14 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
return S_ISDIR(s.mode)
|
||||
}
|
||||
|
||||
is_file :: proc {is_file_path, is_file_handle}
|
||||
is_dir :: proc {is_dir_path, is_dir_handle}
|
||||
@(require_results)
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
exists :: proc(path: string) -> bool {
|
||||
_exists :: proc(path: string) -> bool {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cpath := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
res := _unix_access(cpath, O_RDONLY)
|
||||
@@ -685,14 +703,14 @@ stdout: Handle = 1
|
||||
stderr: Handle = 2
|
||||
|
||||
@(require_results)
|
||||
last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) {
|
||||
_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) {
|
||||
_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
|
||||
@@ -802,14 +820,14 @@ _readlink :: proc(path: string) -> (string, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
buf: [MAX_PATH]byte
|
||||
_ = fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0]))) or_return
|
||||
return strings.clone_from_cstring(cstring(&buf[0]))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
rel := rel
|
||||
if rel == "" {
|
||||
rel = "."
|
||||
@@ -829,7 +847,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
_access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
|
||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
@@ -841,7 +859,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
_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)
|
||||
@@ -853,13 +871,32 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
value, _ = lookup_env(key, allocator)
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_current_directory :: proc() -> string {
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
unimplemented("TODO: _environ")
|
||||
}
|
||||
|
||||
_set_env :: proc(key, value: string) -> Error {
|
||||
unimplemented("TODO: _set_env")
|
||||
}
|
||||
_unset_env :: proc(key: string) -> Error {
|
||||
unimplemented("TODO: _unset_env")
|
||||
}
|
||||
|
||||
_clear_env :: proc() {
|
||||
unimplemented("TODO: _clear_env")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@(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.
|
||||
// The largest value I could find was 4096, so might as well use the page size.
|
||||
@@ -879,7 +916,7 @@ get_current_directory :: proc() -> string {
|
||||
unreachable()
|
||||
}
|
||||
|
||||
set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
_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)
|
||||
@@ -889,13 +926,13 @@ set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(c.int(code))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
return int(_lwp_self())
|
||||
}
|
||||
|
||||
@@ -927,7 +964,7 @@ dlerror :: proc() -> string {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_page_size :: proc() -> int {
|
||||
_get_page_size :: proc() -> int {
|
||||
// NOTE(tetra): The page size never changes, so why do anything complicated
|
||||
// if we don't have to.
|
||||
@static page_size := -1
|
||||
|
||||
@@ -389,12 +389,12 @@ foreign libc {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_path_separator :: proc(r: rune) -> bool {
|
||||
_is_path_separator :: proc "contextless" (r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
return Platform_Error(__error()^)
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ fork :: proc() -> (Pid, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
|
||||
_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))
|
||||
@@ -418,7 +418,7 @@ open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Err
|
||||
return handle, nil
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Error {
|
||||
_close :: proc(fd: Handle) -> Error {
|
||||
result := _unix_close(fd)
|
||||
if result == -1 {
|
||||
return get_last_error()
|
||||
@@ -426,7 +426,7 @@ close :: proc(fd: Handle) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_flush :: proc(fd: Handle) -> Error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
@@ -439,7 +439,7 @@ flush :: proc(fd: Handle) -> Error {
|
||||
@(private)
|
||||
MAX_RW :: 1 << 30
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_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 {
|
||||
@@ -448,7 +448,7 @@ read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_read), nil
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
_write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -461,7 +461,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||
return int(bytes_written), nil
|
||||
}
|
||||
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -471,7 +471,7 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
|
||||
_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)
|
||||
@@ -481,7 +481,7 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error)
|
||||
return
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
_seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
res := _unix_seek(fd, offset, c.int(whence))
|
||||
if res == -1 {
|
||||
return -1, get_last_error()
|
||||
@@ -490,14 +490,18 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (size: i64, err: Error) {
|
||||
_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) -> Error {
|
||||
_exists :: proc(path: string) -> bool {
|
||||
unimplemented("TODO: _exists")
|
||||
}
|
||||
|
||||
_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)
|
||||
@@ -508,7 +512,7 @@ rename :: proc(old_path, new_path: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
remove :: proc(path: string) -> Error {
|
||||
_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)
|
||||
@@ -518,7 +522,7 @@ remove :: proc(path: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
make_directory :: proc(path: string, mode: mode_t = 0o775) -> Error {
|
||||
_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)
|
||||
@@ -528,7 +532,7 @@ make_directory :: proc(path: string, mode: mode_t = 0o775) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
remove_directory :: proc(path: string) -> Error {
|
||||
_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)
|
||||
@@ -539,7 +543,28 @@ remove_directory :: proc(path: string) -> Error {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("TODO: _link")
|
||||
}
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _unlink")
|
||||
}
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _ftruncate")
|
||||
}
|
||||
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _truncate")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -548,7 +573,7 @@ is_file_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -563,7 +588,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -572,7 +597,7 @@ is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
_is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Error
|
||||
if follow_links {
|
||||
@@ -586,9 +611,6 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
return S_ISDIR(s.mode)
|
||||
}
|
||||
|
||||
is_file :: proc {is_file_path, is_file_handle}
|
||||
is_dir :: proc {is_dir_path, is_dir_handle}
|
||||
|
||||
// NOTE(bill): Uses startup to initialize it
|
||||
|
||||
stdin: Handle = 0
|
||||
@@ -600,14 +622,14 @@ 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) {
|
||||
_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) {
|
||||
_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
|
||||
@@ -718,12 +740,12 @@ _readlink :: proc(path: string) -> (string, Error) {
|
||||
|
||||
// XXX OpenBSD
|
||||
@(require_results)
|
||||
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||
return "", Error(ENOSYS)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
rel := rel
|
||||
if rel == "" {
|
||||
rel = "."
|
||||
@@ -743,7 +765,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
_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))
|
||||
@@ -754,7 +776,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
_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)
|
||||
cstr := _unix_getenv(path_str)
|
||||
@@ -765,13 +787,30 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
value, _ = lookup_env(key, allocator)
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_current_directory :: proc() -> string {
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
unimplemented("TODO: _environ")
|
||||
}
|
||||
|
||||
_set_env :: proc(key, value: string) -> Error {
|
||||
unimplemented("TODO: _set_env")
|
||||
}
|
||||
_unset_env :: proc(key: string) -> Error {
|
||||
unimplemented("TODO: _unset_env")
|
||||
}
|
||||
|
||||
_clear_env :: proc() {
|
||||
unimplemented("TODO: _clear_env")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_get_current_directory :: proc() -> string {
|
||||
buf := make([dynamic]u8, MAX_PATH)
|
||||
for {
|
||||
cwd := _unix_getcwd(cstring(raw_data(buf)), c.size_t(len(buf)))
|
||||
@@ -787,7 +826,7 @@ get_current_directory :: proc() -> string {
|
||||
unreachable()
|
||||
}
|
||||
|
||||
set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
_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)
|
||||
@@ -797,13 +836,13 @@ set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(c.int(code))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
return _unix_getthrid()
|
||||
}
|
||||
|
||||
@@ -832,7 +871,7 @@ dlerror :: proc() -> string {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
get_page_size :: proc() -> int {
|
||||
_get_page_size :: proc() -> int {
|
||||
// NOTE(tetra): The page size never changes, so why do anything complicated
|
||||
// if we don't have to.
|
||||
@static page_size := -1
|
||||
|
||||
@@ -6,6 +6,8 @@ import "base:runtime"
|
||||
Handle :: distinct i32
|
||||
_Platform_Error :: wasi.errno_t
|
||||
|
||||
File_Time :: i64
|
||||
|
||||
INVALID_HANDLE :: -1
|
||||
|
||||
O_RDONLY :: 0x00000
|
||||
@@ -145,28 +147,33 @@ wasi_match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) {
|
||||
return match.fd, relative, true
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||
@(require_results, no_instrumentation)
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_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), Platform_Error(err)
|
||||
}
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||
_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), Platform_Error(err)
|
||||
}
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||
_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), Platform_Error(err)
|
||||
}
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||
_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), Platform_Error(err)
|
||||
}
|
||||
@(require_results)
|
||||
open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
|
||||
_open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
|
||||
oflags: wasi.oflags_t
|
||||
if mode & O_CREATE == O_CREATE {
|
||||
oflags += {.CREATE}
|
||||
@@ -204,22 +211,22 @@ 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), Platform_Error(err)
|
||||
}
|
||||
close :: proc(fd: Handle) -> Errno {
|
||||
_close :: proc(fd: Handle) -> Errno {
|
||||
err := wasi.fd_close(wasi.fd_t(fd))
|
||||
return Platform_Error(err)
|
||||
}
|
||||
|
||||
flush :: proc(fd: Handle) -> Error {
|
||||
_flush :: proc(fd: Handle) -> Error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
_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), Platform_Error(err)
|
||||
}
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
return 0
|
||||
}
|
||||
@(private, require_results)
|
||||
@@ -228,14 +235,156 @@ _processor_core_count :: proc() -> int {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
file_size :: proc(fd: Handle) -> (size: i64, err: Errno) {
|
||||
_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
|
||||
}
|
||||
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
wasi.proc_exit(wasi.exitcode_t(code))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
_last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) {
|
||||
unimplemented("TODO: _last_write_time")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) {
|
||||
unimplemented("TODO: _last_write_time_by_name")
|
||||
}
|
||||
|
||||
|
||||
_is_path_separator :: proc "contextless" (r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_file_handle :: proc(fd: Handle) -> bool {
|
||||
unimplemented("TODO: _is_file_handle")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
unimplemented("TODO: _is_file_path")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
unimplemented("TODO: _is_dir_handle")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
unimplemented("TODO: _is_dir_path")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_exists :: proc(path: string) -> bool {
|
||||
unimplemented("TODO: _exists")
|
||||
}
|
||||
|
||||
_rename :: proc(old, new: string) -> Error {
|
||||
unimplemented("TODO: _rename")
|
||||
}
|
||||
|
||||
_remove :: proc(path: string) -> Error {
|
||||
unimplemented("TODO: _remove")
|
||||
}
|
||||
|
||||
_link :: proc(old_name, new_name: string) -> (err: Error) {
|
||||
unimplemented("TODO: _link")
|
||||
}
|
||||
_unlink :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _unlink")
|
||||
}
|
||||
_ftruncate :: proc(fd: Handle, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _ftruncate")
|
||||
}
|
||||
|
||||
_truncate :: proc(path: string, length: i64) -> (err: Error) {
|
||||
unimplemented("TODO: _truncate")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_pipe :: proc() -> (r, w: Handle, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||
unimplemented("TODO: __read_dir")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
unimplemented("TODO: _absolute_path_from_handle")
|
||||
}
|
||||
@(require_results)
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
unimplemented("TODO: _absolute_path_from_relative")
|
||||
}
|
||||
|
||||
_access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
unimplemented("TODO: _access")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_environ :: proc(allocator := context.allocator) -> []string {
|
||||
unimplemented("TODO: _environ")
|
||||
}
|
||||
@(require_results)
|
||||
_lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
unimplemented("TODO: _lookup_env")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
|
||||
unimplemented("TODO: _get_env")
|
||||
}
|
||||
|
||||
_set_env :: proc(key, value: string) -> Error {
|
||||
unimplemented("TODO: _set_env")
|
||||
}
|
||||
_unset_env :: proc(key: string) -> Error {
|
||||
unimplemented("TODO: _unset_env")
|
||||
}
|
||||
|
||||
_clear_env :: proc() {
|
||||
unimplemented("TODO: _clear_env")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_get_current_directory :: proc() -> string {
|
||||
unimplemented("TODO: _get_current_directory")
|
||||
}
|
||||
|
||||
|
||||
_set_current_directory :: proc(path: string) -> (err: Error) {
|
||||
unimplemented("TODO: _set_current_directory")
|
||||
}
|
||||
|
||||
|
||||
|
||||
_make_directory :: proc(path: string, mode: u32 = 0o775) -> Error {
|
||||
unimplemented("TODO: _make_directory")
|
||||
}
|
||||
|
||||
_remove_directory :: proc(path: string) -> Error {
|
||||
unimplemented("TODO: _remove_directory")
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_get_page_size :: proc() -> int {
|
||||
return 1<<16
|
||||
}
|
||||
@@ -61,7 +61,7 @@ ERROR_FILE_IS_NOT_DIR :: General_Error.Not_Dir
|
||||
args := _alloc_command_line_arguments()
|
||||
|
||||
@(require_results, no_instrumentation)
|
||||
get_last_error :: proc "contextless" () -> Error {
|
||||
_get_last_error :: proc "contextless" () -> Error {
|
||||
err := win32.GetLastError()
|
||||
if err == 0 {
|
||||
return nil
|
||||
@@ -113,7 +113,7 @@ get_last_error :: proc "contextless" () -> Error {
|
||||
|
||||
|
||||
@(require_results)
|
||||
last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
|
||||
_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, get_last_error()
|
||||
@@ -124,7 +124,7 @@ last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
|
||||
_last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
|
||||
data: win32.WIN32_FILE_ATTRIBUTE_DATA
|
||||
|
||||
wide_path := win32.utf8_to_wstring(name)
|
||||
@@ -139,7 +139,7 @@ last_write_time_by_name :: proc(name: string) -> (File_Time, Error) {
|
||||
|
||||
|
||||
@(require_results)
|
||||
get_page_size :: proc() -> int {
|
||||
_get_page_size :: proc() -> int {
|
||||
// NOTE(tetra): The page size never changes, so why do anything complicated
|
||||
// if we don't have to.
|
||||
@static page_size := -1
|
||||
@@ -177,7 +177,7 @@ _processor_core_count :: proc() -> int {
|
||||
return thread_count
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
win32.ExitProcess(win32.DWORD(code))
|
||||
}
|
||||
@@ -185,10 +185,23 @@ exit :: proc "contextless" (code: int) -> ! {
|
||||
|
||||
|
||||
@(require_results)
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
return int(win32.GetCurrentThreadId())
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||
unimplemented("TODO: _absolute_path_from_handle")
|
||||
}
|
||||
@(require_results)
|
||||
_absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) {
|
||||
unimplemented("TODO: _absolute_path_from_relative")
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_access :: proc(path: string, mask: int) -> (bool, Error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
|
||||
Reference in New Issue
Block a user