summaryrefslogtreecommitdiff
path: root/src/fs.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs.zig')
-rw-r--r--src/fs.zig19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/fs.zig b/src/fs.zig
index 4414c150..6feaa972 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -224,12 +224,12 @@ pub fn osHandle(p: *pardes.Pardes, req: Req) Reply {
if (fd < 0) return Reply.fail(req.tag, E.PERM);
defer _ = libc.close(fd);
if (req.op == .setattr) {
- if (!req.truncate or req.off != 0 or libc.ftruncate(fd, 0) != 0) return Reply.fail(req.tag, E.INVAL);
+ if (!req.truncate or req.off != 0 or libc.ftruncate(fd, 0) != 0) return tree.failText(req.tag, E.INVAL, "invalid truncate: only to zero");
var truncated = attr;
truncated.size = 0;
return .{ .tag = req.tag, .attr = truncated };
}
- if (req.off > std.math.maxInt(i64)) return Reply.fail(req.tag, E.INVAL);
+ if (req.off > std.math.maxInt(i64)) return tree.failText(req.tag, E.INVAL, "invalid offset: past what a file may hold");
if (libc.lseek(fd, @intCast(req.off), libc.SEEK.SET) < 0) return Reply.fail(req.tag, E.IO);
if (req.op == .write) {
const written = libc.write(fd, req.data.ptr, req.data.len);
@@ -677,7 +677,9 @@ pub fn resolve(p: ?*pardes.Pardes, word: []const u8, cwd: []const u8, out: *[409
if (std.mem.startsWith(u8, joined, "/virtual/")) return resolveVirtual(p, joined[8..], out);
if (resolveOs(joined, out)) |found| return found;
if (resolveVirtual(p, joined, out)) |found| return found;
- if (resolveVirtual(p, word, out)) |found| return found;
+ // `.`, `..` and `./x` name the pane's directory, never the served tree:
+ // with that directory gone they name nothing (`.` would be /virtual/).
+ if (!dotRelative(word)) if (resolveVirtual(p, word, out)) |found| return found;
if (resolveEmbedded(word, cwd, out)) |source| {
const path = std.fmt.bufPrint(out, "/virtual/{s}", .{source.path}) catch return null;
return .{ .path = path };
@@ -685,6 +687,14 @@ pub fn resolve(p: ?*pardes.Pardes, word: []const u8, cwd: []const u8, out: *[409
return null;
}
+/// Whether `word` is spelled relative to the directory it is looked from:
+/// `.`, `..`, `./x`, `../x`.
+pub fn dotRelative(word: []const u8) bool {
+ const w = std.mem.trimEnd(u8, word, "/");
+ return std.mem.eql(u8, w, ".") or std.mem.eql(u8, w, "..") or
+ std.mem.startsWith(u8, word, "./") or std.mem.startsWith(u8, word, "../");
+}
+
/// Where a path really is on the host, and whether it is a directory. The
/// path may lie in a mount this editor serves, so the turn is given up for
/// the syscalls: another thread answers them.
@@ -1306,6 +1316,9 @@ pub const Namespace = struct {
/// The serial of the pane the root's exec or look last ran a line at
/// (the keyboard's), 0 before one: its err record names that pane.
ran_at: u32 = 0,
+ /// The output pane a search just filled again rather than made
+ /// (Output.fillResults): what an exec reads back.
+ refilled: ?u32 = null,
/// Every failure said (Messages.reportFailure), counted: a builtin
/// that said one while it ran failed.
failures: u32 = 0,