Skip to content

Commit 0a9e7f6

Browse files
committed
Fix windows chdir
1 parent 5bdbcc3 commit 0a9e7f6

File tree

1 file changed

+32
-1
lines changed
  • crates/vm/src/stdlib

1 file changed

+32
-1
lines changed

crates/vm/src/stdlib/os.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,38 @@ pub(super) mod _os {
11241124
#[pyfunction]
11251125
fn chdir(path: OsPath, vm: &VirtualMachine) -> PyResult<()> {
11261126
env::set_current_dir(&path.path)
1127-
.map_err(|err| OSErrorBuilder::with_filename(&err, path, vm))
1127+
.map_err(|err| OSErrorBuilder::with_filename(&err, path, vm))?;
1128+
1129+
// On Windows, set the per-drive CWD environment variable (=X:)
1130+
// This is required for GetFullPathNameW to work correctly with drive-relative paths
1131+
// Matches CPython's win32_wchdir() in Modules/posixmodule.c
1132+
#[cfg(windows)]
1133+
{
1134+
use std::os::windows::ffi::OsStrExt;
1135+
use windows_sys::Win32::System::Environment::SetEnvironmentVariableW;
1136+
1137+
if let Ok(cwd) = env::current_dir() {
1138+
let cwd_str = cwd.as_os_str();
1139+
let mut cwd_wide: Vec<u16> = cwd_str.encode_wide().collect();
1140+
1141+
// Check for UNC-like paths (\\server\share or //server/share)
1142+
// CPython: wcsncmp(new_path, L"\\\\", 2) == 0 || wcsncmp(new_path, L"//", 2) == 0
1143+
let is_unc_like_path = cwd_wide.len() >= 2
1144+
&& ((cwd_wide[0] == b'\\' as u16 && cwd_wide[1] == b'\\' as u16)
1145+
|| (cwd_wide[0] == b'/' as u16 && cwd_wide[1] == b'/' as u16));
1146+
1147+
if !is_unc_like_path {
1148+
// Create env var name "=X:" where X is the drive letter
1149+
let env_name: [u16; 4] = [b'=' as u16, cwd_wide[0], b':' as u16, 0];
1150+
cwd_wide.push(0); // null-terminate the path
1151+
unsafe {
1152+
SetEnvironmentVariableW(env_name.as_ptr(), cwd_wide.as_ptr());
1153+
}
1154+
}
1155+
}
1156+
}
1157+
1158+
Ok(())
11281159
}
11291160

11301161
#[pyfunction]

0 commit comments

Comments
 (0)