Skip to content

Commit c24a514

Browse files
sylvestrecakebaker
andauthored
cat: return the same error message as GNU with loop symlink (#5466)
* 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 Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>
1 parent 64916b0 commit c24a514

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/uu/cat/src/cat.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
// spell-checker:ignore (ToDO) nonprint nonblank nonprinting
6+
// spell-checker:ignore (ToDO) nonprint nonblank nonprinting ELOOP
77
use clap::{crate_version, Arg, ArgAction, Command};
88
use std::fs::{metadata, File};
99
use std::io::{self, IsTerminal, Read, Write};
@@ -50,6 +50,8 @@ enum CatError {
5050
IsDirectory,
5151
#[error("input file is output file")]
5252
OutputIsInput,
53+
#[error("Too many levels of symbolic links")]
54+
TooManySymlinks,
5355
}
5456

5557
type CatResult<T> = Result<T, CatError>;
@@ -401,7 +403,23 @@ fn get_input_type(path: &str) -> CatResult<InputType> {
401403
return Ok(InputType::StdIn);
402404
}
403405

404-
let ft = metadata(path)?.file_type();
406+
let ft = match metadata(path) {
407+
Ok(md) => md.file_type(),
408+
Err(e) => {
409+
if let Some(raw_error) = e.raw_os_error() {
410+
// On Unix-like systems, the error code for "Too many levels of symbolic links" is 40 (ELOOP).
411+
// we want to provide a proper error message in this case.
412+
#[cfg(not(target_os = "macos"))]
413+
let too_many_symlink_code = 40;
414+
#[cfg(target_os = "macos")]
415+
let too_many_symlink_code = 62;
416+
if raw_error == too_many_symlink_code {
417+
return Err(CatError::TooManySymlinks);
418+
}
419+
}
420+
return Err(CatError::Io(e));
421+
}
422+
};
405423
match ft {
406424
#[cfg(unix)]
407425
ft if ft.is_block_device() => Ok(InputType::BlockDevice),

tests/by-util/test_cat.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,3 +540,15 @@ fn test_write_to_self() {
540540
"first_file_content.second_file_content."
541541
);
542542
}
543+
544+
#[test]
545+
#[cfg(unix)]
546+
fn test_error_loop() {
547+
let (at, mut ucmd) = at_and_ucmd!();
548+
at.symlink_file("2", "1");
549+
at.symlink_file("3", "2");
550+
at.symlink_file("1", "3");
551+
ucmd.arg("1")
552+
.fails()
553+
.stderr_is("cat: 1: Too many levels of symbolic links\n");
554+
}

0 commit comments

Comments
 (0)