authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-05 15:52:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-06 12:15:05-07:00
loge73170f9725c530befc688dd40053022072f5058
tree89893ba2d5df1d0db3ea7cadbea06c07a74da186
parentcb012490eeae618b42361990872b9001e5672be1

std: fix WASI regressions

This branch largely reverts 58f961f4cb9875bbce3070969438ecf08f392c9f. I would like to revisit the proposal to modify the standard library in this way and think more carefully about it before adding isAbsolute() checks everywhere.

5 files changed, 32 insertions(+), 52 deletions(-)

lib/std/fs.zig+8-15
......@@ -1488,19 +1488,7 @@ pub const Dir = struct {
14881488 /// See also `Dir.realpathZ`, `Dir.realpathW`, and `Dir.realpathAlloc`.
14891489 pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) ![]u8 {
14901490 if (builtin.os.tag == .wasi) {
1491 if (self.fd == os.wasi.AT.FDCWD or path.isAbsolute(pathname)) {
1492 var buffer: [MAX_PATH_BYTES]u8 = undefined;
1493 const out_path = try os.realpath(pathname, &buffer);
1494 if (out_path.len > out_buffer.len) {
1495 return error.NameTooLong;
1496 }
1497 mem.copy(u8, out_buffer, out_path);
1498 return out_buffer[0..out_path.len];
1499 } else {
1500 // Unfortunately, we have no ability to look up the path for an fd_t
1501 // on WASI, so we have to give up here.
1502 return error.InvalidHandle;
1503 }
1491 @compileError("realpath is not available on WASI");
15041492 }
15051493 if (builtin.os.tag == .windows) {
15061494 const pathname_w = try os.windows.sliceToPrefixedFileW(pathname);
......@@ -2652,8 +2640,13 @@ pub const Dir = struct {
26522640pub fn cwd() Dir {
26532641 if (builtin.os.tag == .windows) {
26542642 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
2655 } else if (builtin.os.tag == .wasi and @hasDecl(root, "wasi_cwd")) {
2656 return root.wasi_cwd();
2643 } else if (builtin.os.tag == .wasi) {
2644 if (@hasDecl(root, "wasi_cwd")) {
2645 return root.wasi_cwd();
2646 } else {
2647 // Expect the first preopen to be current working directory.
2648 return .{ .fd = 3 };
2649 }
26572650 } else {
26582651 return Dir{ .fd = os.AT.FDCWD };
26592652 }
lib/std/fs/test.zig+5-15
......@@ -48,8 +48,7 @@ fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !vo
4848}
4949
5050test "accessAbsolute" {
51 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
52 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
51 if (builtin.os.tag == .wasi) return error.SkipZigTest;
5352
5453 var tmp = tmpDir(.{});
5554 defer tmp.cleanup();
......@@ -67,8 +66,7 @@ test "accessAbsolute" {
6766}
6867
6968test "openDirAbsolute" {
70 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
71 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
69 if (builtin.os.tag == .wasi) return error.SkipZigTest;
7270
7371 var tmp = tmpDir(.{});
7472 defer tmp.cleanup();
......@@ -104,8 +102,7 @@ test "openDir cwd parent .." {
104102}
105103
106104test "readLinkAbsolute" {
107 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
108 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
105 if (builtin.os.tag == .wasi) return error.SkipZigTest;
109106
110107 var tmp = tmpDir(.{});
111108 defer tmp.cleanup();
......@@ -187,8 +184,6 @@ test "Dir.Iterator" {
187184}
188185
189186test "Dir.Iterator many entries" {
190 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
191
192187 var tmp_dir = tmpIterableDir(.{});
193188 defer tmp_dir.cleanup();
194189
......@@ -638,8 +633,7 @@ test "rename" {
638633}
639634
640635test "renameAbsolute" {
641 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
642 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
636 if (builtin.os.tag == .wasi) return error.SkipZigTest;
643637
644638 var tmp_dir = tmpDir(.{});
645639 defer tmp_dir.cleanup();
......@@ -1149,7 +1143,6 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" {
11491143
11501144test "walker" {
11511145 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
1152 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
11531146
11541147 var tmp = tmpIterableDir(.{});
11551148 defer tmp.cleanup();
......@@ -1203,7 +1196,6 @@ test "walker" {
12031196
12041197test "walker without fully iterating" {
12051198 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
1206 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
12071199
12081200 var tmp = tmpIterableDir(.{});
12091201 defer tmp.cleanup();
......@@ -1227,7 +1219,6 @@ test "walker without fully iterating" {
12271219
12281220test ". and .. in fs.Dir functions" {
12291221 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
1230 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
12311222
12321223 var tmp = tmpDir(.{});
12331224 defer tmp.cleanup();
......@@ -1255,8 +1246,7 @@ test ". and .. in fs.Dir functions" {
12551246}
12561247
12571248test ". and .. in absolute functions" {
1258 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
1259 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
1249 if (builtin.os.tag == .wasi) return error.SkipZigTest;
12601250
12611251 var tmp = tmpDir(.{});
12621252 defer tmp.cleanup();
lib/std/os.zig+2-1
......@@ -2032,7 +2032,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin
20322032 if (builtin.os.tag == .windows) {
20332033 @compileError("symlink is not supported on Windows; use std.os.windows.CreateSymbolicLink instead");
20342034 } else if (builtin.os.tag == .wasi and !builtin.link_libc) {
2035 return symlink(mem.sliceTo(target_path, 0), mem.sliceTo(sym_link_path, 0));
2035 return symlinkatZ(target_path, fs.cwd().fd, sym_link_path);
20362036 }
20372037 switch (errno(system.symlink(target_path, sym_link_path))) {
20382038 .SUCCESS => return,
......@@ -2078,6 +2078,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
20782078 .SUCCESS => {},
20792079 .FAULT => unreachable,
20802080 .INVAL => unreachable,
2081 .BADF => unreachable,
20812082 .ACCES => return error.AccessDenied,
20822083 .PERM => return error.AccessDenied,
20832084 .DQUOT => return error.DiskQuota,
lib/std/os/test.zig+10-20
......@@ -22,8 +22,7 @@ const Dir = std.fs.Dir;
2222const ArenaAllocator = std.heap.ArenaAllocator;
2323
2424test "chdir smoke test" {
25 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
26 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/preopens/cwd");
25 if (native_os == .wasi) return error.SkipZigTest;
2726
2827 // Get current working directory path
2928 var old_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined;
......@@ -75,8 +74,7 @@ test "chdir smoke test" {
7574}
7675
7776test "open smoke test" {
78 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
79 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
77 if (native_os == .wasi) return error.SkipZigTest;
8078
8179 // TODO verify file attributes using `fstat`
8280
......@@ -131,7 +129,6 @@ test "open smoke test" {
131129
132130test "openat smoke test" {
133131 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
134 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
135132
136133 // TODO verify file attributes using `fstatat`
137134
......@@ -168,7 +165,6 @@ test "openat smoke test" {
168165
169166test "symlink with relative paths" {
170167 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
171 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
172168
173169 const cwd = fs.cwd();
174170 cwd.deleteFile("file.txt") catch {};
......@@ -219,15 +215,10 @@ fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {
219215}
220216
221217test "link with relative paths" {
218 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
219
222220 switch (native_os) {
223 .wasi => {
224 if (builtin.link_libc) {
225 return error.SkipZigTest;
226 } else {
227 try os.initPreopensWasi(std.heap.page_allocator, "/");
228 }
229 },
230 .linux, .solaris => {},
221 .wasi, .linux, .solaris => {},
231222 else => return error.SkipZigTest,
232223 }
233224 var cwd = fs.cwd();
......@@ -263,9 +254,10 @@ test "link with relative paths" {
263254}
264255
265256test "linkat with different directories" {
257 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
258
266259 switch (native_os) {
267 .wasi => if (!builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/"),
268 .linux, .solaris => {},
260 .wasi, .linux, .solaris => {},
269261 else => return error.SkipZigTest,
270262 }
271263 var cwd = fs.cwd();
......@@ -950,8 +942,7 @@ test "POSIX file locking with fcntl" {
950942}
951943
952944test "rename smoke test" {
953 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
954 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
945 if (native_os == .wasi) return error.SkipZigTest;
955946
956947 var tmp = tmpDir(.{});
957948 defer tmp.cleanup();
......@@ -1007,8 +998,7 @@ test "rename smoke test" {
1007998}
1008999
10091000test "access smoke test" {
1010 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
1011 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
1001 if (native_os == .wasi) return error.SkipZigTest;
10121002
10131003 var tmp = tmpDir(.{});
10141004 defer tmp.cleanup();
lib/std/os/wasi.zig+7-1
......@@ -1,6 +1,7 @@
11// wasi_snapshot_preview1 spec available (in witx format) here:
22// * typenames -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx
33// * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx
4const builtin = @import("builtin");
45const std = @import("std");
56const assert = std.debug.assert;
67
......@@ -157,7 +158,12 @@ pub const IOV_MAX = 1024;
157158
158159pub const AT = struct {
159160 pub const REMOVEDIR: u32 = 0x4;
160 pub const FDCWD: fd_t = -2;
161 /// When linking libc, we follow their convention and use -2 for current working directory.
162 /// However, without libc, Zig does a different convention: it assumes the
163 /// current working directory is the first preopen. This behavior can be
164 /// overridden with a public function called `wasi_cwd` in the root source
165 /// file.
166 pub const FDCWD: fd_t = if (builtin.link_libc) -2 else 3;
161167};
162168
163169// As defined in the wasi_snapshot_preview1 spec file: