diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin index 426375a5a..d76b2d549 100644 --- a/core/os/os2/errors.odin +++ b/core/os/os2/errors.odin @@ -13,6 +13,12 @@ General_Error :: enum u32 { Timeout, + Broken_Pipe, + + // Indicates that an attempt to retrieve a file's size was made, but the + // file doesn't have a size. + No_Size, + Invalid_File, Invalid_Dir, Invalid_Path, @@ -51,6 +57,8 @@ error_string :: proc(ferr: Error) -> string { case .Not_Exist: return "file does not exist" case .Closed: return "file already closed" case .Timeout: return "i/o timeout" + case .Broken_Pipe: return "Broken pipe" + case .No_Size: return "file has no definite size" case .Invalid_File: return "invalid file" case .Invalid_Dir: return "invalid directory" case .Invalid_Path: return "invalid path" diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin index 459544fc0..0708f708e 100644 --- a/core/os/os2/file_util.odin +++ b/core/os/os2/file_util.odin @@ -87,26 +87,50 @@ read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator) - read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (data: []byte, err: Error) { size: int + has_size := true if size64, err := file_size(f); err == nil { if i64(int(size64)) != size64 { size = int(size64) } + } else if err == .No_Size { + has_size = false + } else { + return } size += 1 // for EOF // TODO(bill): Is this correct logic? - total: int - data = make([]byte, size, allocator) or_return - for { - n: int - n, err = read(f, data[total:]) - total += n - if err != nil { - if err == .EOF { - err = nil + if has_size { + total: int + data = make([]byte, size, allocator) or_return + for { + n: int + n, err = read(f, data[total:]) + total += n + if err != nil { + if err == .EOF { + err = nil + } + data = data[:total] + return + } + } + } else { + buffer: [1024]u8 + out_buffer := make([dynamic]u8, 0, 0, allocator) + total := 0 + for { + n: int = --- + n, err = read(f, buffer[:]) + total += n + append_elems(&out_buffer, ..buffer[:total]) + if err != nil { + if err == .EOF || err == .Broken_Pipe { + err = nil + } + data = out_buffer[:total] + return } - data = data[:total] - return } } } diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 8cb040a0a..fc3cebaea 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -434,6 +434,9 @@ _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 { + return 0, .No_Size + } handle := _handle(f) if !win32.GetFileSizeEx(handle, &length) { err = _get_platform_error() @@ -766,7 +769,6 @@ _is_dir :: proc(path: string) -> bool { _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) ferr: Error - i: int switch mode { case .Read: n, ferr = _read(f, p)