Without this patch, Bash can hand out user-visible timestamps that are out of order, because on GNU/Linux the 'time' function uses a different clock than file timestamps and the 'gettimeofday' function. See <https://sourceware.org/bugzilla/show_bug.cgi?id=30200>. * include/posixtime.h (getnow): New function. All calls to 'time' changed to use this function. * support/man2html.c (print_sig): Prefer gettimeofday if available.
(This patch assumes my recent patch proposed for localtime <https://lists.gnu.org/r/bug-bash/2023-03/msg00089.html>.) --- general.h | 2 +- include/posixtime.h | 10 ++++++++++ lib/readline/history.c | 4 +++- lib/readline/posixtime.h | 10 ++++++++++ parse.y | 6 +++--- support/man2html.c | 8 +++++++- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/general.h b/general.h index 8064c50e..9b082cbc 100644 --- a/general.h +++ b/general.h @@ -245,7 +245,7 @@ typedef int sh_builtin_func_t PARAMS((WORD_LIST *)); /* sh_wlist_func_t */ #endif /* SH_FUNCTION_TYPEDEF */ -#define NOW ((time_t) time ((time_t *) 0)) +#define NOW getnow () #define GETTIME(tv) gettimeofday(&(tv), NULL) /* Some defines for calling file status functions. */ diff --git a/include/posixtime.h b/include/posixtime.h index e70ebec6..a7b2957a 100644 --- a/include/posixtime.h +++ b/include/posixtime.h @@ -52,6 +52,16 @@ struct timeval extern int gettimeofday PARAMS((struct timeval *, void *)); #endif +static inline time_t +getnow (void) +{ + /* Avoid time (NULL), which can disagree with gettimeofday and with + filesystem timestamps. */ + struct timeval now; + gettimeofday (&now, 0); + return now.tv_sec; +} + /* These exist on BSD systems, at least. */ #if !defined (timerclear) # define timerclear(tvp) do { (tvp)->tv_sec = 0; (tvp)->tv_usec = 0; } while (0) diff --git a/lib/readline/history.c b/lib/readline/history.c index 81d4c168..d141e942 100644 --- a/lib/readline/history.c +++ b/lib/readline/history.c @@ -48,6 +48,7 @@ #include "history.h" #include "histlib.h" +#include "posixtime.h" #include "xmalloc.h" #if !defined (errno) @@ -261,7 +262,8 @@ hist_inittime (void) time_t t; char ts[64], *ret; - t = (time_t) time ((time_t *)0); + t = getnow (); + #if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */ snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t); #else diff --git a/lib/readline/posixtime.h b/lib/readline/posixtime.h index e70ebec6..a7b2957a 100644 --- a/lib/readline/posixtime.h +++ b/lib/readline/posixtime.h @@ -52,6 +52,16 @@ struct timeval extern int gettimeofday PARAMS((struct timeval *, void *)); #endif +static inline time_t +getnow (void) +{ + /* Avoid time (NULL), which can disagree with gettimeofday and with + filesystem timestamps. */ + struct timeval now; + gettimeofday (&now, 0); + return now.tv_sec; +} + /* These exist on BSD systems, at least. */ #if !defined (timerclear) # define timerclear(tvp) do { (tvp)->tv_sec = 0; (tvp)->tv_usec = 0; } while (0) diff --git a/parse.y b/parse.y index 1d188101..6f9c626f 100644 --- a/parse.y +++ b/parse.y @@ -84,7 +84,7 @@ typedef void *alias_t; # ifndef _MINIX # include <sys/param.h> # endif -# include <time.h> +# include "posixtime.h" # if defined (TM_IN_SYS_TIME) # include <sys/types.h> # include <sys/time.h> @@ -5769,7 +5769,7 @@ decode_prompt_string (string) case '@': case 'A': /* Make the current time/date into a string. */ - (void) time (&the_time); + the_time = getnow (); #if defined (HAVE_TZSET) sv_tz ("TZ"); /* XXX -- just make sure */ #endif @@ -5803,7 +5803,7 @@ decode_prompt_string (string) if (string[1] != '{') /* } */ goto not_escape; - (void) time (&the_time); + the_time = getnow (); tm = localtime (&the_time); string += 2; /* skip { */ t = string; diff --git a/support/man2html.c b/support/man2html.c index e6f441b4..6f552388 100644 --- a/support/man2html.c +++ b/support/man2html.c @@ -452,8 +452,14 @@ print_sig(void) struct tm *timetm; time_t clock; - datbuf[0] = '\0'; +#ifdef HAVE_GETTIMEOFDAY + struct timeval tv; + gettimeofday (&tv, NULL); + clock = tv.tv_sec; +#else clock = time(NULL); +#endif + datbuf[0] = '\0'; timetm = localtime(&clock); strftime(datbuf, MED_STR_MAX, TIMEFORMAT, timetm); printf(signature, manpage, datbuf); -- 2.39.2