From 6f5bade936afb34fc6d2fadce6e1130f9d17d51f Mon Sep 17 00:00:00 2001 From: lyra den Date: Wed, 4 Feb 2026 09:52:45 +0000 Subject: [PATCH 1/4] readlink: Set silent mode as default --- src/uu/readlink/src/readlink.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/uu/readlink/src/readlink.rs b/src/uu/readlink/src/readlink.rs index f220d6a0515..43fe7a15d64 100644 --- a/src/uu/readlink/src/readlink.rs +++ b/src/uu/readlink/src/readlink.rs @@ -6,6 +6,7 @@ // spell-checker:ignore (ToDO) errno use clap::{Arg, ArgAction, Command}; +use std::env; use std::ffi::OsString; use std::fs; use std::io::{Write, stdout}; @@ -35,8 +36,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let mut no_trailing_delimiter = matches.get_flag(OPT_NO_NEWLINE); let use_zero = matches.get_flag(OPT_ZERO); - let silent = matches.get_flag(OPT_SILENT) || matches.get_flag(OPT_QUIET); - let verbose = matches.get_flag(OPT_VERBOSE); + let verbose = matches.get_flag(OPT_VERBOSE) || env::var("POSIXLY_CORRECT").is_ok(); // GNU readlink -f/-e/-m follows symlinks first and then applies `..` (physical resolution). // ResolveMode::Logical collapses `..` before following links, which yields the opposite order, @@ -70,7 +70,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { )); } - if no_trailing_delimiter && files.len() > 1 && !silent { + if no_trailing_delimiter && files.len() > 1 { show_error!("{}", translate!("readlink-error-ignoring-no-newline")); no_trailing_delimiter = false; } @@ -93,7 +93,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { show(&path, line_ending).map_err_context(String::new)?; } Err(err) => { - if silent && !verbose { + if !verbose { return Err(1.into()); } @@ -151,6 +151,7 @@ pub fn uu_app() -> Command { .short('q') .long(OPT_QUIET) .help(translate!("readlink-help-quiet")) + .overrides_with_all([OPT_QUIET, OPT_SILENT, OPT_VERBOSE]) .action(ArgAction::SetTrue), ) .arg( @@ -158,6 +159,7 @@ pub fn uu_app() -> Command { .short('s') .long(OPT_SILENT) .help(translate!("readlink-help-silent")) + .overrides_with_all([OPT_QUIET, OPT_SILENT, OPT_VERBOSE]) .action(ArgAction::SetTrue), ) .arg( @@ -165,6 +167,7 @@ pub fn uu_app() -> Command { .short('v') .long(OPT_VERBOSE) .help(translate!("readlink-help-verbose")) + .overrides_with_all([OPT_QUIET, OPT_SILENT, OPT_VERBOSE]) .action(ArgAction::SetTrue), ) .arg( From ef85753099b0d61a8f780100c3bfc2e6936ee81c Mon Sep 17 00:00:00 2001 From: lyra den Date: Wed, 4 Feb 2026 15:28:43 +0000 Subject: [PATCH 2/4] readlink: Add tests for verbose and silent options --- tests/by-util/test_readlink.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/by-util/test_readlink.rs b/tests/by-util/test_readlink.rs index 7c7cb01d405..4ff9299be39 100644 --- a/tests/by-util/test_readlink.rs +++ b/tests/by-util/test_readlink.rs @@ -138,6 +138,15 @@ fn test_posixly_correct_regular_file() { .fails_with_code(1) .stderr_contains("Invalid argument") .no_stdout(); + + // GNU behavior is to ignore -s and -q when POSIXLY_CORRECT is set. + scene + .ucmd() + .env("POSIXLY_CORRECT", "1") + .args(&["-s", "regfile"]) + .fails_with_code(1) + .stderr_contains("Invalid argument") + .no_stdout(); } #[test] @@ -433,3 +442,28 @@ fn test_readlink_non_utf8_paths() { let output = result.stdout_str_lossy(); assert!(output.contains(file_name)); } + +#[test] +fn test_verbose_or_silent() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + at.touch("regfile"); + scene + .ucmd() + .arg("regfile") + .fails_with_code(1) + .no_stderr() + .no_stdout(); + scene + .ucmd() + .args(&["-v", "regfile"]) + .fails_with_code(1) + .stderr_contains("Invalid argument") + .no_stdout(); + scene + .ucmd() + .args(&["-vs", "regfile"]) + .fails_with_code(1) + .no_stderr() + .no_stdout(); +} From 23341a968b4693f6c20f34feea7a9cd6fa45e370 Mon Sep 17 00:00:00 2001 From: lyra den Date: Fri, 6 Feb 2026 04:45:15 +0000 Subject: [PATCH 3/4] readlink: Change test to work with Windows-specific error message --- tests/by-util/test_readlink.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/by-util/test_readlink.rs b/tests/by-util/test_readlink.rs index 4ff9299be39..a17aa3a18fe 100644 --- a/tests/by-util/test_readlink.rs +++ b/tests/by-util/test_readlink.rs @@ -458,7 +458,12 @@ fn test_verbose_or_silent() { .ucmd() .args(&["-v", "regfile"]) .fails_with_code(1) - .stderr_contains("Invalid argument") + .stderr_contains( + #[cfg(not(windows))] + "Invalid argument", + #[cfg(windows)] + "regfile: The file or directory is not a reparse point.", + ) .no_stdout(); scene .ucmd() From 7fa58c12d6ce3ab8ecc53e1e99530789d83f81e9 Mon Sep 17 00:00:00 2001 From: lyra den Date: Sat, 7 Feb 2026 20:10:56 +0000 Subject: [PATCH 4/4] readlink: Add additional test cases --- tests/by-util/test_readlink.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/by-util/test_readlink.rs b/tests/by-util/test_readlink.rs index a17aa3a18fe..8145d3d332a 100644 --- a/tests/by-util/test_readlink.rs +++ b/tests/by-util/test_readlink.rs @@ -147,6 +147,13 @@ fn test_posixly_correct_regular_file() { .fails_with_code(1) .stderr_contains("Invalid argument") .no_stdout(); + scene + .ucmd() + .env("POSIXLY_CORRECT", "1") + .args(&["-q", "regfile"]) + .fails_with_code(1) + .stderr_contains("Invalid argument") + .no_stdout(); } #[test] @@ -471,4 +478,15 @@ fn test_verbose_or_silent() { .fails_with_code(1) .no_stderr() .no_stdout(); + scene + .ucmd() + .args(&["-sv", "regfile"]) + .fails_with_code(1) + .stderr_contains( + #[cfg(not(windows))] + "Invalid argument", + #[cfg(windows)] + "regfile: The file or directory is not a reparse point.", + ) + .no_stdout(); }