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