windows: implement expandPath

This commit is contained in:
Will Pragnell
2023-09-14 18:31:46 -07:00
parent 57894786d4
commit d700fb6fc7

View File

@ -232,9 +232,19 @@ pub fn expandPath(alloc: Allocator, cmd: []const u8) !?[]u8 {
return try alloc.dupe(u8, cmd); return try alloc.dupe(u8, cmd);
} }
const PATH = os.getenvZ("PATH") orelse return null; const PATH = switch (builtin.os.tag) {
.windows => blk: {
const win_path = os.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse return null;
const path = try std.unicode.utf16leToUtf8Alloc(alloc, win_path);
break :blk path;
},
else => os.getenvZ("PATH") orelse return null,
};
defer if (builtin.os.tag == .windows) alloc.free(PATH);
var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
var it = std.mem.tokenize(u8, PATH, ":"); const path_separator = if (builtin.os.tag == .windows) ";" else ":";
var it = std.mem.tokenize(u8, PATH, path_separator);
var seen_eacces = false; var seen_eacces = false;
while (it.next()) |search_path| { while (it.next()) |search_path| {
// We need enough space in our path buffer to store this // We need enough space in our path buffer to store this
@ -243,7 +253,7 @@ pub fn expandPath(alloc: Allocator, cmd: []const u8) !?[]u8 {
// Copy in the full path // Copy in the full path
mem.copy(u8, &path_buf, search_path); mem.copy(u8, &path_buf, search_path);
path_buf[search_path.len] = '/'; path_buf[search_path.len] = if (builtin.os.tag == .windows) '\\' else '/';
mem.copy(u8, path_buf[search_path.len + 1 ..], cmd); mem.copy(u8, path_buf[search_path.len + 1 ..], cmd);
path_buf[path_len] = 0; path_buf[path_len] = 0;
const full_path = path_buf[0..path_len :0]; const full_path = path_buf[0..path_len :0];
@ -276,10 +286,12 @@ fn isExecutable(mode: std.fs.File.Mode) bool {
return mode & 0o0111 != 0; return mode & 0o0111 != 0;
} }
test "expandPath: env" { // `hostname` is present on both *nix and windows
const path = (try expandPath(testing.allocator, "env")).?; test "expandPath: hostname" {
const executable = if (builtin.os.tag == .windows) "hostname.exe" else "hostname";
const path = (try expandPath(testing.allocator, executable)).?;
defer testing.allocator.free(path); defer testing.allocator.free(path);
try testing.expect(path.len > 0); try testing.expect(path.len > executable.len);
} }
test "expandPath: does not exist" { test "expandPath: does not exist" {