diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2024-07-17 19:43:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-17 19:43:40 -0700 |
commit | bf9c08b705725bf35b60fb8a468edbc35ba3cdde (patch) | |
tree | 347996eea1af4a4d70601273a1a04e9462b1c0d8 /ext/fs | |
parent | f1228454450c320c8dce1a6968890aa7d807906f (diff) |
fix(ext/node): stat.mode on windows (#24434)
Diffstat (limited to 'ext/fs')
-rw-r--r-- | ext/fs/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/fs/std_fs.rs | 56 |
2 files changed, 57 insertions, 0 deletions
diff --git a/ext/fs/Cargo.toml b/ext/fs/Cargo.toml index 05d4164af..2bd0212cf 100644 --- a/ext/fs/Cargo.toml +++ b/ext/fs/Cargo.toml @@ -34,4 +34,5 @@ nix.workspace = true [target.'cfg(windows)'.dependencies] winapi = { workspace = true, features = ["winbase"] } +windows-sys.workspace = true junction.workspace = true diff --git a/ext/fs/std_fs.rs b/ext/fs/std_fs.rs index 7fc33a8ad..3cbd154d5 100644 --- a/ext/fs/std_fs.rs +++ b/ext/fs/std_fs.rs @@ -821,6 +821,29 @@ fn stat_extra( Ok(info.dwVolumeSerialNumber as u64) } + use windows_sys::Wdk::Storage::FileSystem::FILE_ALL_INFORMATION; + + unsafe fn query_file_information( + handle: winapi::shared::ntdef::HANDLE, + ) -> std::io::Result<FILE_ALL_INFORMATION> { + use windows_sys::Wdk::Storage::FileSystem::NtQueryInformationFile; + + let mut info = std::mem::MaybeUninit::<FILE_ALL_INFORMATION>::zeroed(); + let status = NtQueryInformationFile( + handle as _, + std::ptr::null_mut(), + info.as_mut_ptr() as *mut _, + std::mem::size_of::<FILE_ALL_INFORMATION>() as _, + 18, /* FileAllInformation */ + ); + + if status < 0 { + return Err(std::io::Error::last_os_error()); + } + + Ok(info.assume_init()) + } + // SAFETY: winapi calls unsafe { let mut path: Vec<_> = path.as_os_str().encode_wide().collect(); @@ -842,6 +865,39 @@ fn stat_extra( CloseHandle(file_handle); fsstat.dev = result?; + if let Ok(file_info) = query_file_information(file_handle) { + if file_info.BasicInformation.FileAttributes + & winapi::um::winnt::FILE_ATTRIBUTE_REPARSE_POINT + != 0 + { + fsstat.is_symlink = true; + } + + if file_info.BasicInformation.FileAttributes + & winapi::um::winnt::FILE_ATTRIBUTE_DIRECTORY + != 0 + { + fsstat.mode |= libc::S_IFDIR as u32; + fsstat.size = 0; + } else { + fsstat.mode |= libc::S_IFREG as u32; + fsstat.size = file_info.StandardInformation.EndOfFile as u64; + } + + if file_info.BasicInformation.FileAttributes + & winapi::um::winnt::FILE_ATTRIBUTE_READONLY + != 0 + { + fsstat.mode |= + (libc::S_IREAD | (libc::S_IREAD >> 3) | (libc::S_IREAD >> 6)) as u32; + } else { + fsstat.mode |= ((libc::S_IREAD | libc::S_IWRITE) + | ((libc::S_IREAD | libc::S_IWRITE) >> 3) + | ((libc::S_IREAD | libc::S_IWRITE) >> 6)) + as u32; + } + } + Ok(()) } } |