| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | // * typenames -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx |
| 3 | 3 | // * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx |
| 4 | 4 | const std = @import("std"); |
| 5 | const mem = std.mem; |
| 5 | 6 | const assert = std.debug.assert; |
| 6 | 7 | |
| 7 | 8 | pub usingnamespace @import("bits.zig"); |
| ... | ... | @@ -65,6 +66,71 @@ pub fn resolve_preopen(path: []const u8, dirfd: *fd_t, prefix: *usize) errno_t { |
| 65 | 66 | return ENOTCAPABLE; |
| 66 | 67 | } |
| 67 | 68 | |
| 69 | pub const PreopenType = enum { |
| 70 | Dir, |
| 71 | }; |
| 72 | |
| 73 | pub 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 | |
| 89 | pub const GetPreopenError = std.os.UnexpectedError || mem.Allocator.Error; |
| 90 | |
| 91 | pub 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 | |
| 125 | pub 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 | |
| 68 | 134 | pub extern "wasi_snapshot_preview1" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t; |
| 69 | 135 | pub extern "wasi_snapshot_preview1" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; |
| 70 | 136 | |