| 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,6 +12,7 @@ const is_darwin = std.Target.current.os.tag.isDarwin(); |
| 12 | 12 | ||
| 13 | pub const path = @import("fs/path.zig"); | 13 | pub const path = @import("fs/path.zig"); |
| 14 | pub const File = @import("fs/file.zig").File; | 14 | pub const File = @import("fs/file.zig").File; |
| 15 | pub const wasi = @import("fs/wasi.zig"); | ||
| 15 | 16 | ||
| 16 | // TODO audit these APIs with respect to Dir and absolute paths | 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,7 +38,7 @@ pub const Watch = @import("fs/watch.zig").Watch; |
| 37 | /// fit into a UTF-8 encoded array of this length. | 38 | /// fit into a UTF-8 encoded array of this length. |
| 38 | /// The byte count includes room for a null sentinel byte. | 39 | /// The byte count includes room for a null sentinel byte. |
| 39 | pub const MAX_PATH_BYTES = switch (builtin.os.tag) { | 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 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. | 42 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. |
| 42 | // If it would require 4 UTF-8 bytes, then there would be a surrogate | 43 | // If it would require 4 UTF-8 bytes, then there would be a surrogate |
| 43 | // pair in the UTF-16LE, and we (over)account 3 bytes for it that way. | 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,7 +701,6 @@ pub const Dir = struct { |
| 700 | pub const createFileC = @compileError("deprecated: renamed to createFileZ"); | 701 | pub const createFileC = @compileError("deprecated: renamed to createFileZ"); |
| 701 | 702 | ||
| 702 | fn createFileWasi(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { | 703 | fn createFileWasi(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { |
| 703 | const wasi = os.wasi; | ||
| 704 | var oflags: wasi.oflags_t = wasi.O_CREAT; | 704 | var oflags: wasi.oflags_t = wasi.O_CREAT; |
| 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; | 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 | if (flags.read) { | 706 | if (flags.read) { |
| ... | @@ -712,9 +712,7 @@ pub const Dir = struct { | ... | @@ -712,9 +712,7 @@ pub const Dir = struct { |
| 712 | if (flags.exclusive) { | 712 | if (flags.exclusive) { |
| 713 | oflags |= wasi.O_EXCL; | 713 | oflags |= wasi.O_EXCL; |
| 714 | } | 714 | } |
| 715 | |||
| 716 | const fd = try wasi.openat(self.fd, sub_path, oflags, 0x0, rights); | 715 | const fd = try wasi.openat(self.fd, sub_path, oflags, 0x0, rights); |
| 717 | |||
| 718 | return File{ .handle = fd }; | 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,9 +2,7 @@ |
| 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 std = @import("std"); | 4 | const std = @import("std"); |
| 5 | const mem = std.mem; | ||
| 6 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| 7 | const Allocator = mem.Allocator; | ||
| 8 | 6 | ||
| 9 | pub usingnamespace @import("bits.zig"); | 7 | pub usingnamespace @import("bits.zig"); |
| 10 | 8 | ||
| ... | @@ -22,104 +20,6 @@ comptime { | ... | @@ -22,104 +20,6 @@ comptime { |
| 22 | pub const iovec_t = iovec; | 20 | pub const iovec_t = iovec; |
| 23 | pub const ciovec_t = iovec_const; | 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 | pub extern "wasi_snapshot_preview1" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t; | 23 | pub extern "wasi_snapshot_preview1" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t; |
| 124 | pub extern "wasi_snapshot_preview1" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; | 24 | pub extern "wasi_snapshot_preview1" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; |
| 125 | 25 |