Skip to content
Merged
27 changes: 18 additions & 9 deletions src/uu/tail/src/tail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,24 @@ fn tail_file(
observer: &mut Observer,
offset: u64,
) -> UResult<()> {
if !path.exists() {
set_exit_code(1);
show_error!(
"{}",
translate!("tail-error-cannot-open-no-such-file", "file" => input.display_name.clone(), "error" => translate!("tail-no-such-file-or-directory"))
);
observer.add_bad_path(path, input.display_name.as_str(), false)?;
} else if path.is_dir() {
let md = path.metadata();
if let Err(ref e) = md {
if e.kind() == ErrorKind::NotFound {
set_exit_code(1);
show_error!(
"{}",
translate!(
"tail-error-cannot-open-no-such-file",
"file" => input.display_name.clone(),
"error" => translate!("tail-no-such-file-or-directory")
)
);
observer.add_bad_path(path, input.display_name.as_str(), false)?;
return Ok(());
}
}

if path.is_dir() {
set_exit_code(1);

header_printer.print_input(input);
Expand All @@ -146,7 +156,6 @@ fn tail_file(
);
}
if !observer.follow_name_retry() {
// skip directory if not retry
return Ok(());
}
observer.add_bad_path(path, input.display_name.as_str(), false)?;
Expand Down
25 changes: 25 additions & 0 deletions tests/by-util/test_tail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,31 @@ fn test_follow_non_utf8_bytes() {
child.kill();
}

#[test]
#[cfg(unix)]
fn test_permission_denied_is_not_reported_as_not_found() {
use std::fs;
use std::os::unix::fs::PermissionsExt;

if unsafe { libc::geteuid() } == 0 {
return;
}

let (at, mut ucmd) = at_and_ucmd!();

at.mkdir("noexec");
at.touch("noexec/file");

let dir = at.plus("noexec");
fs::set_permissions(&dir, fs::Permissions::from_mode(0o000)).unwrap();

ucmd.arg("noexec/file")
.fails()
.stderr_contains("Permission denied");

fs::set_permissions(&dir, fs::Permissions::from_mode(0o700)).unwrap();
}

#[test]
#[cfg(not(target_os = "windows"))] // FIXME: test times out
fn test_follow_multiple() {
Expand Down
Loading