From dd238352a4d3a9f02ff62d32cd109adabee30b66 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 4 May 2020 21:20:00 +0200 Subject: [PATCH] Encapsulate getPreopens inside PreopenList --- lib/std/os.zig | 20 ------- lib/std/os/wasi.zig | 132 +++++++++++++++++--------------------------- 2 files changed, 50 insertions(+), 102 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index c3f5bc55ea..5335b2ca24 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -869,26 +869,6 @@ pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { return openZ(&file_path_c, flags, perm); } -pub fn openWasi(file_path: []const u8, oflags: wasi.oflags_t, fdflags: wasi.fdflags_t, rights: wasi.rights_t) OpenError!fd_t { - var dirfd: fd_t = undefined; - var prefix: usize = undefined; - - switch (wasi.resolve_preopen(file_path, &dirfd, &prefix)) { - 0 => {}, - else => |err| return unexpectedErrno(err), - } - - const rel_path = file_path[prefix + 1 ..]; - var fd: fd_t = undefined; - switch (wasi.path_open(dirfd, 0x0, rel_path.ptr, rel_path.len, oflags, rights, 0x0, fdflags, &fd)) { - 0 => {}, - // TODO map errors - else => |err| return unexpectedErrno(err), - } - - return fd; -} - pub const openC = @compileError("deprecated: renamed to openZ"); /// Open and possibly create a file. Keeps trying if it gets interrupted. diff --git a/lib/std/os/wasi.zig b/lib/std/os/wasi.zig index 9acf9001f6..07f6786518 100644 --- a/lib/std/os/wasi.zig +++ b/lib/std/os/wasi.zig @@ -4,6 +4,7 @@ const std = @import("std"); const mem = std.mem; const assert = std.debug.assert; +const Allocator = mem.Allocator; pub usingnamespace @import("bits.zig"); @@ -21,51 +22,6 @@ 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 const PreopenType = enum { Dir, }; @@ -86,50 +42,62 @@ pub const Preopen = struct { } }; -pub const GetPreopenError = std.os.UnexpectedError || mem.Allocator.Error; +pub const PreopenList = struct { + const InnerList = std.ArrayList(Preopen); -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 + buffer: InnerList, - 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; + const Self = @This(); + pub const Error = std.os.UnexpectedError || Allocator.Error; + + pub fn init(allocator: *Allocator) Self { + return Self{ .buffer = InnerList.init(allocator) }; } - return preopens.toOwnedSlice(); -} + pub fn deinit(pm: Self) void { + for (pm.buffer.items) |preopen| { + switch (preopen.@"type") { + PreopenType.Dir => |path| pm.buffer.allocator.free(path), + } + } + pm.buffer.deinit(); + } -pub fn freePreopens(allocator: *mem.Allocator, preopens: std.ArrayList(Preopen)) void { - for (preopens.items) |preopen| { - switch (preopen.@"type") { - PreopenType.Dir => |path| allocator.free(path), + pub fn populate(self: *Self) Error!void { + errdefer self.deinit(); + 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 self.buffer.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 self.buffer.append(preopen); + fd += 1; } } - preopens.deinit(); -} + + pub fn asSlice(self: *const Self) []const Preopen { + return self.buffer.items; + } +}; 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;