diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index d2196b97b..482c9b5b4 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -6,15 +6,15 @@ import "core:time" import "base:runtime" import "core:sys/linux" -_File :: struct { - using file: File, +File_Impl :: struct { + file: File, name: string, fd: linux.Fd, allocator: runtime.Allocator, } _stdin := File{ - impl = &_File{ + impl = &File_Impl{ name = "/proc/self/fd/0", fd = 0, allocator = _file_allocator(), @@ -25,7 +25,7 @@ _stdin := File{ fstat = _fstat, } _stdout := File{ - impl = &_File{ + impl = &File_Impl{ name = "/proc/self/fd/1", fd = 1, allocator = _file_allocator(), @@ -36,7 +36,7 @@ _stdout := File{ fstat = _fstat, } _stderr := File{ - impl = &_File{ + impl = &File_Impl{ name = "/proc/self/fd/2", fd = 2, allocator = _file_allocator(), @@ -93,35 +93,35 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (f: ^File, er } _new_file :: proc(fd: uintptr, _: string = "") -> ^File { - impl := new(_File, file_allocator()) + impl := new(File_Impl, file_allocator()) + impl.file.impl = impl impl.fd = linux.Fd(fd) impl.allocator = file_allocator() impl.name = _get_full_path(impl.fd, impl.allocator) impl.file.stream = { - data = &impl.file, + data = impl, procedure = _file_stream_proc, } - impl.fstat = _fstat - return impl + impl.file.fstat = _fstat + return &impl.file } -_destroy :: proc(f: ^File) -> Error { - if f == nil || f.impl == nil { +_destroy :: proc(f: ^File_Impl) -> Error { + if f == nil { return nil } - impl := (^_File)(f.impl) - delete(impl.name, impl.allocator) - free(f, impl.allocator) + a := f.allocator + delete(f.name, a) + free(f, a) return nil } -_close :: proc(f: ^File) -> Error { - if f == nil || f.impl == nil { +_close :: proc(f: ^File_Impl) -> Error { + if f == nil{ return nil } - impl := (^_File)(f.impl) - errno := linux.close(impl.fd) + errno := linux.close(f.fd) if errno == .EBADF { // avoid possible double free return _get_platform_error(errno) } @@ -133,41 +133,38 @@ _fd :: proc(f: ^File) -> uintptr { if f == nil || f.impl == nil { return ~uintptr(0) } - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return uintptr(impl.fd) } _name :: proc(f: ^File) -> string { - return (^_File)(f.impl).name if f != nil && f.impl != nil else "" + return (^File_Impl)(f.impl).name if f != nil && f.impl != nil else "" } -_seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { - impl := (^_File)(f.impl) - n, errno := linux.lseek(impl.fd, offset, linux.Seek_Whence(whence)) +_seek :: proc(f: ^File_Impl, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { + n, errno := linux.lseek(f.fd, offset, linux.Seek_Whence(whence)) if errno != .NONE { return -1, _get_platform_error(errno) } return n, nil } -_read :: proc(f: ^File, p: []byte) -> (i64, Error) { +_read :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) { if len(p) == 0 { return 0, nil } - impl := (^_File)(f.impl) - n, errno := linux.read(impl.fd, p[:]) + n, errno := linux.read(f.fd, p[:]) if errno != .NONE { return -1, _get_platform_error(errno) } return i64(n), n == 0 ? io.Error.EOF : nil } -_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) { +_read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) { if offset < 0 { return 0, .Invalid_Offset } - impl := (^_File)(f.impl) - n, errno := linux.pread(impl.fd, p[:], offset) + n, errno := linux.pread(f.fd, p[:], offset) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -177,35 +174,31 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) { return i64(n), nil } -_write :: proc(f: ^File, p: []byte) -> (i64, Error) { +_write :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) { if len(p) == 0 { return 0, nil } - impl := (^_File)(f.impl) - n, errno := linux.write(impl.fd, p[:]) + n, errno := linux.write(f.fd, p[:]) if errno != .NONE { return -1, _get_platform_error(errno) } return i64(n), nil } -_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) { +_write_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) { if offset < 0 { return 0, .Invalid_Offset } - - impl := (^_File)(f.impl) - n, errno := linux.pwrite(impl.fd, p[:], offset) + n, errno := linux.pwrite(f.fd, p[:], offset) if errno != .NONE { return -1, _get_platform_error(errno) } return i64(n), nil } -_file_size :: proc(f: ^File) -> (n: i64, err: Error) { +_file_size :: proc(f: ^File_Impl) -> (n: i64, err: Error) { s: linux.Stat = --- - impl := (^_File)(f.impl) - errno := linux.fstat(impl.fd, &s) + errno := linux.fstat(f.fd, &s) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -213,17 +206,16 @@ _file_size :: proc(f: ^File) -> (n: i64, err: Error) { } _sync :: proc(f: ^File) -> Error { - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return _get_platform_error(linux.fsync(impl.fd)) } -_flush :: proc(f: ^File) -> Error { - impl := (^_File)(f.impl) - return _get_platform_error(linux.fsync(impl.fd)) +_flush :: proc(f: ^File_Impl) -> Error { + return _get_platform_error(linux.fsync(f.fd)) } _truncate :: proc(f: ^File, size: i64) -> Error { - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return _get_platform_error(linux.ftruncate(impl.fd, size)) } @@ -300,7 +292,7 @@ _chdir :: proc(name: string) -> Error { } _fchdir :: proc(f: ^File) -> Error { - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return _get_platform_error(linux.fchdir(impl.fd)) } @@ -311,7 +303,7 @@ _chmod :: proc(name: string, mode: File_Mode) -> Error { } _fchmod :: proc(f: ^File, mode: File_Mode) -> Error { - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode)))) } @@ -331,7 +323,7 @@ _lchown :: proc(name: string, uid, gid: int) -> Error { // NOTE: will throw error without super user priviledges _fchown :: proc(f: ^File, uid, gid: int) -> Error { - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return _get_platform_error(linux.fchown(impl.fd, linux.Uid(uid), linux.Gid(gid))) } @@ -362,7 +354,7 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error { uint(mtime._nsec) % uint(time.Second), }, } - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return _get_platform_error(linux.utimensat(impl.fd, nil, ×[0], nil)) } @@ -455,7 +447,7 @@ _read_entire_pseudo_file_cstring :: proc(name: cstring, allocator: runtime.Alloc @(private="package") _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { - f := (^File)(stream_data) + f := (^File_Impl)(stream_data) ferr: Error switch mode { case .Read: diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 0ccea7f96..b11e7745f 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -17,19 +17,19 @@ _ERROR_BAD_NETPATH :: 53 MAX_RW :: 1<<30 -_File_Kind :: enum u8 { +File_Impl_Kind :: enum u8 { File, Console, Pipe, } -_File :: struct { - using file: File, +File_Impl :: struct { + file: File, fd: rawptr, name: string, wname: win32.wstring, - kind: _File_Kind, + kind: File_Impl_Kind, allocator: runtime.Allocator, @@ -132,79 +132,81 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File { if handle == INVALID_HANDLE { return nil } - f := new(_File, file_allocator()) + impl := new(File_Impl, file_allocator()) + impl.file.impl = impl - f.allocator = file_allocator() - f.fd = rawptr(handle) - f.name, _ = clone_string(name, f.allocator) - f.wname = win32.utf8_to_wstring(name, f.allocator) + impl.allocator = file_allocator() + impl.fd = rawptr(handle) + impl.name, _ = clone_string(name, impl.allocator) + impl.wname = win32.utf8_to_wstring(name, impl.allocator) - handle := _handle(f) - kind := _File_Kind.File + handle := _handle(&impl.file) + kind := File_Impl_Kind.File if m: u32; win32.GetConsoleMode(handle, &m) { kind = .Console } if win32.GetFileType(handle) == win32.FILE_TYPE_PIPE { kind = .Pipe } - f.kind = kind + impl.kind = kind - f.stream = { - data = f, + impl.file.stream = { + data = impl, procedure = _file_stream_proc, } - f.fstat = _fstat + impl.file.fstat = _fstat - return f + return &impl.file } _fd :: proc(f: ^File) -> uintptr { if f == nil || f.impl == nil { return INVALID_HANDLE } - return uintptr((^_File)(f.impl).fd) + return uintptr((^File_Impl)(f.impl).fd) } -_destroy :: proc(f: ^File) -> Error { - if f == nil || f.impl == nil { +_destroy :: proc(f: ^File_Impl) -> Error { + if f == nil { return nil } - _f := (^_File)(f.impl) - a := _f.allocator - free(_f.wname, a) - delete(_f.name, a) - free(_f, a) + a := f.allocator + err0 := free(f.wname, a) + err1 := delete(f.name, a) + err2 := free(f, a) + err0 or_return + err1 or_return + err2 or_return return nil } -_close :: proc(f: ^File) -> Error { - if f == nil || f.impl == nil { +_close :: proc(f: ^File_Impl) -> Error { + if f == nil { return nil } - if !win32.CloseHandle(win32.HANDLE((^_File)(f.impl).fd)) { + if !win32.CloseHandle(win32.HANDLE(f.fd)) { return .Closed } return _destroy(f) } _name :: proc(f: ^File) -> string { - return (^_File)(f.impl).name if f != nil && f.impl != nil else "" + return (^File_Impl)(f.impl).name if f != nil && f.impl != nil else "" } -_seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { - handle := _handle(f) +_seek :: proc(f: ^File_Impl, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { + handle := _handle(&f.file) if handle == win32.INVALID_HANDLE { return 0, .Invalid_File } - impl := (^_File)(f.impl) - if impl.kind == .Pipe { + if f.kind == .Pipe { return 0, .Invalid_File } - sync.guard(&impl.rw_mutex) + sync.guard(&f.rw_mutex) w: u32 switch whence { @@ -222,7 +224,7 @@ _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Er return i64(hi)<<32 + i64(dw_ptr), nil } -_read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { +_read :: 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 @@ -273,19 +275,18 @@ _read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { return } - handle := _handle(f) + handle := _handle(&f.file) single_read_length: win32.DWORD total_read: int length := len(p) - impl := (^_File)(f.impl) - sync.shared_guard(&impl.rw_mutex) // multiple readers + sync.shared_guard(&f.rw_mutex) // multiple readers - if sync.guard(&impl.p_mutex) { + if sync.guard(&f.p_mutex) { to_read := min(win32.DWORD(length), MAX_RW) ok: win32.BOOL - if impl.kind == .Console { + if f.kind == .Console { n, cerr := read_console(handle, p[total_read:][:to_read]) total_read += n if cerr != nil { @@ -305,15 +306,15 @@ _read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { return i64(total_read), err } -_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { - pread :: proc(f: ^File, data: []byte, offset: i64) -> (n: i64, err: Error) { +_read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (n: i64, err: Error) { + pread :: proc(f: ^File_Impl, data: []byte, offset: i64) -> (n: i64, err: Error) { buf := data if len(buf) > MAX_RW { buf = buf[:MAX_RW] } - curr_offset := seek(f, offset, .Current) or_return - defer seek(f, curr_offset, .Start) + curr_offset := _seek(f, offset, .Current) or_return + defer _seek(f, curr_offset, .Start) o := win32.OVERLAPPED{ OffsetHigh = u32(offset>>32), @@ -322,7 +323,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { // TODO(bill): Determine the correct behaviour for consoles - h := _handle(f) + h := _handle(&f.file) done: win32.DWORD if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) { err = _get_platform_error() @@ -332,8 +333,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { return } - impl := (^_File)(f.impl) - sync.guard(&impl.p_mutex) + sync.guard(&f.p_mutex) p, offset := p, offset for len(p) > 0 { @@ -345,7 +345,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { return } -_write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { +_write :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) { if len(p) == 0 { return } @@ -354,10 +354,9 @@ _write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { total_write: i64 length := i64(len(p)) - handle := _handle(f) + handle := _handle(&f.file) - impl := (^_File)(f.impl) - sync.guard(&impl.rw_mutex) + sync.guard(&f.rw_mutex) for total_write < length { remaining := length - total_write to_write := win32.DWORD(min(i32(remaining), MAX_RW)) @@ -373,22 +372,22 @@ _write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) { return i64(total_write), nil } -_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { - pwrite :: proc(f: ^File, data: []byte, offset: i64) -> (n: i64, err: Error) { +_write_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (n: i64, err: Error) { + pwrite :: proc(f: ^File_Impl, data: []byte, offset: i64) -> (n: i64, err: Error) { buf := data if len(buf) > MAX_RW { buf = buf[:MAX_RW] } - curr_offset := seek(f, offset, .Current) or_return - defer seek(f, curr_offset, .Start) + curr_offset := _seek(f, offset, .Current) or_return + defer _seek(f, curr_offset, .Start) o := win32.OVERLAPPED{ OffsetHigh = u32(offset>>32), Offset = u32(offset), } - h := _handle(f) + h := _handle(&f.file) done: win32.DWORD if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) { err = _get_platform_error() @@ -398,8 +397,7 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { return } - impl := (^_File)(f.impl) - sync.guard(&impl.p_mutex) + sync.guard(&f.p_mutex) p, offset := p, offset for len(p) > 0 { m := pwrite(f, p, offset) or_return @@ -410,13 +408,12 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { return } -_file_size :: proc(f: ^File) -> (n: i64, err: Error) { +_file_size :: proc(f: ^File_Impl) -> (n: i64, err: Error) { length: win32.LARGE_INTEGER - impl := (^_File)(f.impl) - if impl.kind == .Pipe { + if f.kind == .Pipe { return 0, .No_Size } - handle := _handle(f) + handle := _handle(&f.file) if !win32.GetFileSizeEx(handle, &length) { err = _get_platform_error() } @@ -426,11 +423,14 @@ _file_size :: proc(f: ^File) -> (n: i64, err: Error) { _sync :: proc(f: ^File) -> Error { - return _flush(f) + if f != nil && f.impl != nil { + return _flush((^File_Impl)(f.impl)) + } + return nil } -_flush :: proc(f: ^File) -> Error { - handle := _handle(f) +_flush :: proc(f: ^File_Impl) -> Error { + handle := _handle(&f.file) if !win32.FlushFileBuffers(handle) { return _get_platform_error() } @@ -628,7 +628,7 @@ _fchdir :: proc(f: ^File) -> Error { if f == nil || f.impl == nil { return nil } - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) if !win32.SetCurrentDirectoryW(impl.wname) { return _get_platform_error() } @@ -747,7 +747,7 @@ _is_dir :: proc(path: string) -> bool { @(private="package") _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { - f := (^File)(stream_data) + f := (^File_Impl)(stream_data) ferr: Error switch mode { case .Read: diff --git a/core/os/os2/stat_linux.odin b/core/os/os2/stat_linux.odin index a6df4e67a..ee4011f96 100644 --- a/core/os/os2/stat_linux.odin +++ b/core/os/os2/stat_linux.odin @@ -7,7 +7,7 @@ import "core:sys/linux" import "core:path/filepath" _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { - impl := (^_File)(f.impl) + impl := (^File_Impl)(f.impl) return _fstat_internal(impl.fd, allocator) } diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin index 5f7daa062..0a18433c1 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 || (^_File)(f.impl).fd == nil { + if f == nil || (^File_Impl)(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 || (^_File)(f.impl).fd == nil { + if f == 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 || (^_File)(f.impl).fd == nil { + if f == nil { return nil, nil } h := _handle(f)