diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 0feec928fca854237041a140b644a38e0bd1c1e4..60be4a8d4c8211d9045e20ee291fab0541f441bb 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -15193,7 +15193,26 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const cwd_w = if (options.cwd) |cwd| try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd) else null; + const cwd_w = cwd_w: { + if (options.cwd_dir) |cwd_dir| { + var dir_path_buffer = try arena.alloc(u16, windows.PATH_MAX_WIDE + 1); + // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks + try Thread.checkCancel(); + const dir_path = try windows.GetFinalPathNameByHandle( + cwd_dir.handle, + .{}, + dir_path_buffer[0..windows.PATH_MAX_WIDE], + ); + dir_path_buffer[dir_path.len] = 0; + // Shrink the allocation down to just the path buffer + sentinel + dir_path_buffer = try arena.realloc(dir_path_buffer, dir_path.len + 1); + break :cwd_w dir_path_buffer[0..dir_path.len :0]; + } else if (options.cwd) |cwd| { + break :cwd_w try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd); + } else { + break :cwd_w null; + } + }; const cwd_w_ptr = if (cwd_w) |cwd| cwd.ptr else null; const maybe_envp_buf = if (options.environ_map) |environ_map| try environ_map.createBlockWindows(arena) else null; @@ -15204,16 +15223,13 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro // The cwd provided by options is in effect when choosing the executable // path to match POSIX semantics. - var cwd_path_w_needs_free = false; const cwd_path_w = x: { // If the app name is absolute, then we need to use its dirname as the cwd if (app_name_is_absolute) { - cwd_path_w_needs_free = true; const dir = Dir.path.dirname(app_name_wtf8).?; break :x try std.unicode.wtf8ToWtf16LeAllocZ(arena, dir); - } else if (options.cwd) |cwd| { - cwd_path_w_needs_free = true; - break :x try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd); + } else if (cwd_w) |cwd| { + break :x cwd; } else { break :x &[_:0]u16{}; // empty for cwd } diff --git a/lib/std/process.zig b/lib/std/process.zig index 3b5a0ecebd5e38ced3748bd0a012adc6d1d6d0a2..d4e5e689316db4d356c25362bfae6b0aea844f18 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -359,6 +359,9 @@ pub const SpawnError = error{ /// children of the calling process and the child had already performed an /// image replacement. ProcessAlreadyExec, + /// On Windows, the volume does not contain a recognized file system. File + /// system drivers might not be loaded, or the volume may be corrupt. + UnrecognizedVolume, } || Io.Dir.PathNameError || Io.Cancelable || Io.UnexpectedError; pub const SpawnOptions = struct {