Start drafting out openZ

master
Jakub Konka 2020-04-30 18:06:15 +02:00
parent f127dee474
commit d7ca220121
3 changed files with 71 additions and 0 deletions

View File

@ -879,6 +879,30 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t
return openW(file_path_w.span(), flags, perm);
}
while (true) {
if (builtin.os.tag == .wasi and !builtin.link_libc) {
var dirfd: fd_t = undefined;
var prefix: usize = undefined;
const path = mem.span(file_path);
switch (wasi.resolve_preopen(path, &dirfd, &prefix)) {
0 => {},
else => |err| return unexpectedErrno(err),
}
const rel_path = path[prefix + 1 ..];
// TODO map flags to wasi.oflag_t
// TODO call wasi.fd_fdstat_get to verify rights
// TODO adjust all flags to path_open
var fd: fd_t = undefined;
switch (wasi.path_open(dirfd, 0x0, rel_path.ptr, rel_path.len, wasi.O_CREAT, 0x0, 0x0, 0x0, &fd)) {
0 => {},
else => |err| return unexpectedErrno(err),
}
return fd;
}
const rc = system.open(file_path, flags, perm);
switch (errno(rc)) {
0 => return @intCast(fd_t, rc),

View File

@ -12,6 +12,8 @@ pub const timespec = extern struct {
tv_nsec: isize,
};
pub const PATH_MAX = 4096; // TODO verify this!
// As defined in the wasi_snapshot_preview1 spec file:
// https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx
pub const advice_t = u8;

View File

@ -20,6 +20,51 @@ comptime {
pub const iovec_t = iovec;
pub const ciovec_t = iovec_const;
fn is_prefix(preopen: []const u8, path: []const u8) bool {
if (preopen.len > path.len) {
return false;
}
var i: usize = 0;
while (i < preopen.len) {
std.debug.warn("{} == {}", .{ preopen[i], path[i] });
if (preopen[i] != path[i]) {
return false;
}
i += 1;
}
return true;
}
pub fn resolve_preopen(path: []const u8, dirfd: *fd_t, prefix: *usize) errno_t {
var fd: fd_t = 3; // start fd has to be beyond stdio fds
var preopen_path = [_]u8{0} ** PATH_MAX;
while (true) {
var buf: prestat_t = undefined;
switch (fd_prestat_get(fd, &buf)) {
ESUCCESS => {},
EBADF => {
break;
},
else => |err| return err,
}
const preopen_len = buf.u.dir.pr_name_len;
switch (fd_prestat_dir_name(fd, &preopen_path, preopen_len)) {
ESUCCESS => {},
else => |err| return err,
}
if (is_prefix(preopen_path[0..preopen_len], path)) {
dirfd.* = fd;
prefix.* = preopen_len;
return ESUCCESS;
}
std.mem.set(u8, &preopen_path, 0);
fd += 1;
}
return ENOTCAPABLE;
}
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;