summaryrefslogtreecommitdiff
path: root/src/9p_io.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-10-01 04:00:32 -0300
committerGabriel Schneider <[email protected]>2026-10-01 04:00:32 -0300
commit8dc84e6f9f1c3802f1d28de4d49907381cdf224b (patch)
tree3ed7727a61de9ae4c473413d81de3ac95844af78 /src/9p_io.zig
parenta4e17d350a7afdeee4916584c44c4770243c84e4 (diff)
downloadpardes-8dc84e6f9f1c3802f1d28de4d49907381cdf224b.tar.gz
pardes-8dc84e6f9f1c3802f1d28de4d49907381cdf224b.zip
pardes - asks /pager for its +Pager and reads the serial on the same open: another client's exec meanwhile can never take the text into its pane
pardes - wrote `pager <dir>` to /ctl, then read /exec on a fresh open, which answers the session's last answer: a client that exec'd in between had its pane overwritten by the paged text. /pager takes the directory and answers the +Pager's serial on the open that wrote it, as /pane/new answers its own open; the ctl verb is gone. Client.ask writes and reads on one open. The README's look recipe reads its answer on its own open too. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/9p_io.zig')
-rw-r--r--src/9p_io.zig26
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