fix: Windows path length may exceed MAX_PATH (#3137)

This commit is contained in:
三咲雅 misaki masa 2025-09-04 17:02:18 +08:00 committed by GitHub
parent cfc7238638
commit b997e56a60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 84 additions and 82 deletions

96
Cargo.lock generated
View file

@ -255,9 +255,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.3"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
dependencies = [
"serde",
]
@ -383,9 +383,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.46"
version = "4.5.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57"
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931"
dependencies = [
"clap_builder",
"clap_derive",
@ -393,9 +393,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.46"
version = "4.5.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41"
checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6"
dependencies = [
"anstream",
"anstyle",
@ -434,9 +434,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.45"
version = "4.5.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c"
dependencies = [
"heck",
"proc-macro2",
@ -570,7 +570,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"crossterm_winapi",
"mio",
"parking_lot",
@ -586,7 +586,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"crossterm_winapi",
"derive_more",
"document-features",
@ -1135,9 +1135,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "image"
version = "0.25.7"
version = "0.25.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c6a3ce16143778e24df6f95365f12ed105425b22abefd289dd88a64bab59605"
checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7"
dependencies = [
"bytemuck",
"byteorder-lite",
@ -1194,7 +1194,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"inotify-sys",
"libc",
]
@ -1238,7 +1238,7 @@ version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"cfg-if",
"libc",
]
@ -1356,7 +1356,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"libc",
]
@ -1390,9 +1390,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.27"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "loop9"
@ -1588,7 +1588,7 @@ version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"fsevent-sys",
"inotify",
"kqueue",
@ -1710,7 +1710,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"objc2",
]
@ -1741,7 +1741,7 @@ version = "6.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"libc",
"once_cell",
"onig_sys",
@ -1893,7 +1893,7 @@ version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"crc32fast",
"fdeflate",
"flate2",
@ -2099,7 +2099,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"cassowary",
"compact_str",
"crossterm 0.28.1",
@ -2179,7 +2179,7 @@ version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
]
[[package]]
@ -2255,7 +2255,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@ -2268,7 +2268,7 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"errno",
"libc",
"linux-raw-sys 0.9.4",
@ -2467,12 +2467,6 @@ version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "smawk"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
[[package]]
name = "socket2"
version = "0.6.0"
@ -2574,17 +2568,6 @@ version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "textwrap"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
dependencies = [
"smawk",
"unicode-linebreak",
"unicode-width 0.2.0",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@ -2656,9 +2639,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.42"
version = "0.3.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca967379f9d8eb8058d86ed467d81d03e81acd45757e4ca341c24affbe8e8e3"
checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031"
dependencies = [
"deranged",
"libc",
@ -2672,15 +2655,15 @@ dependencies = [
[[package]]
name = "time-core"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9108bb380861b07264b950ded55a44a14a4adc68b9f5efd85aafc3aa4d40a68"
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
[[package]]
name = "time-macros"
version = "0.2.23"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7182799245a7264ce590b349d90338f1c1affad93d2639aed5f8f69c090b334c"
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
dependencies = [
"num-conv",
"time-core",
@ -2907,9 +2890,9 @@ dependencies = [
[[package]]
name = "twox-hash"
version = "2.1.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56"
checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c"
dependencies = [
"rand 0.9.2",
]
@ -2926,12 +2909,6 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
@ -3622,7 +3599,7 @@ name = "yazi-config"
version = "25.6.11"
dependencies = [
"anyhow",
"bitflags 2.9.3",
"bitflags 2.9.4",
"crossterm 0.29.0",
"dirs",
"globset",
@ -3721,7 +3698,6 @@ dependencies = [
"ratatui",
"scopeguard",
"signal-hook-tokio",
"textwrap",
"tikv-jemallocator",
"tokio",
"tokio-stream",
@ -3752,7 +3728,7 @@ version = "25.6.11"
dependencies = [
"anyhow",
"arc-swap",
"bitflags 2.9.3",
"bitflags 2.9.4",
"core-foundation-sys",
"dirs",
"foldhash 0.2.0",
@ -3787,7 +3763,7 @@ name = "yazi-parser"
version = "25.6.11"
dependencies = [
"anyhow",
"bitflags 2.9.3",
"bitflags 2.9.4",
"crossterm 0.29.0",
"hashbrown 0.16.0",
"mlua",

View file

@ -23,8 +23,8 @@ lto = false
ansi-to-tui = "7.0.0"
anyhow = "1.0.99"
base64 = "0.22.1"
bitflags = { version = "2.9.3", features = [ "serde" ] }
clap = { version = "4.5.46", features = [ "derive" ] }
bitflags = { version = "2.9.4", features = [ "serde" ] }
clap = { version = "4.5.47", features = [ "derive" ] }
core-foundation-sys = "0.8.7"
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
dirs = "6.0.0"
@ -51,6 +51,6 @@ tokio-stream = "0.1.17"
tokio-util = "0.7.16"
toml = { version = "0.9.5" }
tracing = { version = "0.1.41", features = [ "max_level_debug", "release_max_level_debug" ] }
twox-hash = { version = "2.1.1", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
unicode-width = { version = "0.2.0", default-features = false }
twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
uzers = "0.12.1"

View file

@ -20,7 +20,7 @@ ansi-to-tui = { workspace = true }
anyhow = { workspace = true }
base64 = { workspace = true }
crossterm = { workspace = true }
image = { version = "0.25.7", default-features = false, features = [ "avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "webp" ] }
image = { version = "0.25.8", default-features = false, features = [ "avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "webp" ] }
palette = { version = "0.7.6", default-features = false }
quantette = { version = "0.3.0", default-features = false }
ratatui = { workspace = true }

View file

@ -50,7 +50,6 @@ mlua = { workspace = true }
paste = { workspace = true }
ratatui = { workspace = true }
scopeguard = { workspace = true }
textwrap = "0.16.2"
tokio = { workspace = true }
tokio-stream = { workspace = true }

View file

@ -127,30 +127,43 @@ 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, MAX_PATH}, 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()
.access_mode(0)
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)
.open(path)?;
let mut buf = [0u16; MAX_PATH as usize];
let len = unsafe {
GetFinalPathNameByHandleW(
file.as_raw_handle() as HANDLE,
buf.as_mut_ptr(),
buf.len() as u32,
VOLUME_NAME_DOS,
)
};
fn inner(file: &File, buf: &mut [u16]) -> io::Result<Either<PathBuf, u32>> {
let len = unsafe {
GetFinalPathNameByHandleW(
file.as_raw_handle() as HANDLE,
buf.as_mut_ptr(),
buf.len() as u32,
VOLUME_NAME_DOS,
)
};
if len == 0 {
Err(io::Error::last_os_error())
} else if buf.starts_with(&[92, 92, 63, 92]) {
Ok(PathBuf::from(OsString::from_wide(&buf[4..len as usize])))
} else {
Ok(PathBuf::from(OsString::from_wide(&buf[0..len as usize])))
Ok(if len == 0 {
Err(io::Error::last_os_error())?
} else if len as usize > buf.len() {
Either::Right(len)
} else if buf.starts_with(&[92, 92, 63, 92]) {
Either::Left(PathBuf::from(OsString::from_wide(&buf[4..len as usize])))
} else {
Either::Left(PathBuf::from(OsString::from_wide(&buf[0..len as usize])))
})
}
match inner(&file, &mut [0u16; 512])? {
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"))
}
}
}

View file

@ -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()),
}
}
}