authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-08 23:03:34-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:08-08:00
log5b436d2c5125b9cf9a08b3bff0dcb0248c4d1ec0
tree67c4a021da0c5dd24b8e0369278a90fe81d65cf3
parent90f7259ef17e8e07c2c3f71bea65d103cfe52c07

build_runner compiling again


7 files changed, 111 insertions(+), 148 deletions(-)

lib/std/Io/Dir.zig+23-58
......@@ -198,7 +198,7 @@ pub const SelectiveWalker = struct {
198198 // likely just fail with the same error.
199199 var item = self.stack.pop().?;
200200 if (self.stack.items.len != 0) {
201 item.iter.dir.close(io);
201 item.iter.reader.dir.close(io);
202202 }
203203 return err;
204204 }) |entry| {
......@@ -211,7 +211,7 @@ pub const SelectiveWalker = struct {
211211 self.name_buffer.appendSliceAssumeCapacity(entry.name);
212212 self.name_buffer.appendAssumeCapacity(0);
213213 const walker_entry: Walker.Entry = .{
214 .dir = top.iter.dir,
214 .dir = top.iter.reader.dir,
215215 .basename = self.name_buffer.items[dirname_len .. self.name_buffer.items.len - 1 :0],
216216 .path = self.name_buffer.items[0 .. self.name_buffer.items.len - 1 :0],
217217 .kind = entry.kind,
......@@ -220,7 +220,7 @@ pub const SelectiveWalker = struct {
220220 } else {
221221 var item = self.stack.pop().?;
222222 if (self.stack.items.len != 0) {
223 item.iter.dir.close(io);
223 item.iter.reader.dir.close(io);
224224 }
225225 }
226226 }
......@@ -260,7 +260,7 @@ pub const SelectiveWalker = struct {
260260 var item = self.stack.pop().?;
261261 if (self.stack.items.len != 0) {
262262 @branchHint(.likely);
263 item.iter.dir.close(io);
263 item.iter.reader.dir.close(io);
264264 }
265265 }
266266};
......@@ -741,7 +741,6 @@ pub const RealPathError = error{
741741 FileNotFound,
742742 AccessDenied,
743743 PermissionDenied,
744 NameTooLong,
745744 NotSupported,
746745 NotDir,
747746 SymLinkLoop,
......@@ -757,9 +756,6 @@ pub const RealPathError = error{
757756 DeviceBusy,
758757 SharingViolation,
759758 PipeBusy,
760 /// Windows: file paths provided by the user must be valid WTF-8.
761 /// https://wtf-8.codeberg.page/
762 BadPathName,
763759 /// On Windows, `\\server` or `\\server\share` was not found.
764760 NetworkNotFound,
765761 PathAlreadyExists,
......@@ -772,7 +768,7 @@ pub const RealPathError = error{
772768 /// On Windows, the volume does not contain a recognized file system. File
773769 /// system drivers might not be loaded, or the volume may be corrupt.
774770 UnrecognizedVolume,
775} || Io.Cancelable || Io.UnexpectedError;
771} || PathNameError || Io.Cancelable || Io.UnexpectedError;
776772
777773/// This function returns the canonicalized absolute pathname of `pathname`
778774/// relative to this `Dir`. If `pathname` is absolute, ignores this `Dir`
......@@ -824,19 +820,12 @@ pub const DeleteFileError = error{
824820 FileSystem,
825821 IsDir,
826822 SymLinkLoop,
827 NameTooLong,
828823 NotDir,
829824 SystemResources,
830825 ReadOnlyFileSystem,
831 /// WASI: file paths must be valid UTF-8.
832 /// Windows: file paths provided by the user must be valid WTF-8.
833 /// https://wtf-8.codeberg.page/
834 /// Windows: file paths cannot contain these characters:
835 /// '/', '*', '?', '"', '<', '>', '|'
836 BadPathName,
837826 /// On Windows, `\\server` or `\\server\share` was not found.
838827 NetworkNotFound,
839} || Io.Cancelable || Io.UnexpectedError;
828} || PathNameError || Io.Cancelable || Io.UnexpectedError;
840829
841830/// Delete a file name and possibly the file it refers to, based on an open directory handle.
842831///
......@@ -864,17 +853,12 @@ pub const DeleteDirError = error{
864853 FileBusy,
865854 FileSystem,
866855 SymLinkLoop,
867 NameTooLong,
868856 NotDir,
869857 SystemResources,
870858 ReadOnlyFileSystem,
871 /// WASI: file paths must be valid UTF-8.
872 /// Windows: file paths provided by the user must be valid WTF-8.
873 /// https://wtf-8.codeberg.page/
874 BadPathName,
875859 /// On Windows, `\\server` or `\\server\share` was not found.
876860 NetworkNotFound,
877} || Io.Cancelable || Io.UnexpectedError;
861} || PathNameError || Io.Cancelable || Io.UnexpectedError;
878862
879863/// Returns `error.DirNotEmpty` if the directory is not empty.
880864///
......@@ -910,7 +894,6 @@ pub const RenameError = error{
910894 IsDir,
911895 SymLinkLoop,
912896 LinkQuotaExceeded,
913 NameTooLong,
914897 FileNotFound,
915898 NotDir,
916899 SystemResources,
......@@ -918,10 +901,6 @@ pub const RenameError = error{
918901 PathAlreadyExists,
919902 ReadOnlyFileSystem,
920903 RenameAcrossMountPoints,
921 /// WASI: file paths must be valid UTF-8.
922 /// Windows: file paths provided by the user must be valid WTF-8.
923 /// https://wtf-8.codeberg.page/
924 BadPathName,
925904 NoDevice,
926905 SharingViolation,
927906 PipeBusy,
......@@ -933,7 +912,7 @@ pub const RenameError = error{
933912 /// intercepts file system operations and makes them significantly slower
934913 /// in addition to possibly failing with this error code.
935914 AntivirusInterference,
936} || Io.Cancelable || Io.UnexpectedError;
915} || PathNameError || Io.Cancelable || Io.UnexpectedError;
937916
938917/// Change the name or location of a file or directory.
939918///
......@@ -985,12 +964,7 @@ pub const SymLinkError = error{
985964 NoSpaceLeft,
986965 ReadOnlyFileSystem,
987966 NotDir,
988 NameTooLong,
989 /// WASI: file paths must be valid UTF-8.
990 /// Windows: file paths provided by the user must be valid WTF-8.
991 /// https://wtf-8.codeberg.page/
992 BadPathName,
993} || Io.Cancelable || Io.UnexpectedError;
967} || PathNameError || Io.Cancelable || Io.UnexpectedError;
994968
995969/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`.
996970///
......@@ -1075,15 +1049,10 @@ pub const ReadLinkError = error{
10751049 PermissionDenied,
10761050 FileSystem,
10771051 SymLinkLoop,
1078 NameTooLong,
10791052 FileNotFound,
10801053 SystemResources,
10811054 NotLink,
10821055 NotDir,
1083 /// WASI: file paths must be valid UTF-8.
1084 /// Windows: file paths provided by the user must be valid WTF-8.
1085 /// https://wtf-8.codeberg.page/
1086 BadPathName,
10871056 /// Windows-only. This error may occur if the opened reparse point is
10881057 /// of unsupported type.
10891058 UnsupportedReparsePointType,
......@@ -1095,7 +1064,7 @@ pub const ReadLinkError = error{
10951064 /// intercepts file system operations and makes them significantly slower
10961065 /// in addition to possibly failing with this error code.
10971066 AntivirusInterference,
1098} || Io.Cancelable || Io.UnexpectedError;
1067} || PathNameError || Io.Cancelable || Io.UnexpectedError;
10991068
11001069/// Obtain target of a symbolic link.
11011070///
......@@ -1183,7 +1152,6 @@ pub const DeleteTreeError = error{
11831152 FileTooBig,
11841153 SymLinkLoop,
11851154 ProcessFdQuotaExceeded,
1186 NameTooLong,
11871155 SystemFdQuotaExceeded,
11881156 NoDevice,
11891157 SystemResources,
......@@ -1194,15 +1162,9 @@ pub const DeleteTreeError = error{
11941162 /// One of the path components was not a directory.
11951163 /// This error is unreachable if `sub_path` does not contain a path separator.
11961164 NotDir,
1197 /// WASI: file paths must be valid UTF-8.
1198 /// Windows: file paths provided by the user must be valid WTF-8.
1199 /// https://wtf-8.codeberg.page/
1200 /// On Windows, file paths cannot contain these characters:
1201 /// '/', '*', '?', '"', '<', '>', '|'
1202 BadPathName,
12031165 /// On Windows, `\\server` or `\\server\share` was not found.
12041166 NetworkNotFound,
1205} || Io.Cancelable || Io.UnexpectedError;
1167} || PathNameError || Io.Cancelable || Io.UnexpectedError;
12061168
12071169/// Whether `sub_path` describes a symlink, file, or directory, this function
12081170/// removes it. If it cannot be removed because it is a non-empty directory,
......@@ -1222,7 +1184,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
12221184 iter: Dir.Iterator,
12231185
12241186 fn closeAll(inner_io: Io, items: []@This()) void {
1225 for (items) |*item| item.iter.dir.close(inner_io);
1187 for (items) |*item| item.iter.reader.dir.close(inner_io);
12261188 }
12271189 };
12281190
......@@ -1243,7 +1205,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
12431205 handle_entry: while (true) {
12441206 if (treat_as_dir) {
12451207 if (stack.unusedCapacitySlice().len >= 1) {
1246 var iterable_dir = top.iter.dir.openDir(io, entry.name, .{
1208 var iterable_dir = top.iter.reader.dir.openDir(io, entry.name, .{
12471209 .follow_symlinks = false,
12481210 .iterate = true,
12491211 }) catch |err| switch (err) {
......@@ -1273,16 +1235,16 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
12731235 };
12741236 stack.appendAssumeCapacity(.{
12751237 .name = entry.name,
1276 .parent_dir = top.iter.dir,
1238 .parent_dir = top.iter.reader.dir,
12771239 .iter = iterable_dir.iterateAssumeFirstIteration(),
12781240 });
12791241 continue :process_stack;
12801242 } else {
1281 try top.iter.dir.deleteTreeMinStackSizeWithKindHint(io, entry.name, entry.kind);
1243 try top.iter.reader.dir.deleteTreeMinStackSizeWithKindHint(io, entry.name, entry.kind);
12821244 break :handle_entry;
12831245 }
12841246 } else {
1285 if (top.iter.dir.deleteFile(io, entry.name)) {
1247 if (top.iter.reader.dir.deleteFile(io, entry.name)) {
12861248 break :handle_entry;
12871249 } else |err| switch (err) {
12881250 error.FileNotFound => break :handle_entry,
......@@ -1305,6 +1267,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
13051267 error.FileBusy,
13061268 error.BadPathName,
13071269 error.NetworkNotFound,
1270 error.Canceled,
13081271 error.Unexpected,
13091272 => |e| return e,
13101273 }
......@@ -1314,7 +1277,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
13141277
13151278 // On Windows, we can't delete until the dir's handle has been closed, so
13161279 // close it before we try to delete.
1317 top.iter.dir.close(io);
1280 top.iter.reader.dir.close(io);
13181281
13191282 // In order to avoid double-closing the directory when cleaning up
13201283 // the stack in the case of an error, we save the relevant portions and
......@@ -1324,7 +1287,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
13241287 stack.items.len -= 1;
13251288
13261289 var need_to_retry: bool = false;
1327 parent_dir.deleteDir(name) catch |err| switch (err) {
1290 parent_dir.deleteDir(io, name) catch |err| switch (err) {
13281291 error.FileNotFound => {},
13291292 error.DirNotEmpty => need_to_retry = true,
13301293 else => |e| return e,
......@@ -1389,6 +1352,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
13891352 error.FileBusy,
13901353 error.BadPathName,
13911354 error.NetworkNotFound,
1355 error.Canceled,
13921356 error.Unexpected,
13931357 => |e| return e,
13941358 }
......@@ -1437,7 +1401,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8,
14371401
14381402 scan_dir: while (true) {
14391403 var dir_it = dir.iterateAssumeFirstIteration();
1440 dir_it: while (try dir_it.next()) |entry| {
1404 dir_it: while (try dir_it.next(io)) |entry| {
14411405 var treat_as_dir = entry.kind == .directory;
14421406 handle_entry: while (true) {
14431407 if (treat_as_dir) {
......@@ -1500,6 +1464,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8,
15001464 error.FileBusy,
15011465 error.BadPathName,
15021466 error.NetworkNotFound,
1467 error.Canceled,
15031468 error.Unexpected,
15041469 => |e| return e,
15051470 }
......@@ -1727,7 +1692,7 @@ pub fn setOwner(dir: Dir, io: Io, owner: ?File.Uid, group: ?File.Gid) SetOwnerEr
17271692 return io.vtable.dirSetOwner(io.userdata, dir, owner, group);
17281693}
17291694
1730pub const SetTimestampsError = File.SetTimestampsError;
1695pub const SetTimestampsError = File.SetTimestampsError || PathNameError;
17311696
17321697pub const SetTimestampsOptions = struct {
17331698 follow_symlinks: bool = true,
lib/std/Io/File.zig+3-14
......@@ -284,7 +284,9 @@ pub fn isTty(file: File, io: Io) bool {
284284 return io.vtable.fileIsTty(io.userdata, file);
285285}
286286
287pub const EnableAnsiEscapeCodesError = error{} || Io.Cancelable || Io.UnexpectedError;
287pub const EnableAnsiEscapeCodesError = error{
288 NotTerminalDevice,
289} || Io.Cancelable || Io.UnexpectedError;
288290
289291pub fn enableAnsiEscapeCodes(file: File, io: Io) EnableAnsiEscapeCodesError!void {
290292 return io.vtable.fileEnableAnsiEscapeCodes(io.userdata, file);
......@@ -492,19 +494,6 @@ pub fn writePositional(file: File, io: Io, buffer: []const []const u8, offset: u
492494 return io.vtable.fileWritePositional(io.userdata, file, buffer, offset);
493495}
494496
495pub const WriteFileStreamingError = error{
496 /// `out_fd` is an unconnected socket, or out_fd closed its read end.
497 BrokenPipe,
498 /// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd.
499 UnsupportedOperation,
500 /// Nonblocking I/O has been selected but the write would block.
501 WouldBlock,
502 /// Unspecified error while reading from in_fd.
503 InputOutput,
504 /// Insufficient kernel memory to read from in_fd.
505 SystemResources,
506} || Io.Cancelable || Io.UnexpectedError;
507
508497pub const SeekError = error{
509498 Unseekable,
510499 /// The file descriptor does not hold the required rights to seek on it.
lib/std/Io/File/Writer.zig+14-11
......@@ -28,7 +28,9 @@ pub const Error = error{
2828 /// File descriptor does not hold the required rights to write to it.
2929 AccessDenied,
3030 PermissionDenied,
31 /// File is an unconnected socket, or closed its read end.
3132 BrokenPipe,
33 /// Insufficient kernel memory to read from in_fd.
3234 SystemResources,
3335 NotOpenForWriting,
3436 /// The process cannot access the file because another process has locked
......@@ -39,20 +41,15 @@ pub const Error = error{
3941 /// This error occurs when a device gets disconnected before or mid-flush
4042 /// while it's being written to - errno(6): No such device or address.
4143 NoDevice,
44 FileBusy,
4245} || Io.Cancelable || Io.UnexpectedError;
4346
44pub const WriteFileError = error{
45 /// `out_fd` is an unconnected socket, or out_fd closed its read end.
46 BrokenPipe,
47pub const WriteFileError = Error || error{
4748 /// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd.
48 UnsupportedOperation,
49 /// Nonblocking I/O has been selected but the write would block.
50 WouldBlock,
51 /// Unspecified error while reading from in_fd.
52 InputOutput,
53 /// Insufficient kernel memory to read from in_fd.
54 SystemResources,
55} || Io.Cancelable || Io.UnexpectedError;
49 Unimplemented,
50 EndOfStream,
51 ReadFailed,
52};
5653
5754pub const SeekError = Io.File.SeekError;
5855
......@@ -175,6 +172,9 @@ fn sendFilePositional(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit)
175172 w.err = error.Canceled;
176173 return error.WriteFailed;
177174 },
175 error.EndOfStream => return error.EndOfStream,
176 error.Unimplemented => return error.Unimplemented,
177 error.ReadFailed => return error.ReadFailed,
178178 else => |e| {
179179 w.write_file_err = e;
180180 return error.WriteFailed;
......@@ -192,6 +192,9 @@ fn sendFileStreaming(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit)
192192 w.err = error.Canceled;
193193 return error.WriteFailed;
194194 },
195 error.EndOfStream => return error.EndOfStream,
196 error.Unimplemented => return error.Unimplemented,
197 error.ReadFailed => return error.ReadFailed,
195198 else => |e| {
196199 w.write_file_err = e;
197200 return error.WriteFailed;
lib/std/Io/Threaded.zig+60-56
......@@ -696,6 +696,7 @@ pub fn io(t: *Threaded) Io {
696696 .dirOpenFile = dirOpenFile,
697697 .dirOpenDir = dirOpenDir,
698698 .dirClose = dirClose,
699 .dirRead = dirRead,
699700 .dirRealPath = dirRealPath,
700701 .dirDeleteFile = dirDeleteFile,
701702 .dirDeleteDir = dirDeleteDir,
......@@ -822,6 +823,7 @@ pub fn ioBasic(t: *Threaded) Io {
822823 .dirOpenFile = dirOpenFile,
823824 .dirOpenDir = dirOpenDir,
824825 .dirClose = dirClose,
826 .dirRead = dirRead,
825827 .dirRealPath = dirRealPath,
826828 .dirDeleteFile = dirDeleteFile,
827829 .dirDeleteDir = dirDeleteDir,
......@@ -1621,7 +1623,7 @@ fn dirMakeOpenPathPosix(
16211623) Dir.MakeOpenPathError!Dir {
16221624 const t: *Threaded = @ptrCast(@alignCast(userdata));
16231625 const t_io = ioBasic(t);
1624 return dirOpenDirPosix(t, dir, sub_path, permissions, options) catch |err| switch (err) {
1626 return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) {
16251627 error.FileNotFound => {
16261628 _ = try dir.makePathStatus(t_io, sub_path, permissions);
16271629 return dirOpenDirPosix(t, dir, sub_path, options);
......@@ -2388,7 +2390,7 @@ fn dirCreateFilePosix(
23882390
23892391 try current_thread.beginSyscall();
23902392 const fd: posix.fd_t = while (true) {
2391 const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.mode);
2393 const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.permissions.toMode());
23922394 switch (posix.errno(rc)) {
23932395 .SUCCESS => {
23942396 current_thread.endSyscall();
......@@ -3256,6 +3258,14 @@ fn dirClose(userdata: ?*anyopaque, dirs: []const Dir) void {
32563258 for (dirs) |dir| posix.close(dir.handle);
32573259}
32583260
3261fn dirRead(userdata: ?*anyopaque, dir_reader: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize {
3262 const t: *Threaded = @ptrCast(@alignCast(userdata));
3263 _ = t;
3264 _ = dir_reader;
3265 _ = buffer;
3266 @panic("TODO");
3267}
3268
32593269const dirRealPath = switch (native_os) {
32603270 .windows => dirRealPathWindows,
32613271 else => dirRealPathPosix,
......@@ -3412,7 +3422,6 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b
34123422 switch (e) {
34133423 .ACCES => return error.AccessDenied,
34143424 .FAULT => |err| return errnoBug(err),
3415 .INVAL => return error.NotLink,
34163425 .IO => return error.FileSystem,
34173426 .LOOP => return error.SymLinkLoop,
34183427 .NAMETOOLONG => return error.NameTooLong,
......@@ -4562,7 +4571,7 @@ fn fileSyncPosix(userdata: ?*anyopaque, file: File) File.SyncError!void {
45624571 const current_thread = Thread.getCurrent(t);
45634572 try current_thread.beginSyscall();
45644573 while (true) {
4565 switch (posix.system.fsync(file.handle)) {
4574 switch (posix.errno(posix.system.fsync(file.handle))) {
45664575 .SUCCESS => return current_thread.endSyscall(),
45674576 .CANCELED => return current_thread.endSyscallCanceled(),
45684577 .INTR => {
......@@ -4640,7 +4649,7 @@ fn isTty(current_thread: *Thread, file: File) Io.Cancelable!bool {
46404649 const linux = std.os.linux;
46414650 try current_thread.beginSyscall();
46424651 while (true) {
4643 var wsz: linux.winsize = undefined;
4652 var wsz: posix.winsize = undefined;
46444653 const fd: usize = @bitCast(@as(isize, file.handle));
46454654 const rc = linux.syscall3(.ioctl, fd, linux.T.IOCGWINSZ, @intFromPtr(&wsz));
46464655 switch (linux.errno(rc)) {
......@@ -4948,7 +4957,7 @@ fn dirSetTimestamps(
49484957 last_accessed: Io.Timestamp,
49494958 last_modified: Io.Timestamp,
49504959 options: Dir.SetTimestampsOptions,
4951) File.SetTimestampsError!void {
4960) Dir.SetTimestampsError!void {
49524961 const t: *Threaded = @ptrCast(@alignCast(userdata));
49534962 const current_thread = Thread.getCurrent(t);
49544963
......@@ -4961,8 +4970,8 @@ fn dirSetTimestamps(
49614970 }
49624971
49634972 const times: [2]posix.timespec = .{
4964 timestampToPosix(last_accessed),
4965 timestampToPosix(last_modified),
4973 timestampToPosix(last_accessed.nanoseconds),
4974 timestampToPosix(last_modified.nanoseconds),
49664975 };
49674976
49684977 const flags: u32 = if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0;
......@@ -5000,7 +5009,7 @@ fn dirSetTimestampsNow(
50005009 dir: Dir,
50015010 sub_path: []const u8,
50025011 options: Dir.SetTimestampsOptions,
5003) File.SetTimestampsError!void {
5012) Dir.SetTimestampsError!void {
50045013 const t: *Threaded = @ptrCast(@alignCast(userdata));
50055014 const current_thread = Thread.getCurrent(t);
50065015
......@@ -5068,8 +5077,8 @@ fn fileSetTimestamps(
50685077 }
50695078
50705079 const times: [2]posix.timespec = .{
5071 timestampToPosix(last_accessed),
5072 timestampToPosix(last_modified),
5080 timestampToPosix(last_accessed.nanoseconds),
5081 timestampToPosix(last_modified.nanoseconds),
50735082 };
50745083
50755084 if (native_os == .wasi and !builtin.link_libc) {
......@@ -5226,7 +5235,7 @@ fn fileLock(userdata: ?*anyopaque, file: File, lock: File.Lock) File.LockError!v
52265235 }
52275236 }
52285237
5229 const operation = switch (lock) {
5238 const operation: i32 = switch (lock) {
52305239 .none => posix.LOCK.UN,
52315240 .shared => posix.LOCK.SH,
52325241 .exclusive => posix.LOCK.EX,
......@@ -5288,7 +5297,7 @@ fn fileTryLock(userdata: ?*anyopaque, file: File, lock: File.Lock) File.LockErro
52885297 }
52895298 }
52905299
5291 const operation = switch (lock) {
5300 const operation: i32 = switch (lock) {
52925301 .none => posix.LOCK.UN,
52935302 .shared => posix.LOCK.SH | posix.LOCK.NB,
52945303 .exclusive => posix.LOCK.EX | posix.LOCK.NB,
......@@ -5346,27 +5355,16 @@ fn fileUnlock(userdata: ?*anyopaque, file: File) void {
53465355 return;
53475356 }
53485357
5349 try current_thread.beginSyscall();
53505358 while (true) {
53515359 switch (posix.errno(posix.system.flock(file.handle, posix.LOCK.UN))) {
5352 .SUCCESS => return current_thread.endSyscall(),
5353 .CANCELED => return current_thread.endSyscallCanceled(),
5354 .INTR => {
5355 try current_thread.checkCancel();
5356 continue;
5357 },
5358 else => |e| {
5359 current_thread.endSyscall();
5360 if (is_debug) switch (e) {
5361 .AGAIN => unreachable, // unlocking can't block
5362 .BADF => unreachable, // File descriptor used after closed.
5363 .INVAL => unreachable, // invalid parameters
5364 .NOLCK => unreachable, // Resource deallocation.
5365 .OPNOTSUPP => unreachable, // We already got the lock.
5366 else => unreachable, // Resource deallocation must succeed.
5367 };
5368 return;
5369 },
5360 .SUCCESS => return,
5361 .CANCELED, .INTR => continue,
5362 .AGAIN => return assert(!is_debug), // unlocking can't block
5363 .BADF => return assert(!is_debug), // File descriptor used after closed.
5364 .INVAL => return assert(!is_debug), // invalid parameters
5365 .NOLCK => return assert(!is_debug), // Resource deallocation.
5366 .OPNOTSUPP => return assert(!is_debug), // We already got the lock.
5367 else => return assert(!is_debug), // Resource deallocation must succeed.
53705368 }
53715369 }
53725370}
......@@ -5424,7 +5422,7 @@ fn fileDowngradeLock(userdata: ?*anyopaque, file: File) File.DowngradeLockError!
54245422 switch (posix.errno(posix.system.flock(file.handle, operation))) {
54255423 .SUCCESS => {
54265424 current_thread.endSyscall();
5427 return true;
5425 return;
54285426 },
54295427 .CANCELED => return current_thread.endSyscallCanceled(),
54305428 .INTR => {
......@@ -6255,8 +6253,9 @@ fn fileWritePositional(
62556253 .NOSPC => return error.NoSpaceLeft,
62566254 .PERM => return error.PermissionDenied,
62576255 .PIPE => return error.BrokenPipe,
6258 .CONNRESET => return error.ConnectionResetByPeer,
6256 .CONNRESET => |err| return errnoBug(err), // Not a socket handle.
62596257 .BUSY => return error.DeviceBusy,
6258 .TXTBSY => return error.FileBusy,
62606259 .NXIO => return error.Unseekable,
62616260 .SPIPE => return error.Unseekable,
62626261 .OVERFLOW => return error.Unseekable,
......@@ -6373,7 +6372,7 @@ fn fileWriteStreaming(
63736372 .NOSPC => return error.NoSpaceLeft,
63746373 .PERM => return error.PermissionDenied,
63756374 .PIPE => return error.BrokenPipe,
6376 .CONNRESET => return error.ConnectionResetByPeer,
6375 .CONNRESET => |err| return errnoBug(err), // Not a socket handle.
63776376 .BUSY => return error.DeviceBusy,
63786377 else => |err| return posix.unexpectedErrno(err),
63796378 }
......@@ -6388,12 +6387,12 @@ fn fileWriteFileStreaming(
63886387 header: []const u8,
63896388 file_reader: *File.Reader,
63906389 limit: Io.Limit,
6391) File.WriteFileStreamingError!usize {
6390) File.Writer.WriteFileError!usize {
63926391 const t: *Threaded = @ptrCast(@alignCast(userdata));
63936392 const reader_buffered = file_reader.interface.buffered();
63946393 if (reader_buffered.len >= @intFromEnum(limit)) {
63956394 const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1);
6396 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6395 file_reader.interface.toss(n -| header.len);
63976396 return n;
63986397 }
63996398 const file_limit = @intFromEnum(limit) - reader_buffered.len;
......@@ -6404,7 +6403,7 @@ fn fileWriteFileStreaming(
64046403 if (size - file_reader.pos == 0) {
64056404 if (reader_buffered.len != 0) {
64066405 const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1);
6407 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6406 file_reader.interface.toss(n -| header.len);
64086407 return n;
64096408 } else {
64106409 return error.EndOfStream;
......@@ -6495,7 +6494,7 @@ fn fileWriteFileStreaming(
64956494 return error.EndOfStream;
64966495 }
64976496 const ubytes: usize = @intCast(sbytes);
6498 file_reader.seekBy(ubytes -| header.len) catch return error.ReadFailed;
6497 file_reader.interface.toss(ubytes -| header.len);
64996498 return ubytes;
65006499 }
65016500
......@@ -6581,7 +6580,7 @@ fn fileWriteFileStreaming(
65816580 return error.EndOfStream;
65826581 }
65836582 const u_len: usize = @bitCast(len);
6584 file_reader.seekBy(u_len -| header.len) catch return error.ReadFailed;
6583 file_reader.interface.toss(u_len -| header.len);
65856584 return u_len;
65866585 }
65876586
......@@ -6591,7 +6590,7 @@ fn fileWriteFileStreaming(
65916590 // Linux sendfile does not support headers.
65926591 if (header.len != 0 or reader_buffered.len != 0) {
65936592 const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1);
6594 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6593 file_reader.interface.toss(n -| header.len);
65956594 return n;
65966595 }
65976596 const max_count = 0x7ffff000; // Avoid EINVAL.
......@@ -6671,7 +6670,7 @@ fn fileWriteFileStreaming(
66716670 if (@atomicLoad(UseCopyFileRange, &t.use_copy_file_range, .monotonic) == .disabled) break :cfr;
66726671 if (header.len != 0 or reader_buffered.len != 0) {
66736672 const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1);
6674 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6673 file_reader.interface.toss(n -| header.len);
66756674 return n;
66766675 }
66776676 var off_in: i64 = undefined;
......@@ -6682,7 +6681,7 @@ fn fileWriteFileStreaming(
66826681 break :p &off_in;
66836682 },
66846683 .streaming => null,
6685 .failure => return error.WriteFailed,
6684 .failure => return error.ReadFailed,
66866685 };
66876686 const current_thread = Thread.getCurrent(t);
66886687 const n: usize = switch (native_os) {
......@@ -6712,13 +6711,16 @@ fn fileWriteFileStreaming(
67126711 assert(error.Unexpected == switch (e) {
67136712 .FBIG => return error.FileTooBig,
67146713 .IO => return error.InputOutput,
6715 .ISDIR => return error.IsDir,
67166714 .NOMEM => return error.SystemResources,
67176715 .NOSPC => return error.NoSpaceLeft,
6718 .OVERFLOW => return error.Overflow,
6716 .OVERFLOW => |err| errnoBug(err), // We avoid passing too large a count.
67196717 .PERM => return error.PermissionDenied,
6720 .TXTBSY => return error.SwapFile,
6721 .XDEV => return error.NotSameFileSystem,
6718 .BUSY => return error.DeviceBusy,
6719 .TXTBSY => return error.FileBusy,
6720 // copy_file_range can still work but not on
6721 // this pair of file descriptors.
6722 .XDEV => return error.Unimplemented,
6723 .ISDIR => |err| errnoBug(err),
67226724 .BADF => |err| errnoBug(err),
67236725 else => |err| posix.unexpectedErrno(err),
67246726 });
......@@ -6791,7 +6793,7 @@ fn netWriteFile(
67916793 _ = header;
67926794 _ = file_reader;
67936795 _ = limit;
6794 return error.Unimplemented; // TODO
6796 @panic("TODO");
67956797}
67966798
67976799fn netWriteFileUnavailable(
......@@ -6822,7 +6824,7 @@ fn fileWriteFilePositional(
68226824 const reader_buffered = file_reader.interface.buffered();
68236825 if (reader_buffered.len >= @intFromEnum(limit)) {
68246826 const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset);
6825 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6827 file_reader.interface.toss(n -| header.len);
68266828 return n;
68276829 }
68286830 const out_fd = file.handle;
......@@ -6832,7 +6834,7 @@ fn fileWriteFilePositional(
68326834 if (size - file_reader.pos == 0) {
68336835 if (reader_buffered.len != 0) {
68346836 const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset);
6835 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6837 file_reader.interface.toss(n -| header.len);
68366838 return n;
68376839 } else {
68386840 return error.EndOfStream;
......@@ -6844,7 +6846,7 @@ fn fileWriteFilePositional(
68446846 if (@atomicLoad(UseCopyFileRange, &t.use_copy_file_range, .monotonic) == .disabled) break :cfr;
68456847 if (header.len != 0 or reader_buffered.len != 0) {
68466848 const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset);
6847 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6849 file_reader.interface.toss(n -| header.len);
68486850 return n;
68496851 }
68506852 var off_in: i64 = undefined;
......@@ -6855,7 +6857,7 @@ fn fileWriteFilePositional(
68556857 break :p &off_in;
68566858 },
68576859 .streaming => null,
6858 .failure => return error.WriteFailed,
6860 .failure => return error.ReadFailed,
68596861 };
68606862 var off_out: i64 = @intCast(offset);
68616863 const current_thread = Thread.getCurrent(t);
......@@ -6886,15 +6888,17 @@ fn fileWriteFilePositional(
68866888 assert(error.Unexpected == switch (e) {
68876889 .FBIG => return error.FileTooBig,
68886890 .IO => return error.InputOutput,
6889 .ISDIR => return error.IsDir,
68906891 .NOMEM => return error.SystemResources,
68916892 .NOSPC => return error.NoSpaceLeft,
68926893 .OVERFLOW => return error.Unseekable,
68936894 .NXIO => return error.Unseekable,
68946895 .SPIPE => return error.Unseekable,
68956896 .PERM => return error.PermissionDenied,
6896 .TXTBSY => return error.SwapFile,
6897 .XDEV => return error.NotSameFileSystem,
6897 .TXTBSY => return error.FileBusy,
6898 // copy_file_range can still work but not on
6899 // this pair of file descriptors.
6900 .XDEV => return error.Unimplemented,
6901 .ISDIR => |err| errnoBug(err),
68986902 .BADF => |err| errnoBug(err),
68996903 else => |err| posix.unexpectedErrno(err),
69006904 });
......@@ -6962,7 +6966,7 @@ fn fileWriteFilePositional(
69626966 const size = file_reader.getSize() catch break :fcf;
69636967 if (header.len != 0 or reader_buffered.len != 0) {
69646968 const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset);
6965 file_reader.seekBy(n -| header.len) catch return error.ReadFailed;
6969 file_reader.interface.toss(n -| header.len);
69666970 return n;
69676971 }
69686972 const current_thread = Thread.getCurrent(t);
lib/std/Io/net.zig+3-1
......@@ -1290,7 +1290,9 @@ pub const Stream = struct {
12901290 SocketNotBound,
12911291 } || Io.UnexpectedError || Io.Cancelable;
12921292
1293 pub const WriteFileError = error{} || Io.Cancelable || Io.UnexpectedError;
1293 pub const WriteFileError = error{
1294 NetworkDown,
1295 } || Io.Cancelable || Io.UnexpectedError;
12941296
12951297 pub fn init(stream: Stream, io: Io, buffer: []u8) Writer {
12961298 return .{
lib/std/fs/test.zig+6-6
......@@ -844,7 +844,7 @@ test "directory operations on files" {
844844
845845 try testing.expectError(error.PathAlreadyExists, ctx.dir.makeDir(io, test_file_name, .default_dir));
846846 try testing.expectError(error.NotDir, ctx.dir.openDir(io, test_file_name, .{}));
847 try testing.expectError(error.NotDir, ctx.dir.deleteDir(test_file_name));
847 try testing.expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name));
848848
849849 if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) {
850850 try testing.expectError(error.PathAlreadyExists, fs.makeDirAbsolute(test_file_name));
......@@ -934,16 +934,16 @@ test "deleteDir" {
934934 const test_file_path = try ctx.transformPath("test_dir" ++ fs.path.sep_str ++ "test_file");
935935
936936 // deleting a non-existent directory
937 try testing.expectError(error.FileNotFound, ctx.dir.deleteDir(test_dir_path));
937 try testing.expectError(error.FileNotFound, ctx.dir.deleteDir(io, test_dir_path));
938938
939939 // deleting a non-empty directory
940940 try ctx.dir.makeDir(io, test_dir_path, .default_dir);
941941 try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" });
942 try testing.expectError(error.DirNotEmpty, ctx.dir.deleteDir(test_dir_path));
942 try testing.expectError(error.DirNotEmpty, ctx.dir.deleteDir(io, test_dir_path));
943943
944944 // deleting an empty directory
945945 try ctx.dir.deleteFile(io, test_file_path);
946 try ctx.dir.deleteDir(test_dir_path);
946 try ctx.dir.deleteDir(io, test_dir_path);
947947 }
948948 }.impl);
949949}
......@@ -2062,7 +2062,7 @@ test "'.' and '..' in Io.Dir functions" {
20622062 const prev_status = try dir.updateFile(io, file_path, dir, update_path, .{});
20632063 try testing.expectEqual(Io.Dir.PrevStatus.stale, prev_status);
20642064
2065 try ctx.dir.deleteDir(subdir_path);
2065 try ctx.dir.deleteDir(io, subdir_path);
20662066 }
20672067 }.impl);
20682068}
......@@ -2174,7 +2174,7 @@ test "invalid UTF-8/WTF-8 paths" {
21742174
21752175 try testing.expectError(expected_err, ctx.dir.deleteFile(invalid_path));
21762176
2177 try testing.expectError(expected_err, ctx.dir.deleteDir(invalid_path));
2177 try testing.expectError(expected_err, ctx.dir.deleteDir(io, invalid_path));
21782178
21792179 try testing.expectError(expected_err, ctx.dir.rename(invalid_path, ctx.dir, invalid_path, io));
21802180
src/Package/Fetch.zig+2-2
......@@ -578,7 +578,7 @@ fn runResource(
578578 };
579579 // Remove temporary directory root if not already renamed to global cache.
580580 if (!std.mem.eql(u8, package_sub_path, tmp_dir_sub_path)) {
581 cache_root.handle.deleteDir(tmp_dir_sub_path) catch {};
581 cache_root.handle.deleteDir(io, tmp_dir_sub_path) catch {};
582582 }
583583
584584 // Validate the computed hash against the expected hash. If invalid, this
......@@ -1593,7 +1593,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
15931593 var i: usize = 0;
15941594 while (i < sus_dirs.count()) : (i += 1) {
15951595 const sus_dir = sus_dirs.keys()[i];
1596 root_dir.deleteDir(sus_dir) catch |err| switch (err) {
1596 root_dir.deleteDir(io, sus_dir) catch |err| switch (err) {
15971597 error.DirNotEmpty => continue,
15981598 error.FileNotFound => continue,
15991599 else => |e| {