From 363e40e09b9be43d821604678bc126e9e935a6b9 Mon Sep 17 00:00:00 2001 From: Christopher Dryden Date: Tue, 10 Feb 2026 01:51:29 +0000 Subject: [PATCH 1/3] tail: print inaccessible message when symlink target changes --- src/uu/tail/src/follow/watch.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/uu/tail/src/follow/watch.rs b/src/uu/tail/src/follow/watch.rs index 06a355b2217..c1fa3775ec7 100644 --- a/src/uu/tail/src/follow/watch.rs +++ b/src/uu/tail/src/follow/watch.rs @@ -381,6 +381,14 @@ impl Observer { } self.files.update_metadata(event_path, Some(new_md)); } else if event_path.is_symlink() && settings.retry { + if let Some(old_md) = self.files.get_mut_metadata(event_path) { + if old_md.is_tailable() && self.files.get(event_path).reader.is_some() { + show_error!( + "{}", + translate!("tail-status-file-became-inaccessible", "file" => display_name.quote(), "become_inaccessible" => translate!("tail-become-inaccessible"), "no_such_file" => translate!("tail-no-such-file-or-directory")) + ); + } + } self.files.reset_reader(event_path); self.orphans.push(event_path.clone()); } From baf3b5a7ef5ca85fda9fac0acaeb120697c88d20 Mon Sep 17 00:00:00 2001 From: Christopher Dryden Date: Tue, 10 Feb 2026 02:39:15 +0000 Subject: [PATCH 2/3] tail: report blocking mode in --debug for non-regular files --- src/uu/tail/locales/en-US.ftl | 1 + src/uu/tail/locales/fr-FR.ftl | 5 +++++ src/uu/tail/src/tail.rs | 10 ++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/uu/tail/locales/en-US.ftl b/src/uu/tail/locales/en-US.ftl index 6d434ae9862..20ba82fd057 100644 --- a/src/uu/tail/locales/en-US.ftl +++ b/src/uu/tail/locales/en-US.ftl @@ -73,5 +73,6 @@ tail-no-files-remaining = no files remaining tail-become-inaccessible = has become inaccessible # Debug messages +tail-debug-using-blocking-mode = using blocking mode tail-debug-using-notification-mode = using notification mode tail-debug-using-polling-mode = using polling mode diff --git a/src/uu/tail/locales/fr-FR.ftl b/src/uu/tail/locales/fr-FR.ftl index 85d973571ae..67008ef7550 100644 --- a/src/uu/tail/locales/fr-FR.ftl +++ b/src/uu/tail/locales/fr-FR.ftl @@ -70,3 +70,8 @@ tail-giving-up-on-this-name = ; abandon de ce nom tail-stdin-header = entrée standard tail-no-files-remaining = aucun fichier restant tail-become-inaccessible = est devenu inaccessible + +# Messages de débogage +tail-debug-using-blocking-mode = utilisation du mode bloquant +tail-debug-using-notification-mode = utilisation du mode notification +tail-debug-using-polling-mode = utilisation du mode sondage diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index ad568db7628..d5248a53701 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -22,7 +22,7 @@ mod platform; pub mod text; pub use args::uu_app; -use args::{FilterMode, Settings, Signum, parse_args}; +use args::{FilterMode, FollowMode, Settings, Signum, parse_args}; use chunks::ReverseChunks; use follow::Observer; use memchr::{memchr_iter, memrchr_iter}; @@ -68,8 +68,14 @@ fn uu_tail(settings: &Settings) -> UResult<()> { // Print debug info about the follow implementation being used if settings.debug && settings.follow.is_some() { - if observer.use_polling { + if observer.use_polling || settings.follow == Some(FollowMode::Name) { show_error!("{}", translate!("tail-debug-using-polling-mode")); + } else if settings + .inputs + .iter() + .all(|i| !matches!(i.kind(), InputKind::File(p) if p.is_file())) + { + show_error!("{}", translate!("tail-debug-using-blocking-mode")); } else { show_error!("{}", translate!("tail-debug-using-notification-mode")); } From 1f29b7416e27f46e1c7fe5427c5b25d1e604e33e Mon Sep 17 00:00:00 2001 From: Christopher Dryden Date: Tue, 10 Feb 2026 13:50:42 +0000 Subject: [PATCH 3/3] tail: fix debug mode reporting for follow=name with regular files --- src/uu/tail/src/tail.rs | 10 ++++----- tests/by-util/test_tail.rs | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index d5248a53701..87c9099e309 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -68,13 +68,13 @@ fn uu_tail(settings: &Settings) -> UResult<()> { // Print debug info about the follow implementation being used if settings.debug && settings.follow.is_some() { - if observer.use_polling || settings.follow == Some(FollowMode::Name) { - show_error!("{}", translate!("tail-debug-using-polling-mode")); - } else if settings + let all_non_regular = settings .inputs .iter() - .all(|i| !matches!(i.kind(), InputKind::File(p) if p.is_file())) - { + .all(|i| !matches!(i.kind(), InputKind::File(p) if p.is_file())); + if observer.use_polling || (all_non_regular && settings.follow == Some(FollowMode::Name)) { + show_error!("{}", translate!("tail-debug-using-polling-mode")); + } else if all_non_regular { show_error!("{}", translate!("tail-debug-using-blocking-mode")); } else { show_error!("{}", translate!("tail-debug-using-notification-mode")); diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index f2875e7b1e3..8f466f07268 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -5133,6 +5133,50 @@ fn test_debug_flag_with_polling() { .stderr_contains("tail: using polling mode"); } +#[test] +#[cfg(target_os = "linux")] +fn test_debug_flag_blocking_mode_non_regular() { + let mut child = new_ucmd!() + .args(&["--debug", "-f", "/dev/null"]) + .run_no_wait(); + child.make_assertion_with_delay(500).is_alive(); + child + .kill() + .make_assertion() + .with_all_output() + .stderr_contains("tail: using blocking mode"); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_debug_flag_polling_mode_non_regular_follow_name() { + let mut child = new_ucmd!() + .args(&["--debug", "-F", "/dev/null"]) + .run_no_wait(); + child.make_assertion_with_delay(500).is_alive(); + child + .kill() + .make_assertion() + .with_all_output() + .stderr_contains("tail: using polling mode"); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_debug_flag_notification_mode_regular_follow_name() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + at.touch("f"); + + let mut child = ts.ucmd().args(&["--debug", "-F", "f"]).run_no_wait(); + child.make_assertion_with_delay(500).is_alive(); + child + .kill() + .make_assertion() + .with_all_output() + .stderr_contains("tail: using notification mode"); +} + #[test] #[cfg(target_os = "linux")] fn test_debug_flag_with_inotify() {