diff options
Diffstat (limited to 'src/fs.zig')
| -rw-r--r-- | src/fs.zig | 20 |
1 files changed, 20 insertions, 0 deletions
@@ -685,6 +685,26 @@ pub fn makeDirs(dir: []const u8) void { _ = libc.mkdir(z[0..dir.len :0], 0o755); } +/// Whether `dir` is not there to make because one above it refuses: its +/// nearest ancestor that is there may not be searched or written (EACCES: +/// `noperm/a/b`, `/proc/1/root/x`). +pub fn deniedAbove(dir: []const u8) bool { + if (comptime !platform_has_fs) return false; + var at: ?[]const u8 = dir; + while (at) |d| : (at = std.fs.path.dirname(d)) { + var z: [4096]u8 = undefined; + const dz = std.fmt.bufPrintSentinel(&z, "{s}", .{d}, 0) catch return false; + if (libc.access(dz.ptr, 0) != 0) continue; // F_OK + return libc.access(dz.ptr, 2 | 1) != 0; // W_OK | X_OK + } + return false; +} + +test "a directory under one that may not be searched or written is denied, one merely missing is not" { + try std.testing.expect(deniedAbove("/proc/1/root/x/y")); + try std.testing.expect(!deniedAbove("/tmp/pardes-surely-missing-dir/a/b")); +} + 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..]; |
