mirror of
https://github.com/denoland/deno.git
synced 2025-02-24 06:02:18 -05:00
Fix NtQueryInformationFile and get ChangeTime from single sys call
This commit is contained in:
parent
eed2a7a8a7
commit
6d48778991
1 changed files with 19 additions and 35 deletions
|
@ -821,35 +821,6 @@ fn stat_extra(
|
||||||
Ok(info.dwVolumeSerialNumber as u64)
|
Ok(info.dwVolumeSerialNumber as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_change_time(
|
|
||||||
handle: winapi::shared::ntdef::HANDLE,
|
|
||||||
) -> std::io::Result<u64> {
|
|
||||||
use winapi::shared::minwindef::FALSE;
|
|
||||||
use winapi::um::fileapi::FILE_BASIC_INFO;
|
|
||||||
use winapi::um::minwinbase::FileBasicInfo;
|
|
||||||
use winapi::um::winbase::GetFileInformationByHandleEx;
|
|
||||||
|
|
||||||
let file_info = {
|
|
||||||
let mut file_info = std::mem::MaybeUninit::<FILE_BASIC_INFO>::zeroed();
|
|
||||||
if GetFileInformationByHandleEx(
|
|
||||||
handle,
|
|
||||||
FileBasicInfo,
|
|
||||||
&mut file_info as *mut _ as *mut _,
|
|
||||||
std::mem::size_of::<FILE_BASIC_INFO>() as u32,
|
|
||||||
) == FALSE
|
|
||||||
{
|
|
||||||
return Err(std::io::Error::last_os_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
file_info.assume_init()
|
|
||||||
};
|
|
||||||
|
|
||||||
let change_time = file_info.ChangeTime.QuadPart();
|
|
||||||
let unix_time_msec = windows_time_to_unix_time_msec(change_time);
|
|
||||||
|
|
||||||
Ok(unix_time_msec as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
const WINDOWS_TICK: i64 = 10_000; // 100-nanosecond intervals in a millisecond
|
const WINDOWS_TICK: i64 = 10_000; // 100-nanosecond intervals in a millisecond
|
||||||
const SEC_TO_UNIX_EPOCH: i64 = 11_644_473_600; // Seconds between Windows epoch and Unix epoch
|
const SEC_TO_UNIX_EPOCH: i64 = 11_644_473_600; // Seconds between Windows epoch and Unix epoch
|
||||||
|
|
||||||
|
@ -859,23 +830,36 @@ fn stat_extra(
|
||||||
}
|
}
|
||||||
|
|
||||||
use windows_sys::Wdk::Storage::FileSystem::FILE_ALL_INFORMATION;
|
use windows_sys::Wdk::Storage::FileSystem::FILE_ALL_INFORMATION;
|
||||||
|
use windows_sys::Win32::Foundation::NTSTATUS;
|
||||||
|
|
||||||
unsafe fn query_file_information(
|
unsafe fn query_file_information(
|
||||||
handle: winapi::shared::ntdef::HANDLE,
|
handle: winapi::shared::ntdef::HANDLE,
|
||||||
) -> std::io::Result<FILE_ALL_INFORMATION> {
|
) -> Result<FILE_ALL_INFORMATION, NTSTATUS> {
|
||||||
|
use windows_sys::Win32::Foundation::RtlNtStatusToDosError;
|
||||||
|
use windows_sys::Win32::Foundation::ERROR_MORE_DATA;
|
||||||
|
use windows_sys::Win32::System::IO::IO_STATUS_BLOCK;
|
||||||
use windows_sys::Wdk::Storage::FileSystem::NtQueryInformationFile;
|
use windows_sys::Wdk::Storage::FileSystem::NtQueryInformationFile;
|
||||||
|
|
||||||
let mut info = std::mem::MaybeUninit::<FILE_ALL_INFORMATION>::zeroed();
|
let mut info = std::mem::MaybeUninit::<FILE_ALL_INFORMATION>::zeroed();
|
||||||
|
let mut io_status_block = std::mem::MaybeUninit::<IO_STATUS_BLOCK>::zeroed();
|
||||||
let status = NtQueryInformationFile(
|
let status = NtQueryInformationFile(
|
||||||
handle as _,
|
handle as _,
|
||||||
std::ptr::null_mut(),
|
io_status_block.as_mut_ptr(),
|
||||||
info.as_mut_ptr() as *mut _,
|
info.as_mut_ptr() as *mut _,
|
||||||
std::mem::size_of::<FILE_ALL_INFORMATION>() as _,
|
std::mem::size_of::<FILE_ALL_INFORMATION>() as _,
|
||||||
18, /* FileAllInformation */
|
18, /* FileAllInformation */
|
||||||
);
|
);
|
||||||
|
|
||||||
if status < 0 {
|
if status < 0 {
|
||||||
return Err(std::io::Error::last_os_error());
|
let converted_status = RtlNtStatusToDosError(status);
|
||||||
|
|
||||||
|
// If error more data is returned, then it means that the buffer is too small to get full filename information
|
||||||
|
// to have that we should retry. However, since we only use BasicInformation and StandardInformation, it is fine to ignore it
|
||||||
|
// since struct is populated with other data anyway.
|
||||||
|
|
||||||
|
if converted_status != ERROR_MORE_DATA {
|
||||||
|
return Err(converted_status as NTSTATUS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(info.assume_init())
|
Ok(info.assume_init())
|
||||||
|
@ -900,11 +884,10 @@ fn stat_extra(
|
||||||
|
|
||||||
let result = get_dev(file_handle);
|
let result = get_dev(file_handle);
|
||||||
fsstat.dev = result?;
|
fsstat.dev = result?;
|
||||||
fsstat.ctime = get_change_time(file_handle).ok();
|
|
||||||
|
|
||||||
CloseHandle(file_handle);
|
|
||||||
|
|
||||||
if let Ok(file_info) = query_file_information(file_handle) {
|
if let Ok(file_info) = query_file_information(file_handle) {
|
||||||
|
fsstat.ctime = Some(windows_time_to_unix_time_msec(&file_info.BasicInformation.ChangeTime) as u64);
|
||||||
|
|
||||||
if file_info.BasicInformation.FileAttributes
|
if file_info.BasicInformation.FileAttributes
|
||||||
& winapi::um::winnt::FILE_ATTRIBUTE_REPARSE_POINT
|
& winapi::um::winnt::FILE_ATTRIBUTE_REPARSE_POINT
|
||||||
!= 0
|
!= 0
|
||||||
|
@ -937,6 +920,7 @@ fn stat_extra(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CloseHandle(file_handle);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue