summaryrefslogtreecommitdiff
path: root/ext/fs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-07-17 19:43:40 -0700
committerGitHub <noreply@github.com>2024-07-17 19:43:40 -0700
commitbf9c08b705725bf35b60fb8a468edbc35ba3cdde (patch)
tree347996eea1af4a4d70601273a1a04e9462b1c0d8 /ext/fs
parentf1228454450c320c8dce1a6968890aa7d807906f (diff)
fix(ext/node): stat.mode on windows (#24434)
Diffstat (limited to 'ext/fs')
-rw-r--r--ext/fs/Cargo.toml1
-rw-r--r--ext/fs/std_fs.rs56
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(())
}
}