diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 232250dcf3..a2912d63e2 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -35,7 +35,7 @@ use std::{ time::Duration, }; use term_grid::{Direction, Filling, Grid, GridOptions}; -use uucore::error::USimpleError; +use uucore::error::{strip_errno, USimpleError}; use uucore::format::human::{human_readable, SizeFormat}; #[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))] use uucore::fsxattr::has_acl; @@ -271,9 +271,9 @@ impl Display for LsError { _ => { write!( f, - "unknown io error: '{:?}', '{:?}'", + "cannot access '{}': {}", p.to_string_lossy(), - e + strip_errno(e), ) } }, diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 90254d229e..e5fd434853 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -5058,3 +5058,243 @@ fn test_suffix_case_sensitivity() { /* cSpell:enable */ ); } + +#[test] +fn test_ls_trailing_slash() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + at.mkdir("existing_dir"); + at.touch("existing_file"); + + #[cfg(unix)] + { + scene + .ucmd() + .arg("non_existing") + .fails() + .stderr_contains("'non_existing': No such file or directory") + .code_is(2); + + scene + .ucmd() + .arg("non_existing/") + .fails() + .stderr_contains("'non_existing/': No such file or directory") + .code_is(2); + + scene + .ucmd() + .arg("existing_dir") + .succeeds() + .no_stderr() + .code_is(0); + + scene + .ucmd() + .arg("existing_dir/") + .succeeds() + .no_stderr() + .code_is(0); + + scene + .ucmd() + .arg("existing_file") + .succeeds() + .no_stderr() + .code_is(0); + + scene + .ucmd() + .arg("existing_file/") + .fails() + .stderr_contains("'existing_file/': Not a directory") + .code_is(2); + } + + #[cfg(windows)] + { + scene + .ucmd() + .arg("non_existing") + .fails() + .stderr_contains("'non_existing': No such file or directory") + .code_is(2); + + scene + .ucmd() + .arg("non_existing/") + .fails() + .stderr_contains("'non_existing/': No such file or directory") + .code_is(2); + + scene + .ucmd() + .arg("non_existing\\") + .fails() + .stderr_contains("'non_existing\\': No such file or directory") + .code_is(2); + + scene + .ucmd() + .arg("existing_dir") + .succeeds() + .no_stderr() + .code_is(0); + + scene + .ucmd() + .arg("existing_dir/") + .succeeds() + .no_stderr() + .code_is(0); + + scene + .ucmd() + .arg("existing_dir\\") + .succeeds() + .no_stderr() + .code_is(0); + + scene + .ucmd() + .arg("existing_file") + .succeeds() + .no_stderr() + .code_is(0); + + scene.ucmd().arg("existing_file/").fails().stderr_contains( + "'existing_file/': The filename, directory name, or volume label syntax is incorrect", + ).code_is(2); + + scene.ucmd().arg("existing_file\\").fails().stderr_contains( + "'existing_file\\': The filename, directory name, or volume label syntax is incorrect", + ).code_is(2); + } +} + +#[test] +fn test_ls_long_file_name() { + let scene = TestScenario::new(util_name!()); + let long_file_name = "long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name_long_file_name"; + + #[cfg(unix)] + { + scene + .ucmd() + .arg(long_file_name) + .fails() + .stderr_contains(format!("'{}': File name too long", long_file_name)) + .code_is(2); + } + + #[cfg(windows)] + { + scene + .ucmd() + .arg(long_file_name) + .fails() + .stderr_contains(format!( + "'{}': The filename, directory name, or volume label syntax is incorrect", + long_file_name + )) + .code_is(2); + } +} + +#[cfg(windows)] +#[test] +fn test_ls_invalid_file_name() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + at.touch("existing_file"); + + scene + .ucmd() + .arg("existing_file*") + .succeeds() + .no_stderr() + .code_is(0); + + scene + .ucmd() + .arg("non_existing*") + .fails() + .stderr_contains( + "'non_existing*': The filename, directory name, or volume label syntax is incorrect", + ) + .code_is(2); + + scene + .ucmd() + .arg("non_existing?") + .fails() + .stderr_contains( + "'non_existing?': The filename, directory name, or volume label syntax is incorrect", + ) + .code_is(2); + + scene + .ucmd() + .arg("non_existing<") + .fails() + .stderr_contains( + "'non_existing<': The filename, directory name, or volume label syntax is incorrect", + ) + .code_is(2); + + scene + .ucmd() + .arg("non_existing>") + .fails() + .stderr_contains( + "'non_existing>': The filename, directory name, or volume label syntax is incorrect", + ) + .code_is(2); + + scene + .ucmd() + .arg("non_existing:") + .fails() + .stderr_contains( + "'non_existing:': The filename, directory name, or volume label syntax is incorrect", + ) + .code_is(2); + + scene + .ucmd() + .arg("non_existing|") + .fails() + .stderr_contains( + "'non_existing|': The filename, directory name, or volume label syntax is incorrect", + ) + .code_is(2); + + scene + .ucmd() + .arg("non_existing\n") + .fails() + .stderr_contains( + "'non_existing\n': The filename, directory name, or volume label syntax is incorrect", + ) + .code_is(2); +} + +#[cfg(windows)] +#[test] +fn test_ls_reserved_file_name() { + let scene = TestScenario::new(util_name!()); + + scene + .ucmd() + .arg("CON") + .fails() + .stderr_contains("'CON': The parameter is incorrect.") + .code_is(2); + + scene + .ucmd() + .arg("NUL") + .fails() + .stderr_contains("'NUL': Incorrect function.") + .code_is(2); +}