diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin index dc618db37..be03155ff 100644 --- a/core/os/os2/file.odin +++ b/core/os/os2/file.odin @@ -5,9 +5,9 @@ import "core:time" import "base:runtime" File :: struct { - impl: _File, + impl: rawptr, stream: io.Stream, - fstat: Fstat_Callback, + fstat: Fstat_Callback, } File_Mode :: distinct u32 diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index eaded51c9..d2196b97b 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -7,13 +7,14 @@ import "base:runtime" import "core:sys/linux" _File :: struct { + using file: File, name: string, fd: linux.Fd, allocator: runtime.Allocator, } -_stdin : File = { - impl = { +_stdin := File{ + impl = &_File{ name = "/proc/self/fd/0", fd = 0, allocator = _file_allocator(), @@ -21,9 +22,10 @@ _stdin : File = { stream = { procedure = _file_stream_proc, }, + fstat = _fstat, } -_stdout : File = { - impl = { +_stdout := File{ + impl = &_File{ name = "/proc/self/fd/1", fd = 1, allocator = _file_allocator(), @@ -31,9 +33,10 @@ _stdout : File = { stream = { procedure = _file_stream_proc, }, + fstat = _fstat, } -_stderr : File = { - impl = { +_stderr := File{ + impl = &_File{ name = "/proc/self/fd/2", fd = 2, allocator = _file_allocator(), @@ -41,6 +44,7 @@ _stderr : File = { stream = { procedure = _file_stream_proc, }, + fstat = _fstat, } @init @@ -89,35 +93,35 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (f: ^File, er } _new_file :: proc(fd: uintptr, _: string = "") -> ^File { - file := new(File, file_allocator()) - file.impl = { - fd = linux.Fd(fd), - allocator = file_allocator(), - name = _get_full_path(file.impl.fd, file.impl.allocator), - } - file.stream = { - data = file, + impl := new(_File, file_allocator()) + impl.fd = linux.Fd(fd) + impl.allocator = file_allocator() + impl.name = _get_full_path(impl.fd, impl.allocator) + impl.file.stream = { + data = &impl.file, procedure = _file_stream_proc, } - file.fstat = _fstat - return file + impl.fstat = _fstat + return impl } _destroy :: proc(f: ^File) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } - delete(f.impl.name, f.impl.allocator) - free(f, f.impl.allocator) + impl := (^_File)(f.impl) + delete(impl.name, impl.allocator) + free(f, impl.allocator) return nil } _close :: proc(f: ^File) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } - errno := linux.close(f.impl.fd) + impl := (^_File)(f.impl) + errno := linux.close(impl.fd) if errno == .EBADF { // avoid possible double free return _get_platform_error(errno) } @@ -126,18 +130,20 @@ _close :: proc(f: ^File) -> Error { } _fd :: proc(f: ^File) -> uintptr { - if f == nil { + if f == nil || f.impl == nil { return ~uintptr(0) } - return uintptr(f.impl.fd) + impl := (^_File)(f.impl) + return uintptr(impl.fd) } _name :: proc(f: ^File) -> string { - return f.impl.name if f != nil else "" + return (^_File)(f.impl).name if f != nil && f.impl != nil else "" } _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { - n, errno := linux.lseek(f.impl.fd, offset, linux.Seek_Whence(whence)) + impl := (^_File)(f.impl) + n, errno := linux.lseek(impl.fd, offset, linux.Seek_Whence(whence)) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -148,7 +154,8 @@ _read :: proc(f: ^File, p: []byte) -> (i64, Error) { if len(p) == 0 { return 0, nil } - n, errno := linux.read(f.impl.fd, p[:]) + impl := (^_File)(f.impl) + n, errno := linux.read(impl.fd, p[:]) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -159,8 +166,8 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) { if offset < 0 { return 0, .Invalid_Offset } - - n, errno := linux.pread(f.impl.fd, p[:], offset) + impl := (^_File)(f.impl) + n, errno := linux.pread(impl.fd, p[:], offset) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -174,7 +181,8 @@ _write :: proc(f: ^File, p: []byte) -> (i64, Error) { if len(p) == 0 { return 0, nil } - n, errno := linux.write(f.impl.fd, p[:]) + impl := (^_File)(f.impl) + n, errno := linux.write(impl.fd, p[:]) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -186,7 +194,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) { return 0, .Invalid_Offset } - n, errno := linux.pwrite(f.impl.fd, p[:], offset) + impl := (^_File)(f.impl) + n, errno := linux.pwrite(impl.fd, p[:], offset) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -195,7 +204,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) { _file_size :: proc(f: ^File) -> (n: i64, err: Error) { s: linux.Stat = --- - errno := linux.fstat(f.impl.fd, &s) + impl := (^_File)(f.impl) + errno := linux.fstat(impl.fd, &s) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -203,15 +213,18 @@ _file_size :: proc(f: ^File) -> (n: i64, err: Error) { } _sync :: proc(f: ^File) -> Error { - return _get_platform_error(linux.fsync(f.impl.fd)) + impl := (^_File)(f.impl) + return _get_platform_error(linux.fsync(impl.fd)) } _flush :: proc(f: ^File) -> Error { - return _get_platform_error(linux.fsync(f.impl.fd)) + impl := (^_File)(f.impl) + return _get_platform_error(linux.fsync(impl.fd)) } _truncate :: proc(f: ^File, size: i64) -> Error { - return _get_platform_error(linux.ftruncate(f.impl.fd, size)) + impl := (^_File)(f.impl) + return _get_platform_error(linux.ftruncate(impl.fd, size)) } _remove :: proc(name: string) -> Error { @@ -287,7 +300,8 @@ _chdir :: proc(name: string) -> Error { } _fchdir :: proc(f: ^File) -> Error { - return _get_platform_error(linux.fchdir(f.impl.fd)) + impl := (^_File)(f.impl) + return _get_platform_error(linux.fchdir(impl.fd)) } _chmod :: proc(name: string, mode: File_Mode) -> Error { @@ -297,7 +311,8 @@ _chmod :: proc(name: string, mode: File_Mode) -> Error { } _fchmod :: proc(f: ^File, mode: File_Mode) -> Error { - return _get_platform_error(linux.fchmod(f.impl.fd, transmute(linux.Mode)(u32(mode)))) + impl := (^_File)(f.impl) + return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode)))) } // NOTE: will throw error without super user priviledges @@ -316,7 +331,8 @@ _lchown :: proc(name: string, uid, gid: int) -> Error { // NOTE: will throw error without super user priviledges _fchown :: proc(f: ^File, uid, gid: int) -> Error { - return _get_platform_error(linux.fchown(f.impl.fd, linux.Uid(uid), linux.Gid(gid))) + impl := (^_File)(f.impl) + return _get_platform_error(linux.fchown(impl.fd, linux.Uid(uid), linux.Gid(gid))) } _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error { @@ -346,7 +362,8 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error { uint(mtime._nsec) % uint(time.Second), }, } - return _get_platform_error(linux.utimensat(f.impl.fd, nil, ×[0], nil)) + impl := (^_File)(f.impl) + return _get_platform_error(linux.utimensat(impl.fd, nil, ×[0], nil)) } _exists :: proc(name: string) -> bool { diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 8953edafb..0ccea7f96 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -24,6 +24,8 @@ _File_Kind :: enum u8 { } _File :: struct { + using file: File, + fd: rawptr, name: string, wname: win32.wstring, @@ -130,12 +132,12 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File { if handle == INVALID_HANDLE { return nil } - f := new(File, file_allocator()) + f := new(_File, file_allocator()) - f.impl.allocator = file_allocator() - f.impl.fd = rawptr(handle) - f.impl.name, _ = clone_string(name, f.impl.allocator) - f.impl.wname = win32.utf8_to_wstring(name, f.impl.allocator) + f.allocator = file_allocator() + f.fd = rawptr(handle) + f.name, _ = clone_string(name, f.allocator) + f.wname = win32.utf8_to_wstring(name, f.allocator) handle := _handle(f) kind := _File_Kind.File @@ -145,7 +147,7 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File { if win32.GetFileType(handle) == win32.FILE_TYPE_PIPE { kind = .Pipe } - f.impl.kind = kind + f.kind = kind f.stream = { data = f, @@ -157,37 +159,38 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File { } _fd :: proc(f: ^File) -> uintptr { - if f == nil { + if f == nil || f.impl == nil { return INVALID_HANDLE } - return uintptr(f.impl.fd) + return uintptr((^_File)(f.impl).fd) } _destroy :: proc(f: ^File) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } - a := f.impl.allocator - free(f.impl.wname, a) - delete(f.impl.name, a) - free(f, a) + _f := (^_File)(f.impl) + a := _f.allocator + free(_f.wname, a) + delete(_f.name, a) + free(_f, a) return nil } _close :: proc(f: ^File) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } - if !win32.CloseHandle(win32.HANDLE(f.impl.fd)) { + if !win32.CloseHandle(win32.HANDLE((^_File)(f.impl).fd)) { return .Closed } return _destroy(f) } _name :: proc(f: ^File) -> string { - return f.impl.name if f != nil else "" + return (^_File)(f.impl).name if f != nil && f.impl != nil else "" } _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { @@ -195,11 +198,13 @@ _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Er if handle == win32.INVALID_HANDLE { return 0, .Invalid_File } - if f.impl.kind == .Pipe { + impl := (^_File)(f.impl) + + if impl.kind == .Pipe { return 0, .Invalid_File } - sync.guard(&f.impl.rw_mutex) + sync.guard(&impl.rw_mutex) w: u32 switch whence { @@ -274,12 +279,13 @@ _read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { total_read: int length := len(p) - sync.shared_guard(&f.impl.rw_mutex) // multiple readers + impl := (^_File)(f.impl) + sync.shared_guard(&impl.rw_mutex) // multiple readers - if sync.guard(&f.impl.p_mutex) { + if sync.guard(&impl.p_mutex) { to_read := min(win32.DWORD(length), MAX_RW) ok: win32.BOOL - if f.impl.kind == .Console { + if impl.kind == .Console { n, cerr := read_console(handle, p[total_read:][:to_read]) total_read += n if cerr != nil { @@ -326,7 +332,8 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { return } - sync.guard(&f.impl.p_mutex) + impl := (^_File)(f.impl) + sync.guard(&impl.p_mutex) p, offset := p, offset for len(p) > 0 { @@ -349,7 +356,8 @@ _write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { handle := _handle(f) - sync.guard(&f.impl.rw_mutex) + impl := (^_File)(f.impl) + sync.guard(&impl.rw_mutex) for total_write < length { remaining := length - total_write to_write := win32.DWORD(min(i32(remaining), MAX_RW)) @@ -390,7 +398,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { return } - sync.guard(&f.impl.p_mutex) + impl := (^_File)(f.impl) + sync.guard(&impl.p_mutex) p, offset := p, offset for len(p) > 0 { m := pwrite(f, p, offset) or_return @@ -403,7 +412,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { _file_size :: proc(f: ^File) -> (n: i64, err: Error) { length: win32.LARGE_INTEGER - if f.impl.kind == .Pipe { + impl := (^_File)(f.impl) + if impl.kind == .Pipe { return 0, .No_Size } handle := _handle(f) @@ -428,7 +438,7 @@ _flush :: proc(f: ^File) -> Error { } _truncate :: proc(f: ^File, size: i64) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } curr_off := seek(f, 0, .Current) or_return @@ -615,17 +625,18 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er _fchdir :: proc(f: ^File) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } - if !win32.SetCurrentDirectoryW(f.impl.wname) { + impl := (^_File)(f.impl) + if !win32.SetCurrentDirectoryW(impl.wname) { return _get_platform_error() } return nil } _fchmod :: proc(f: ^File, mode: File_Mode) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } d: win32.BY_HANDLE_FILE_INFORMATION @@ -680,7 +691,7 @@ _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error { return _fchtimes(f, atime, mtime) } _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error { - if f == nil { + if f == nil || f.impl == nil { return nil } d: win32.BY_HANDLE_FILE_INFORMATION diff --git a/core/os/os2/stat_linux.odin b/core/os/os2/stat_linux.odin index c0b3088b4..a6df4e67a 100644 --- a/core/os/os2/stat_linux.odin +++ b/core/os/os2/stat_linux.odin @@ -7,7 +7,8 @@ import "core:sys/linux" import "core:path/filepath" _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { - return _fstat_internal(f.impl.fd, allocator) + impl := (^_File)(f.impl) + return _fstat_internal(impl.fd, allocator) } _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (File_Info, Error) { diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin index 03ad2052f..5f7daa062 100644 --- a/core/os/os2/stat_windows.odin +++ b/core/os/os2/stat_windows.odin @@ -7,7 +7,7 @@ import "core:strings" import win32 "core:sys/windows" _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { - if f == nil || f.impl.fd == nil { + if f == nil || (^_File)(f.impl).fd == nil { return {}, nil } @@ -122,7 +122,7 @@ _cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (string, Error) { - if f == nil || f.impl.fd == nil { + if f == nil || (^_File)(f.impl).fd == nil { return "", nil } h := _handle(f) @@ -138,7 +138,7 @@ _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (strin } _cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) { - if f == nil || f.impl.fd == nil { + if f == nil || (^_File)(f.impl).fd == nil { return nil, nil } h := _handle(f)