| ... | ... | @@ -5,18 +5,30 @@ const Allocator = mem.Allocator; |
| 5 | 5 | |
| 6 | 6 | usingnamespace std.os.wasi; |
| 7 | 7 | |
| 8 | /// Type of WASI preopen. |
| 9 | /// |
| 10 | /// WASI currently offers only `Dir` as a valid preopen resource. |
| 8 | 11 | pub const PreopenType = enum { |
| 9 | 12 | Dir, |
| 10 | 13 | }; |
| 11 | 14 | |
| 15 | /// WASI preopen struct. This struct consists of a WASI file descriptor |
| 16 | /// and type of WASI preopen. It can be obtained directly from the WASI |
| 17 | /// runtime using `PreopenList.populate()` method. |
| 12 | 18 | pub const Preopen = struct { |
| 19 | /// WASI file descriptor. |
| 13 | 20 | fd: fd_t, |
| 21 | |
| 22 | /// Type of the preopen. |
| 14 | 23 | @"type": union(PreopenType) { |
| 24 | /// Path to a preopened directory. |
| 15 | 25 | Dir: []const u8, |
| 16 | 26 | }, |
| 17 | 27 | |
| 18 | 28 | const Self = @This(); |
| 19 | 29 | |
| 30 | /// Construct new `Preopen` instance of type `PreopenType.Dir` from |
| 31 | /// WASI file descriptor and WASI path. |
| 20 | 32 | pub fn newDir(fd: fd_t, path: []const u8) Self { |
| 21 | 33 | return Self{ |
| 22 | 34 | .fd = fd, |
| ... | ... | @@ -25,18 +37,29 @@ pub const Preopen = struct { |
| 25 | 37 | } |
| 26 | 38 | }; |
| 27 | 39 | |
| 40 | /// Dynamically-sized array list of WASI preopens. This struct is a |
| 41 | /// convenience wrapper for issuing `std.os.wasi.fd_prestat_get` and |
| 42 | /// `std.os.wasi.fd_prestat_dir_name` syscalls to the WASI runtime, and |
| 43 | /// collecting the returned preopens. |
| 44 | /// |
| 45 | /// This struct is intended to be used in any WASI program which intends |
| 46 | /// to use the capabilities as passed on by the user of the runtime. |
| 28 | 47 | pub const PreopenList = struct { |
| 29 | 48 | const InnerList = std.ArrayList(Preopen); |
| 30 | 49 | |
| 50 | /// Internal dynamically-sized buffer for storing the gathered preopens. |
| 31 | 51 | buffer: InnerList, |
| 32 | 52 | |
| 33 | 53 | const Self = @This(); |
| 54 | |
| 34 | 55 | pub const Error = os.UnexpectedError || Allocator.Error; |
| 35 | 56 | |
| 57 | /// Deinitialize with `deinit`. |
| 36 | 58 | pub fn init(allocator: *Allocator) Self { |
| 37 | 59 | return Self{ .buffer = InnerList.init(allocator) }; |
| 38 | 60 | } |
| 39 | 61 | |
| 62 | /// Release all allocated memory. |
| 40 | 63 | pub fn deinit(pm: Self) void { |
| 41 | 64 | for (pm.buffer.items) |preopen| { |
| 42 | 65 | switch (preopen.@"type") { |
| ... | ... | @@ -46,6 +69,8 @@ pub const PreopenList = struct { |
| 46 | 69 | pm.buffer.deinit(); |
| 47 | 70 | } |
| 48 | 71 | |
| 72 | /// Populate the list with the preopens by issuing `std.os.wasi.fd_prestat_get` |
| 73 | /// and `std.os.wasi.fd_prestat_dir_name` syscalls to the runtime. |
| 49 | 74 | pub fn populate(self: *Self) Error!void { |
| 50 | 75 | errdefer self.deinit(); |
| 51 | 76 | var fd: fd_t = 3; // start fd has to be beyond stdio fds |
| ... | ... | @@ -77,6 +102,12 @@ pub const PreopenList = struct { |
| 77 | 102 | } |
| 78 | 103 | } |
| 79 | 104 | |
| 105 | /// Find preopen by path. If the preopen exists, return it. |
| 106 | /// Otherwise, return `null`. |
| 107 | /// |
| 108 | /// TODO make the function more generic by searching by `PreopenType` union. This will |
| 109 | /// be needed in the future when WASI extends its capabilities to resources |
| 110 | /// other than preopened directories. |
| 80 | 111 | pub fn find(self: *const Self, path: []const u8) ?*const Preopen { |
| 81 | 112 | for (self.buffer.items) |preopen| { |
| 82 | 113 | switch (preopen.@"type") { |
| ... | ... | @@ -88,12 +119,14 @@ pub const PreopenList = struct { |
| 88 | 119 | return null; |
| 89 | 120 | } |
| 90 | 121 | |
| 122 | /// Return the inner buffer as read-only slice. |
| 91 | 123 | pub fn asSlice(self: *const Self) []const Preopen { |
| 92 | 124 | return self.buffer.items; |
| 93 | 125 | } |
| 94 | 126 | }; |
| 95 | 127 | |
| 96 | | pub fn openat(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags: fdflags_t, rights: rights_t) std.os.OpenError!fd_t { |
| 128 | /// Convenience wrapper for `std.os.wasi.path_open` syscall. |
| 129 | pub fn openat(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags: fdflags_t, rights: rights_t) os.OpenError!fd_t { |
| 97 | 130 | var fd: fd_t = undefined; |
| 98 | 131 | switch (path_open(dir_fd, 0x0, file_path.ptr, file_path.len, oflags, rights, 0x0, fdflags, &fd)) { |
| 99 | 132 | 0 => {}, |