1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-08 15:19:40 -05:00

perf(fs/windows): stat - only open file once (#27487)

This commit is contained in:
David Sherret 2024-12-31 11:29:51 -05:00 committed by GitHub
parent 4638caa740
commit 88bd5f09f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -61,7 +61,7 @@ impl FileSystem for RealFs {
umask(Mode::from_bits_truncate(mask as mode_t))
} else {
// If no mask provided, we query the current. Requires two syscalls.
let prev = umask(Mode::from_bits_truncate(0o777));
let prev = umask(Mode::from_bits_truncate(0));
let _ = umask(prev);
prev
};
@ -761,11 +761,16 @@ fn stat(path: &Path) -> FsResult<FsStat> {
#[cfg(windows)]
fn stat(path: &Path) -> FsResult<FsStat> {
let metadata = fs::metadata(path)?;
let mut fsstat = FsStat::from_std(metadata);
use std::os::windows::fs::OpenOptionsExt;
use winapi::um::winbase::FILE_FLAG_BACKUP_SEMANTICS;
let path = path.canonicalize()?;
stat_extra(&mut fsstat, &path, FILE_FLAG_BACKUP_SEMANTICS)?;
let mut opts = fs::OpenOptions::new();
opts.access_mode(0); // no read or write
opts.custom_flags(FILE_FLAG_BACKUP_SEMANTICS);
let file = opts.open(path)?;
let metadata = file.metadata()?;
let mut fsstat = FsStat::from_std(metadata);
stat_extra(&file, &mut fsstat)?;
Ok(fsstat)
}
@ -777,34 +782,24 @@ fn lstat(path: &Path) -> FsResult<FsStat> {
#[cfg(windows)]
fn lstat(path: &Path) -> FsResult<FsStat> {
use std::os::windows::fs::OpenOptionsExt;
use winapi::um::winbase::FILE_FLAG_BACKUP_SEMANTICS;
use winapi::um::winbase::FILE_FLAG_OPEN_REPARSE_POINT;
let metadata = fs::symlink_metadata(path)?;
let mut opts = fs::OpenOptions::new();
opts.access_mode(0); // no read or write
opts.custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT);
let file = opts.open(path)?;
let metadata = file.metadata()?;
let mut fsstat = FsStat::from_std(metadata);
stat_extra(
&mut fsstat,
path,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
)?;
stat_extra(&file, &mut fsstat)?;
Ok(fsstat)
}
#[cfg(windows)]
fn stat_extra(
fsstat: &mut FsStat,
path: &Path,
file_flags: winapi::shared::minwindef::DWORD,
) -> FsResult<()> {
use std::os::windows::prelude::OsStrExt;
use winapi::um::fileapi::CreateFileW;
use winapi::um::fileapi::OPEN_EXISTING;
use winapi::um::handleapi::CloseHandle;
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::winnt::FILE_SHARE_DELETE;
use winapi::um::winnt::FILE_SHARE_READ;
use winapi::um::winnt::FILE_SHARE_WRITE;
fn stat_extra(file: &std::fs::File, fsstat: &mut FsStat) -> FsResult<()> {
use std::os::windows::io::AsRawHandle;
unsafe fn get_dev(
handle: winapi::shared::ntdef::HANDLE,
@ -873,23 +868,9 @@ fn stat_extra(
// SAFETY: winapi calls
unsafe {
let mut path: Vec<_> = path.as_os_str().encode_wide().collect();
path.push(0);
let file_handle = CreateFileW(
path.as_ptr(),
0,
FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
std::ptr::null_mut(),
OPEN_EXISTING,
file_flags,
std::ptr::null_mut(),
);
if file_handle == INVALID_HANDLE_VALUE {
return Err(std::io::Error::last_os_error().into());
}
let file_handle = file.as_raw_handle();
let result = get_dev(file_handle);
fsstat.dev = result?;
fsstat.dev = get_dev(file_handle)?;
if let Ok(file_info) = query_file_information(file_handle) {
fsstat.ctime = Some(windows_time_to_unix_time_msec(
@ -928,7 +909,6 @@ fn stat_extra(
}
}
CloseHandle(file_handle);
Ok(())
}
}