[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Work around GNU/Linux timestamp glitch
From: |
Paul Eggert |
Subject: |
[PATCH] Work around GNU/Linux timestamp glitch |
Date: |
Thu, 23 Mar 2023 17:24:04 -0700 |
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
- [PATCH] Work around GNU/Linux timestamp glitch,
Paul Eggert <=