Commit d4215ffaa0
Changed files (3)
lib
std
lib/std/fs/Dir.zig
@@ -938,31 +938,6 @@ pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File
const path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path);
return self.createFileW(path_w.span(), flags);
}
- if (native_os == .wasi) {
- return .{
- .handle = try posix.openatWasi(self.fd, sub_path, .{}, .{
- .CREAT = true,
- .TRUNC = flags.truncate,
- .EXCL = flags.exclusive,
- }, .{}, .{
- .FD_READ = flags.read,
- .FD_WRITE = true,
- .FD_DATASYNC = true,
- .FD_SEEK = true,
- .FD_TELL = true,
- .FD_FDSTAT_SET_FLAGS = true,
- .FD_SYNC = true,
- .FD_ALLOCATE = true,
- .FD_ADVISE = true,
- .FD_FILESTAT_SET_TIMES = true,
- .FD_FILESTAT_SET_SIZE = true,
- .FD_FILESTAT_GET = true,
- // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or
- // FD_WRITE is also set.
- .POLL_FD_READWRITE = true,
- }, .{}),
- };
- }
var threaded: Io.Threaded = .init_single_threaded;
const io = threaded.io();
const new_file = try Io.Dir.createFile(self.adaptToNewApi(), io, sub_path, flags);
lib/std/Io/Threaded.zig
@@ -190,7 +190,7 @@ pub fn io(t: *Threaded) Io {
},
.dirCreateFile = switch (builtin.os.tag) {
.windows => @panic("TODO"),
- .wasi => @panic("TODO"),
+ .wasi => dirCreateFileWasi,
else => dirCreateFilePosix,
},
.dirOpenFile = dirOpenFile,
@@ -1378,6 +1378,74 @@ fn dirCreateFilePosix(
return .{ .handle = fd };
}
+fn dirCreateFileWasi(
+ userdata: ?*anyopaque,
+ dir: Io.Dir,
+ sub_path: []const u8,
+ flags: Io.File.CreateFlags,
+) Io.File.OpenError!Io.File {
+ const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const wasi = std.os.wasi;
+ const lookup_flags: wasi.lookupflags_t = .{};
+ const oflags: wasi.oflags_t = .{
+ .CREAT = true,
+ .TRUNC = flags.truncate,
+ .EXCL = flags.exclusive,
+ };
+ const fdflags: wasi.fdflags_t = .{};
+ const base: wasi.rights_t = .{
+ .FD_READ = flags.read,
+ .FD_WRITE = true,
+ .FD_DATASYNC = true,
+ .FD_SEEK = true,
+ .FD_TELL = true,
+ .FD_FDSTAT_SET_FLAGS = true,
+ .FD_SYNC = true,
+ .FD_ALLOCATE = true,
+ .FD_ADVISE = true,
+ .FD_FILESTAT_SET_TIMES = true,
+ .FD_FILESTAT_SET_SIZE = true,
+ .FD_FILESTAT_GET = true,
+ // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or
+ // FD_WRITE is also set.
+ .POLL_FD_READWRITE = true,
+ };
+ const inheriting: wasi.rights_t = .{};
+ var fd: posix.fd_t = undefined;
+ while (true) {
+ try t.checkCancel();
+ switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, inheriting, fdflags, &fd)) {
+ .SUCCESS => return .{ .handle = fd },
+ .INTR => continue,
+ .CANCELED => return error.Canceled,
+
+ .FAULT => |err| return errnoBug(err),
+ // Provides INVAL with a linux host on a bad path name, but NOENT on Windows
+ .INVAL => return error.BadPathName,
+ .BADF => |err| return errnoBug(err),
+ .ACCES => return error.AccessDenied,
+ .FBIG => return error.FileTooBig,
+ .OVERFLOW => return error.FileTooBig,
+ .ISDIR => return error.IsDir,
+ .LOOP => return error.SymLinkLoop,
+ .MFILE => return error.ProcessFdQuotaExceeded,
+ .NAMETOOLONG => return error.NameTooLong,
+ .NFILE => return error.SystemFdQuotaExceeded,
+ .NODEV => return error.NoDevice,
+ .NOENT => return error.FileNotFound,
+ .NOMEM => return error.SystemResources,
+ .NOSPC => return error.NoSpaceLeft,
+ .NOTDIR => return error.NotDir,
+ .PERM => return error.PermissionDenied,
+ .EXIST => return error.PathAlreadyExists,
+ .BUSY => return error.DeviceBusy,
+ .NOTCAPABLE => return error.AccessDenied,
+ .ILSEQ => return error.BadPathName,
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ }
+}
+
fn dirOpenFile(
userdata: ?*anyopaque,
dir: Io.Dir,
lib/std/posix.zig
@@ -1610,119 +1610,12 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: O, mode: mode_t) OpenE
if (native_os == .windows) {
@compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API");
} else if (native_os == .wasi and !builtin.link_libc) {
- // `mode` is ignored on WASI, which does not support unix-style file permissions
- const opts = try openOptionsFromFlagsWasi(flags);
- const fd = try openatWasi(
- dir_fd,
- file_path,
- opts.lookup_flags,
- opts.oflags,
- opts.fs_flags,
- opts.fs_rights_base,
- opts.fs_rights_inheriting,
- );
- errdefer close(fd);
-
- if (flags.write) {
- const info = try std.os.fstat_wasi(fd);
- if (info.filetype == .DIRECTORY)
- return error.IsDir;
- }
-
- return fd;
+ @compileError("use std.Io instead");
}
const file_path_c = try toPosixPath(file_path);
return openatZ(dir_fd, &file_path_c, flags, mode);
}
-/// Open and possibly create a file in WASI.
-pub fn openatWasi(
- dir_fd: fd_t,
- file_path: []const u8,
- lookup_flags: wasi.lookupflags_t,
- oflags: wasi.oflags_t,
- fdflags: wasi.fdflags_t,
- base: wasi.rights_t,
- inheriting: wasi.rights_t,
-) OpenError!fd_t {
- while (true) {
- var fd: fd_t = undefined;
- switch (wasi.path_open(dir_fd, lookup_flags, file_path.ptr, file_path.len, oflags, base, inheriting, fdflags, &fd)) {
- .SUCCESS => return fd,
- .INTR => continue,
-
- .FAULT => unreachable,
- // Provides INVAL with a linux host on a bad path name, but NOENT on Windows
- .INVAL => return error.BadPathName,
- .BADF => unreachable,
- .ACCES => return error.AccessDenied,
- .FBIG => return error.FileTooBig,
- .OVERFLOW => return error.FileTooBig,
- .ISDIR => return error.IsDir,
- .LOOP => return error.SymLinkLoop,
- .MFILE => return error.ProcessFdQuotaExceeded,
- .NAMETOOLONG => return error.NameTooLong,
- .NFILE => return error.SystemFdQuotaExceeded,
- .NODEV => return error.NoDevice,
- .NOENT => return error.FileNotFound,
- .NOMEM => return error.SystemResources,
- .NOSPC => return error.NoSpaceLeft,
- .NOTDIR => return error.NotDir,
- .PERM => return error.PermissionDenied,
- .EXIST => return error.PathAlreadyExists,
- .BUSY => return error.DeviceBusy,
- .NOTCAPABLE => return error.AccessDenied,
- .ILSEQ => return error.BadPathName,
- else => |err| return unexpectedErrno(err),
- }
- }
-}
-
-/// A struct to contain all lookup/rights flags accepted by `wasi.path_open`
-const WasiOpenOptions = struct {
- oflags: wasi.oflags_t,
- lookup_flags: wasi.lookupflags_t,
- fs_rights_base: wasi.rights_t,
- fs_rights_inheriting: wasi.rights_t,
- fs_flags: wasi.fdflags_t,
-};
-
-/// Compute rights + flags corresponding to the provided POSIX access mode.
-fn openOptionsFromFlagsWasi(oflag: O) OpenError!WasiOpenOptions {
- const w = std.os.wasi;
-
- // Next, calculate the read/write rights to request, depending on the
- // provided POSIX access mode
- var rights: w.rights_t = .{};
- if (oflag.read) {
- rights.FD_READ = true;
- rights.FD_READDIR = true;
- }
- if (oflag.write) {
- rights.FD_DATASYNC = true;
- rights.FD_WRITE = true;
- rights.FD_ALLOCATE = true;
- rights.FD_FILESTAT_SET_SIZE = true;
- }
-
- // https://github.com/ziglang/zig/issues/18882
- const flag_bits: u32 = @bitCast(oflag);
- const oflags_int: u16 = @as(u12, @truncate(flag_bits >> 12));
- const fs_flags_int: u16 = @as(u12, @truncate(flag_bits));
-
- return .{
- // https://github.com/ziglang/zig/issues/18882
- .oflags = @bitCast(oflags_int),
- .lookup_flags = .{
- .SYMLINK_FOLLOW = !oflag.NOFOLLOW,
- },
- .fs_rights_base = rights,
- .fs_rights_inheriting = rights,
- // https://github.com/ziglang/zig/issues/18882
- .fs_flags = @bitCast(fs_flags_int),
- };
-}
-
/// Open and possibly create a file. Keeps trying if it gets interrupted.
/// `file_path` is relative to the open directory handle `dir_fd`.
/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).