bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 2/2] Work around GNU/Linux timestamp glitch


From: Paul Eggert
Subject: [PATCH v2 2/2] Work around GNU/Linux timestamp glitch
Date: Fri, 24 Mar 2023 14:08:11 -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.
The out-of-order timestamps can lead to user-confusion.
https://sourceware.org/bugzilla/show_bug.cgi?id=30200

This fixes a bug reported against Bash in 2020 by felix
https://lists.gnu.org/archive/html/bug-bash/2020-04/msg00072.html

* include/posixtime.h (getnow): New function.
All calls to 'time' changed to use this function.
* support/man2html.c (print_sig): Prefer gettimeofday if available.
---
 general.h              |  2 +-
 include/posixtime.h    | 10 ++++++++++
 lib/readline/history.c |  4 +++-
 parse.y                |  6 +++---
 support/man2html.c     |  8 +++++++-
 5 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/general.h b/general.h
index fa57251a..2232fabd 100644
--- a/general.h
+++ b/general.h
@@ -242,7 +242,7 @@ typedef int sh_builtin_func_t (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 319cb168..7b0fc035 100644
--- a/include/posixtime.h
+++ b/include/posixtime.h
@@ -52,6 +52,16 @@ struct timeval
 extern int gettimeofday (struct timeval * restrict, void * restrict);
 #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 42580301..9dc90147 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/parse.y b/parse.y
index b758756a..2a61eb8c 100644
--- a/parse.y
+++ b/parse.y
@@ -85,7 +85,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>
@@ -5976,7 +5976,7 @@ decode_prompt_string (char *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
@@ -6010,7 +6010,7 @@ decode_prompt_string (char *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 58165796..61f05f10 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';
+#if HAVE_GETTIMEOFDAY
+       struct timeval tv;
+       gettimeofday (&tv, NULL);
+       clock = tv.tv_sec;
+#else
        clock = time(NULL);
+#endif
+       datbuf[0] = '\0';
        timetm = localtime(&clock);
        if (timetm)
          strftime(datbuf, MED_STR_MAX, TIMEFORMAT, timetm);
-- 
2.39.2




reply via email to

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