| author | |
| committer | |
| log | 558bb24601c6de5f05cded4e99b795e85bb3b8e6 |
| tree | c14c072c0421ef1b8253064419732941dd6e6e8b |
| parent | d4c33129cf86441a59079e15fd887711fae8d924 |
Previously, the path and preopens helpers were prototyped in `std.os.wasi`
module, but since they are higher-level abstraction over wasi, they belong in
`std.fs.wasi` module.3 files changed, 106 insertions(+), 104 deletions(-)
lib/std/fs.zig+2-4| ... | ... | @@ -12,6 +12,7 @@ const is_darwin = std.Target.current.os.tag.isDarwin(); |
| 12 | 12 | |
| 13 | 13 | pub const path = @import("fs/path.zig"); |
| 14 | 14 | pub const File = @import("fs/file.zig").File; |
| 15 | pub const wasi = @import("fs/wasi.zig"); | |
| 15 | 16 | |
| 16 | 17 | // TODO audit these APIs with respect to Dir and absolute paths |
| 17 | 18 | |
| ... | ... | @@ -37,7 +38,7 @@ pub const Watch = @import("fs/watch.zig").Watch; |
| 37 | 38 | /// fit into a UTF-8 encoded array of this length. |
| 38 | 39 | /// The byte count includes room for a null sentinel byte. |
| 39 | 40 | pub const MAX_PATH_BYTES = switch (builtin.os.tag) { |
| 40 | .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly, .wasi => os.PATH_MAX, | |
| 41 | .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX, | |
| 41 | 42 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. |
| 42 | 43 | // If it would require 4 UTF-8 bytes, then there would be a surrogate |
| 43 | 44 | // pair in the UTF-16LE, and we (over)account 3 bytes for it that way. |
| ... | ... | @@ -700,7 +701,6 @@ pub const Dir = struct { |
| 700 | 701 | pub const createFileC = @compileError("deprecated: renamed to createFileZ"); |
| 701 | 702 | |
| 702 | 703 | fn createFileWasi(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { |
| 703 | const wasi = os.wasi; | |
| 704 | 704 | var oflags: wasi.oflags_t = wasi.O_CREAT; |
| 705 | 705 | var rights: wasi.rights_t = wasi.RIGHT_FD_WRITE | wasi.RIGHT_FD_DATASYNC | wasi.RIGHT_FD_SEEK | wasi.RIGHT_FD_FDSTAT_SET_FLAGS | wasi.RIGHT_FD_SYNC | wasi.RIGHT_FD_ALLOCATE | wasi.RIGHT_FD_ADVISE | wasi.RIGHT_FD_FILESTAT_SET_TIMES | wasi.RIGHT_FD_FILESTAT_SET_SIZE; |
| 706 | 706 | if (flags.read) { |
| ... | ... | @@ -712,9 +712,7 @@ pub const Dir = struct { |
| 712 | 712 | if (flags.exclusive) { |
| 713 | 713 | oflags |= wasi.O_EXCL; |
| 714 | 714 | } |
| 715 | ||
| 716 | 715 | const fd = try wasi.openat(self.fd, sub_path, oflags, 0x0, rights); |
| 717 | ||
| 718 | 716 | return File{ .handle = fd }; |
| 719 | 717 | } |
| 720 | 718 |
lib/std/fs/wasi.zig created+104| ... | ... | @@ -0,0 +1,104 @@ |
| 1 | const std = @import("std"); | |
| 2 | const os = std.os; | |
| 3 | const mem = std.mem; | |
| 4 | const Allocator = mem.Allocator; | |
| 5 | ||
| 6 | usingnamespace std.os.wasi; | |
| 7 | ||
| 8 | pub const PreopenType = enum { | |
| 9 | Dir, | |
| 10 | }; | |
| 11 | ||
| 12 | pub const Preopen = struct { | |
| 13 | fd: fd_t, | |
| 14 | @"type": union(PreopenType) { | |
| 15 | Dir: []const u8, | |
| 16 | }, | |
| 17 | ||
| 18 | const Self = @This(); | |
| 19 | ||
| 20 | pub fn newDir(fd: fd_t, path: []const u8) Self { | |
| 21 | return Self{ | |
| 22 | .fd = fd, | |
| 23 | .@"type" = .{ .Dir = path }, | |
| 24 | }; | |
| 25 | } | |
| 26 | }; | |
| 27 | ||
| 28 | pub const PreopenList = struct { | |
| 29 | const InnerList = std.ArrayList(Preopen); | |
| 30 | ||
| 31 | buffer: InnerList, | |
| 32 | ||
| 33 | const Self = @This(); | |
| 34 | pub const Error = os.UnexpectedError || Allocator.Error; | |
| 35 | ||
| 36 | pub fn init(allocator: *Allocator) Self { | |
| 37 | return Self{ .buffer = InnerList.init(allocator) }; | |
| 38 | } | |
| 39 | ||
| 40 | pub fn deinit(pm: Self) void { | |
| 41 | for (pm.buffer.items) |preopen| { | |
| 42 | switch (preopen.@"type") { | |
| 43 | PreopenType.Dir => |path| pm.buffer.allocator.free(path), | |
| 44 | } | |
| 45 | } | |
| 46 | pm.buffer.deinit(); | |
| 47 | } | |
| 48 | ||
| 49 | pub fn populate(self: *Self) Error!void { | |
| 50 | errdefer self.deinit(); | |
| 51 | var fd: fd_t = 3; // start fd has to be beyond stdio fds | |
| 52 | ||
| 53 | while (true) { | |
| 54 | var buf: prestat_t = undefined; | |
| 55 | switch (fd_prestat_get(fd, &buf)) { | |
| 56 | ESUCCESS => {}, | |
| 57 | ENOTSUP => { | |
| 58 | // not a preopen, so keep going | |
| 59 | continue; | |
| 60 | }, | |
| 61 | EBADF => { | |
| 62 | // OK, no more fds available | |
| 63 | break; | |
| 64 | }, | |
| 65 | else => |err| return os.unexpectedErrno(err), | |
| 66 | } | |
| 67 | const preopen_len = buf.u.dir.pr_name_len; | |
| 68 | const path_buf = try self.buffer.allocator.alloc(u8, preopen_len); | |
| 69 | mem.set(u8, path_buf, 0); | |
| 70 | switch (fd_prestat_dir_name(fd, path_buf.ptr, preopen_len)) { | |
| 71 | ESUCCESS => {}, | |
| 72 | else => |err| return os.unexpectedErrno(err), | |
| 73 | } | |
| 74 | const preopen = Preopen.newDir(fd, path_buf); | |
| 75 | try self.buffer.append(preopen); | |
| 76 | fd += 1; | |
| 77 | } | |
| 78 | } | |
| 79 | ||
| 80 | pub fn find(self: *const Self, path: []const u8) ?*const Preopen { | |
| 81 | for (self.buffer.items) |preopen| { | |
| 82 | switch (preopen.@"type") { | |
| 83 | PreopenType.Dir => |preopen_path| { | |
| 84 | if (mem.eql(u8, path, preopen_path)) return &preopen; | |
| 85 | }, | |
| 86 | } | |
| 87 | } | |
| 88 | return null; | |
| 89 | } | |
| 90 | ||
| 91 | pub fn asSlice(self: *const Self) []const Preopen { | |
| 92 | return self.buffer.items; | |
| 93 | } | |
| 94 | }; | |
| 95 | ||
| 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 { | |
| 97 | var fd: fd_t = undefined; | |
| 98 | switch (path_open(dir_fd, 0x0, file_path.ptr, file_path.len, oflags, rights, 0x0, fdflags, &fd)) { | |
| 99 | 0 => {}, | |
| 100 | // TODO map errors | |
| 101 | else => |err| return std.os.unexpectedErrno(err), | |
| 102 | } | |
| 103 | return fd; | |
| 104 | } |
lib/std/os/wasi.zig-100| ... | ... | @@ -2,9 +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; | |
| 6 | 5 | const assert = std.debug.assert; |
| 7 | const Allocator = mem.Allocator; | |
| 8 | 6 | |
| 9 | 7 | pub usingnamespace @import("bits.zig"); |
| 10 | 8 | |
| ... | ... | @@ -22,104 +20,6 @@ comptime { |
| 22 | 20 | pub const iovec_t = iovec; |
| 23 | 21 | pub const ciovec_t = iovec_const; |
| 24 | 22 | |
| 25 | pub const PreopenType = enum { | |
| 26 | Dir, | |
| 27 | }; | |
| 28 | ||
| 29 | pub const Preopen = struct { | |
| 30 | fd: fd_t, | |
| 31 | @"type": union(PreopenType) { | |
| 32 | Dir: []const u8, | |
| 33 | }, | |
| 34 | ||
| 35 | const Self = @This(); | |
| 36 | ||
| 37 | pub fn newDir(fd: fd_t, path: []const u8) Self { | |
| 38 | return Self{ | |
| 39 | .fd = fd, | |
| 40 | .@"type" = .{ .Dir = path }, | |
| 41 | }; | |
| 42 | } | |
| 43 | }; | |
| 44 | ||
| 45 | pub const PreopenList = struct { | |
| 46 | const InnerList = std.ArrayList(Preopen); | |
| 47 | ||
| 48 | buffer: InnerList, | |
| 49 | ||
| 50 | const Self = @This(); | |
| 51 | pub const Error = std.os.UnexpectedError || Allocator.Error; | |
| 52 | ||
| 53 | pub fn init(allocator: *Allocator) Self { | |
| 54 | return Self{ .buffer = InnerList.init(allocator) }; | |
| 55 | } | |
| 56 | ||
| 57 | pub fn deinit(pm: Self) void { | |
| 58 | for (pm.buffer.items) |preopen| { | |
| 59 | switch (preopen.@"type") { | |
| 60 | PreopenType.Dir => |path| pm.buffer.allocator.free(path), | |
| 61 | } | |
| 62 | } | |
| 63 | pm.buffer.deinit(); | |
| 64 | } | |
| 65 | ||
| 66 | pub fn populate(self: *Self) Error!void { | |
| 67 | errdefer self.deinit(); | |
| 68 | var fd: fd_t = 3; // start fd has to be beyond stdio fds | |
| 69 | ||
| 70 | while (true) { | |
| 71 | var buf: prestat_t = undefined; | |
| 72 | switch (fd_prestat_get(fd, &buf)) { | |
| 73 | ESUCCESS => {}, | |
| 74 | ENOTSUP => { | |
| 75 | // not a preopen, so keep going | |
| 76 | continue; | |
| 77 | }, | |
| 78 | EBADF => { | |
| 79 | // OK, no more fds available | |
| 80 | break; | |
| 81 | }, | |
| 82 | else => |err| return std.os.unexpectedErrno(err), | |
| 83 | } | |
| 84 | const preopen_len = buf.u.dir.pr_name_len; | |
| 85 | const path_buf = try self.buffer.allocator.alloc(u8, preopen_len); | |
| 86 | mem.set(u8, path_buf, 0); | |
| 87 | switch (fd_prestat_dir_name(fd, path_buf.ptr, preopen_len)) { | |
| 88 | ESUCCESS => {}, | |
| 89 | else => |err| return std.os.unexpectedErrno(err), | |
| 90 | } | |
| 91 | const preopen = Preopen.newDir(fd, path_buf); | |
| 92 | try self.buffer.append(preopen); | |
| 93 | fd += 1; | |
| 94 | } | |
| 95 | } | |
| 96 | ||
| 97 | pub fn find(self: *const Self, path: []const u8) ?*const Preopen { | |
| 98 | for (self.buffer.items) |preopen| { | |
| 99 | switch (preopen.@"type") { | |
| 100 | PreopenType.Dir => |preopen_path| { | |
| 101 | if (mem.eql(u8, path, preopen_path)) return &preopen; | |
| 102 | }, | |
| 103 | } | |
| 104 | } | |
| 105 | return null; | |
| 106 | } | |
| 107 | ||
| 108 | pub fn asSlice(self: *const Self) []const Preopen { | |
| 109 | return self.buffer.items; | |
| 110 | } | |
| 111 | }; | |
| 112 | ||
| 113 | 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 { | |
| 114 | var fd: fd_t = undefined; | |
| 115 | switch (path_open(dir_fd, 0x0, file_path.ptr, file_path.len, oflags, rights, 0x0, fdflags, &fd)) { | |
| 116 | 0 => {}, | |
| 117 | // TODO map errors | |
| 118 | else => |err| return std.os.unexpectedErrno(err), | |
| 119 | } | |
| 120 | return fd; | |
| 121 | } | |
| 122 | ||
| 123 | 23 | pub extern "wasi_snapshot_preview1" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t; |
| 124 | 24 | pub extern "wasi_snapshot_preview1" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; |
| 125 | 25 |