diff --git a/src/locate/mod.rs b/src/locate/mod.rs index c4afd42a..06dbb00b 100644 --- a/src/locate/mod.rs +++ b/src/locate/mod.rs @@ -591,6 +591,15 @@ fn match_entry(entry: &CStr, config: &Config, patterns: &Patterns) -> bool { patterns_match && existence_matches } +/// Whether a database of the given `age` is older than `max_age` days. +/// A `max_age` too large for `i64`/`chrono` to represent can never be exceeded. +fn is_db_too_old(age: TimeDelta, max_age: usize) -> bool { + match i64::try_from(max_age).ok().and_then(TimeDelta::try_days) { + Some(limit) => age > limit, + None => false, + } +} + fn do_locate(args: &[&str]) -> LocateResult<()> { let matches = uu_app().try_get_matches_from(args); match matches { @@ -626,7 +635,7 @@ fn do_locate(args: &[&str]) -> LocateResult<()> { let modified: DateTime = time.into(); let now = Local::now(); let delta = now - modified; - if delta > TimeDelta::days(config.max_age as i64) { + if is_db_too_old(delta, config.max_age) { eprintln!( "{}: warning: database ‘{}’ is more than {} days old (actual age is {:.1} days)", args[0], @@ -710,7 +719,9 @@ mod tests { use std::io::{self, Write}; use std::path::Path; - use super::{path_exists, DbReader, Statistics}; + use chrono::TimeDelta; + + use super::{is_db_too_old, path_exists, DbReader, Statistics}; /// A writer that always fails, to emulate stdout with no space left /// (`> /dev/full`) or a closed pipe. @@ -739,6 +750,24 @@ mod tests { assert!(stats.print(&mut FailWriter, &dbreader).is_err()); } + #[test] + fn db_too_old_compares_ordinary_ages() { + let day = TimeDelta::days(1); + assert!(is_db_too_old(day, 0)); + assert!(!is_db_too_old(day, 8)); + } + + #[test] + fn db_too_old_ignores_max_age_beyond_i64() { + assert!(!is_db_too_old(TimeDelta::days(1), usize::MAX)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn db_too_old_ignores_max_age_beyond_chrono_range() { + assert!(!is_db_too_old(TimeDelta::days(1), 1_000_000_000_000)); + } + /// Create a symlink at `link` pointing at `target`, cross-platform. #[cfg(unix)] fn make_symlink(target: &Path, link: &Path) -> io::Result<()> { diff --git a/tests/db_tests.rs b/tests/db_tests.rs index 609071ec..d6c5cb5f 100644 --- a/tests/db_tests.rs +++ b/tests/db_tests.rs @@ -130,6 +130,19 @@ fn test_locate_outdated_db() { .success(); } +#[test] +fn test_locate_large_max_database_age() { + for age in ["1000000000000", "18446744073709551615"] { + Command::cargo_bin("locate") + .expect("couldn't find locate binary") + .arg("test_data") + .arg(format!("--max-database-age={age}")) + .arg(OLD_DB_FLAG) + .assert() + .success(); + } +} + #[test] fn test_locate_print_help() { Command::cargo_bin("locate")