authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-28 06:33:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:52-07:00
logb39f3d294da3ce9075bbc08651965615839219f2
tree89096136184f6d491bba689ba559541a8750745b
parent4114392369c28a2455a508e4da67d945ebad2b44

std.Io.Threaded: implement dirMakeOpenPath for WASI

and fix error code when file operation occurs on director handle

5 files changed, 40 insertions(+), 37 deletions(-)

lib/std/Io.zig+1-1
...@@ -684,7 +684,7 @@ pub const VTable = struct {...@@ -684,7 +684,7 @@ pub const VTable = struct {
684 fileWriteStreaming: *const fn (?*anyopaque, File, buffer: [][]const u8) File.WriteStreamingError!usize,684 fileWriteStreaming: *const fn (?*anyopaque, File, buffer: [][]const u8) File.WriteStreamingError!usize,
685 fileWritePositional: *const fn (?*anyopaque, File, buffer: [][]const u8, offset: u64) File.WritePositionalError!usize,685 fileWritePositional: *const fn (?*anyopaque, File, buffer: [][]const u8, offset: u64) File.WritePositionalError!usize,
686 /// Returns 0 on end of stream.686 /// Returns 0 on end of stream.
687 fileReadStreaming: *const fn (?*anyopaque, File, data: [][]u8) File.ReadStreamingError!usize,687 fileReadStreaming: *const fn (?*anyopaque, File, data: [][]u8) File.Reader.Error!usize,
688 /// Returns 0 on end of stream.688 /// Returns 0 on end of stream.
689 fileReadPositional: *const fn (?*anyopaque, File, data: [][]u8, offset: u64) File.ReadPositionalError!usize,689 fileReadPositional: *const fn (?*anyopaque, File, data: [][]u8, offset: u64) File.ReadPositionalError!usize,
690 fileSeekBy: *const fn (?*anyopaque, File, relative_offset: i64) File.SeekError!void,690 fileSeekBy: *const fn (?*anyopaque, File, relative_offset: i64) File.SeekError!void,
lib/std/Io/File.zig+24-24
...@@ -213,29 +213,7 @@ pub fn openSelfExe(io: Io, flags: OpenFlags) OpenSelfExeError!File {...@@ -213,29 +213,7 @@ pub fn openSelfExe(io: Io, flags: OpenFlags) OpenSelfExeError!File {
213 return io.vtable.openSelfExe(io.userdata, flags);213 return io.vtable.openSelfExe(io.userdata, flags);
214}214}
215215
216pub const ReadStreamingError = error{216pub const ReadPositionalError = Reader.Error || error{Unseekable};
217 InputOutput,
218 SystemResources,
219 IsDir,
220 BrokenPipe,
221 ConnectionResetByPeer,
222 Timeout,
223 NotOpenForReading,
224 SocketUnconnected,
225 /// This error occurs when no global event loop is configured,
226 /// and reading from the file descriptor would block.
227 WouldBlock,
228 /// In WASI, this error occurs when the file descriptor does
229 /// not hold the required rights to read from it.
230 AccessDenied,
231 /// This error occurs in Linux if the process to be read from
232 /// no longer exists.
233 ProcessNotFound,
234 /// Unable to read file due to lock.
235 LockViolation,
236} || Io.Cancelable || Io.UnexpectedError;
237
238pub const ReadPositionalError = ReadStreamingError || error{Unseekable};
239217
240pub fn readPositional(file: File, io: Io, buffer: []u8, offset: u64) ReadPositionalError!usize {218pub fn readPositional(file: File, io: Io, buffer: []u8, offset: u64) ReadPositionalError!usize {
241 return io.vtable.fileReadPositional(io.userdata, file, buffer, offset);219 return io.vtable.fileReadPositional(io.userdata, file, buffer, offset);
...@@ -301,7 +279,29 @@ pub const Reader = struct {...@@ -301,7 +279,29 @@ pub const Reader = struct {
301 seek_err: ?Reader.SeekError = null,279 seek_err: ?Reader.SeekError = null,
302 interface: Io.Reader,280 interface: Io.Reader,
303281
304 pub const Error = std.posix.ReadError || Io.Cancelable;282 pub const Error = error{
283 InputOutput,
284 SystemResources,
285 IsDir,
286 BrokenPipe,
287 ConnectionResetByPeer,
288 Timeout,
289 /// In WASI, EBADF is mapped to this error because it is returned when
290 /// trying to read a directory file descriptor as if it were a file.
291 NotOpenForReading,
292 SocketUnconnected,
293 /// This error occurs when no global event loop is configured,
294 /// and reading from the file descriptor would block.
295 WouldBlock,
296 /// In WASI, this error occurs when the file descriptor does
297 /// not hold the required rights to read from it.
298 AccessDenied,
299 /// This error occurs in Linux if the process to be read from
300 /// no longer exists.
301 ProcessNotFound,
302 /// Unable to read file due to lock.
303 LockViolation,
304 } || Io.Cancelable || Io.UnexpectedError;
305305
306 pub const SizeError = std.os.windows.GetFileSizeError || StatError || error{306 pub const SizeError = std.os.windows.GetFileSizeError || StatError || error{
307 /// Occurs if, for example, the file handle is a network socket and therefore does not have a size.307 /// Occurs if, for example, the file handle is a network socket and therefore does not have a size.
lib/std/Io/Kqueue.zig+1-1
...@@ -1226,7 +1226,7 @@ fn fileWritePositional(userdata: ?*anyopaque, file: File, buffer: [][]const u8,...@@ -1226,7 +1226,7 @@ fn fileWritePositional(userdata: ?*anyopaque, file: File, buffer: [][]const u8,
1226 _ = offset;1226 _ = offset;
1227 @panic("TODO");1227 @panic("TODO");
1228}1228}
1229fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: [][]u8) File.ReadStreamingError!usize {1229fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: [][]u8) File.Reader.Error!usize {
1230 const k: *Kqueue = @ptrCast(@alignCast(userdata));1230 const k: *Kqueue = @ptrCast(@alignCast(userdata));
1231 _ = k;1231 _ = k;
1232 _ = file;1232 _ = file;
lib/std/Io/Threaded.zig+13-10
...@@ -1219,14 +1219,17 @@ fn dirMakeOpenPathWasi(...@@ -1219,14 +1219,17 @@ fn dirMakeOpenPathWasi(
1219 userdata: ?*anyopaque,1219 userdata: ?*anyopaque,
1220 dir: Io.Dir,1220 dir: Io.Dir,
1221 sub_path: []const u8,1221 sub_path: []const u8,
1222 mode: Io.Dir.OpenOptions,1222 options: Io.Dir.OpenOptions,
1223) Io.Dir.MakeOpenPathError!Io.Dir {1223) Io.Dir.MakeOpenPathError!Io.Dir {
1224 const t: *Threaded = @ptrCast(@alignCast(userdata));1224 const t: *Threaded = @ptrCast(@alignCast(userdata));
1225 _ = t;1225 const t_io = ioBasic(t);
1226 _ = dir;1226 return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) {
1227 _ = sub_path;1227 error.FileNotFound => {
1228 _ = mode;1228 try dir.makePath(t_io, sub_path);
1229 @panic("TODO implement dirMakeOpenPathWasi");1229 return dirOpenDirWasi(t, dir, sub_path, options);
1230 },
1231 else => |e| return e,
1232 };
1230}1233}
12311234
1232fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat {1235fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat {
...@@ -2498,7 +2501,7 @@ const fileReadStreaming = switch (native_os) {...@@ -2498,7 +2501,7 @@ const fileReadStreaming = switch (native_os) {
2498 else => fileReadStreamingPosix,2501 else => fileReadStreamingPosix,
2499};2502};
25002503
2501fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {2504fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.Reader.Error!usize {
2502 const t: *Threaded = @ptrCast(@alignCast(userdata));2505 const t: *Threaded = @ptrCast(@alignCast(userdata));
25032506
2504 var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;2507 var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;
...@@ -2523,7 +2526,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io...@@ -2523,7 +2526,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io
25232526
2524 .INVAL => |err| return errnoBug(err),2527 .INVAL => |err| return errnoBug(err),
2525 .FAULT => |err| return errnoBug(err),2528 .FAULT => |err| return errnoBug(err),
2526 .BADF => |err| return errnoBug(err), // File descriptor used after closed.2529 .BADF => return error.NotOpenForReading, // File operation on directory.
2527 .IO => return error.InputOutput,2530 .IO => return error.InputOutput,
2528 .ISDIR => return error.IsDir,2531 .ISDIR => return error.IsDir,
2529 .NOBUFS => return error.SystemResources,2532 .NOBUFS => return error.SystemResources,
...@@ -2561,7 +2564,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io...@@ -2561,7 +2564,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io
2561 }2564 }
2562}2565}
25632566
2564fn fileReadStreamingWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {2567fn fileReadStreamingWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.Reader.Error!usize {
2565 const t: *Threaded = @ptrCast(@alignCast(userdata));2568 const t: *Threaded = @ptrCast(@alignCast(userdata));
25662569
2567 const DWORD = windows.DWORD;2570 const DWORD = windows.DWORD;
...@@ -2617,7 +2620,7 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o...@@ -2617,7 +2620,7 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o
2617 .INVAL => |err| return errnoBug(err),2620 .INVAL => |err| return errnoBug(err),
2618 .FAULT => |err| return errnoBug(err),2621 .FAULT => |err| return errnoBug(err),
2619 .AGAIN => |err| return errnoBug(err),2622 .AGAIN => |err| return errnoBug(err),
2620 .BADF => |err| return errnoBug(err), // File descriptor used after closed.2623 .BADF => return error.NotOpenForReading, // File operation on directory.
2621 .IO => return error.InputOutput,2624 .IO => return error.InputOutput,
2622 .ISDIR => return error.IsDir,2625 .ISDIR => return error.IsDir,
2623 .NOBUFS => return error.SystemResources,2626 .NOBUFS => return error.SystemResources,
lib/std/posix.zig+1-1
...@@ -814,7 +814,7 @@ pub fn exit(status: u8) noreturn {...@@ -814,7 +814,7 @@ pub fn exit(status: u8) noreturn {
814 system.exit(status);814 system.exit(status);
815}815}
816816
817pub const ReadError = std.Io.File.ReadStreamingError;817pub const ReadError = std.Io.File.Reader.Error;
818818
819/// Returns the number of bytes that were read, which can be less than819/// Returns the number of bytes that were read, which can be less than
820/// buf.len. If 0 bytes were read, that means EOF.820/// buf.len. If 0 bytes were read, that means EOF.