zig/lib/std/fs/wasi.zig
Andrew Kelley d5312d53a0 WASI: remove absolute path emulation from std lib
Instead of checking for absolute paths and current working directories
in various file system operations, there is one simple solution: allow
overriding `std.fs.cwd` on WASI.

os.realpath is back to causing a compile error when used on WASI. This
caused a compile error in the Sema handling of `@src()`. The compiler
should never call realpath, so the commit that made this change is
reverted (95ab942184427e7c9b840d71f4d093931e3e48fb). If this breaks
debug info, a different strategy is needed to solve it other than using
realpath.

I also removed the preopens code and replaced it with something much
simpler. There is no longer any global state in the standard library.

Additionally-
 * os.openat no longer does an unnecessary fstat on WASI when O.WRONLY
   is not provided.
 * os.chdir is back to causing a compile error on WASI.
2022-12-06 12:15:04 -07:00

57 lines
1.8 KiB
Zig

const std = @import("std");
const builtin = @import("builtin");
const os = std.os;
const mem = std.mem;
const math = std.math;
const fs = std.fs;
const assert = std.debug.assert;
const Allocator = mem.Allocator;
const wasi = std.os.wasi;
const fd_t = wasi.fd_t;
const prestat_t = wasi.prestat_t;
pub const Preopens = struct {
// Indexed by file descriptor number.
names: []const []const u8,
pub fn find(p: Preopens, name: []const u8) ?os.fd_t {
for (p.names) |elem_name, i| {
if (mem.eql(u8, elem_name, name)) {
return @intCast(os.fd_t, i);
}
}
return null;
}
};
pub fn preopensAlloc(gpa: Allocator) Allocator.Error!Preopens {
var names: std.ArrayListUnmanaged([]const u8) = .{};
defer names.deinit(gpa);
try names.ensureUnusedCapacity(gpa, 3);
names.appendAssumeCapacity("stdin"); // 0
names.appendAssumeCapacity("stdout"); // 1
names.appendAssumeCapacity("stderr"); // 2
while (true) {
const fd = @intCast(wasi.fd_t, names.items.len);
var prestat: prestat_t = undefined;
switch (wasi.fd_prestat_get(fd, &prestat)) {
.SUCCESS => {},
.OPNOTSUPP, .BADF => return .{ .names = names.toOwnedSlice(gpa) },
else => @panic("fd_prestat_get: unexpected error"),
}
try names.ensureUnusedCapacity(gpa, 1);
// This length does not include a null byte. Let's keep it this way to
// gently encourage WASI implementations to behave properly.
const name_len = prestat.u.dir.pr_name_len;
const name = try gpa.alloc(u8, name_len);
errdefer gpa.free(name);
switch (wasi.fd_prestat_dir_name(fd, name.ptr, name.len)) {
.SUCCESS => {},
else => @panic("fd_prestat_dir_name: unexpected error"),
}
names.appendAssumeCapacity(name);
}
}