bug-bash
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]