From b997e56a60de6798e73a147366187aa3dd966fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20misaki=20masa?= Date: Thu, 4 Sep 2025 17:02:18 +0800 Subject: [PATCH] fix: Windows path length may exceed `MAX_PATH` (#3137) --- Cargo.lock | 96 ++++++++++---------------- Cargo.toml | 6 +- yazi-adapter/Cargo.toml | 2 +- yazi-fm/Cargo.toml | 1 - yazi-fs/src/provider/local/casefold.rs | 47 ++++++++----- yazi-shared/src/either.rs | 14 ++++ 6 files changed, 84 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2e30974..648bad52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index 01503344..a1c936f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/yazi-adapter/Cargo.toml b/yazi-adapter/Cargo.toml index ac5ea638..b53e5b0a 100644 --- a/yazi-adapter/Cargo.toml +++ b/yazi-adapter/Cargo.toml @@ -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 } diff --git a/yazi-fm/Cargo.toml b/yazi-fm/Cargo.toml index 5dc17dbe..8f26da5d 100644 --- a/yazi-fm/Cargo.toml +++ b/yazi-fm/Cargo.toml @@ -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 } diff --git a/yazi-fs/src/provider/local/casefold.rs b/yazi-fs/src/provider/local/casefold.rs index 6b70ef5f..73c631f8 100644 --- a/yazi-fs/src/provider/local/casefold.rs +++ b/yazi-fs/src/provider/local/casefold.rs @@ -127,30 +127,43 @@ fn final_path(path: &Path) -> io::Result { #[cfg(target_os = "windows")] fn final_path(path: &Path) -> io::Result { - 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> { + 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")) + } } } diff --git a/yazi-shared/src/either.rs b/yazi-shared/src/either.rs index dfa6e6e9..988f7a4d 100644 --- a/yazi-shared/src/either.rs +++ b/yazi-shared/src/either.rs @@ -54,4 +54,18 @@ impl Either { _ => None, } } + + pub fn left_or_err E>(self, f: F) -> Result { + match self { + Either::Left(l) => Ok(l), + _ => Err(f()), + } + } + + pub fn right_or_err E>(self, f: F) -> Result { + match self { + Either::Right(r) => Ok(r), + _ => Err(f()), + } + } }