From 0a304d32e56a1e2c8ebc01f6b0b4b95189f8c83a Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 28 Oct 2023 10:17:11 +0200 Subject: [PATCH 1/2] cat: return the same error message as GNU with loop symlink Should fix tests/du/long-sloop.sh because it is using cat as a ref for error messages --- src/uu/cat/src/cat.rs | 23 +++++++++++++++++++++-- tests/by-util/test_cat.rs | 12 ++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index d49f4aa0707..be719cc335d 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) nonprint nonblank nonprinting +// spell-checker:ignore (ToDO) nonprint nonblank nonprinting ELOOP // last synced with: cat (GNU coreutils) 8.13 use clap::{crate_version, Arg, ArgAction, Command}; @@ -52,6 +52,8 @@ enum CatError { IsDirectory, #[error("input file is output file")] OutputIsInput, + #[error("Too many levels of symbolic links")] + TooManySymlinks, } type CatResult = Result; @@ -403,7 +405,24 @@ fn get_input_type(path: &str) -> CatResult { return Ok(InputType::StdIn); } - let ft = metadata(path)?.file_type(); + let metadata_result = metadata(path); + let ft = match metadata_result { + Ok(md) => md.file_type(), + Err(e) => { + if let Some(raw_error) = e.raw_os_error() { + // On Unix-like systems, the error code for "Too many levels of symbolic links" is 40 (ELOOP). + // we want to provide a proper error message in this case. + #[cfg(not(target_os = "macos"))] + let too_many_symlink_code = 40; + #[cfg(target_os = "macos")] + let too_many_symlink_code = 62; + if raw_error == too_many_symlink_code { + return Err(CatError::TooManySymlinks); + } + } + return Err(CatError::Io(e)); + } + }; match ft { #[cfg(unix)] ft if ft.is_block_device() => Ok(InputType::BlockDevice), diff --git a/tests/by-util/test_cat.rs b/tests/by-util/test_cat.rs index 27f40356de5..aa86ab06652 100644 --- a/tests/by-util/test_cat.rs +++ b/tests/by-util/test_cat.rs @@ -540,3 +540,15 @@ fn test_write_to_self() { "first_file_content.second_file_content." ); } + +#[test] +#[cfg(unix)] +fn test_error_loop() { + let (at, mut ucmd) = at_and_ucmd!(); + at.symlink_file("2", "1"); + at.symlink_file("3", "2"); + at.symlink_file("1", "3"); + ucmd.arg("1") + .fails() + .stderr_is("cat: 1: Too many levels of symbolic links\n"); +} From 3bacaaf3e46a6db096d1c26df707606271c24e22 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 28 Oct 2023 18:22:53 +0200 Subject: [PATCH 2/2] Simplify code Co-authored-by: Daniel Hofstetter --- src/uu/cat/src/cat.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index be719cc335d..61bdc7e8a38 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -405,8 +405,7 @@ fn get_input_type(path: &str) -> CatResult { return Ok(InputType::StdIn); } - let metadata_result = metadata(path); - let ft = match metadata_result { + let ft = match metadata(path) { Ok(md) => md.file_type(), Err(e) => { if let Some(raw_error) = e.raw_os_error() {