diff options
Diffstat (limited to 'src/9p_io.zig')
| -rw-r--r-- | src/9p_io.zig | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/9p_io.zig b/src/9p_io.zig index b11a4997..9fc19df9 100644 --- a/src/9p_io.zig +++ b/src/9p_io.zig @@ -2319,6 +2319,32 @@ pub const Client = struct { gpa.destroy(s); } + /// Writes `request` to `path` and reads the answer on the same open, + /// as /pane/new answers its own open: a session's last answer, from + /// another client, can never be what comes back. `exec 3<>file`. + pub fn ask(gpa: std.mem.Allocator, dial: []const u8, path: []const u8, request: []const u8) ![]u8 { + if (comptime !supported) return error.Unsupported; + var names: [max_depth][]const u8 = undefined; + const n = try elements(path, &names); + var sock_buf: [sun_path_len]u8 = undefined; + const sock = try resolve(&sock_buf, dial); + var remote: RemoteError = .{}; + errdefer said = remote; + const s = try startSession(gpa, sock, path); + defer endSession(gpa, s); + const fid = (try walkTo(s, names[0..n], &remote)).fid; + _ = try s.ask(.{ .open = .{ .fid = fid, .mode = ninep.ordwr } }, &remote); + _ = try s.ask(.{ .write = .{ .fid = fid, .offset = 0, .data = request } }, &remote); + var out: std.ArrayList(u8) = .empty; + errdefer out.deinit(gpa); + while (true) { + const data = (try s.ask(.{ .read = .{ .fid = fid, .offset = out.items.len, .count = s.cl.maxRead() } }, &remote)).read; + if (data.len == 0) return out.toOwnedSlice(gpa); + if (out.items.len + data.len > 4096) return Error.FileTooLarge; + try out.appendSlice(gpa, data); + } + } + /// Opens `path` on one connection and writes `first` to it (/log's /// `follow new`), all with the usual deadline; then, once `ready(ctx)` /// has said it is not done already, reads it with no deadline, a read at |
