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,32 +127,44 @@ fn final_path(path: &Path) -> io::Result<PathBuf> {
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn final_path(path: &Path) -> io::Result<PathBuf> {
|
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 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()
|
let file = std::fs::OpenOptions::new()
|
||||||
.access_mode(0)
|
.access_mode(0)
|
||||||
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)
|
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)
|
||||||
.open(path)?;
|
.open(path)?;
|
||||||
|
|
||||||
let mut buf = [0u16; 512];
|
fn inner(file: &File, buf: &mut [u16]) -> io::Result<Either<PathBuf, u32>> {
|
||||||
let len = unsafe {
|
let len = unsafe {
|
||||||
GetFinalPathNameByHandleW(
|
GetFinalPathNameByHandleW(
|
||||||
file.as_raw_handle() as HANDLE,
|
file.as_raw_handle() as HANDLE,
|
||||||
buf.as_mut_ptr(),
|
buf.as_mut_ptr(),
|
||||||
buf.len() as u32,
|
buf.len() as u32,
|
||||||
VOLUME_NAME_DOS,
|
VOLUME_NAME_DOS,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if len == 0 {
|
Ok(if len == 0 {
|
||||||
Err(io::Error::last_os_error())
|
Err(io::Error::last_os_error())?
|
||||||
} else if len as usize > buf.len() {
|
} 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]) {
|
} 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 {
|
} 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,
|
_ => 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