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 {...@@ -1488,19 +1488,7 @@ pub const Dir = struct {
1488 /// See also `Dir.realpathZ`, `Dir.realpathW`, and `Dir.realpathAlloc`.1488 /// See also `Dir.realpathZ`, `Dir.realpathW`, and `Dir.realpathAlloc`.
1489 pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) ![]u8 {1489 pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) ![]u8 {
1490 if (builtin.os.tag == .wasi) {1490 if (builtin.os.tag == .wasi) {
1491 if (self.fd == os.wasi.AT.FDCWD or path.isAbsolute(pathname)) {1491 @compileError("realpath is not available on WASI");
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 }
1504 }1492 }
1505 if (builtin.os.tag == .windows) {1493 if (builtin.os.tag == .windows) {
1506 const pathname_w = try os.windows.sliceToPrefixedFileW(pathname);1494 const pathname_w = try os.windows.sliceToPrefixedFileW(pathname);
...@@ -2652,8 +2640,13 @@ pub const Dir = struct {...@@ -2652,8 +2640,13 @@ pub const Dir = struct {
2652pub fn cwd() Dir {2640pub fn cwd() Dir {
2653 if (builtin.os.tag == .windows) {2641 if (builtin.os.tag == .windows) {
2654 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };2642 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
2655 } else if (builtin.os.tag == .wasi and @hasDecl(root, "wasi_cwd")) {2643 } else if (builtin.os.tag == .wasi) {
2656 return root.wasi_cwd();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 }
2657 } else {2650 } else {
2658 return Dir{ .fd = os.AT.FDCWD };2651 return Dir{ .fd = os.AT.FDCWD };
2659 }2652 }
lib/std/fs/test.zig+5-15
...@@ -48,8 +48,7 @@ fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !vo...@@ -48,8 +48,7 @@ fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !vo
48}48}
4949
50test "accessAbsolute" {50test "accessAbsolute" {
51 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;51 if (builtin.os.tag == .wasi) return error.SkipZigTest;
52 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
5352
54 var tmp = tmpDir(.{});53 var tmp = tmpDir(.{});
55 defer tmp.cleanup();54 defer tmp.cleanup();
...@@ -67,8 +66,7 @@ test "accessAbsolute" {...@@ -67,8 +66,7 @@ test "accessAbsolute" {
67}66}
6867
69test "openDirAbsolute" {68test "openDirAbsolute" {
70 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;69 if (builtin.os.tag == .wasi) return error.SkipZigTest;
71 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
7270
73 var tmp = tmpDir(.{});71 var tmp = tmpDir(.{});
74 defer tmp.cleanup();72 defer tmp.cleanup();
...@@ -104,8 +102,7 @@ test "openDir cwd parent .." {...@@ -104,8 +102,7 @@ test "openDir cwd parent .." {
104}102}
105103
106test "readLinkAbsolute" {104test "readLinkAbsolute" {
107 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;105 if (builtin.os.tag == .wasi) return error.SkipZigTest;
108 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
109106
110 var tmp = tmpDir(.{});107 var tmp = tmpDir(.{});
111 defer tmp.cleanup();108 defer tmp.cleanup();
...@@ -187,8 +184,6 @@ test "Dir.Iterator" {...@@ -187,8 +184,6 @@ test "Dir.Iterator" {
187}184}
188185
189test "Dir.Iterator many entries" {186test "Dir.Iterator many entries" {
190 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
191
192 var tmp_dir = tmpIterableDir(.{});187 var tmp_dir = tmpIterableDir(.{});
193 defer tmp_dir.cleanup();188 defer tmp_dir.cleanup();
194189
...@@ -638,8 +633,7 @@ test "rename" {...@@ -638,8 +633,7 @@ test "rename" {
638}633}
639634
640test "renameAbsolute" {635test "renameAbsolute" {
641 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;636 if (builtin.os.tag == .wasi) return error.SkipZigTest;
642 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
643637
644 var tmp_dir = tmpDir(.{});638 var tmp_dir = tmpDir(.{});
645 defer tmp_dir.cleanup();639 defer tmp_dir.cleanup();
...@@ -1149,7 +1143,6 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" {...@@ -1149,7 +1143,6 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" {
11491143
1150test "walker" {1144test "walker" {
1151 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;1145 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
1154 var tmp = tmpIterableDir(.{});1147 var tmp = tmpIterableDir(.{});
1155 defer tmp.cleanup();1148 defer tmp.cleanup();
...@@ -1203,7 +1196,6 @@ test "walker" {...@@ -1203,7 +1196,6 @@ test "walker" {
12031196
1204test "walker without fully iterating" {1197test "walker without fully iterating" {
1205 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;1198 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
1208 var tmp = tmpIterableDir(.{});1200 var tmp = tmpIterableDir(.{});
1209 defer tmp.cleanup();1201 defer tmp.cleanup();
...@@ -1227,7 +1219,6 @@ test "walker without fully iterating" {...@@ -1227,7 +1219,6 @@ test "walker without fully iterating" {
12271219
1228test ". and .. in fs.Dir functions" {1220test ". and .. in fs.Dir functions" {
1229 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;1221 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
1232 var tmp = tmpDir(.{});1223 var tmp = tmpDir(.{});
1233 defer tmp.cleanup();1224 defer tmp.cleanup();
...@@ -1255,8 +1246,7 @@ test ". and .. in fs.Dir functions" {...@@ -1255,8 +1246,7 @@ test ". and .. in fs.Dir functions" {
1255}1246}
12561247
1257test ". and .. in absolute functions" {1248test ". and .. in absolute functions" {
1258 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;1249 if (builtin.os.tag == .wasi) return error.SkipZigTest;
1259 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
12601250
1261 var tmp = tmpDir(.{});1251 var tmp = tmpDir(.{});
1262 defer tmp.cleanup();1252 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...@@ -2032,7 +2032,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin
2032 if (builtin.os.tag == .windows) {2032 if (builtin.os.tag == .windows) {
2033 @compileError("symlink is not supported on Windows; use std.os.windows.CreateSymbolicLink instead");2033 @compileError("symlink is not supported on Windows; use std.os.windows.CreateSymbolicLink instead");
2034 } else if (builtin.os.tag == .wasi and !builtin.link_libc) {2034 } 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);
2036 }2036 }
2037 switch (errno(system.symlink(target_path, sym_link_path))) {2037 switch (errno(system.symlink(target_path, sym_link_path))) {
2038 .SUCCESS => return,2038 .SUCCESS => return,
...@@ -2078,6 +2078,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c...@@ -2078,6 +2078,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
2078 .SUCCESS => {},2078 .SUCCESS => {},
2079 .FAULT => unreachable,2079 .FAULT => unreachable,
2080 .INVAL => unreachable,2080 .INVAL => unreachable,
2081 .BADF => unreachable,
2081 .ACCES => return error.AccessDenied,2082 .ACCES => return error.AccessDenied,
2082 .PERM => return error.AccessDenied,2083 .PERM => return error.AccessDenied,
2083 .DQUOT => return error.DiskQuota,2084 .DQUOT => return error.DiskQuota,
lib/std/os/test.zig+10-20
...@@ -22,8 +22,7 @@ const Dir = std.fs.Dir;...@@ -22,8 +22,7 @@ const Dir = std.fs.Dir;
22const ArenaAllocator = std.heap.ArenaAllocator;22const ArenaAllocator = std.heap.ArenaAllocator;
2323
24test "chdir smoke test" {24test "chdir smoke test" {
25 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;25 if (native_os == .wasi) return error.SkipZigTest;
26 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/preopens/cwd");
2726
28 // Get current working directory path27 // Get current working directory path
29 var old_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined;28 var old_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined;
...@@ -75,8 +74,7 @@ test "chdir smoke test" {...@@ -75,8 +74,7 @@ test "chdir smoke test" {
75}74}
7675
77test "open smoke test" {76test "open smoke test" {
78 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;77 if (native_os == .wasi) return error.SkipZigTest;
79 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
8078
81 // TODO verify file attributes using `fstat`79 // TODO verify file attributes using `fstat`
8280
...@@ -131,7 +129,6 @@ test "open smoke test" {...@@ -131,7 +129,6 @@ test "open smoke test" {
131129
132test "openat smoke test" {130test "openat smoke test" {
133 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;131 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
136 // TODO verify file attributes using `fstatat`133 // TODO verify file attributes using `fstatat`
137134
...@@ -168,7 +165,6 @@ test "openat smoke test" {...@@ -168,7 +165,6 @@ test "openat smoke test" {
168165
169test "symlink with relative paths" {166test "symlink with relative paths" {
170 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;167 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
173 const cwd = fs.cwd();169 const cwd = fs.cwd();
174 cwd.deleteFile("file.txt") catch {};170 cwd.deleteFile("file.txt") catch {};
...@@ -219,15 +215,10 @@ fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {...@@ -219,15 +215,10 @@ fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {
219}215}
220216
221test "link with relative paths" {217test "link with relative paths" {
218 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
219
222 switch (native_os) {220 switch (native_os) {
223 .wasi => {221 .wasi, .linux, .solaris => {},
224 if (builtin.link_libc) {
225 return error.SkipZigTest;
226 } else {
227 try os.initPreopensWasi(std.heap.page_allocator, "/");
228 }
229 },
230 .linux, .solaris => {},
231 else => return error.SkipZigTest,222 else => return error.SkipZigTest,
232 }223 }
233 var cwd = fs.cwd();224 var cwd = fs.cwd();
...@@ -263,9 +254,10 @@ test "link with relative paths" {...@@ -263,9 +254,10 @@ test "link with relative paths" {
263}254}
264255
265test "linkat with different directories" {256test "linkat with different directories" {
257 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
258
266 switch (native_os) {259 switch (native_os) {
267 .wasi => if (!builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/"),260 .wasi, .linux, .solaris => {},
268 .linux, .solaris => {},
269 else => return error.SkipZigTest,261 else => return error.SkipZigTest,
270 }262 }
271 var cwd = fs.cwd();263 var cwd = fs.cwd();
...@@ -950,8 +942,7 @@ test "POSIX file locking with fcntl" {...@@ -950,8 +942,7 @@ test "POSIX file locking with fcntl" {
950}942}
951943
952test "rename smoke test" {944test "rename smoke test" {
953 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;945 if (native_os == .wasi) return error.SkipZigTest;
954 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
955946
956 var tmp = tmpDir(.{});947 var tmp = tmpDir(.{});
957 defer tmp.cleanup();948 defer tmp.cleanup();
...@@ -1007,8 +998,7 @@ test "rename smoke test" {...@@ -1007,8 +998,7 @@ test "rename smoke test" {
1007}998}
1008999
1009test "access smoke test" {1000test "access smoke test" {
1010 if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;1001 if (native_os == .wasi) return error.SkipZigTest;
1011 if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
10121002
1013 var tmp = tmpDir(.{});1003 var tmp = tmpDir(.{});
1014 defer tmp.cleanup();1004 defer tmp.cleanup();
lib/std/os/wasi.zig+7-1
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1// wasi_snapshot_preview1 spec available (in witx format) here:1// wasi_snapshot_preview1 spec available (in witx format) here:
2// * typenames -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx2// * typenames -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx
3// * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx3// * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx
4const builtin = @import("builtin");
4const std = @import("std");5const std = @import("std");
5const assert = std.debug.assert;6const assert = std.debug.assert;
67
...@@ -157,7 +158,12 @@ pub const IOV_MAX = 1024;...@@ -157,7 +158,12 @@ pub const IOV_MAX = 1024;
157158
158pub const AT = struct {159pub const AT = struct {
159 pub const REMOVEDIR: u32 = 0x4;160 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;
161};167};
162168
163// As defined in the wasi_snapshot_preview1 spec file:169// As defined in the wasi_snapshot_preview1 spec file: