authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-17 00:31:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:50-07:00
logda6b959f647f62aeaf96f380ad2828c16142f23f
tree29234a99ff64a032249fb29e94c2ff830ee682b4
parente87ceb76c242cf991f85c9aa6619f5faf4059af3

std.Io.Threaded: implement dirOpenFile for WASI


3 files changed, 77 insertions(+), 32 deletions(-)

lib/std/Io/Threaded.zig+75-3
......@@ -193,7 +193,11 @@ pub fn io(t: *Threaded) Io {
193193 .wasi => dirCreateFileWasi,
194194 else => dirCreateFilePosix,
195195 },
196 .dirOpenFile = dirOpenFile,
196 .dirOpenFile = switch (builtin.os.tag) {
197 .windows => @panic("TODO"),
198 .wasi => dirOpenFileWasi,
199 else => dirOpenFilePosix,
200 },
197201 .fileClose = fileClose,
198202 .fileWriteStreaming = fileWriteStreaming,
199203 .fileWritePositional = fileWritePositional,
......@@ -1451,7 +1455,7 @@ fn dirCreateFileWasi(
14511455 }
14521456}
14531457
1454fn dirOpenFile(
1458fn dirOpenFilePosix(
14551459 userdata: ?*anyopaque,
14561460 dir: Io.Dir,
14571461 sub_path: []const u8,
......@@ -1584,6 +1588,74 @@ fn dirOpenFile(
15841588 return .{ .handle = fd };
15851589}
15861590
1591fn dirOpenFileWasi(
1592 userdata: ?*anyopaque,
1593 dir: Io.Dir,
1594 sub_path: []const u8,
1595 flags: Io.File.OpenFlags,
1596) Io.File.OpenError!Io.File {
1597 if (builtin.link_libc) return dirOpenFilePosix(userdata, dir, sub_path, flags);
1598 const t: *Threaded = @ptrCast(@alignCast(userdata));
1599 const wasi = std.os.wasi;
1600 var base: std.os.wasi.rights_t = .{};
1601 // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or FD_WRITE
1602 // is also set.
1603 if (flags.isRead()) {
1604 base.FD_READ = true;
1605 base.FD_TELL = true;
1606 base.FD_SEEK = true;
1607 base.FD_FILESTAT_GET = true;
1608 base.POLL_FD_READWRITE = true;
1609 }
1610 if (flags.isWrite()) {
1611 base.FD_WRITE = true;
1612 base.FD_TELL = true;
1613 base.FD_SEEK = true;
1614 base.FD_DATASYNC = true;
1615 base.FD_FDSTAT_SET_FLAGS = true;
1616 base.FD_SYNC = true;
1617 base.FD_ALLOCATE = true;
1618 base.FD_ADVISE = true;
1619 base.FD_FILESTAT_SET_TIMES = true;
1620 base.FD_FILESTAT_SET_SIZE = true;
1621 base.POLL_FD_READWRITE = true;
1622 }
1623 const lookup_flags: wasi.lookupflags_t = .{};
1624 const oflags: wasi.oflags_t = .{};
1625 const inheriting: wasi.rights_t = .{};
1626 const fdflags: wasi.fdflags_t = .{};
1627 var fd: posix.fd_t = undefined;
1628 while (true) {
1629 try t.checkCancel();
1630 switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, inheriting, fdflags, &fd)) {
1631 .SUCCESS => return .{ .handle = fd },
1632 .INTR => continue,
1633 .CANCELED => return error.Canceled,
1634
1635 .FAULT => |err| return errnoBug(err),
1636 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
1637 .ACCES => return error.AccessDenied,
1638 .FBIG => return error.FileTooBig,
1639 .OVERFLOW => return error.FileTooBig,
1640 .ISDIR => return error.IsDir,
1641 .LOOP => return error.SymLinkLoop,
1642 .MFILE => return error.ProcessFdQuotaExceeded,
1643 .NFILE => return error.SystemFdQuotaExceeded,
1644 .NODEV => return error.NoDevice,
1645 .NOENT => return error.FileNotFound,
1646 .NOMEM => return error.SystemResources,
1647 .NOTDIR => return error.NotDir,
1648 .PERM => return error.PermissionDenied,
1649 .BUSY => return error.DeviceBusy,
1650 .NOTCAPABLE => return error.AccessDenied,
1651 .NAMETOOLONG => return error.NameTooLong,
1652 .INVAL => return error.BadPathName,
1653 .ILSEQ => return error.BadPathName,
1654 else => |err| return posix.unexpectedErrno(err),
1655 }
1656 }
1657}
1658
15871659fn fileClose(userdata: ?*anyopaque, file: Io.File) void {
15881660 const t: *Threaded = @ptrCast(@alignCast(userdata));
15891661 _ = t;
......@@ -3319,7 +3391,7 @@ fn clockToPosix(clock: Io.Clock) posix.clockid_t {
33193391
33203392fn clockToWasi(clock: Io.Clock) std.os.wasi.clockid_t {
33213393 return switch (clock) {
3322 .realtime => .REALTIME,
3394 .real => .REALTIME,
33233395 .awake => .MONOTONIC,
33243396 .boot => .MONOTONIC,
33253397 .cpu_process => .PROCESS_CPUTIME_ID,
lib/std/fs/Dir.zig-27
......@@ -858,33 +858,6 @@ pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.Ope
858858 const path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path);
859859 return self.openFileW(path_w.span(), flags);
860860 }
861 if (native_os == .wasi and !builtin.link_libc) {
862 var base: std.os.wasi.rights_t = .{};
863 // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or FD_WRITE
864 // is also set.
865 if (flags.isRead()) {
866 base.FD_READ = true;
867 base.FD_TELL = true;
868 base.FD_SEEK = true;
869 base.FD_FILESTAT_GET = true;
870 base.POLL_FD_READWRITE = true;
871 }
872 if (flags.isWrite()) {
873 base.FD_WRITE = true;
874 base.FD_TELL = true;
875 base.FD_SEEK = true;
876 base.FD_DATASYNC = true;
877 base.FD_FDSTAT_SET_FLAGS = true;
878 base.FD_SYNC = true;
879 base.FD_ALLOCATE = true;
880 base.FD_ADVISE = true;
881 base.FD_FILESTAT_SET_TIMES = true;
882 base.FD_FILESTAT_SET_SIZE = true;
883 base.POLL_FD_READWRITE = true;
884 }
885 const fd = try posix.openatWasi(self.fd, sub_path, .{}, .{}, .{}, base, .{});
886 return .{ .handle = fd };
887 }
888861 var threaded: Io.Threaded = .init_single_threaded;
889862 const io = threaded.io();
890863 return .adaptFromNewApi(try Io.Dir.openFile(self.adaptToNewApi(), io, sub_path, flags));
lib/std/fs/test.zig+2-2
......@@ -1407,7 +1407,7 @@ test "setEndPos" {
14071407 try f.setEndPos(initial_size);
14081408 try testing.expectEqual(initial_size, try f.getEndPos());
14091409 try reader.seekTo(0);
1410 try testing.expectEqual(initial_size, reader.interface.readSliceShort(&buffer));
1410 try testing.expectEqual(initial_size, try reader.interface.readSliceShort(&buffer));
14111411 try testing.expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]);
14121412 }
14131413
......@@ -1416,7 +1416,7 @@ test "setEndPos" {
14161416 try f.setEndPos(larger);
14171417 try testing.expectEqual(larger, try f.getEndPos());
14181418 try reader.seekTo(0);
1419 try testing.expectEqual(larger, reader.interface.readSliceShort(&buffer));
1419 try testing.expectEqual(larger, try reader.interface.readSliceShort(&buffer));
14201420 try testing.expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]);
14211421 }
14221422