1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Merge pull request #3921 from niyaznigmatullin/ls_exit_code_2_some_cases

ls: exit code 2 when `IOError` happened for argument
This commit is contained in:
Sylvestre Ledru 2022-09-12 22:20:08 +02:00 committed by GitHub
commit 1ed281fce9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 8 deletions

View file

@ -153,7 +153,7 @@ const DEFAULT_BLOCK_SIZE: u64 = 1024;
enum LsError { enum LsError {
InvalidLineWidth(String), InvalidLineWidth(String),
IOError(std::io::Error), IOError(std::io::Error),
IOErrorContext(std::io::Error, PathBuf), IOErrorContext(std::io::Error, PathBuf, bool),
BlockSizeParseError(String), BlockSizeParseError(String),
AlreadyListedError(PathBuf), AlreadyListedError(PathBuf),
} }
@ -163,7 +163,8 @@ impl UError for LsError {
match self { match self {
Self::InvalidLineWidth(_) => 2, Self::InvalidLineWidth(_) => 2,
Self::IOError(_) => 1, Self::IOError(_) => 1,
Self::IOErrorContext(_, _) => 1, Self::IOErrorContext(_, _, false) => 1,
Self::IOErrorContext(_, _, true) => 2,
Self::BlockSizeParseError(_) => 1, Self::BlockSizeParseError(_) => 1,
Self::AlreadyListedError(_) => 2, Self::AlreadyListedError(_) => 2,
} }
@ -180,7 +181,7 @@ impl Display for LsError {
} }
Self::InvalidLineWidth(s) => write!(f, "invalid line width: {}", s.quote()), Self::InvalidLineWidth(s) => write!(f, "invalid line width: {}", s.quote()),
Self::IOError(e) => write!(f, "general io error: {}", e), Self::IOError(e) => write!(f, "general io error: {}", e),
Self::IOErrorContext(e, p) => { Self::IOErrorContext(e, p, _) => {
let error_kind = e.kind(); let error_kind = e.kind();
let errno = e.raw_os_error().unwrap_or(1i32); let errno = e.raw_os_error().unwrap_or(1i32);
@ -1566,6 +1567,7 @@ struct PathData {
p_buf: PathBuf, p_buf: PathBuf,
must_dereference: bool, must_dereference: bool,
security_context: String, security_context: String,
command_line: bool,
} }
impl PathData { impl PathData {
@ -1649,6 +1651,7 @@ impl PathData {
p_buf, p_buf,
must_dereference, must_dereference,
security_context, security_context,
command_line,
} }
} }
@ -1677,7 +1680,11 @@ impl PathData {
return dir_entry.metadata().ok(); return dir_entry.metadata().ok();
} }
} }
show!(LsError::IOErrorContext(err, self.p_buf.clone(),)); show!(LsError::IOErrorContext(
err,
self.p_buf.clone(),
self.command_line
));
None None
} }
Ok(md) => Some(md), Ok(md) => Some(md),
@ -1739,7 +1746,11 @@ pub fn list(locs: Vec<&Path>, config: &Config) -> UResult<()> {
Err(err) => { Err(err) => {
// flush stdout buffer before the error to preserve formatting and order // flush stdout buffer before the error to preserve formatting and order
out.flush()?; out.flush()?;
show!(LsError::IOErrorContext(err, path_data.p_buf.clone())); show!(LsError::IOErrorContext(
err,
path_data.p_buf.clone(),
path_data.command_line
));
continue; continue;
} }
Ok(rd) => rd, Ok(rd) => rd,
@ -1916,7 +1927,11 @@ fn enter_directory(
match fs::read_dir(&e.p_buf) { match fs::read_dir(&e.p_buf) {
Err(err) => { Err(err) => {
out.flush()?; out.flush()?;
show!(LsError::IOErrorContext(err, e.p_buf.clone())); show!(LsError::IOErrorContext(
err,
e.p_buf.clone(),
e.command_line
));
continue; continue;
} }
Ok(rd) => { Ok(rd) => {

View file

@ -385,6 +385,7 @@ fn test_ls_io_errors() {
.arg("-1") .arg("-1")
.arg("some-dir1") .arg("some-dir1")
.fails() .fails()
.code_is(2)
.stderr_contains("cannot open directory") .stderr_contains("cannot open directory")
.stderr_contains("Permission denied"); .stderr_contains("Permission denied");
@ -393,6 +394,7 @@ fn test_ls_io_errors() {
.arg("-Li") .arg("-Li")
.arg("some-dir2") .arg("some-dir2")
.fails() .fails()
.code_is(1)
.stderr_contains("cannot access") .stderr_contains("cannot access")
.stderr_contains("No such file or directory") .stderr_contains("No such file or directory")
.stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" }); .stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" });
@ -408,6 +410,7 @@ fn test_ls_io_errors() {
.arg("-laR") .arg("-laR")
.arg("some-dir3") .arg("some-dir3")
.fails() .fails()
.code_is(1)
.stderr_contains("some-dir4") .stderr_contains("some-dir4")
.stderr_contains("cannot open directory") .stderr_contains("cannot open directory")
.stderr_contains("Permission denied") .stderr_contains("Permission denied")
@ -2987,8 +2990,18 @@ fn test_ls_dangling_symlinks() {
at.mkdir("temp_dir"); at.mkdir("temp_dir");
at.symlink_file("does_not_exist", "temp_dir/dangle"); at.symlink_file("does_not_exist", "temp_dir/dangle");
scene.ucmd().arg("-L").arg("temp_dir/dangle").fails(); scene
scene.ucmd().arg("-H").arg("temp_dir/dangle").fails(); .ucmd()
.arg("-L")
.arg("temp_dir/dangle")
.fails()
.code_is(2);
scene
.ucmd()
.arg("-H")
.arg("temp_dir/dangle")
.fails()
.code_is(2);
scene scene
.ucmd() .ucmd()
@ -3001,6 +3014,7 @@ fn test_ls_dangling_symlinks() {
.arg("-Li") .arg("-Li")
.arg("temp_dir") .arg("temp_dir")
.fails() .fails()
.code_is(1)
.stderr_contains("cannot access") .stderr_contains("cannot access")
.stderr_contains("No such file or directory") .stderr_contains("No such file or directory")
.stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" }); .stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" });
@ -3010,6 +3024,7 @@ fn test_ls_dangling_symlinks() {
.arg("-Ll") .arg("-Ll")
.arg("temp_dir") .arg("temp_dir")
.fails() .fails()
.code_is(1)
.stdout_contains("l?????????"); .stdout_contains("l?????????");
#[cfg(unix)] #[cfg(unix)]
@ -3018,6 +3033,7 @@ fn test_ls_dangling_symlinks() {
at.touch("temp_dir/real_file"); at.touch("temp_dir/real_file");
let real_file_res = scene.ucmd().arg("-Li1").arg("temp_dir").fails(); let real_file_res = scene.ucmd().arg("-Li1").arg("temp_dir").fails();
real_file_res.code_is(1);
let real_file_stdout_len = String::from_utf8(real_file_res.stdout().to_owned()) let real_file_stdout_len = String::from_utf8(real_file_res.stdout().to_owned())
.ok() .ok()
.unwrap() .unwrap()
@ -3029,6 +3045,7 @@ fn test_ls_dangling_symlinks() {
.len(); .len();
let dangle_file_res = scene.ucmd().arg("-Li1").arg("temp_dir").fails(); let dangle_file_res = scene.ucmd().arg("-Li1").arg("temp_dir").fails();
dangle_file_res.code_is(1);
let dangle_stdout_len = String::from_utf8(dangle_file_res.stdout().to_owned()) let dangle_stdout_len = String::from_utf8(dangle_file_res.stdout().to_owned())
.ok() .ok()
.unwrap() .unwrap()
@ -3199,6 +3216,7 @@ fn test_ls_dereference_looped_symlinks_recursive() {
ucmd.args(&["-RL", "loop"]) ucmd.args(&["-RL", "loop"])
.fails() .fails()
.code_is(2)
.stderr_contains("not listing already-listed directory"); .stderr_contains("not listing already-listed directory");
} }