| ... | ... | @@ -708,6 +708,7 @@ pub fn io(t: *Threaded) Io { |
| 708 | 708 | .dirSetTimestampsNow = dirSetTimestampsNow, |
| 709 | 709 | |
| 710 | 710 | .fileStat = fileStat, |
| 711 | .fileLength = fileLength, |
| 711 | 712 | .fileClose = fileClose, |
| 712 | 713 | .fileWriteStreaming = fileWriteStreaming, |
| 713 | 714 | .fileWritePositional = fileWritePositional, |
| ... | ... | @@ -832,6 +833,7 @@ pub fn ioBasic(t: *Threaded) Io { |
| 832 | 833 | .dirSetTimestampsNow = dirSetTimestampsNow, |
| 833 | 834 | |
| 834 | 835 | .fileStat = fileStat, |
| 836 | .fileLength = fileLength, |
| 835 | 837 | .fileClose = fileClose, |
| 836 | 838 | .fileWriteStreaming = fileWriteStreaming, |
| 837 | 839 | .fileWritePositional = fileWritePositional, |
| ... | ... | @@ -1940,6 +1942,51 @@ fn dirStatPathWasi( |
| 1940 | 1942 | } |
| 1941 | 1943 | } |
| 1942 | 1944 | |
| 1945 | fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { |
| 1946 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1947 | |
| 1948 | if (native_os == .linux) { |
| 1949 | const current_thread = Thread.getCurrent(t); |
| 1950 | const linux = std.os.linux; |
| 1951 | |
| 1952 | try current_thread.beginSyscall(); |
| 1953 | while (true) { |
| 1954 | var statx = std.mem.zeroes(linux.Statx); |
| 1955 | switch (linux.errno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_SIZE, &statx))) { |
| 1956 | .SUCCESS => { |
| 1957 | current_thread.endSyscall(); |
| 1958 | return statx.size; |
| 1959 | }, |
| 1960 | .INTR => { |
| 1961 | try current_thread.checkCancel(); |
| 1962 | continue; |
| 1963 | }, |
| 1964 | .CANCELED => return current_thread.endSyscallCanceled(), |
| 1965 | else => |e| { |
| 1966 | current_thread.endSyscall(); |
| 1967 | switch (e) { |
| 1968 | .ACCES => |err| return errnoBug(err), |
| 1969 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| 1970 | .FAULT => |err| return errnoBug(err), |
| 1971 | .INVAL => |err| return errnoBug(err), |
| 1972 | .LOOP => |err| return errnoBug(err), |
| 1973 | .NAMETOOLONG => |err| return errnoBug(err), |
| 1974 | .NOENT => |err| return errnoBug(err), |
| 1975 | .NOMEM => return error.SystemResources, |
| 1976 | .NOTDIR => |err| return errnoBug(err), |
| 1977 | else => |err| return posix.unexpectedErrno(err), |
| 1978 | } |
| 1979 | }, |
| 1980 | } |
| 1981 | } |
| 1982 | } else if (is_windows) { |
| 1983 | // TODO call NtQueryInformationFile and ask for only the size instead of "all" |
| 1984 | } |
| 1985 | |
| 1986 | const stat = try fileStat(ioBasic(t), file); |
| 1987 | return stat.size; |
| 1988 | } |
| 1989 | |
| 1943 | 1990 | const fileStat = switch (native_os) { |
| 1944 | 1991 | .linux => fileStatLinux, |
| 1945 | 1992 | .windows => fileStatWindows, |
| ... | ... | @@ -5479,7 +5526,7 @@ const fileReadStreaming = switch (native_os) { |
| 5479 | 5526 | else => fileReadStreamingPosix, |
| 5480 | 5527 | }; |
| 5481 | 5528 | |
| 5482 | | fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: [][]u8) File.Reader.Error!usize { |
| 5529 | fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) File.Reader.Error!usize { |
| 5483 | 5530 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 5484 | 5531 | const current_thread = Thread.getCurrent(t); |
| 5485 | 5532 | |
| ... | ... | @@ -5567,7 +5614,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: [][]u8) File. |
| 5567 | 5614 | } |
| 5568 | 5615 | } |
| 5569 | 5616 | |
| 5570 | | fn fileReadStreamingWindows(userdata: ?*anyopaque, file: File, data: [][]u8) File.Reader.Error!usize { |
| 5617 | fn fileReadStreamingWindows(userdata: ?*anyopaque, file: File, data: []const []u8) File.Reader.Error!usize { |
| 5571 | 5618 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 5572 | 5619 | const current_thread = Thread.getCurrent(t); |
| 5573 | 5620 | |
| ... | ... | @@ -5596,7 +5643,7 @@ fn fileReadStreamingWindows(userdata: ?*anyopaque, file: File, data: [][]u8) Fil |
| 5596 | 5643 | } |
| 5597 | 5644 | } |
| 5598 | 5645 | |
| 5599 | | fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: [][]u8, offset: u64) File.ReadPositionalError!usize { |
| 5646 | fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { |
| 5600 | 5647 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 5601 | 5648 | const current_thread = Thread.getCurrent(t); |
| 5602 | 5649 | |
| ... | ... | @@ -5698,7 +5745,7 @@ const fileReadPositional = switch (native_os) { |
| 5698 | 5745 | else => fileReadPositionalPosix, |
| 5699 | 5746 | }; |
| 5700 | 5747 | |
| 5701 | | fn fileReadPositionalWindows(userdata: ?*anyopaque, file: File, data: [][]u8, offset: u64) File.ReadPositionalError!usize { |
| 5748 | fn fileReadPositionalWindows(userdata: ?*anyopaque, file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { |
| 5702 | 5749 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 5703 | 5750 | const current_thread = Thread.getCurrent(t); |
| 5704 | 5751 | |