mirror of
https://github.com/denoland/deno.git
synced 2025-08-31 07:47:46 +00:00
feat(ext/fs): add ctime to Deno.stats and use it in node compat layer (#24801)
This PR fixes #24453, by introducing a ctime (using ctime for UNIX and ChangeTime for Windows) to Deno.stats. Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
parent
43812ee8ff
commit
7becd83a38
10 changed files with 88 additions and 15 deletions
|
@ -821,24 +821,46 @@ fn stat_extra(
|
|||
Ok(info.dwVolumeSerialNumber as u64)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
fn windows_time_to_unix_time_msec(windows_time: &i64) -> i64 {
|
||||
let milliseconds_since_windows_epoch = windows_time / WINDOWS_TICK;
|
||||
milliseconds_since_windows_epoch - SEC_TO_UNIX_EPOCH * 1000
|
||||
}
|
||||
|
||||
use windows_sys::Wdk::Storage::FileSystem::FILE_ALL_INFORMATION;
|
||||
use windows_sys::Win32::Foundation::NTSTATUS;
|
||||
|
||||
unsafe fn query_file_information(
|
||||
handle: winapi::shared::ntdef::HANDLE,
|
||||
) -> std::io::Result<FILE_ALL_INFORMATION> {
|
||||
) -> Result<FILE_ALL_INFORMATION, NTSTATUS> {
|
||||
use windows_sys::Wdk::Storage::FileSystem::NtQueryInformationFile;
|
||||
use windows_sys::Win32::Foundation::RtlNtStatusToDosError;
|
||||
use windows_sys::Win32::Foundation::ERROR_MORE_DATA;
|
||||
use windows_sys::Win32::System::IO::IO_STATUS_BLOCK;
|
||||
|
||||
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(
|
||||
handle as _,
|
||||
std::ptr::null_mut(),
|
||||
io_status_block.as_mut_ptr(),
|
||||
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());
|
||||
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.
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntqueryinformationfile#remarksdd
|
||||
if converted_status != ERROR_MORE_DATA {
|
||||
return Err(converted_status as NTSTATUS);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(info.assume_init())
|
||||
|
@ -862,10 +884,13 @@ fn stat_extra(
|
|||
}
|
||||
|
||||
let result = get_dev(file_handle);
|
||||
CloseHandle(file_handle);
|
||||
fsstat.dev = result?;
|
||||
|
||||
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
|
||||
& winapi::um::winnt::FILE_ATTRIBUTE_REPARSE_POINT
|
||||
!= 0
|
||||
|
@ -898,6 +923,7 @@ fn stat_extra(
|
|||
}
|
||||
}
|
||||
|
||||
CloseHandle(file_handle);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue