mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
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.
This commit is contained in:
parent
05fb3e79fe
commit
8bce1b6981
@ -1440,17 +1440,7 @@ pub fn cwd() Dir {
|
||||
if (builtin.os.tag == .windows) {
|
||||
return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
|
||||
} else if (builtin.os.tag == .wasi) {
|
||||
const wasi = os.wasi;
|
||||
// On WASI we indeed don't have a concept of cwd; however, we can approximate it with
|
||||
// trying to obtain a preopen for ".".
|
||||
// TODO `cwd()` should be a fallible operation if we're going to support WASI this way.
|
||||
var fd: wasi.fd_t = undefined;
|
||||
var prefix: usize = undefined;
|
||||
switch (wasi.resolve_preopen(".", &fd, &prefix)) {
|
||||
0 => {},
|
||||
else => {},
|
||||
}
|
||||
return Dir{ .fd = fd };
|
||||
@compileError("WASI doesn't have a concept of cwd; use TODO instead");
|
||||
} else {
|
||||
return Dir{ .fd = os.AT_FDCWD };
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
// * typenames -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx
|
||||
// * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
pub usingnamespace @import("bits.zig");
|
||||
@ -65,6 +66,71 @@ pub fn resolve_preopen(path: []const u8, dirfd: *fd_t, prefix: *usize) errno_t {
|
||||
return ENOTCAPABLE;
|
||||
}
|
||||
|
||||
pub const PreopenType = enum {
|
||||
Dir,
|
||||
};
|
||||
|
||||
pub const Preopen = struct {
|
||||
fd: fd_t,
|
||||
@"type": union(PreopenType) {
|
||||
Dir: []const u8,
|
||||
},
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn newDir(fd: fd_t, path: []const u8) Self {
|
||||
return Self{
|
||||
.fd = fd,
|
||||
.@"type" = .{ .Dir = path },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const GetPreopenError = std.os.UnexpectedError || mem.Allocator.Error;
|
||||
|
||||
pub fn getPreopens(allocator: *mem.Allocator) GetPreopenError![]Preopen {
|
||||
var preopens = std.ArrayList(Preopen).init(allocator);
|
||||
errdefer freePreopens(allocator, preopens);
|
||||
var fd: fd_t = 3; // start fd has to be beyond stdio fds
|
||||
|
||||
while (true) {
|
||||
var buf: prestat_t = undefined;
|
||||
switch (fd_prestat_get(fd, &buf)) {
|
||||
ESUCCESS => {},
|
||||
ENOTSUP => {
|
||||
// not a preopen, so keep going
|
||||
continue;
|
||||
},
|
||||
EBADF => {
|
||||
// OK, no more fds available
|
||||
break;
|
||||
},
|
||||
else => |err| return std.os.unexpectedErrno(err),
|
||||
}
|
||||
const preopen_len = buf.u.dir.pr_name_len;
|
||||
const path_buf = try allocator.alloc(u8, preopen_len);
|
||||
mem.set(u8, path_buf, 0);
|
||||
switch (fd_prestat_dir_name(fd, path_buf.ptr, preopen_len)) {
|
||||
ESUCCESS => {},
|
||||
else => |err| return std.os.unexpectedErrno(err),
|
||||
}
|
||||
const preopen = Preopen.newDir(fd, path_buf);
|
||||
try preopens.append(preopen);
|
||||
fd += 1;
|
||||
}
|
||||
|
||||
return preopens.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn freePreopens(allocator: *mem.Allocator, preopens: std.ArrayList(Preopen)) void {
|
||||
for (preopens.items) |preopen| {
|
||||
switch (preopen.@"type") {
|
||||
PreopenType.Dir => |path| allocator.free(path),
|
||||
}
|
||||
}
|
||||
preopens.deinit();
|
||||
}
|
||||
|
||||
pub extern "wasi_snapshot_preview1" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t;
|
||||
pub extern "wasi_snapshot_preview1" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user