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")