authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-05-04 13:30:21+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-05-05 15:08:52+02:00
log8bce1b6981d5ec71100823dfd135402a32d9609b
treeb5df521eac089658e0cf50ed99cfa15ad88cdd8d
parent05fb3e79fecc689def1a4186da8783546e17f1ae

Refactor resolve_preopen into getPreopens function

This commit refactors `std.os.wasi.resolve_preopen` into a (higher-level) `std.os.wasi.getPreopens` funtion which returns a slice with _all_ preopens at any given time. This fn allows the WASI module to inquire at any given time for all preopens provided by the runtime. This commit also makes `cwd()` a compile error on WASI.

2 files changed, 67 insertions(+), 11 deletions(-)

lib/std/fs.zig+1-11
...@@ -1440,17 +1440,7 @@ pub fn cwd() Dir {...@@ -1440,17 +1440,7 @@ pub fn cwd() Dir {
1440 if (builtin.os.tag == .windows) {1440 if (builtin.os.tag == .windows) {
1441 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };1441 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
1442 } else if (builtin.os.tag == .wasi) {1442 } else if (builtin.os.tag == .wasi) {
1443 const wasi = os.wasi;1443 @compileError("WASI doesn't have a concept of cwd; use TODO instead");
1444 // On WASI we indeed don't have a concept of cwd; however, we can approximate it with
1445 // trying to obtain a preopen for ".".
1446 // TODO `cwd()` should be a fallible operation if we're going to support WASI this way.
1447 var fd: wasi.fd_t = undefined;
1448 var prefix: usize = undefined;
1449 switch (wasi.resolve_preopen(".", &fd, &prefix)) {
1450 0 => {},
1451 else => {},
1452 }
1453 return Dir{ .fd = fd };
1454 } else {1444 } else {
1455 return Dir{ .fd = os.AT_FDCWD };1445 return Dir{ .fd = os.AT_FDCWD };
1456 }1446 }
lib/std/os/wasi.zig+66
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
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 std = @import("std");4const std = @import("std");
5const mem = std.mem;
5const assert = std.debug.assert;6const assert = std.debug.assert;
67
7pub usingnamespace @import("bits.zig");8pub usingnamespace @import("bits.zig");
...@@ -65,6 +66,71 @@ pub fn resolve_preopen(path: []const u8, dirfd: *fd_t, prefix: *usize) errno_t {...@@ -65,6 +66,71 @@ pub fn resolve_preopen(path: []const u8, dirfd: *fd_t, prefix: *usize) errno_t {
65 return ENOTCAPABLE;66 return ENOTCAPABLE;
66}67}
6768
69pub const PreopenType = enum {
70 Dir,
71};
72
73pub const Preopen = struct {
74 fd: fd_t,
75 @"type": union(PreopenType) {
76 Dir: []const u8,
77 },
78
79 const Self = @This();
80
81 pub fn newDir(fd: fd_t, path: []const u8) Self {
82 return Self{
83 .fd = fd,
84 .@"type" = .{ .Dir = path },
85 };
86 }
87};
88
89pub const GetPreopenError = std.os.UnexpectedError || mem.Allocator.Error;
90
91pub fn getPreopens(allocator: *mem.Allocator) GetPreopenError![]Preopen {
92 var preopens = std.ArrayList(Preopen).init(allocator);
93 errdefer freePreopens(allocator, preopens);
94 var fd: fd_t = 3; // start fd has to be beyond stdio fds
95
96 while (true) {
97 var buf: prestat_t = undefined;
98 switch (fd_prestat_get(fd, &buf)) {
99 ESUCCESS => {},
100 ENOTSUP => {
101 // not a preopen, so keep going
102 continue;
103 },
104 EBADF => {
105 // OK, no more fds available
106 break;
107 },
108 else => |err| return std.os.unexpectedErrno(err),
109 }
110 const preopen_len = buf.u.dir.pr_name_len;
111 const path_buf = try allocator.alloc(u8, preopen_len);
112 mem.set(u8, path_buf, 0);
113 switch (fd_prestat_dir_name(fd, path_buf.ptr, preopen_len)) {
114 ESUCCESS => {},
115 else => |err| return std.os.unexpectedErrno(err),
116 }
117 const preopen = Preopen.newDir(fd, path_buf);
118 try preopens.append(preopen);
119 fd += 1;
120 }
121
122 return preopens.toOwnedSlice();
123}
124
125pub fn freePreopens(allocator: *mem.Allocator, preopens: std.ArrayList(Preopen)) void {
126 for (preopens.items) |preopen| {
127 switch (preopen.@"type") {
128 PreopenType.Dir => |path| allocator.free(path),
129 }
130 }
131 preopens.deinit();
132}
133
68pub extern "wasi_snapshot_preview1" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t;134pub extern "wasi_snapshot_preview1" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t;
69pub extern "wasi_snapshot_preview1" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;135pub extern "wasi_snapshot_preview1" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
70136