1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
pub fn get_current_working_directory() -> Option<alloc::string::String> {
const MAX_PATH_LENGTH: usize = 131072;
const INITIAL_PATH_LENGTH: usize = 260;
let mut buffer = alloc::vec![0u8; INITIAL_PATH_LENGTH];
let mut current_len = INITIAL_PATH_LENGTH;
loop {
let result = unsafe {
#[cfg(windows)]
{
use core::ffi::{c_char, c_int};
extern "C" {
fn _getcwd(buffer: *mut c_char, maxlen: c_int) -> *mut c_char;
}
_getcwd(buffer.as_mut_ptr() as *mut c_char, buffer.len() as c_int)
}
#[cfg(not(windows))]
{
use core::ffi::{c_char, c_ulong};
extern "C" {
fn getcwd(buffer: *mut c_char, size: usize) -> *mut c_char;
}
getcwd(buffer.as_mut_ptr() as *mut c_char, buffer.len())
}
};
if !result.is_null() {
let c_str = unsafe { core::ffi::CStr::from_ptr(result) };
// The require resolver / VfsNavigator work in a forward-slash virtual
// path space (they split and join on '/'). On Windows `_getcwd` returns
// backslashes and a drive letter (e.g. `D:\a\luaur`), which the resolver
// treated as one opaque component: the drive never componentized,
// `absolute_path_prefix` kept backslashes while `get_module_path` stripped
// the drive with forward slashes, and the two were concatenated into an
// inconsistent cache key. That broke require cycle detection on Windows
// (the same module got different keys), so a module that re-required
// itself recursed forever -> stack overflow (0xC0000409) across the
// require-by-string tests. Normalize to forward slashes here so Windows
// drive-letter cwds flow through the resolver exactly like POSIX paths.
// No-op on Unix (POSIX paths contain no backslashes).
return Some(c_str.to_string_lossy().replace('\\', "/"));
}
let err = std::io::Error::last_os_error();
if err.raw_os_error() != Some(34) || current_len * 2 > MAX_PATH_LENGTH {
return None;
}
current_len *= 2;
buffer.resize(current_len, 0);
}
}