aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/which.zig23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/which.zig b/src/which.zig
index 9303d6503..189bbce43 100644
--- a/src/which.zig
+++ b/src/which.zig
@@ -6,15 +6,32 @@ fn isValid(buf: *[bun.MAX_PATH_BYTES]u8, segment: []const u8, bin: []const u8) ?
std.mem.copy(u8, buf[segment.len + 1 ..], bin);
buf[segment.len + 1 + bin.len ..][0] = 0;
const filepath = buf[0 .. segment.len + 1 + bin.len :0];
- // we cannot use access() here even though all we want to do now here is check it is executable
- // directories can be considered executable
- std.os.accessZ(filepath, std.os.X_OK) catch return null;
+ if (!checkPath(filepath)) return null;
return @intCast(u16, filepath.len);
}
+fn checkPath(filepath: [:0]const u8) bool {
+ std.os.accessZ(filepath, std.os.X_OK) catch return false;
+ return true;
+}
+
// Like /usr/bin/which but without needing to exec a child process
// Remember to resolve the symlink if necessary
pub fn which(buf: *[bun.MAX_PATH_BYTES]u8, path: []const u8, cwd: []const u8, bin: []const u8) ?[:0]const u8 {
+ if (bin.len == 0) return null;
+
+ // handle absolute paths
+ if (std.fs.path.isAbsolute(bin)) {
+ std.mem.copy(u8, buf, bin);
+ buf[bin.len] = 0;
+ var binZ: [:0]u8 = buf[0..bin.len :0];
+ if (checkPath(binZ)) return binZ;
+
+ // note that directories are often executable
+ // TODO: should we return null here? What about the case where ytou have
+ // /foo/bar/baz as a path and you're in /home/jarred?
+ }
+
if (isValid(buf, std.mem.trimRight(u8, cwd, std.fs.path.sep_str), bin)) |len| {
return buf[0..len :0];
}