mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
a1e4f7781c
commit
5efde5366a
2 changed files with 44 additions and 18 deletions
|
|
@ -127,16 +127,17 @@ fn final_path(path: &Path) -> io::Result<PathBuf> {
|
|||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn final_path(path: &Path) -> io::Result<PathBuf> {
|
||||
use std::{ffi::OsString, os::windows::{ffi::OsStringExt, fs::OpenOptionsExt, io::AsRawHandle}};
|
||||
use std::{ffi::OsString, fs::File, os::windows::{ffi::OsStringExt, fs::OpenOptionsExt, io::AsRawHandle}};
|
||||
|
||||
use windows_sys::Win32::{Foundation::HANDLE, Storage::FileSystem::{FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, GetFinalPathNameByHandleW, VOLUME_NAME_DOS}};
|
||||
use yazi_shared::Either;
|
||||
|
||||
let file = std::fs::OpenOptions::new()
|
||||
.access_mode(0)
|
||||
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)
|
||||
.open(path)?;
|
||||
|
||||
let mut buf = [0u16; 512];
|
||||
fn inner(file: &File, buf: &mut [u16]) -> io::Result<Either<PathBuf, u32>> {
|
||||
let len = unsafe {
|
||||
GetFinalPathNameByHandleW(
|
||||
file.as_raw_handle() as HANDLE,
|
||||
|
|
@ -146,13 +147,24 @@ fn final_path(path: &Path) -> io::Result<PathBuf> {
|
|||
)
|
||||
};
|
||||
|
||||
if len == 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
Ok(if len == 0 {
|
||||
Err(io::Error::last_os_error())?
|
||||
} else if len as usize > buf.len() {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Path too long"))
|
||||
Either::Right(len)
|
||||
} else if buf.starts_with(&[92, 92, 63, 92]) {
|
||||
Ok(PathBuf::from(OsString::from_wide(&buf[4..len as usize])))
|
||||
Either::Left(PathBuf::from(OsString::from_wide(&buf[4..len as usize])))
|
||||
} else {
|
||||
Ok(PathBuf::from(OsString::from_wide(&buf[0..len as usize])))
|
||||
Either::Left(PathBuf::from(OsString::from_wide(&buf[0..len as usize])))
|
||||
})
|
||||
}
|
||||
|
||||
let mut buf = [0u16; 512];
|
||||
match inner(&file, &mut buf)? {
|
||||
Either::Left(path) => Ok(path),
|
||||
Either::Right(len) => {
|
||||
let mut buf = vec![0u16; len as usize];
|
||||
inner(&file, &mut buf)?
|
||||
.left_or_err(|| io::Error::new(io::ErrorKind::InvalidData, "path too long"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,4 +54,18 @@ impl<L, R> Either<L, R> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn left_or_err<E, F: FnOnce() -> E>(self, f: F) -> Result<L, E> {
|
||||
match self {
|
||||
Either::Left(l) => Ok(l),
|
||||
_ => Err(f()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn right_or_err<E, F: FnOnce() -> E>(self, f: F) -> Result<R, E> {
|
||||
match self {
|
||||
Either::Right(r) => Ok(r),
|
||||
_ => Err(f()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue