1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

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>
This commit is contained in:
Sylvestre Ledru 2023-10-28 22:29:24 +02:00 committed by GitHub
parent 64916b0698
commit c24a51403a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 2 deletions

View file

@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE // For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code. // file that was distributed with this source code.
// spell-checker:ignore (ToDO) nonprint nonblank nonprinting // spell-checker:ignore (ToDO) nonprint nonblank nonprinting ELOOP
use clap::{crate_version, Arg, ArgAction, Command}; use clap::{crate_version, Arg, ArgAction, Command};
use std::fs::{metadata, File}; use std::fs::{metadata, File};
use std::io::{self, IsTerminal, Read, Write}; use std::io::{self, IsTerminal, Read, Write};
@ -50,6 +50,8 @@ enum CatError {
IsDirectory, IsDirectory,
#[error("input file is output file")] #[error("input file is output file")]
OutputIsInput, OutputIsInput,
#[error("Too many levels of symbolic links")]
TooManySymlinks,
} }
type CatResult<T> = Result<T, CatError>; type CatResult<T> = Result<T, CatError>;
@ -401,7 +403,23 @@ fn get_input_type(path: &str) -> CatResult<InputType> {
return Ok(InputType::StdIn); return Ok(InputType::StdIn);
} }
let ft = metadata(path)?.file_type(); let ft = match metadata(path) {
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 { match ft {
#[cfg(unix)] #[cfg(unix)]
ft if ft.is_block_device() => Ok(InputType::BlockDevice), ft if ft.is_block_device() => Ok(InputType::BlockDevice),

View file

@ -540,3 +540,15 @@ fn test_write_to_self() {
"first_file_content.second_file_content." "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");
}