diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin index 8692ecf01..52fd02478 100644 --- a/core/os/os2/file.odin +++ b/core/os/os2/file.odin @@ -106,7 +106,7 @@ open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File, @(require_results) new_file :: proc(handle: uintptr, name: string) -> ^File { - return _new_file(handle, name) + return _new_file(handle, name) or_else panic("Out of memory") } @(require_results) diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index cf643b31a..d2a7483ca 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -88,21 +88,24 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err return nil, _get_platform_error(errno) } - return _new_file(uintptr(fd), name), nil + return _new_file(uintptr(fd), name) } -_new_file :: proc(fd: uintptr, _: string = "") -> ^File { - impl := new(File_Impl, file_allocator()) +_new_file :: proc(fd: uintptr, _: string = "") -> (f: ^File, err: Error) { + impl := new(File_Impl, file_allocator()) or_return + defer if err != nil { + free(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.name = _get_full_path(impl.fd, file_allocator()) or_return impl.file.stream = { data = impl, procedure = _file_stream_proc, } impl.file.fstat = _fstat - return &impl.file + return &impl.file, nil } _destroy :: proc(f: ^File_Impl) -> Error { diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 3c18d0546..39a3e7867 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -126,20 +126,24 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) { flags := flags if flags != nil else {.Read} handle := _open_internal(name, flags, perm) or_return - return _new_file(handle, name), nil + return _new_file(handle, name) } -_new_file :: proc(handle: uintptr, name: string) -> ^File { +_new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) { if handle == INVALID_HANDLE { - return nil + return } - impl := new(File_Impl, file_allocator()) + impl := new(File_Impl, file_allocator()) or_return + defer if err != nil { + free(impl, file_allocator()) + } + impl.file.impl = impl impl.allocator = file_allocator() impl.fd = rawptr(handle) - impl.name, _ = clone_string(name, impl.allocator) - impl.wname, _ = win32_utf8_to_wstring(name, impl.allocator) + impl.name = clone_string(name, impl.allocator) or_return + impl.wname = win32_utf8_to_wstring(name, impl.allocator) or_return handle := _handle(&impl.file) kind := File_Impl_Kind.File @@ -157,7 +161,7 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File { } impl.file.fstat = _fstat - return &impl.file + return &impl.file, nil } _fd :: proc(f: ^File) -> uintptr { diff --git a/core/os/os2/path_linux.odin b/core/os/os2/path_linux.odin index 1634c79c8..be60f9b86 100644 --- a/core/os/os2/path_linux.odin +++ b/core/os/os2/path_linux.odin @@ -188,7 +188,7 @@ _set_working_directory :: proc(dir: string) -> Error { return _get_platform_error(linux.chdir(dir_cstr)) } -_get_full_path :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> string { +_get_full_path :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fullpath: string, err: Error) { PROC_FD_PATH :: "/proc/self/fd/" buf: [32]u8 @@ -196,10 +196,9 @@ _get_full_path :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> string { strconv.itoa(buf[len(PROC_FD_PATH):], int(fd)) - fullpath: string - err: Error if fullpath, err = _read_link_cstr(cstring(&buf[0]), allocator); err != nil || fullpath[0] != '/' { - return "" + delete(fullpath, allocator) + fullpath = "" } - return fullpath + return } diff --git a/core/os/os2/pipe_linux.odin b/core/os/os2/pipe_linux.odin index 8835cc30f..c3fecfb9e 100644 --- a/core/os/os2/pipe_linux.odin +++ b/core/os/os2/pipe_linux.odin @@ -10,8 +10,8 @@ _pipe :: proc() -> (r, w: ^File, err: Error) { return nil, nil,_get_platform_error(errno) } - r = _new_file(uintptr(fds[0])) - w = _new_file(uintptr(fds[1])) + r = _new_file(uintptr(fds[0])) or_return + w = _new_file(uintptr(fds[1])) or_return return } diff --git a/core/os/os2/stat_linux.odin b/core/os/os2/stat_linux.odin index 39a364c9a..eb31e2200 100644 --- a/core/os/os2/stat_linux.odin +++ b/core/os/os2/stat_linux.odin @@ -11,7 +11,7 @@ _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { return _fstat_internal(impl.fd, allocator) } -_fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (File_Info, Error) { +_fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { s: linux.Stat errno := linux.fstat(fd, &s) if errno != .NONE { @@ -30,20 +30,20 @@ _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (File_Inf mode := int(0o7777 & transmute(u32)s.mode) // TODO: As of Linux 4.11, the new statx syscall can retrieve creation_time - fi := File_Info { - fullpath = _get_full_path(fd, allocator), - name = "", - inode = u64(s.ino), - size = i64(s.size), - mode = mode, - type = type, + fi = File_Info { + fullpath = _get_full_path(fd, allocator) or_return, + name = "", + inode = u64(s.ino), + size = i64(s.size), + mode = mode, + type = type, modification_time = time.Time {i64(s.mtime.time_sec) * i64(time.Second) + i64(s.mtime.time_nsec)}, - access_time = time.Time {i64(s.atime.time_sec) * i64(time.Second) + i64(s.atime.time_nsec)}, - creation_time = time.Time{i64(s.ctime.time_sec) * i64(time.Second) + i64(s.ctime.time_nsec)}, // regular stat does not provide this + access_time = time.Time {i64(s.atime.time_sec) * i64(time.Second) + i64(s.atime.time_nsec)}, + creation_time = time.Time{i64(s.ctime.time_sec) * i64(time.Second) + i64(s.ctime.time_nsec)}, // regular stat does not provide this } fi.creation_time = fi.modification_time fi.name = filepath.base(fi.fullpath) - return fi, nil + return } // NOTE: _stat and _lstat are using _fstat to avoid a race condition when populating fullpath