From d0c59414b260c6651e597226dfe896193d895364 Mon Sep 17 00:00:00 2001 From: Jay Hemnani <193022578+jayhemnani9910@users.noreply.github.com> Date: Thu, 22 Oct 2026 00:37:27 +0530 Subject: [PATCH] last: show the first record's time in "begins" when -n, --since or --until skip records --- src/uu/last/src/platform/unix.rs | 21 ++++++++++----------- tests/by-util/test_last.rs | 25 +++++++++++++++++++++---- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/uu/last/src/platform/unix.rs b/src/uu/last/src/platform/unix.rs index 9958e600..46764a31 100644 --- a/src/uu/last/src/platform/unix.rs +++ b/src/uu/last/src/platform/unix.rs @@ -222,23 +222,22 @@ impl Last { ut_stack.push(*utmpx); }); + // "begins" is the time of the first record, whatever -n, --since and + // --until skip + let first_ut_time = ut_stack.first().map(|ut| { + let first_login_time = ut.login_time(); + self.utmp_file_time( + first_login_time.unix_timestamp(), + first_login_time.nanosecond().into(), + ) + }); + let mut counter = 0; - let mut first_ut_time = None; while let Some(ut) = ut_stack.pop() { if ut.login_time() < self.since || ut.login_time() > self.until { continue; } - if ut_stack.is_empty() { - // By the end of loop we will have the earliest time - // (This avoids getting into issues with the compiler) - let first_login_time = ut.login_time(); - first_ut_time = Some(self.utmp_file_time( - first_login_time.unix_timestamp(), - first_login_time.nanosecond().into(), - )); - } - if counter >= self.limit && self.limit > 0 { break; } diff --git a/tests/by-util/test_last.rs b/tests/by-util/test_last.rs index dce5b3c4..7ccf28f9 100644 --- a/tests/by-util/test_last.rs +++ b/tests/by-util/test_last.rs @@ -144,14 +144,17 @@ fn test_since_only_shows_entries_after_time() { let expected_entry_time = "16:29"; let unexpected_entry_time = "16:24"; - new_ucmd!() + let result = new_ucmd!() .arg("--file") .arg("last.input.1") .arg("--since") .arg("2025-03-08 16:28") - .succeeds() - .stdout_contains(expected_entry_time) - .stdout_does_not_contain(unexpected_entry_time); + .succeeds(); + + // The "begins" line after the entries shows the first record, 16:24:36 + let entries = result.stdout_str().split("\n\n").next().unwrap(); + assert!(entries.contains(expected_entry_time)); + assert!(!entries.contains(unexpected_entry_time)); } #[test] @@ -169,3 +172,17 @@ fn test_until_only_shows_entries_before_time() { .stdout_contains(expected_entry_time) .stdout_does_not_contain(unexpected_entry_time); } + +#[test] +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "openbsd")))] +fn test_begins_is_the_first_record_when_records_are_skipped() { + for args in [&["-n", "1"][..], &["--since", "2025-03-08 16:28"][..]] { + new_ucmd!() + .env("TZ", "UTC") + .arg("--file") + .arg("last.input.1") + .args(args) + .succeeds() + .stdout_contains("last.input.1 begins Sat Mar 8 16:24:36 2025"); + } +}