| author | |
| committer | |
| log | e73170f9725c530befc688dd40053022072f5058 |
| tree | 89893ba2d5df1d0db3ea7cadbea06c07a74da186 |
| parent | cb012490eeae618b42361990872b9001e5672be1 |
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 { |
| 2652 | pub fn cwd() Dir { | 2640 | pub 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 | } |
| 49 | 49 | ||
| 50 | test "accessAbsolute" { | 50 | test "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, "/"); | ||
| 53 | 52 | ||
| 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 | } |
| 68 | 67 | ||
| 69 | test "openDirAbsolute" { | 68 | test "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, "/"); | ||
| 72 | 70 | ||
| 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 | } |
| 105 | 103 | ||
| 106 | test "readLinkAbsolute" { | 104 | test "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, "/"); | ||
| 109 | 106 | ||
| 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 | } |
| 188 | 185 | ||
| 189 | test "Dir.Iterator many entries" { | 186 | test "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(); |
| 194 | 189 | ||
| ... | @@ -638,8 +633,7 @@ test "rename" { | ... | @@ -638,8 +633,7 @@ test "rename" { |
| 638 | } | 633 | } |
| 639 | 634 | ||
| 640 | test "renameAbsolute" { | 635 | test "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, "/"); | ||
| 643 | 637 | ||
| 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)" { |
| 1149 | 1143 | ||
| 1150 | test "walker" { | 1144 | test "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, "/"); | ||
| 1153 | 1146 | ||
| 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" { |
| 1203 | 1196 | ||
| 1204 | test "walker without fully iterating" { | 1197 | test "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, "/"); | ||
| 1207 | 1199 | ||
| 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" { |
| 1227 | 1219 | ||
| 1228 | test ". and .. in fs.Dir functions" { | 1220 | test ". 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, "/"); | ||
| 1231 | 1222 | ||
| 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 | } |
| 1256 | 1247 | ||
| 1257 | test ". and .. in absolute functions" { | 1248 | test ". 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, "/"); | ||
| 1260 | 1250 | ||
| 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; |
| 22 | const ArenaAllocator = std.heap.ArenaAllocator; | 22 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 23 | 23 | ||
| 24 | test "chdir smoke test" { | 24 | test "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"); | ||
| 27 | 26 | ||
| 28 | // Get current working directory path | 27 | // 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 | } |
| 76 | 75 | ||
| 77 | test "open smoke test" { | 76 | test "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, "/"); | ||
| 80 | 78 | ||
| 81 | // TODO verify file attributes using `fstat` | 79 | // TODO verify file attributes using `fstat` |
| 82 | 80 | ||
| ... | @@ -131,7 +129,6 @@ test "open smoke test" { | ... | @@ -131,7 +129,6 @@ test "open smoke test" { |
| 131 | 129 | ||
| 132 | test "openat smoke test" { | 130 | test "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, "/"); | ||
| 135 | 132 | ||
| 136 | // TODO verify file attributes using `fstatat` | 133 | // TODO verify file attributes using `fstatat` |
| 137 | 134 | ||
| ... | @@ -168,7 +165,6 @@ test "openat smoke test" { | ... | @@ -168,7 +165,6 @@ test "openat smoke test" { |
| 168 | 165 | ||
| 169 | test "symlink with relative paths" { | 166 | test "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, "/"); | ||
| 172 | 168 | ||
| 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 | } |
| 220 | 216 | ||
| 221 | test "link with relative paths" { | 217 | test "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 | } |
| 264 | 255 | ||
| 265 | test "linkat with different directories" { | 256 | test "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 | } |
| 951 | 943 | ||
| 952 | test "rename smoke test" { | 944 | test "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, "/"); | ||
| 955 | 946 | ||
| 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 | } |
| 1008 | 999 | ||
| 1009 | test "access smoke test" { | 1000 | test "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, "/"); | ||
| 1012 | 1002 | ||
| 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.witx | 2 | // * 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.witx | 3 | // * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx |
| 4 | const builtin = @import("builtin"); | ||
| 4 | const std = @import("std"); | 5 | const std = @import("std"); |
| 5 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 6 | 7 | ||
| ... | @@ -157,7 +158,12 @@ pub const IOV_MAX = 1024; | ... | @@ -157,7 +158,12 @@ pub const IOV_MAX = 1024; |
| 157 | 158 | ||
| 158 | pub const AT = struct { | 159 | pub 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 | }; |
| 162 | 168 | ||
| 163 | // As defined in the wasi_snapshot_preview1 spec file: | 169 | // As defined in the wasi_snapshot_preview1 spec file: |