From 80c7ed9732562633a63aea8d0705b7ffe9a99bf8 Mon Sep 17 00:00:00 2001 From: Guillaume Ranquet Date: Thu, 8 Jun 2023 11:26:21 +0200 Subject: [PATCH] ls: force fetching metadata when called with -L -Z The metadata are not used but it permits to check the symlink is valid. We then return 1 on invalid symlinks when ls is invoked with ls -L -Z Signed-off-by: Guillaume Ranquet --- src/uu/ls/src/ls.rs | 14 ++++++++++++++ tests/by-util/test_ls.rs | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 7db591cf3b7..342c52cbac9 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -3008,6 +3008,20 @@ fn display_inode(metadata: &Metadata) -> String { #[allow(unused_variables)] fn get_security_context(config: &Config, p_buf: &Path, must_dereference: bool) -> String { let substitute_string = "?".to_string(); + // If we must dereference, ensure that the symlink is actually valid even if the system + // does not support SELinux. + // Conforms to the GNU coreutils where a dangling symlink results in exit code 1. + if must_dereference { + match get_metadata(p_buf, must_dereference) { + Err(err) => { + // The Path couldn't be dereferenced, so return early and set exit code 1 + // to indicate a minor error + show!(LsError::IOErrorContext(err, p_buf.to_path_buf(), false)); + return substitute_string; + } + Ok(md) => (), + } + } if config.selinux_supported { #[cfg(feature = "selinux")] { diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 1266a7cab92..ad2c6424f69 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -3137,6 +3137,16 @@ fn test_ls_dangling_symlinks() { .stderr_contains("No such file or directory") .stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" }); + scene + .ucmd() + .arg("-LZ") + .arg("temp_dir") + .fails() + .code_is(1) + .stderr_contains("cannot access") + .stderr_contains("No such file or directory") + .stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" }); + scene .ucmd() .arg("-Ll")