feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.dirOpenFileWasi
fn dirOpenFileWasi(
userdata: ?*anyopaque,
dir: Dir,
sub_path: []const u8,
flags: Dir.OpenFileOptions,
) File.OpenError!File
File
Code
fn dirOpenFileWasi(
userdata: ?*anyopaque,
dir: Dir,
sub_path: []const u8,
flags: Dir.OpenFileOptions,
) File.OpenError!File {
if (builtin.link_libc) return dirOpenFilePosix(userdata, dir, sub_path, flags);
const t: *Threaded = @ptrCast(@alignCast(userdata));
const wasi = std.os.wasi;
var base: std.os.wasi.rights_t = .{};
// is also set.
if (flags.isRead()) {
base.FD_READ = true;
base.FD_TELL = true;
base.FD_SEEK = true;
base.FD_FILESTAT_GET = true;
base.POLL_FD_READWRITE = true;
}
if (flags.isWrite()) {
base.FD_WRITE = true;
base.FD_TELL = true;
base.FD_SEEK = true;
base.FD_DATASYNC = true;
base.FD_FDSTAT_SET_FLAGS = true;
base.FD_SYNC = true;
base.FD_ALLOCATE = true;
base.FD_ADVISE = true;
base.FD_FILESTAT_SET_TIMES = true;
base.FD_FILESTAT_SET_SIZE = true;
base.POLL_FD_READWRITE = true;
}
const lookup_flags: wasi.lookupflags_t = .{};
const oflags: wasi.oflags_t = .{};
const inheriting: wasi.rights_t = .{};
const fdflags: wasi.fdflags_t = .{};
var fd: posix.fd_t = undefined;
const syscall: Syscall = try .start();
while (true) {
switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, inheriting, fdflags, &fd)) {
.SUCCESS => {
syscall.finish();
break;
},
.INTR => {
try syscall.checkCancel();
continue;
},
else => |e| {
syscall.finish();
switch (e) {
.FAULT => |err| return errnoBug(err),
.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,
.NFILE => return error.SystemFdQuotaExceeded,
.NODEV => return error.NoDevice,
.NOENT => return error.FileNotFound,
.NOMEM => return error.SystemResources,
.NOTDIR => return error.NotDir,
.PERM => return error.PermissionDenied,
.BUSY => return error.DeviceBusy,
.NOTCAPABLE => return error.AccessDenied,
.NAMETOOLONG => return error.NameTooLong,
.INVAL => return error.BadPathName,
.ILSEQ => return error.BadPathName,
else => |err| return posix.unexpectedErrno(err),
}
},
}
}
errdefer closeFd(fd);
if (!flags.allow_directory) {
const is_dir = is_dir: {
const stat = fileStat(t, .{ .handle = fd, .flags = .{ .nonblocking = false } }) catch |err| switch (err) {
error.Streaming => break :is_dir false,
else => |e| return e,
};
break :is_dir stat.kind == .directory;
};
if (is_dir) return error.IsDir;
}
return .{
.handle = fd,
.flags = .{ .nonblocking = false },
};
}