diff --git a/src/history.rs b/src/history.rs index 3ccc10dd8..67c75335f 100644 --- a/src/history.rs +++ b/src/history.rs @@ -16,7 +16,7 @@ //! 5. The chaos_mode boolean can be set to true to do things like lower buffer sizes which can //! trigger race conditions. This is useful for testing. -use crate::{common::cstr2wcstring, env::EnvVar, wcstringutil::trim}; +use crate::{common::cstr2wcstring, env::EnvVar, libc::localtime64_r, wcstringutil::trim}; use std::{ borrow::Cow, collections::{BTreeMap, HashMap, HashSet, VecDeque}, @@ -1409,10 +1409,8 @@ fn format_history_record( ) -> WString { let mut result = WString::new(); let seconds = time_to_seconds(item.timestamp()); - let seconds = seconds as libc::time_t; - let mut timestamp: libc::tm = unsafe { std::mem::zeroed() }; if let Some(show_time_format) = show_time_format.and_then(|s| CString::new(s).ok()) { - if !unsafe { libc::localtime_r(&seconds, &mut timestamp).is_null() } { + if let Some(timestamp) = localtime64_r(seconds) { const max_tstamp_length: usize = 100; let mut timestamp_str = [0_u8; max_tstamp_length]; // The libc crate fails to declare strftime on BSD. diff --git a/src/libc.c b/src/libc.c index cee3501fb..ba584c70e 100644 --- a/src/libc.c +++ b/src/libc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #define UNUSED(x) (void)(x) @@ -213,3 +214,8 @@ bool C_fstatat64(int dirfd, const char* file, int flag, uint64_t* st_dev, uint64 *st_mode = buf.st_mode; return true; } + +bool C_localtime64_r(int64_t timep, struct tm* result) { + time_t timep_ = timep; + return localtime_r(&timep_, result); +} diff --git a/src/libc.rs b/src/libc.rs index 9d1d4f368..e960e4856 100644 --- a/src/libc.rs +++ b/src/libc.rs @@ -112,3 +112,14 @@ extern "C" { st_mode: *mut libc::mode_t, ) -> bool; } + +pub(crate) fn localtime64_r(timep: i64) -> Option { + let mut timestamp = unsafe { std::mem::zeroed() }; + if !unsafe { C_localtime64_r(timep, &mut timestamp) } { + return None; + } + Some(timestamp) +} +extern "C" { + fn C_localtime64_r(timep: i64, result: *mut libc::tm) -> bool; +} diff --git a/src/tests/env.rs b/src/tests/env.rs index 3bee4f0c5..d3b15e6ee 100644 --- a/src/tests/env.rs +++ b/src/tests/env.rs @@ -1,4 +1,5 @@ use crate::env::{EnvMode, EnvStack, EnvVar, EnvVarFlags, Environment}; +use crate::libc::localtime64_r; use crate::tests::prelude::*; use crate::wchar::prelude::*; use crate::wutil::wgetcwd; @@ -63,16 +64,8 @@ fn return_timezone_hour(tstamp: SystemTime, timezone: &wstr) -> libc::c_int { let _var = vars.get(L!("TZ")); - let tstamp: libc::time_t = tstamp - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs() - .try_into() - .unwrap(); - let mut local_time: libc::tm = unsafe { std::mem::zeroed() }; - unsafe { libc::localtime_r(&tstamp, &mut local_time) }; - - local_time.tm_hour + let tstamp = tstamp.duration_since(UNIX_EPOCH).unwrap().as_secs(); + localtime64_r(tstamp.try_into().unwrap()).unwrap().tm_hour } /// Verify that setting TZ calls tzset() in the current shell process.