diff options
Diffstat (limited to 'src/fs.zig')
| -rw-r--r-- | src/fs.zig | 17 |
1 files changed, 16 insertions, 1 deletions
@@ -159,7 +159,7 @@ pub fn osHandle(p: *pardes.Pardes, req: Req) Reply { const stat = stat: { pardes.turn.yield(); defer pardes.turn.back(); - break :stat std.Io.Dir.cwd().statFile(io, path, .{}) catch return Reply.fail(req.tag, E.NOENT); + break :stat statPath(io, path, .{}) catch return Reply.fail(req.tag, E.NOENT); }; const attr: Reply.Attr = .{ .name = if (req.node == os_root) "os" else std.fs.path.basename(path), .node = req.node, .dir = stat.kind == .directory, .size = stat.size, .mode = if (stat.kind == .directory) 0o755 else 0o644, .mtime = std.math.cast(u32, stat.mtime.toSeconds()) orelse 0 }; switch (req.op) { @@ -622,6 +622,21 @@ pub fn isVirtual(path: []const u8) bool { std.mem.eql(u8, path, "/n") or std.mem.startsWith(u8, path, "/n/"); } +/// std's `statFile`, but a name with a part over 255 bytes is NameTooLong: +/// std's own takes the kernel's ENAMETOOLONG for that for a bug and panics +/// (Io.Threaded dirStatFileLinux), and such a name comes from anyone who +/// writes one to `name`, `look` or DumpDir. +pub fn statPath(io: std.Io, path: []const u8, options: std.Io.Dir.StatFileOptions) !std.Io.File.Stat { + var parts = std.mem.tokenizeScalar(u8, path, '/'); + while (parts.next()) |part| if (part.len > 255) return error.NameTooLong; + return std.Io.Dir.cwd().statFile(io, path, options); +} + +test "a path with a part over 255 bytes is NameTooLong, never a panic" { + const long = "/tmp/" ++ "x" ** 300 ++ "/f"; + try std.testing.expectError(error.NameTooLong, statPath(std.testing.io, long, .{})); +} + pub fn localPath(path: []const u8) ?[]const u8 { if (std.mem.eql(u8, path, "/n/os")) return "/"; if (std.mem.startsWith(u8, path, "/n/os/")) return path[5..]; |
