authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-12 13:12:56-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:09-08:00
log6484101f7860988d2147b519c0c53b9fdc23b7c2
tree0a8a0e33a90bd8213b2cb542f0c5fc8d81d1c754
parent1ed845e1f6fabdde8795513de2d06bc9b573779c

update occurences of std.fs.openDirAbsolute


4 files changed, 146 insertions(+), 146 deletions(-)

lib/compiler/aro/aro/Diagnostics.zig+1-1
...@@ -292,7 +292,7 @@ const Diagnostics = @This();...@@ -292,7 +292,7 @@ const Diagnostics = @This();
292output: union(enum) {292output: union(enum) {
293 to_writer: struct {293 to_writer: struct {
294 writer: *std.Io.Writer,294 writer: *std.Io.Writer,
295 color: std.Io.tty.Config,295 color: std.Io.File.Writer.Mode,
296 },296 },
297 to_list: struct {297 to_list: struct {
298 messages: std.ArrayList(Message) = .empty,298 messages: std.ArrayList(Message) = .empty,
lib/std/crypto/Certificate/Bundle.zig+3-3
...@@ -9,8 +9,8 @@ const builtin = @import("builtin");...@@ -9,8 +9,8 @@ const builtin = @import("builtin");
99
10const std = @import("../../std.zig");10const std = @import("../../std.zig");
11const Io = std.Io;11const Io = std.Io;
12const Dir = std.Io.Dir;
12const assert = std.debug.assert;13const assert = std.debug.assert;
13const fs = std.fs;
14const mem = std.mem;14const mem = std.mem;
15const crypto = std.crypto;15const crypto = std.crypto;
16const Allocator = std.mem.Allocator;16const Allocator = std.mem.Allocator;
...@@ -192,8 +192,8 @@ pub fn addCertsFromDirPathAbsolute(...@@ -192,8 +192,8 @@ pub fn addCertsFromDirPathAbsolute(
192 now: Io.Timestamp,192 now: Io.Timestamp,
193 abs_dir_path: []const u8,193 abs_dir_path: []const u8,
194) AddCertsFromDirPathError!void {194) AddCertsFromDirPathError!void {
195 assert(fs.path.isAbsolute(abs_dir_path));195 assert(Dir.path.isAbsolute(abs_dir_path));
196 var iterable_dir = try fs.openDirAbsolute(abs_dir_path, .{ .iterate = true });196 var iterable_dir = try Dir.openDirAbsolute(io, abs_dir_path, .{ .iterate = true });
197 defer iterable_dir.close(io);197 defer iterable_dir.close(io);
198 return addCertsFromDir(cb, gpa, io, now, iterable_dir);198 return addCertsFromDir(cb, gpa, io, now, iterable_dir);
199}199}
lib/std/fs/test.zig+6-6
...@@ -346,7 +346,7 @@ test "openDirAbsolute" {...@@ -346,7 +346,7 @@ test "openDirAbsolute" {
346 defer testing.allocator.free(sub_path);346 defer testing.allocator.free(sub_path);
347347
348 // Can open sub_path348 // Can open sub_path
349 var tmp_sub = try fs.openDirAbsolute(sub_path, .{});349 var tmp_sub = try Dir.openDirAbsolute(io, sub_path, .{});
350 defer tmp_sub.close(io);350 defer tmp_sub.close(io);
351351
352 const sub_ino = (try tmp_sub.stat(io)).inode;352 const sub_ino = (try tmp_sub.stat(io)).inode;
...@@ -356,7 +356,7 @@ test "openDirAbsolute" {...@@ -356,7 +356,7 @@ test "openDirAbsolute" {
356 const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".." });356 const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".." });
357 defer testing.allocator.free(dir_path);357 defer testing.allocator.free(dir_path);
358358
359 var dir = try fs.openDirAbsolute(dir_path, .{});359 var dir = try Dir.openDirAbsolute(io, dir_path, .{});
360 defer dir.close(io);360 defer dir.close(io);
361361
362 const ino = (try dir.stat(io)).inode;362 const ino = (try dir.stat(io)).inode;
...@@ -368,7 +368,7 @@ test "openDirAbsolute" {...@@ -368,7 +368,7 @@ test "openDirAbsolute" {
368 const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, "." });368 const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, "." });
369 defer testing.allocator.free(dir_path);369 defer testing.allocator.free(dir_path);
370370
371 var dir = try fs.openDirAbsolute(dir_path, .{});371 var dir = try Dir.openDirAbsolute(io, dir_path, .{});
372 defer dir.close(io);372 defer dir.close(io);
373373
374 const ino = (try dir.stat(io)).inode;374 const ino = (try dir.stat(io)).inode;
...@@ -380,7 +380,7 @@ test "openDirAbsolute" {...@@ -380,7 +380,7 @@ test "openDirAbsolute" {
380 const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".", "..", "." });380 const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".", "..", "." });
381 defer testing.allocator.free(dir_path);381 defer testing.allocator.free(dir_path);
382382
383 var dir = try fs.openDirAbsolute(dir_path, .{});383 var dir = try Dir.openDirAbsolute(io, dir_path, .{});
384 defer dir.close(io);384 defer dir.close(io);
385385
386 const ino = (try dir.stat(io)).inode;386 const ino = (try dir.stat(io)).inode;
...@@ -1978,7 +1978,7 @@ test "'.' and '..' in absolute functions" {...@@ -1978,7 +1978,7 @@ test "'.' and '..' in absolute functions" {
1978 const subdir_path = try fs.path.join(allocator, &.{ base_path, "./subdir" });1978 const subdir_path = try fs.path.join(allocator, &.{ base_path, "./subdir" });
1979 try fs.makeDirAbsolute(subdir_path);1979 try fs.makeDirAbsolute(subdir_path);
1980 try fs.accessAbsolute(subdir_path, .{});1980 try fs.accessAbsolute(subdir_path, .{});
1981 var created_subdir = try fs.openDirAbsolute(subdir_path, .{});1981 var created_subdir = try Dir.openDirAbsolute(io, subdir_path, .{});
1982 created_subdir.close(io);1982 created_subdir.close(io);
19831983
1984 const created_file_path = try fs.path.join(allocator, &.{ subdir_path, "../file" });1984 const created_file_path = try fs.path.join(allocator, &.{ subdir_path, "../file" });
...@@ -2108,7 +2108,7 @@ test "invalid UTF-8/WTF-8 paths" {...@@ -2108,7 +2108,7 @@ test "invalid UTF-8/WTF-8 paths" {
2108 try expectError(expected_err, Dir.makeDirAbsolute(invalid_path));2108 try expectError(expected_err, Dir.makeDirAbsolute(invalid_path));
2109 try expectError(expected_err, Dir.deleteDirAbsolute(invalid_path));2109 try expectError(expected_err, Dir.deleteDirAbsolute(invalid_path));
2110 try expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path));2110 try expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path));
2111 try expectError(expected_err, Dir.openDirAbsolute(invalid_path, .{}));2111 try expectError(expected_err, Dir.openDirAbsolute(io, invalid_path, .{}));
2112 try expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{}));2112 try expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{}));
2113 try expectError(expected_err, Dir.accessAbsolute(invalid_path, .{}));2113 try expectError(expected_err, Dir.accessAbsolute(invalid_path, .{}));
2114 try expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{}));2114 try expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{}));
lib/std/zig/WindowsSdk.zig+136-136
...@@ -3,6 +3,7 @@ const builtin = @import("builtin");...@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33
4const std = @import("std");4const std = @import("std");
5const Io = std.Io;5const Io = std.Io;
6const Dir = std.Io.Dir;
6const Writer = std.Io.Writer;7const Writer = std.Io.Writer;
7const Allocator = std.mem.Allocator;8const Allocator = std.mem.Allocator;
89
...@@ -22,8 +23,8 @@ const product_version_max_length = version_major_minor_max_length + ".65535".len...@@ -22,8 +23,8 @@ const product_version_max_length = version_major_minor_max_length + ".65535".len
2223
23/// Find path and version of Windows 10 SDK and Windows 8.1 SDK, and find path to MSVC's `lib/` directory.24/// Find path and version of Windows 10 SDK and Windows 8.1 SDK, and find path to MSVC's `lib/` directory.
24/// Caller owns the result's fields.25/// Caller owns the result's fields.
25/// After finishing work, call `free(allocator)`.26/// Returns memory allocated by `gpa`
26pub fn find(allocator: Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk {27pub fn find(gpa: Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk {
27 if (builtin.os.tag != .windows) return error.NotFound;28 if (builtin.os.tag != .windows) return error.NotFound;
2829
29 //note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed30 //note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed
...@@ -32,27 +33,27 @@ pub fn find(allocator: Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory,...@@ -32,27 +33,27 @@ pub fn find(allocator: Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory,
32 };33 };
33 defer roots_key.closeKey();34 defer roots_key.closeKey();
3435
35 const windows10sdk = Installation.find(allocator, roots_key, "KitsRoot10", "", "v10.0") catch |err| switch (err) {36 const windows10sdk = Installation.find(gpa, roots_key, "KitsRoot10", "", "v10.0") catch |err| switch (err) {
36 error.InstallationNotFound => null,37 error.InstallationNotFound => null,
37 error.PathTooLong => null,38 error.PathTooLong => null,
38 error.VersionTooLong => null,39 error.VersionTooLong => null,
39 error.OutOfMemory => return error.OutOfMemory,40 error.OutOfMemory => return error.OutOfMemory,
40 };41 };
41 errdefer if (windows10sdk) |*w| w.free(allocator);42 errdefer if (windows10sdk) |*w| w.free(gpa);
4243
43 const windows81sdk = Installation.find(allocator, roots_key, "KitsRoot81", "winver", "v8.1") catch |err| switch (err) {44 const windows81sdk = Installation.find(gpa, roots_key, "KitsRoot81", "winver", "v8.1") catch |err| switch (err) {
44 error.InstallationNotFound => null,45 error.InstallationNotFound => null,
45 error.PathTooLong => null,46 error.PathTooLong => null,
46 error.VersionTooLong => null,47 error.VersionTooLong => null,
47 error.OutOfMemory => return error.OutOfMemory,48 error.OutOfMemory => return error.OutOfMemory,
48 };49 };
49 errdefer if (windows81sdk) |*w| w.free(allocator);50 errdefer if (windows81sdk) |*w| w.free(gpa);
5051
51 const msvc_lib_dir: ?[]const u8 = MsvcLibDir.find(allocator, arch) catch |err| switch (err) {52 const msvc_lib_dir: ?[]const u8 = MsvcLibDir.find(gpa, arch) catch |err| switch (err) {
52 error.MsvcLibDirNotFound => null,53 error.MsvcLibDirNotFound => null,
53 error.OutOfMemory => return error.OutOfMemory,54 error.OutOfMemory => return error.OutOfMemory,
54 };55 };
55 errdefer allocator.free(msvc_lib_dir);56 errdefer gpa.free(msvc_lib_dir);
5657
57 return .{58 return .{
58 .windows10sdk = windows10sdk,59 .windows10sdk = windows10sdk,
...@@ -61,15 +62,15 @@ pub fn find(allocator: Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory,...@@ -61,15 +62,15 @@ pub fn find(allocator: Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory,
61 };62 };
62}63}
6364
64pub fn free(sdk: WindowsSdk, allocator: Allocator) void {65pub fn free(sdk: WindowsSdk, gpa: Allocator) void {
65 if (sdk.windows10sdk) |*w10sdk| {66 if (sdk.windows10sdk) |*w10sdk| {
66 w10sdk.free(allocator);67 w10sdk.free(gpa);
67 }68 }
68 if (sdk.windows81sdk) |*w81sdk| {69 if (sdk.windows81sdk) |*w81sdk| {
69 w81sdk.free(allocator);70 w81sdk.free(gpa);
70 }71 }
71 if (sdk.msvc_lib_dir) |msvc_lib_dir| {72 if (sdk.msvc_lib_dir) |msvc_lib_dir| {
72 allocator.free(msvc_lib_dir);73 gpa.free(msvc_lib_dir);
73 }74 }
74}75}
7576
...@@ -77,8 +78,8 @@ pub fn free(sdk: WindowsSdk, allocator: Allocator) void {...@@ -77,8 +78,8 @@ pub fn free(sdk: WindowsSdk, allocator: Allocator) void {
77/// and a version. Returns slice of version strings sorted in descending order.78/// and a version. Returns slice of version strings sorted in descending order.
78/// Caller owns result.79/// Caller owns result.
79fn iterateAndFilterByVersion(80fn iterateAndFilterByVersion(
80 iterator: *Io.Dir.Iterator,81 iterator: *Dir.Iterator,
81 allocator: Allocator,82 gpa: Allocator,
82 prefix: []const u8,83 prefix: []const u8,
83) error{OutOfMemory}![][]const u8 {84) error{OutOfMemory}![][]const u8 {
84 const Version = struct {85 const Version = struct {
...@@ -95,11 +96,11 @@ fn iterateAndFilterByVersion(...@@ -95,11 +96,11 @@ fn iterateAndFilterByVersion(
95 std.mem.order(u8, lhs.build, rhs.build);96 std.mem.order(u8, lhs.build, rhs.build);
96 }97 }
97 };98 };
98 var versions = std.array_list.Managed(Version).init(allocator);99 var versions = std.array_list.Managed(Version).init(gpa);
99 var dirs = std.array_list.Managed([]const u8).init(allocator);100 var dirs = std.array_list.Managed([]const u8).init(gpa);
100 defer {101 defer {
101 versions.deinit();102 versions.deinit();
102 for (dirs.items) |filtered_dir| allocator.free(filtered_dir);103 for (dirs.items) |filtered_dir| gpa.free(filtered_dir);
103 dirs.deinit();104 dirs.deinit();
104 }105 }
105106
...@@ -119,8 +120,8 @@ fn iterateAndFilterByVersion(...@@ -119,8 +120,8 @@ fn iterateAndFilterByVersion(
119 num.* = Version.parseNum(num_it.next() orelse break) orelse continue :iterate120 num.* = Version.parseNum(num_it.next() orelse break) orelse continue :iterate
120 else if (num_it.next()) |_| continue;121 else if (num_it.next()) |_| continue;
121122
122 const name = try allocator.dupe(u8, suffix);123 const name = try gpa.dupe(u8, suffix);
123 errdefer allocator.free(name);124 errdefer gpa.free(name);
124 if (underscore) |pos| version.build = name[pos + 1 ..];125 if (underscore) |pos| version.build = name[pos + 1 ..];
125126
126 try versions.append(version);127 try versions.append(version);
...@@ -177,7 +178,7 @@ const RegistryWtf8 = struct {...@@ -177,7 +178,7 @@ const RegistryWtf8 = struct {
177178
178 /// Get string from registry.179 /// Get string from registry.
179 /// Caller owns result.180 /// Caller owns result.
180 pub fn getString(reg: RegistryWtf8, allocator: Allocator, subkey: []const u8, value_name: []const u8) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]u8 {181 pub fn getString(reg: RegistryWtf8, gpa: Allocator, subkey: []const u8, value_name: []const u8) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]u8 {
181 const subkey_wtf16le: [:0]const u16 = subkey_wtf16le: {182 const subkey_wtf16le: [:0]const u16 = subkey_wtf16le: {
182 var subkey_wtf16le_buf: [RegistryWtf16Le.key_name_max_len]u16 = undefined;183 var subkey_wtf16le_buf: [RegistryWtf16Le.key_name_max_len]u16 = undefined;
183 const subkey_wtf16le_len: usize = std.unicode.wtf8ToWtf16Le(subkey_wtf16le_buf[0..], subkey) catch unreachable;184 const subkey_wtf16le_len: usize = std.unicode.wtf8ToWtf16Le(subkey_wtf16le_buf[0..], subkey) catch unreachable;
...@@ -193,11 +194,11 @@ const RegistryWtf8 = struct {...@@ -193,11 +194,11 @@ const RegistryWtf8 = struct {
193 };194 };
194195
195 const registry_wtf16le: RegistryWtf16Le = .{ .key = reg.key };196 const registry_wtf16le: RegistryWtf16Le = .{ .key = reg.key };
196 const value_wtf16le = try registry_wtf16le.getString(allocator, subkey_wtf16le, value_name_wtf16le);197 const value_wtf16le = try registry_wtf16le.getString(gpa, subkey_wtf16le, value_name_wtf16le);
197 defer allocator.free(value_wtf16le);198 defer gpa.free(value_wtf16le);
198199
199 const value_wtf8: []u8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, value_wtf16le);200 const value_wtf8: []u8 = try std.unicode.wtf16LeToWtf8Alloc(gpa, value_wtf16le);
200 errdefer allocator.free(value_wtf8);201 errdefer gpa.free(value_wtf8);
201202
202 return value_wtf8;203 return value_wtf8;
203 }204 }
...@@ -285,7 +286,7 @@ const RegistryWtf16Le = struct {...@@ -285,7 +286,7 @@ const RegistryWtf16Le = struct {
285 }286 }
286287
287 /// Get string ([:0]const u16) from registry.288 /// Get string ([:0]const u16) from registry.
288 fn getString(reg: RegistryWtf16Le, allocator: Allocator, subkey_wtf16le: [:0]const u16, value_name_wtf16le: [:0]const u16) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]const u16 {289 fn getString(reg: RegistryWtf16Le, gpa: Allocator, subkey_wtf16le: [:0]const u16, value_name_wtf16le: [:0]const u16) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]const u16 {
289 var actual_type: windows.ULONG = undefined;290 var actual_type: windows.ULONG = undefined;
290291
291 // Calculating length to allocate292 // Calculating length to allocate
...@@ -314,8 +315,8 @@ const RegistryWtf16Le = struct {...@@ -314,8 +315,8 @@ const RegistryWtf16Le = struct {
314 else => return error.NotAString,315 else => return error.NotAString,
315 }316 }
316317
317 const value_wtf16le_buf: []u16 = try allocator.alloc(u16, std.math.divCeil(u32, value_wtf16le_buf_size, 2) catch unreachable);318 const value_wtf16le_buf: []u16 = try gpa.alloc(u16, std.math.divCeil(u32, value_wtf16le_buf_size, 2) catch unreachable);
318 errdefer allocator.free(value_wtf16le_buf);319 errdefer gpa.free(value_wtf16le_buf);
319320
320 return_code_int = windows.advapi32.RegGetValueW(321 return_code_int = windows.advapi32.RegGetValueW(
321 reg.key,322 reg.key,
...@@ -349,7 +350,7 @@ const RegistryWtf16Le = struct {...@@ -349,7 +350,7 @@ const RegistryWtf16Le = struct {
349 break :value_wtf16le std.mem.span(value_wtf16le_overestimated);350 break :value_wtf16le std.mem.span(value_wtf16le_overestimated);
350 };351 };
351352
352 _ = allocator.resize(value_wtf16le_buf, value_wtf16le.len);353 _ = gpa.resize(value_wtf16le_buf, value_wtf16le.len);
353 return value_wtf16le;354 return value_wtf16le;
354 }355 }
355356
...@@ -417,66 +418,65 @@ pub const Installation = struct {...@@ -417,66 +418,65 @@ pub const Installation = struct {
417418
418 /// Find path and version of Windows SDK.419 /// Find path and version of Windows SDK.
419 /// Caller owns the result's fields.420 /// Caller owns the result's fields.
420 /// After finishing work, call `free(allocator)`.
421 fn find(421 fn find(
422 allocator: Allocator,422 gpa: Allocator,
423 roots_key: RegistryWtf8,423 roots_key: RegistryWtf8,
424 roots_subkey: []const u8,424 roots_subkey: []const u8,
425 prefix: []const u8,425 prefix: []const u8,
426 version_key_name: []const u8,426 version_key_name: []const u8,
427 ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation {427 ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation {
428 roots: {428 roots: {
429 const installation = findFromRoot(allocator, roots_key, roots_subkey, prefix) catch429 const installation = findFromRoot(gpa, roots_key, roots_subkey, prefix) catch
430 break :roots;430 break :roots;
431 if (installation.isValidVersion()) return installation;431 if (installation.isValidVersion()) return installation;
432 installation.free(allocator);432 installation.free(gpa);
433 }433 }
434 {434 {
435 const installation = try findFromInstallationFolder(allocator, version_key_name);435 const installation = try findFromInstallationFolder(gpa, version_key_name);
436 if (installation.isValidVersion()) return installation;436 if (installation.isValidVersion()) return installation;
437 installation.free(allocator);437 installation.free(gpa);
438 }438 }
439 return error.InstallationNotFound;439 return error.InstallationNotFound;
440 }440 }
441441
442 fn findFromRoot(442 fn findFromRoot(
443 allocator: Allocator,443 gpa: Allocator,
444 io: Io,444 io: Io,
445 roots_key: RegistryWtf8,445 roots_key: RegistryWtf8,
446 roots_subkey: []const u8,446 roots_subkey: []const u8,
447 prefix: []const u8,447 prefix: []const u8,
448 ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation {448 ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation {
449 const path = path: {449 const path = path: {
450 const path_maybe_with_trailing_slash = roots_key.getString(allocator, "", roots_subkey) catch |err| switch (err) {450 const path_maybe_with_trailing_slash = roots_key.getString(gpa, "", roots_subkey) catch |err| switch (err) {
451 error.NotAString => return error.InstallationNotFound,451 error.NotAString => return error.InstallationNotFound,
452 error.ValueNameNotFound => return error.InstallationNotFound,452 error.ValueNameNotFound => return error.InstallationNotFound,
453 error.StringNotFound => return error.InstallationNotFound,453 error.StringNotFound => return error.InstallationNotFound,
454454
455 error.OutOfMemory => return error.OutOfMemory,455 error.OutOfMemory => return error.OutOfMemory,
456 };456 };
457 if (path_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(path_maybe_with_trailing_slash)) {457 if (path_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(path_maybe_with_trailing_slash)) {
458 allocator.free(path_maybe_with_trailing_slash);458 gpa.free(path_maybe_with_trailing_slash);
459 return error.PathTooLong;459 return error.PathTooLong;
460 }460 }
461461
462 var path = std.array_list.Managed(u8).fromOwnedSlice(allocator, path_maybe_with_trailing_slash);462 var path = std.array_list.Managed(u8).fromOwnedSlice(gpa, path_maybe_with_trailing_slash);
463 errdefer path.deinit();463 errdefer path.deinit();
464464
465 // String might contain trailing slash, so trim it here465 // String might contain trailing slash, so trim it here
466 if (path.items.len > "C:\\".len and path.getLast() == '\\') _ = path.pop();466 if (path.items.len > "C:\\".len and path.getLast() == '\\') _ = path.pop();
467 break :path try path.toOwnedSlice();467 break :path try path.toOwnedSlice();
468 };468 };
469 errdefer allocator.free(path);469 errdefer gpa.free(path);
470470
471 const version = version: {471 const version = version: {
472 var buf: [std.fs.max_path_bytes]u8 = undefined;472 var buf: [Dir.max_path_bytes]u8 = undefined;
473 const sdk_lib_dir_path = std.fmt.bufPrint(buf[0..], "{s}\\Lib\\", .{path}) catch |err| switch (err) {473 const sdk_lib_dir_path = std.fmt.bufPrint(buf[0..], "{s}\\Lib\\", .{path}) catch |err| switch (err) {
474 error.NoSpaceLeft => return error.PathTooLong,474 error.NoSpaceLeft => return error.PathTooLong,
475 };475 };
476 if (!std.fs.path.isAbsolute(sdk_lib_dir_path)) return error.InstallationNotFound;476 if (!Dir.path.isAbsolute(sdk_lib_dir_path)) return error.InstallationNotFound;
477477
478 // enumerate files in sdk path looking for latest version478 // enumerate files in sdk path looking for latest version
479 var sdk_lib_dir = std.fs.openDirAbsolute(sdk_lib_dir_path, .{479 var sdk_lib_dir = Dir.openDirAbsolute(io, sdk_lib_dir_path, .{
480 .iterate = true,480 .iterate = true,
481 }) catch |err| switch (err) {481 }) catch |err| switch (err) {
482 error.NameTooLong => return error.PathTooLong,482 error.NameTooLong => return error.PathTooLong,
...@@ -485,21 +485,21 @@ pub const Installation = struct {...@@ -485,21 +485,21 @@ pub const Installation = struct {
485 defer sdk_lib_dir.close(io);485 defer sdk_lib_dir.close(io);
486486
487 var iterator = sdk_lib_dir.iterate();487 var iterator = sdk_lib_dir.iterate();
488 const versions = try iterateAndFilterByVersion(&iterator, allocator, prefix);488 const versions = try iterateAndFilterByVersion(&iterator, gpa, prefix);
489 if (versions.len == 0) return error.InstallationNotFound;489 if (versions.len == 0) return error.InstallationNotFound;
490 defer {490 defer {
491 for (versions[1..]) |version| allocator.free(version);491 for (versions[1..]) |version| gpa.free(version);
492 allocator.free(versions);492 gpa.free(versions);
493 }493 }
494 break :version versions[0];494 break :version versions[0];
495 };495 };
496 errdefer allocator.free(version);496 errdefer gpa.free(version);
497497
498 return .{ .path = path, .version = version };498 return .{ .path = path, .version = version };
499 }499 }
500500
501 fn findFromInstallationFolder(501 fn findFromInstallationFolder(
502 allocator: Allocator,502 gpa: Allocator,
503 version_key_name: []const u8,503 version_key_name: []const u8,
504 ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation {504 ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation {
505 var key_name_buf: [RegistryWtf16Le.key_name_max_len]u8 = undefined;505 var key_name_buf: [RegistryWtf16Le.key_name_max_len]u8 = undefined;
...@@ -518,7 +518,7 @@ pub const Installation = struct {...@@ -518,7 +518,7 @@ pub const Installation = struct {
518 defer key.closeKey();518 defer key.closeKey();
519519
520 const path: []const u8 = path: {520 const path: []const u8 = path: {
521 const path_maybe_with_trailing_slash = key.getString(allocator, "", "InstallationFolder") catch |err| switch (err) {521 const path_maybe_with_trailing_slash = key.getString(gpa, "", "InstallationFolder") catch |err| switch (err) {
522 error.NotAString => return error.InstallationNotFound,522 error.NotAString => return error.InstallationNotFound,
523 error.ValueNameNotFound => return error.InstallationNotFound,523 error.ValueNameNotFound => return error.InstallationNotFound,
524 error.StringNotFound => return error.InstallationNotFound,524 error.StringNotFound => return error.InstallationNotFound,
...@@ -526,12 +526,12 @@ pub const Installation = struct {...@@ -526,12 +526,12 @@ pub const Installation = struct {
526 error.OutOfMemory => return error.OutOfMemory,526 error.OutOfMemory => return error.OutOfMemory,
527 };527 };
528528
529 if (path_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(path_maybe_with_trailing_slash)) {529 if (path_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(path_maybe_with_trailing_slash)) {
530 allocator.free(path_maybe_with_trailing_slash);530 gpa.free(path_maybe_with_trailing_slash);
531 return error.PathTooLong;531 return error.PathTooLong;
532 }532 }
533533
534 var path = std.array_list.Managed(u8).fromOwnedSlice(allocator, path_maybe_with_trailing_slash);534 var path = std.array_list.Managed(u8).fromOwnedSlice(gpa, path_maybe_with_trailing_slash);
535 errdefer path.deinit();535 errdefer path.deinit();
536536
537 // String might contain trailing slash, so trim it here537 // String might contain trailing slash, so trim it here
...@@ -540,12 +540,12 @@ pub const Installation = struct {...@@ -540,12 +540,12 @@ pub const Installation = struct {
540 const path_without_trailing_slash = try path.toOwnedSlice();540 const path_without_trailing_slash = try path.toOwnedSlice();
541 break :path path_without_trailing_slash;541 break :path path_without_trailing_slash;
542 };542 };
543 errdefer allocator.free(path);543 errdefer gpa.free(path);
544544
545 const version: []const u8 = version: {545 const version: []const u8 = version: {
546546
547 // note(dimenus): Microsoft doesn't include the .0 in the ProductVersion key....547 // note(dimenus): Microsoft doesn't include the .0 in the ProductVersion key....
548 const version_without_0 = key.getString(allocator, "", "ProductVersion") catch |err| switch (err) {548 const version_without_0 = key.getString(gpa, "", "ProductVersion") catch |err| switch (err) {
549 error.NotAString => return error.InstallationNotFound,549 error.NotAString => return error.InstallationNotFound,
550 error.ValueNameNotFound => return error.InstallationNotFound,550 error.ValueNameNotFound => return error.InstallationNotFound,
551 error.StringNotFound => return error.InstallationNotFound,551 error.StringNotFound => return error.InstallationNotFound,
...@@ -553,11 +553,11 @@ pub const Installation = struct {...@@ -553,11 +553,11 @@ pub const Installation = struct {
553 error.OutOfMemory => return error.OutOfMemory,553 error.OutOfMemory => return error.OutOfMemory,
554 };554 };
555 if (version_without_0.len + ".0".len > product_version_max_length) {555 if (version_without_0.len + ".0".len > product_version_max_length) {
556 allocator.free(version_without_0);556 gpa.free(version_without_0);
557 return error.VersionTooLong;557 return error.VersionTooLong;
558 }558 }
559559
560 var version = std.array_list.Managed(u8).fromOwnedSlice(allocator, version_without_0);560 var version = std.array_list.Managed(u8).fromOwnedSlice(gpa, version_without_0);
561 errdefer version.deinit();561 errdefer version.deinit();
562562
563 try version.appendSlice(".0");563 try version.appendSlice(".0");
...@@ -565,14 +565,14 @@ pub const Installation = struct {...@@ -565,14 +565,14 @@ pub const Installation = struct {
565 const version_with_0 = try version.toOwnedSlice();565 const version_with_0 = try version.toOwnedSlice();
566 break :version version_with_0;566 break :version version_with_0;
567 };567 };
568 errdefer allocator.free(version);568 errdefer gpa.free(version);
569569
570 return .{ .path = path, .version = version };570 return .{ .path = path, .version = version };
571 }571 }
572572
573 /// Check whether this version is enumerated in registry.573 /// Check whether this version is enumerated in registry.
574 fn isValidVersion(installation: Installation) bool {574 fn isValidVersion(installation: Installation) bool {
575 var buf: [std.fs.max_path_bytes]u8 = undefined;575 var buf: [Dir.max_path_bytes]u8 = undefined;
576 const reg_query_as_wtf8 = std.fmt.bufPrint(buf[0..], "{s}\\{s}\\Installed Options", .{576 const reg_query_as_wtf8 = std.fmt.bufPrint(buf[0..], "{s}\\{s}\\Installed Options", .{
577 windows_kits_reg_key,577 windows_kits_reg_key,
578 installation.version,578 installation.version,
...@@ -601,21 +601,21 @@ pub const Installation = struct {...@@ -601,21 +601,21 @@ pub const Installation = struct {
601 return (reg_value == 1);601 return (reg_value == 1);
602 }602 }
603603
604 fn free(install: Installation, allocator: Allocator) void {604 fn free(install: Installation, gpa: Allocator) void {
605 allocator.free(install.path);605 gpa.free(install.path);
606 allocator.free(install.version);606 gpa.free(install.version);
607 }607 }
608};608};
609609
610const MsvcLibDir = struct {610const MsvcLibDir = struct {
611 fn findInstancesDirViaSetup(allocator: Allocator) error{ OutOfMemory, PathNotFound }!Io.Dir {611 fn findInstancesDirViaSetup(gpa: Allocator, io: Io) error{ OutOfMemory, PathNotFound }!Dir {
612 const vs_setup_key_path = "SOFTWARE\\Microsoft\\VisualStudio\\Setup";612 const vs_setup_key_path = "SOFTWARE\\Microsoft\\VisualStudio\\Setup";
613 const vs_setup_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, vs_setup_key_path, .{}) catch |err| switch (err) {613 const vs_setup_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, vs_setup_key_path, .{}) catch |err| switch (err) {
614 error.KeyNotFound => return error.PathNotFound,614 error.KeyNotFound => return error.PathNotFound,
615 };615 };
616 defer vs_setup_key.closeKey();616 defer vs_setup_key.closeKey();
617617
618 const packages_path = vs_setup_key.getString(allocator, "", "CachePath") catch |err| switch (err) {618 const packages_path = vs_setup_key.getString(gpa, "", "CachePath") catch |err| switch (err) {
619 error.NotAString,619 error.NotAString,
620 error.ValueNameNotFound,620 error.ValueNameNotFound,
621 error.StringNotFound,621 error.StringNotFound,
...@@ -623,24 +623,24 @@ const MsvcLibDir = struct {...@@ -623,24 +623,24 @@ const MsvcLibDir = struct {
623623
624 error.OutOfMemory => return error.OutOfMemory,624 error.OutOfMemory => return error.OutOfMemory,
625 };625 };
626 defer allocator.free(packages_path);626 defer gpa.free(packages_path);
627627
628 if (!std.fs.path.isAbsolute(packages_path)) return error.PathNotFound;628 if (!Dir.path.isAbsolute(packages_path)) return error.PathNotFound;
629629
630 const instances_path = try std.fs.path.join(allocator, &.{ packages_path, "_Instances" });630 const instances_path = try Dir.path.join(gpa, &.{ packages_path, "_Instances" });
631 defer allocator.free(instances_path);631 defer gpa.free(instances_path);
632632
633 return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound;633 return Dir.openDirAbsolute(io, instances_path, .{ .iterate = true }) catch return error.PathNotFound;
634 }634 }
635635
636 fn findInstancesDirViaCLSID(allocator: Allocator) error{ OutOfMemory, PathNotFound }!Io.Dir {636 fn findInstancesDirViaCLSID(gpa: Allocator, io: Io) error{ OutOfMemory, PathNotFound }!Dir {
637 const setup_configuration_clsid = "{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}";637 const setup_configuration_clsid = "{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}";
638 const setup_config_key = RegistryWtf8.openKey(windows.HKEY_CLASSES_ROOT, "CLSID\\" ++ setup_configuration_clsid, .{}) catch |err| switch (err) {638 const setup_config_key = RegistryWtf8.openKey(windows.HKEY_CLASSES_ROOT, "CLSID\\" ++ setup_configuration_clsid, .{}) catch |err| switch (err) {
639 error.KeyNotFound => return error.PathNotFound,639 error.KeyNotFound => return error.PathNotFound,
640 };640 };
641 defer setup_config_key.closeKey();641 defer setup_config_key.closeKey();
642642
643 const dll_path = setup_config_key.getString(allocator, "InprocServer32", "") catch |err| switch (err) {643 const dll_path = setup_config_key.getString(gpa, "InprocServer32", "") catch |err| switch (err) {
644 error.NotAString,644 error.NotAString,
645 error.ValueNameNotFound,645 error.ValueNameNotFound,
646 error.StringNotFound,646 error.StringNotFound,
...@@ -648,11 +648,11 @@ const MsvcLibDir = struct {...@@ -648,11 +648,11 @@ const MsvcLibDir = struct {
648648
649 error.OutOfMemory => return error.OutOfMemory,649 error.OutOfMemory => return error.OutOfMemory,
650 };650 };
651 defer allocator.free(dll_path);651 defer gpa.free(dll_path);
652652
653 if (!std.fs.path.isAbsolute(dll_path)) return error.PathNotFound;653 if (!Dir.path.isAbsolute(dll_path)) return error.PathNotFound;
654654
655 var path_it = std.fs.path.componentIterator(dll_path);655 var path_it = Dir.path.componentIterator(dll_path);
656 // the .dll filename656 // the .dll filename
657 _ = path_it.last();657 _ = path_it.last();
658 const root_path = while (path_it.previous()) |dir_component| {658 const root_path = while (path_it.previous()) |dir_component| {
...@@ -663,17 +663,17 @@ const MsvcLibDir = struct {...@@ -663,17 +663,17 @@ const MsvcLibDir = struct {
663 return error.PathNotFound;663 return error.PathNotFound;
664 };664 };
665665
666 const instances_path = try std.fs.path.join(allocator, &.{ root_path, "Packages", "_Instances" });666 const instances_path = try Dir.path.join(gpa, &.{ root_path, "Packages", "_Instances" });
667 defer allocator.free(instances_path);667 defer gpa.free(instances_path);
668668
669 return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound;669 return Dir.openDirAbsolute(io, instances_path, .{ .iterate = true }) catch return error.PathNotFound;
670 }670 }
671671
672 fn findInstancesDir(allocator: Allocator) error{ OutOfMemory, PathNotFound }!Io.Dir {672 fn findInstancesDir(gpa: Allocator, io: Io) error{ OutOfMemory, PathNotFound }!Dir {
673 // First, try getting the packages cache path from the registry.673 // First, try getting the packages cache path from the registry.
674 // This only seems to exist when the path is different from the default.674 // This only seems to exist when the path is different from the default.
675 method1: {675 method1: {
676 return findInstancesDirViaSetup(allocator) catch |err| switch (err) {676 return findInstancesDirViaSetup(gpa) catch |err| switch (err) {
677 error.OutOfMemory => |e| return e,677 error.OutOfMemory => |e| return e,
678 error.PathNotFound => break :method1,678 error.PathNotFound => break :method1,
679 };679 };
...@@ -681,7 +681,7 @@ const MsvcLibDir = struct {...@@ -681,7 +681,7 @@ const MsvcLibDir = struct {
681 // Otherwise, try to get the path from the .dll that would have been681 // Otherwise, try to get the path from the .dll that would have been
682 // loaded via COM for SetupConfiguration.682 // loaded via COM for SetupConfiguration.
683 method2: {683 method2: {
684 return findInstancesDirViaCLSID(allocator) catch |err| switch (err) {684 return findInstancesDirViaCLSID(gpa, io) catch |err| switch (err) {
685 error.OutOfMemory => |e| return e,685 error.OutOfMemory => |e| return e,
686 error.PathNotFound => break :method2,686 error.PathNotFound => break :method2,
687 };687 };
...@@ -689,19 +689,19 @@ const MsvcLibDir = struct {...@@ -689,19 +689,19 @@ const MsvcLibDir = struct {
689 // If that can't be found, fall back to manually appending689 // If that can't be found, fall back to manually appending
690 // `Microsoft\VisualStudio\Packages\_Instances` to %PROGRAMDATA%690 // `Microsoft\VisualStudio\Packages\_Instances` to %PROGRAMDATA%
691 method3: {691 method3: {
692 const program_data = std.process.getEnvVarOwned(allocator, "PROGRAMDATA") catch |err| switch (err) {692 const program_data = std.process.getEnvVarOwned(gpa, "PROGRAMDATA") catch |err| switch (err) {
693 error.OutOfMemory => |e| return e,693 error.OutOfMemory => |e| return e,
694 error.InvalidWtf8 => unreachable,694 error.InvalidWtf8 => unreachable,
695 error.EnvironmentVariableNotFound => break :method3,695 error.EnvironmentVariableNotFound => break :method3,
696 };696 };
697 defer allocator.free(program_data);697 defer gpa.free(program_data);
698698
699 if (!std.fs.path.isAbsolute(program_data)) break :method3;699 if (!Dir.path.isAbsolute(program_data)) break :method3;
700700
701 const instances_path = try std.fs.path.join(allocator, &.{ program_data, "Microsoft", "VisualStudio", "Packages", "_Instances" });701 const instances_path = try Dir.path.join(gpa, &.{ program_data, "Microsoft", "VisualStudio", "Packages", "_Instances" });
702 defer allocator.free(instances_path);702 defer gpa.free(instances_path);
703703
704 return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch break :method3;704 return Dir.openDirAbsolute(io, instances_path, .{ .iterate = true }) catch break :method3;
705 }705 }
706 return error.PathNotFound;706 return error.PathNotFound;
707 }707 }
...@@ -752,17 +752,17 @@ const MsvcLibDir = struct {...@@ -752,17 +752,17 @@ const MsvcLibDir = struct {
752 ///752 ///
753 /// The logic in this function is intended to match what ISetupConfiguration does753 /// The logic in this function is intended to match what ISetupConfiguration does
754 /// under-the-hood, as verified using Procmon.754 /// under-the-hood, as verified using Procmon.
755 fn findViaCOM(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {755 fn findViaCOM(gpa: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {
756 // Typically `%PROGRAMDATA%\Microsoft\VisualStudio\Packages\_Instances`756 // Typically `%PROGRAMDATA%\Microsoft\VisualStudio\Packages\_Instances`
757 // This will contain directories with names of instance IDs like 80a758ca,757 // This will contain directories with names of instance IDs like 80a758ca,
758 // which will contain `state.json` files that have the version and758 // which will contain `state.json` files that have the version and
759 // installation directory.759 // installation directory.
760 var instances_dir = try findInstancesDir(allocator);760 var instances_dir = try findInstancesDir(gpa, io);
761 defer instances_dir.close(io);761 defer instances_dir.close(io);
762762
763 var state_subpath_buf: [std.fs.max_name_bytes + 32]u8 = undefined;763 var state_subpath_buf: [Dir.max_name_bytes + 32]u8 = undefined;
764 var latest_version_lib_dir: std.ArrayList(u8) = .empty;764 var latest_version_lib_dir: std.ArrayList(u8) = .empty;
765 errdefer latest_version_lib_dir.deinit(allocator);765 errdefer latest_version_lib_dir.deinit(gpa);
766766
767 var latest_version: u64 = 0;767 var latest_version: u64 = 0;
768 var instances_dir_it = instances_dir.iterateAssumeFirstIteration();768 var instances_dir_it = instances_dir.iterateAssumeFirstIteration();
...@@ -772,13 +772,13 @@ const MsvcLibDir = struct {...@@ -772,13 +772,13 @@ const MsvcLibDir = struct {
772 var writer: Writer = .fixed(&state_subpath_buf);772 var writer: Writer = .fixed(&state_subpath_buf);
773773
774 writer.writeAll(entry.name) catch unreachable;774 writer.writeAll(entry.name) catch unreachable;
775 writer.writeByte(std.fs.path.sep) catch unreachable;775 writer.writeByte(Dir.path.sep) catch unreachable;
776 writer.writeAll("state.json") catch unreachable;776 writer.writeAll("state.json") catch unreachable;
777777
778 const json_contents = instances_dir.readFileAlloc(io, writer.buffered(), allocator, .limited(std.math.maxInt(usize))) catch continue;778 const json_contents = instances_dir.readFileAlloc(io, writer.buffered(), gpa, .limited(std.math.maxInt(usize))) catch continue;
779 defer allocator.free(json_contents);779 defer gpa.free(json_contents);
780780
781 var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue;781 var parsed = std.json.parseFromSlice(std.json.Value, gpa, json_contents, .{}) catch continue;
782 defer parsed.deinit();782 defer parsed.deinit();
783783
784 if (parsed.value != .object) continue;784 if (parsed.value != .object) continue;
...@@ -795,40 +795,40 @@ const MsvcLibDir = struct {...@@ -795,40 +795,40 @@ const MsvcLibDir = struct {
795 const installation_path = parsed.value.object.get("installationPath") orelse continue;795 const installation_path = parsed.value.object.get("installationPath") orelse continue;
796 if (installation_path != .string) continue;796 if (installation_path != .string) continue;
797797
798 const lib_dir_path = libDirFromInstallationPath(allocator, io, installation_path.string, arch) catch |err| switch (err) {798 const lib_dir_path = libDirFromInstallationPath(gpa, io, installation_path.string, arch) catch |err| switch (err) {
799 error.OutOfMemory => |e| return e,799 error.OutOfMemory => |e| return e,
800 error.PathNotFound => continue,800 error.PathNotFound => continue,
801 };801 };
802 defer allocator.free(lib_dir_path);802 defer gpa.free(lib_dir_path);
803803
804 latest_version_lib_dir.clearRetainingCapacity();804 latest_version_lib_dir.clearRetainingCapacity();
805 try latest_version_lib_dir.appendSlice(allocator, lib_dir_path);805 try latest_version_lib_dir.appendSlice(gpa, lib_dir_path);
806 latest_version = parsed_version;806 latest_version = parsed_version;
807 }807 }
808808
809 if (latest_version_lib_dir.items.len == 0) return error.PathNotFound;809 if (latest_version_lib_dir.items.len == 0) return error.PathNotFound;
810 return latest_version_lib_dir.toOwnedSlice(allocator);810 return latest_version_lib_dir.toOwnedSlice(gpa);
811 }811 }
812812
813 fn libDirFromInstallationPath(813 fn libDirFromInstallationPath(
814 allocator: Allocator,814 gpa: Allocator,
815 io: Io,815 io: Io,
816 installation_path: []const u8,816 installation_path: []const u8,
817 arch: std.Target.Cpu.Arch,817 arch: std.Target.Cpu.Arch,
818 ) error{ OutOfMemory, PathNotFound }![]const u8 {818 ) error{ OutOfMemory, PathNotFound }![]const u8 {
819 var lib_dir_buf = try std.array_list.Managed(u8).initCapacity(allocator, installation_path.len + 64);819 var lib_dir_buf = try std.array_list.Managed(u8).initCapacity(gpa, installation_path.len + 64);
820 errdefer lib_dir_buf.deinit();820 errdefer lib_dir_buf.deinit();
821821
822 lib_dir_buf.appendSliceAssumeCapacity(installation_path);822 lib_dir_buf.appendSliceAssumeCapacity(installation_path);
823823
824 if (!std.fs.path.isSep(lib_dir_buf.getLast())) {824 if (!Dir.path.isSep(lib_dir_buf.getLast())) {
825 try lib_dir_buf.append('\\');825 try lib_dir_buf.append('\\');
826 }826 }
827 const installation_path_with_trailing_sep_len = lib_dir_buf.items.len;827 const installation_path_with_trailing_sep_len = lib_dir_buf.items.len;
828828
829 try lib_dir_buf.appendSlice("VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");829 try lib_dir_buf.appendSlice("VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");
830 var default_tools_version_buf: [512]u8 = undefined;830 var default_tools_version_buf: [512]u8 = undefined;
831 const default_tools_version_contents = Io.Dir.cwd().readFile(lib_dir_buf.items, &default_tools_version_buf) catch {831 const default_tools_version_contents = Dir.cwd().readFile(lib_dir_buf.items, &default_tools_version_buf) catch {
832 return error.PathNotFound;832 return error.PathNotFound;
833 };833 };
834 var tokenizer = std.mem.tokenizeAny(u8, default_tools_version_contents, " \r\n");834 var tokenizer = std.mem.tokenizeAny(u8, default_tools_version_contents, " \r\n");
...@@ -854,64 +854,64 @@ const MsvcLibDir = struct {...@@ -854,64 +854,64 @@ const MsvcLibDir = struct {
854 }854 }
855855
856 // https://learn.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2022#editing-the-registry-for-a-visual-studio-instance856 // https://learn.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2022#editing-the-registry-for-a-visual-studio-instance
857 fn findViaRegistry(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {857 fn findViaRegistry(gpa: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {
858858
859 // %localappdata%\Microsoft\VisualStudio\859 // %localappdata%\Microsoft\VisualStudio\
860 // %appdata%\Local\Microsoft\VisualStudio\860 // %appdata%\Local\Microsoft\VisualStudio\
861 const visualstudio_folder_path = std.fs.getAppDataDir(allocator, "Microsoft\\VisualStudio\\") catch return error.PathNotFound;861 const visualstudio_folder_path = std.fs.getAppDataDir(gpa, "Microsoft\\VisualStudio\\") catch return error.PathNotFound;
862 defer allocator.free(visualstudio_folder_path);862 defer gpa.free(visualstudio_folder_path);
863863
864 const vs_versions: []const []const u8 = vs_versions: {864 const vs_versions: []const []const u8 = vs_versions: {
865 if (!std.fs.path.isAbsolute(visualstudio_folder_path)) return error.PathNotFound;865 if (!Dir.path.isAbsolute(visualstudio_folder_path)) return error.PathNotFound;
866 // enumerate folders that contain `privateregistry.bin`, looking for all versions866 // enumerate folders that contain `privateregistry.bin`, looking for all versions
867 // f.i. %localappdata%\Microsoft\VisualStudio\17.0_9e9cbb98\867 // f.i. %localappdata%\Microsoft\VisualStudio\17.0_9e9cbb98\
868 var visualstudio_folder = std.fs.openDirAbsolute(visualstudio_folder_path, .{868 var visualstudio_folder = Dir.openDirAbsolute(io, visualstudio_folder_path, .{
869 .iterate = true,869 .iterate = true,
870 }) catch return error.PathNotFound;870 }) catch return error.PathNotFound;
871 defer visualstudio_folder.close(io);871 defer visualstudio_folder.close(io);
872872
873 var iterator = visualstudio_folder.iterate();873 var iterator = visualstudio_folder.iterate();
874 break :vs_versions try iterateAndFilterByVersion(&iterator, allocator, "");874 break :vs_versions try iterateAndFilterByVersion(&iterator, gpa, "");
875 };875 };
876 defer {876 defer {
877 for (vs_versions) |vs_version| allocator.free(vs_version);877 for (vs_versions) |vs_version| gpa.free(vs_version);
878 allocator.free(vs_versions);878 gpa.free(vs_versions);
879 }879 }
880 var config_subkey_buf: [RegistryWtf16Le.key_name_max_len * 2]u8 = undefined;880 var config_subkey_buf: [RegistryWtf16Le.key_name_max_len * 2]u8 = undefined;
881 const source_directories: []const u8 = source_directories: for (vs_versions) |vs_version| {881 const source_directories: []const u8 = source_directories: for (vs_versions) |vs_version| {
882 const privateregistry_absolute_path = std.fs.path.join(allocator, &.{ visualstudio_folder_path, vs_version, "privateregistry.bin" }) catch continue;882 const privateregistry_absolute_path = Dir.path.join(gpa, &.{ visualstudio_folder_path, vs_version, "privateregistry.bin" }) catch continue;
883 defer allocator.free(privateregistry_absolute_path);883 defer gpa.free(privateregistry_absolute_path);
884 if (!std.fs.path.isAbsolute(privateregistry_absolute_path)) continue;884 if (!Dir.path.isAbsolute(privateregistry_absolute_path)) continue;
885885
886 const visualstudio_registry = RegistryWtf8.loadFromPath(privateregistry_absolute_path) catch continue;886 const visualstudio_registry = RegistryWtf8.loadFromPath(privateregistry_absolute_path) catch continue;
887 defer visualstudio_registry.closeKey();887 defer visualstudio_registry.closeKey();
888888
889 const config_subkey = std.fmt.bufPrint(config_subkey_buf[0..], "Software\\Microsoft\\VisualStudio\\{s}_Config", .{vs_version}) catch unreachable;889 const config_subkey = std.fmt.bufPrint(config_subkey_buf[0..], "Software\\Microsoft\\VisualStudio\\{s}_Config", .{vs_version}) catch unreachable;
890890
891 const source_directories_value = visualstudio_registry.getString(allocator, config_subkey, "Source Directories") catch |err| switch (err) {891 const source_directories_value = visualstudio_registry.getString(gpa, config_subkey, "Source Directories") catch |err| switch (err) {
892 error.OutOfMemory => return error.OutOfMemory,892 error.OutOfMemory => return error.OutOfMemory,
893 else => continue,893 else => continue,
894 };894 };
895 if (source_directories_value.len > (std.fs.max_path_bytes * 30)) { // note(bratishkaerik): guessing from the fact that on my computer it has 15 paths and at least some of them are not of max length895 if (source_directories_value.len > (Dir.max_path_bytes * 30)) { // note(bratishkaerik): guessing from the fact that on my computer it has 15 paths and at least some of them are not of max length
896 allocator.free(source_directories_value);896 gpa.free(source_directories_value);
897 continue;897 continue;
898 }898 }
899899
900 break :source_directories source_directories_value;900 break :source_directories source_directories_value;
901 } else return error.PathNotFound;901 } else return error.PathNotFound;
902 defer allocator.free(source_directories);902 defer gpa.free(source_directories);
903903
904 var source_directories_split = std.mem.splitScalar(u8, source_directories, ';');904 var source_directories_split = std.mem.splitScalar(u8, source_directories, ';');
905905
906 const msvc_dir: []const u8 = msvc_dir: {906 const msvc_dir: []const u8 = msvc_dir: {
907 const msvc_include_dir_maybe_with_trailing_slash = try allocator.dupe(u8, source_directories_split.first());907 const msvc_include_dir_maybe_with_trailing_slash = try gpa.dupe(u8, source_directories_split.first());
908908
909 if (msvc_include_dir_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(msvc_include_dir_maybe_with_trailing_slash)) {909 if (msvc_include_dir_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(msvc_include_dir_maybe_with_trailing_slash)) {
910 allocator.free(msvc_include_dir_maybe_with_trailing_slash);910 gpa.free(msvc_include_dir_maybe_with_trailing_slash);
911 return error.PathNotFound;911 return error.PathNotFound;
912 }912 }
913913
914 var msvc_dir = std.array_list.Managed(u8).fromOwnedSlice(allocator, msvc_include_dir_maybe_with_trailing_slash);914 var msvc_dir = std.array_list.Managed(u8).fromOwnedSlice(gpa, msvc_include_dir_maybe_with_trailing_slash);
915 errdefer msvc_dir.deinit();915 errdefer msvc_dir.deinit();
916916
917 // String might contain trailing slash, so trim it here917 // String might contain trailing slash, so trim it here
...@@ -933,7 +933,7 @@ const MsvcLibDir = struct {...@@ -933,7 +933,7 @@ const MsvcLibDir = struct {
933 const msvc_dir_with_arch = try msvc_dir.toOwnedSlice();933 const msvc_dir_with_arch = try msvc_dir.toOwnedSlice();
934 break :msvc_dir msvc_dir_with_arch;934 break :msvc_dir msvc_dir_with_arch;
935 };935 };
936 errdefer allocator.free(msvc_dir);936 errdefer gpa.free(msvc_dir);
937937
938 if (!verifyLibDir(io, msvc_dir)) {938 if (!verifyLibDir(io, msvc_dir)) {
939 return error.PathNotFound;939 return error.PathNotFound;
...@@ -942,10 +942,10 @@ const MsvcLibDir = struct {...@@ -942,10 +942,10 @@ const MsvcLibDir = struct {
942 return msvc_dir;942 return msvc_dir;
943 }943 }
944944
945 fn findViaVs7Key(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {945 fn findViaVs7Key(gpa: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {
946 var base_path: std.array_list.Managed(u8) = base_path: {946 var base_path: std.array_list.Managed(u8) = base_path: {
947 try_env: {947 try_env: {
948 var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) {948 var env_map = std.process.getEnvMap(gpa) catch |err| switch (err) {
949 error.OutOfMemory => return error.OutOfMemory,949 error.OutOfMemory => return error.OutOfMemory,
950 else => break :try_env,950 else => break :try_env,
951 };951 };
...@@ -953,8 +953,8 @@ const MsvcLibDir = struct {...@@ -953,8 +953,8 @@ const MsvcLibDir = struct {
953953
954 if (env_map.get("VS140COMNTOOLS")) |VS140COMNTOOLS| {954 if (env_map.get("VS140COMNTOOLS")) |VS140COMNTOOLS| {
955 if (VS140COMNTOOLS.len < "C:\\Common7\\Tools".len) break :try_env;955 if (VS140COMNTOOLS.len < "C:\\Common7\\Tools".len) break :try_env;
956 if (!std.fs.path.isAbsolute(VS140COMNTOOLS)) break :try_env;956 if (!Dir.path.isAbsolute(VS140COMNTOOLS)) break :try_env;
957 var list = std.array_list.Managed(u8).init(allocator);957 var list = std.array_list.Managed(u8).init(gpa);
958 errdefer list.deinit();958 errdefer list.deinit();
959959
960 try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools960 try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools
...@@ -968,17 +968,17 @@ const MsvcLibDir = struct {...@@ -968,17 +968,17 @@ const MsvcLibDir = struct {
968 const vs7_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", .{ .wow64_32 = true }) catch return error.PathNotFound;968 const vs7_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", .{ .wow64_32 = true }) catch return error.PathNotFound;
969 defer vs7_key.closeKey();969 defer vs7_key.closeKey();
970 try_vs7_key: {970 try_vs7_key: {
971 const path_maybe_with_trailing_slash = vs7_key.getString(allocator, "", "14.0") catch |err| switch (err) {971 const path_maybe_with_trailing_slash = vs7_key.getString(gpa, "", "14.0") catch |err| switch (err) {
972 error.OutOfMemory => return error.OutOfMemory,972 error.OutOfMemory => return error.OutOfMemory,
973 else => break :try_vs7_key,973 else => break :try_vs7_key,
974 };974 };
975975
976 if (path_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(path_maybe_with_trailing_slash)) {976 if (path_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(path_maybe_with_trailing_slash)) {
977 allocator.free(path_maybe_with_trailing_slash);977 gpa.free(path_maybe_with_trailing_slash);
978 break :try_vs7_key;978 break :try_vs7_key;
979 }979 }
980980
981 var path = std.array_list.Managed(u8).fromOwnedSlice(allocator, path_maybe_with_trailing_slash);981 var path = std.array_list.Managed(u8).fromOwnedSlice(gpa, path_maybe_with_trailing_slash);
982 errdefer path.deinit();982 errdefer path.deinit();
983983
984 // String might contain trailing slash, so trim it here984 // String might contain trailing slash, so trim it here
...@@ -1007,9 +1007,9 @@ const MsvcLibDir = struct {...@@ -1007,9 +1007,9 @@ const MsvcLibDir = struct {
1007 }1007 }
10081008
1009 fn verifyLibDir(io: Io, lib_dir_path: []const u8) bool {1009 fn verifyLibDir(io: Io, lib_dir_path: []const u8) bool {
1010 std.debug.assert(std.fs.path.isAbsolute(lib_dir_path)); // should be already handled in `findVia*`1010 std.debug.assert(Dir.path.isAbsolute(lib_dir_path)); // should be already handled in `findVia*`
10111011
1012 var dir = std.fs.openDirAbsolute(lib_dir_path, .{}) catch return false;1012 var dir = Dir.openDirAbsolute(io, lib_dir_path, .{}) catch return false;
1013 defer dir.close(io);1013 defer dir.close(io);
10141014
1015 const stat = dir.statFile(io, "vcruntime.lib", .{}) catch return false;1015 const stat = dir.statFile(io, "vcruntime.lib", .{}) catch return false;
...@@ -1021,18 +1021,18 @@ const MsvcLibDir = struct {...@@ -1021,18 +1021,18 @@ const MsvcLibDir = struct {
10211021
1022 /// Find path to MSVC's `lib/` directory.1022 /// Find path to MSVC's `lib/` directory.
1023 /// Caller owns the result.1023 /// Caller owns the result.
1024 pub fn find(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 {1024 pub fn find(gpa: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 {
1025 const full_path = MsvcLibDir.findViaCOM(allocator, io, arch) catch |err1| switch (err1) {1025 const full_path = MsvcLibDir.findViaCOM(gpa, io, arch) catch |err1| switch (err1) {
1026 error.OutOfMemory => return error.OutOfMemory,1026 error.OutOfMemory => return error.OutOfMemory,
1027 error.PathNotFound => MsvcLibDir.findViaRegistry(allocator, io, arch) catch |err2| switch (err2) {1027 error.PathNotFound => MsvcLibDir.findViaRegistry(gpa, io, arch) catch |err2| switch (err2) {
1028 error.OutOfMemory => return error.OutOfMemory,1028 error.OutOfMemory => return error.OutOfMemory,
1029 error.PathNotFound => MsvcLibDir.findViaVs7Key(allocator, io, arch) catch |err3| switch (err3) {1029 error.PathNotFound => MsvcLibDir.findViaVs7Key(gpa, io, arch) catch |err3| switch (err3) {
1030 error.OutOfMemory => return error.OutOfMemory,1030 error.OutOfMemory => return error.OutOfMemory,
1031 error.PathNotFound => return error.MsvcLibDirNotFound,1031 error.PathNotFound => return error.MsvcLibDirNotFound,
1032 },1032 },
1033 },1033 },
1034 };1034 };
1035 errdefer allocator.free(full_path);1035 errdefer gpa.free(full_path);
10361036
1037 return full_path;1037 return full_path;
1038 }1038 }