mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
merge commit
This commit is contained in:
+27
-11
@@ -10,20 +10,29 @@ file_allocator :: proc() -> runtime.Allocator {
|
||||
|
||||
temp_allocator_proc :: runtime.arena_allocator_proc
|
||||
|
||||
@(private="file")
|
||||
MAX_TEMP_ARENA_COUNT :: 2
|
||||
|
||||
@(private="file", thread_local)
|
||||
global_default_temp_allocator_arena: runtime.Arena
|
||||
global_default_temp_allocator_arenas: [MAX_TEMP_ARENA_COUNT]runtime.Arena
|
||||
|
||||
@(private="file", thread_local)
|
||||
global_default_temp_allocator_index: uint
|
||||
|
||||
|
||||
@(require_results)
|
||||
temp_allocator :: proc() -> runtime.Allocator {
|
||||
return runtime.Allocator{
|
||||
procedure = temp_allocator_proc,
|
||||
data = &global_default_temp_allocator_arena,
|
||||
data = &global_default_temp_allocator_arenas[global_default_temp_allocator_index],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
temp_allocator_temp_begin :: proc(loc := #caller_location) -> (temp: runtime.Arena_Temp) {
|
||||
temp = runtime.arena_temp_begin(&global_default_temp_allocator_arena, loc)
|
||||
temp = runtime.arena_temp_begin(&global_default_temp_allocator_arenas[global_default_temp_allocator_index], loc)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -33,16 +42,23 @@ temp_allocator_temp_end :: proc(temp: runtime.Arena_Temp, loc := #caller_locatio
|
||||
|
||||
@(fini, private)
|
||||
temp_allocator_fini :: proc() {
|
||||
runtime.arena_destroy(&global_default_temp_allocator_arena)
|
||||
global_default_temp_allocator_arena = {}
|
||||
for &arena in global_default_temp_allocator_arenas {
|
||||
runtime.arena_destroy(&arena)
|
||||
}
|
||||
global_default_temp_allocator_arenas = {}
|
||||
}
|
||||
|
||||
@(deferred_out=temp_allocator_temp_end)
|
||||
TEMP_ALLOCATOR_GUARD :: #force_inline proc(ignore := false, loc := #caller_location) -> (runtime.Arena_Temp, runtime.Source_Code_Location) {
|
||||
if ignore {
|
||||
return {}, loc
|
||||
} else {
|
||||
return temp_allocator_temp_begin(loc), loc
|
||||
TEMP_ALLOCATOR_GUARD_END :: proc(temp: runtime.Arena_Temp, loc := #caller_location) {
|
||||
runtime.arena_temp_end(temp, loc)
|
||||
if temp.arena != nil {
|
||||
global_default_temp_allocator_index = (global_default_temp_allocator_index-1)%MAX_TEMP_ARENA_COUNT
|
||||
}
|
||||
}
|
||||
|
||||
@(deferred_out=TEMP_ALLOCATOR_GUARD_END)
|
||||
TEMP_ALLOCATOR_GUARD :: #force_inline proc(loc := #caller_location) -> (runtime.Arena_Temp, runtime.Source_Code_Location) {
|
||||
tmp := temp_allocator_temp_begin(loc)
|
||||
global_default_temp_allocator_index = (global_default_temp_allocator_index+1)%MAX_TEMP_ARENA_COUNT
|
||||
return tmp, loc
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package os2
|
||||
import "base:runtime"
|
||||
import "core:slice"
|
||||
|
||||
read_dir :: read_directory
|
||||
|
||||
@(require_results)
|
||||
read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files: []File_Info, err: Error) {
|
||||
if f == nil {
|
||||
@@ -57,6 +59,7 @@ read_all_directory_by_path :: proc(path: string, allocator: runtime.Allocator) -
|
||||
}
|
||||
|
||||
|
||||
|
||||
Read_Directory_Iterator :: struct {
|
||||
f: ^File,
|
||||
impl: Read_Directory_Iterator_Impl,
|
||||
@@ -72,7 +75,6 @@ read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) {
|
||||
_read_directory_iterator_destroy(it)
|
||||
}
|
||||
|
||||
|
||||
// NOTE(bill): `File_Info` does not need to deleted on each iteration. Any copies must be manually copied with `file_info_clone`
|
||||
@(require_results)
|
||||
read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) {
|
||||
|
||||
@@ -23,10 +23,21 @@ find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, al
|
||||
|
||||
fi.type, fi.mode = _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, d.dwReserved0)
|
||||
|
||||
// fi.inode = u128(u64(d.nFileIndexHigh)<<32 + u64(d.nFileIndexLow))
|
||||
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
|
||||
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
|
||||
fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
|
||||
|
||||
|
||||
handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0)
|
||||
defer win32.CloseHandle(handle)
|
||||
|
||||
if file_id_info: win32.FILE_ID_INFO; handle != nil && win32.GetFileInformationByHandleEx(handle, .FileIdInfo, &file_id_info, size_of(file_id_info)) {
|
||||
#assert(size_of(fi.inode) == size_of(file_id_info.FileId))
|
||||
#assert(size_of(fi.inode) == 16)
|
||||
runtime.mem_copy_non_overlapping(&fi.inode, &file_id_info.FileId, 16)
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -46,6 +57,8 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info
|
||||
return
|
||||
}
|
||||
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
|
||||
for !it.impl.no_more_files {
|
||||
err: Error
|
||||
file_info_delete(it.impl.prev_fi, file_allocator())
|
||||
|
||||
@@ -42,13 +42,14 @@ Error :: union #shared_nil {
|
||||
ERROR_NONE :: Error{}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
|
||||
v := ferr.(Platform_Error) or_else {}
|
||||
return i32(v), i32(v) != 0
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
error_string :: proc(ferr: Error) -> string {
|
||||
if ferr == nil {
|
||||
return ""
|
||||
|
||||
@@ -4,8 +4,8 @@ package os2
|
||||
import "core:sys/linux"
|
||||
|
||||
@(rodata)
|
||||
_errno_strings : [linux.Errno]string = {
|
||||
.NONE = "Success",
|
||||
_errno_strings := [linux.Errno]string{
|
||||
.NONE = "",
|
||||
.EPERM = "Operation not permitted",
|
||||
.ENOENT = "No such file or directory",
|
||||
.ESRCH = "No such process",
|
||||
|
||||
@@ -104,6 +104,15 @@ open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File,
|
||||
return _open(name, flags, perm)
|
||||
}
|
||||
|
||||
// @(require_results)
|
||||
// open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (^File, Error) {
|
||||
// if buffer_size == 0 {
|
||||
// return _open(name, flags, perm)
|
||||
// }
|
||||
// return _open_buffered(name, buffer_size, flags, perm)
|
||||
// }
|
||||
|
||||
|
||||
@(require_results)
|
||||
new_file :: proc(handle: uintptr, name: string) -> ^File {
|
||||
return _new_file(handle, name) or_else panic("Out of memory")
|
||||
|
||||
+72
-10
@@ -1,9 +1,10 @@
|
||||
//+private
|
||||
package os2
|
||||
|
||||
import "base:runtime"
|
||||
import "core:io"
|
||||
import "core:time"
|
||||
import "base:runtime"
|
||||
import "core:sync"
|
||||
import "core:sys/linux"
|
||||
|
||||
File_Impl :: struct {
|
||||
@@ -11,6 +12,10 @@ File_Impl :: struct {
|
||||
name: string,
|
||||
fd: linux.Fd,
|
||||
allocator: runtime.Allocator,
|
||||
|
||||
buffer: []byte,
|
||||
rw_mutex: sync.RW_Mutex, // read write calls
|
||||
p_mutex: sync.Mutex, // pread pwrite calls
|
||||
}
|
||||
|
||||
_stdin := File{
|
||||
@@ -49,9 +54,9 @@ _standard_stream_init :: proc() {
|
||||
fd = 2,
|
||||
}
|
||||
|
||||
stdin_impl.allocator = _file_allocator()
|
||||
stdout_impl.allocator = _file_allocator()
|
||||
stderr_impl.allocator = _file_allocator()
|
||||
stdin_impl.allocator = file_allocator()
|
||||
stdout_impl.allocator = file_allocator()
|
||||
stderr_impl.allocator = file_allocator()
|
||||
|
||||
_stdin.impl = &stdin_impl
|
||||
_stdout.impl = &stdout_impl
|
||||
@@ -67,10 +72,6 @@ _standard_stream_init :: proc() {
|
||||
stderr = &_stderr
|
||||
}
|
||||
|
||||
_file_allocator :: proc() -> runtime.Allocator {
|
||||
return heap_allocator()
|
||||
}
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
name_cstr := temp_cstring(name) or_return
|
||||
@@ -116,13 +117,30 @@ _new_file :: proc(fd: uintptr, _: string = "") -> (f: ^File, err: Error) {
|
||||
return &impl.file, nil
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
|
||||
assert(buffer_size > 0)
|
||||
f, err = _open(name, flags, perm)
|
||||
if f != nil && err == nil {
|
||||
impl := (^File_Impl)(f.impl)
|
||||
impl.buffer = make([]byte, buffer_size, file_allocator())
|
||||
f.stream.procedure = _file_stream_buffered_proc
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
_destroy :: proc(f: ^File_Impl) -> Error {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
a := f.allocator
|
||||
delete(f.name, a)
|
||||
free(f, a)
|
||||
err0 := delete(f.name, a)
|
||||
err1 := delete(f.buffer, a)
|
||||
err2 := free(f, a)
|
||||
err0 or_return
|
||||
err1 or_return
|
||||
err2 or_return
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -470,3 +488,47 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte,
|
||||
return 0, .Empty
|
||||
}
|
||||
|
||||
|
||||
@(private="package")
|
||||
_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||
f := (^File_Impl)(stream_data)
|
||||
ferr: Error
|
||||
switch mode {
|
||||
case .Read:
|
||||
n, ferr = _read(f, p)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Read_At:
|
||||
n, ferr = _read_at(f, p, offset)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Write:
|
||||
n, ferr = _write(f, p)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Write_At:
|
||||
n, ferr = _write_at(f, p, offset)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Seek:
|
||||
n, ferr = _seek(f, offset, whence)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Size:
|
||||
n, ferr = _file_size(f)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Flush:
|
||||
ferr = _flush(f)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Close, .Destroy:
|
||||
ferr = _close(f)
|
||||
err = error_to_io_error(ferr)
|
||||
return
|
||||
case .Query:
|
||||
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query})
|
||||
}
|
||||
return 0, .Empty
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,24 @@ write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) {
|
||||
if len(buf) < min {
|
||||
return 0, .Short_Buffer
|
||||
}
|
||||
nn := max(int)
|
||||
for nn > 0 && n < min && err == nil {
|
||||
nn, err = read(f, buf[n:])
|
||||
n += nn
|
||||
}
|
||||
if n >= min {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
read_full :: proc(f: ^File, buf: []byte) -> (n: int, err: Error) {
|
||||
return read_at_least(f, buf, len(buf))
|
||||
}
|
||||
|
||||
write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
|
||||
return write(f, ([^]byte)(data)[:len])
|
||||
@@ -155,11 +173,8 @@ write_entire_file :: proc(name: string, data: []byte, perm: int, truncate := tru
|
||||
if truncate {
|
||||
flags |= O_TRUNC
|
||||
}
|
||||
f, err := open(name, flags, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = write(f, data)
|
||||
f := open(name, flags, perm) or_return
|
||||
_, err := write(f, data)
|
||||
if cerr := close(f); cerr != nil && err == nil {
|
||||
err = cerr
|
||||
}
|
||||
|
||||
@@ -33,6 +33,11 @@ File_Impl :: struct {
|
||||
|
||||
allocator: runtime.Allocator,
|
||||
|
||||
r_buf: []byte,
|
||||
w_buf: []byte,
|
||||
w_n: int,
|
||||
max_consecutive_empty_writes: int,
|
||||
|
||||
rw_mutex: sync.RW_Mutex, // read write calls
|
||||
p_mutex: sync.Mutex, // pread pwrite calls
|
||||
}
|
||||
@@ -60,8 +65,9 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
|
||||
err = .Not_Exist
|
||||
return
|
||||
}
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
|
||||
path := _fix_long_path(name) or_return
|
||||
path := _fix_long_path(name, temp_allocator()) or_return
|
||||
access: u32
|
||||
switch flags & {.Read, .Write} {
|
||||
case {.Read}: access = win32.FILE_GENERIC_READ
|
||||
@@ -164,6 +170,26 @@ _new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
|
||||
return &impl.file, nil
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
|
||||
assert(buffer_size > 0)
|
||||
flags := flags if flags != nil else {.Read}
|
||||
handle := _open_internal(name, flags, perm) or_return
|
||||
return _new_file_buffered(handle, name, buffer_size)
|
||||
}
|
||||
|
||||
_new_file_buffered :: proc(handle: uintptr, name: string, buffer_size: uint) -> (f: ^File, err: Error) {
|
||||
f, err = _new_file(handle, name)
|
||||
if f != nil && err == nil {
|
||||
impl := (^File_Impl)(f.impl)
|
||||
impl.r_buf = make([]byte, buffer_size, file_allocator())
|
||||
impl.w_buf = make([]byte, buffer_size, file_allocator())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
_fd :: proc(f: ^File) -> uintptr {
|
||||
if f == nil || f.impl == nil {
|
||||
return INVALID_HANDLE
|
||||
@@ -180,9 +206,13 @@ _destroy :: proc(f: ^File_Impl) -> Error {
|
||||
err0 := free(f.wname, a)
|
||||
err1 := delete(f.name, a)
|
||||
err2 := free(f, a)
|
||||
err3 := delete(f.r_buf, a)
|
||||
err4 := delete(f.w_buf, a)
|
||||
err0 or_return
|
||||
err1 or_return
|
||||
err2 or_return
|
||||
err3 or_return
|
||||
err4 or_return
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -230,6 +260,10 @@ _seek :: proc(f: ^File_Impl, offset: i64, whence: io.Seek_From) -> (ret: i64, er
|
||||
}
|
||||
|
||||
_read :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) {
|
||||
return _read_internal(f, p)
|
||||
}
|
||||
|
||||
_read_internal :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) {
|
||||
read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
@@ -351,6 +385,9 @@ _read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (n: i64, err: Error)
|
||||
}
|
||||
|
||||
_write :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) {
|
||||
return _write_internal(f, p)
|
||||
}
|
||||
_write_internal :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
@@ -435,6 +472,9 @@ _sync :: proc(f: ^File) -> Error {
|
||||
}
|
||||
|
||||
_flush :: proc(f: ^File_Impl) -> Error {
|
||||
return _flush(f)
|
||||
}
|
||||
_flush_internal :: proc(f: ^File_Impl) -> Error {
|
||||
handle := _handle(&f.file)
|
||||
if !win32.FlushFileBuffers(handle) {
|
||||
return _get_platform_error()
|
||||
@@ -457,7 +497,8 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
|
||||
}
|
||||
|
||||
_remove :: proc(name: string) -> Error {
|
||||
p := _fix_long_path(name) or_return
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
p := _fix_long_path(name, temp_allocator()) or_return
|
||||
err, err1: Error
|
||||
if !win32.DeleteFileW(p) {
|
||||
err = _get_platform_error()
|
||||
@@ -494,8 +535,9 @@ _remove :: proc(name: string) -> Error {
|
||||
}
|
||||
|
||||
_rename :: proc(old_path, new_path: string) -> Error {
|
||||
from := _fix_long_path(old_path) or_return
|
||||
to := _fix_long_path(new_path) or_return
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
from := _fix_long_path(old_path, temp_allocator()) or_return
|
||||
to := _fix_long_path(new_path, temp_allocator()) or_return
|
||||
if win32.MoveFileExW(from, to, win32.MOVEFILE_REPLACE_EXISTING) {
|
||||
return nil
|
||||
}
|
||||
@@ -504,8 +546,9 @@ _rename :: proc(old_path, new_path: string) -> Error {
|
||||
}
|
||||
|
||||
_link :: proc(old_name, new_name: string) -> Error {
|
||||
o := _fix_long_path(old_name) or_return
|
||||
n := _fix_long_path(new_name) or_return
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
o := _fix_long_path(old_name, temp_allocator()) or_return
|
||||
n := _fix_long_path(new_name, temp_allocator()) or_return
|
||||
if win32.CreateHardLinkW(n, o, nil) {
|
||||
return nil
|
||||
}
|
||||
@@ -592,8 +635,10 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
|
||||
@thread_local
|
||||
rdb_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]byte
|
||||
|
||||
p := _fix_long_path(name) or_return
|
||||
handle := _open_sym_link(p) or_return
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
|
||||
p := _fix_long_path(name, temp_allocator()) or_return
|
||||
handle := _open_sym_link(p) or_return
|
||||
defer win32.CloseHandle(handle)
|
||||
|
||||
bytes_returned: u32
|
||||
@@ -667,7 +712,8 @@ _fchown :: proc(f: ^File, uid, gid: int) -> Error {
|
||||
}
|
||||
|
||||
_chdir :: proc(name: string) -> Error {
|
||||
p := _fix_long_path(name) or_return
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
p := _fix_long_path(name, temp_allocator()) or_return
|
||||
if !win32.SetCurrentDirectoryW(p) {
|
||||
return _get_platform_error()
|
||||
}
|
||||
@@ -723,7 +769,8 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
||||
}
|
||||
|
||||
_exists :: proc(path: string) -> bool {
|
||||
wpath, _ := _fix_long_path(path)
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
wpath, _ := _fix_long_path(path, temp_allocator())
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
return attribs != win32.INVALID_FILE_ATTRIBUTES
|
||||
}
|
||||
@@ -773,6 +820,7 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte,
|
||||
|
||||
|
||||
|
||||
|
||||
@(private="package", require_results)
|
||||
win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: [^]u16, err: runtime.Allocator_Error) {
|
||||
ws = raw_data(win32_utf8_to_utf16(s, allocator) or_return)
|
||||
|
||||
@@ -13,7 +13,8 @@ _is_path_separator :: proc(c: byte) -> bool {
|
||||
}
|
||||
|
||||
_mkdir :: proc(name: string, perm: int) -> Error {
|
||||
if !win32.CreateDirectoryW(_fix_long_path(name) or_return, nil) {
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
if !win32.CreateDirectoryW(_fix_long_path(name, temp_allocator()) or_return, nil) {
|
||||
return _get_platform_error()
|
||||
}
|
||||
return nil
|
||||
@@ -169,13 +170,13 @@ init_long_path_support :: proc() {
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_fix_long_path_slice :: proc(path: string) -> ([]u16, runtime.Allocator_Error) {
|
||||
return win32_utf8_to_utf16(_fix_long_path_internal(path), temp_allocator())
|
||||
_fix_long_path_slice :: proc(path: string, allocator: runtime.Allocator) -> ([]u16, runtime.Allocator_Error) {
|
||||
return win32_utf8_to_utf16(_fix_long_path_internal(path), allocator)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
_fix_long_path :: proc(path: string) -> (win32.wstring, runtime.Allocator_Error) {
|
||||
return win32_utf8_to_wstring(_fix_long_path_internal(path), temp_allocator())
|
||||
_fix_long_path :: proc(path: string, allocator: runtime.Allocator) -> (win32.wstring, runtime.Allocator_Error) {
|
||||
return win32_utf8_to_wstring(_fix_long_path_internal(path), allocator)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
|
||||
@@ -12,8 +12,8 @@ File_Info :: struct {
|
||||
name: string,
|
||||
|
||||
inode: u128, // might be zero if cannot be determined
|
||||
size: i64,
|
||||
mode: int,
|
||||
size: i64 `fmt:"M"`,
|
||||
mode: int `fmt:"o"`,
|
||||
type: File_Type,
|
||||
|
||||
creation_time: time.Time,
|
||||
|
||||
@@ -6,25 +6,22 @@ import "core:time"
|
||||
import "core:strings"
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) {
|
||||
if f == nil || (^File_Impl)(f.impl).fd == nil {
|
||||
return {}, nil
|
||||
return
|
||||
}
|
||||
|
||||
path, err := _cleanpath_from_handle(f, allocator)
|
||||
if err != nil {
|
||||
return {}, err
|
||||
}
|
||||
path := _cleanpath_from_handle(f, allocator) or_return
|
||||
|
||||
h := _handle(f)
|
||||
switch win32.GetFileType(h) {
|
||||
case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR:
|
||||
fi := File_Info {
|
||||
fi = File_Info {
|
||||
fullpath = path,
|
||||
name = basename(path),
|
||||
type = file_type(h),
|
||||
}
|
||||
return fi, nil
|
||||
return
|
||||
}
|
||||
|
||||
return _file_info_from_get_file_information_by_handle(path, h, allocator)
|
||||
@@ -67,8 +64,9 @@ internal_stat :: proc(name: string, create_file_attributes: u32, allocator: runt
|
||||
if len(name) == 0 {
|
||||
return {}, .Not_Exist
|
||||
}
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
|
||||
wname := _fix_long_path(name) or_return
|
||||
wname := _fix_long_path(name, temp_allocator()) or_return
|
||||
fa: win32.WIN32_FILE_ATTRIBUTE_DATA
|
||||
ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa)
|
||||
if ok && fa.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
||||
|
||||
@@ -3,8 +3,11 @@ package os2
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
|
||||
_temp_dir :: proc(allocator: runtime.Allocator) -> (string, Error) {
|
||||
//TODO
|
||||
return "", nil
|
||||
_temp_dir :: proc(allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) {
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
tmpdir := get_env("TMPDIR", temp_allocator())
|
||||
if tmpdir == "" {
|
||||
tmpdir = "/tmp"
|
||||
}
|
||||
return clone_string(tmpdir, allocator)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user