bug-bash
[Top][All Lists]
Advanced

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

[PATCH] Fix time(1) garbage output when time goes backwards.


From: Ángel González
Subject: [PATCH] Fix time(1) garbage output when time goes backwards.
Date: Sun, 27 Jul 2014 19:58:14 +0200

libfaketime allows for easy testing of this bug:
LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 FAKETIME='-1y' \
 FAKETIME_START_AFTER_SECONDS=1 TIMEFORMAT=%lR /bin/bash -c 'time sleep 2'
---
 execute_cmd.c    | 24 ++++++++++++++++++++----
 lib/sh/timeval.c |  5 -----
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/execute_cmd.c b/execute_cmd.c
index f9a755d..d3cb93b 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1081,7 +1081,12 @@ extern int timeval_to_cpu __P((struct timeval *, struct 
timeval *, struct timeva
 
 static const int precs[] = { 0, 100, 10, 1 };
 
-/* Expand one `%'-prefixed escape sequence from a time format string. */
+/* Expand one `%'-prefixed escape sequence from a time format string,
+   buf is the buffer where we are writing the timestamp, prec is the
+   precision (number of decimal places after the .), lng a boolean
+   stating that the time should be shown in minutes and seconds instead
+   of only seconds, and (rs, rsf) are the seconds and milliseconds ellapsed.
+ */
 static int
 mkfmt (buf, prec, lng, sec, sec_fraction)
      char *buf;
@@ -1090,12 +1095,23 @@ mkfmt (buf, prec, lng, sec, sec_fraction)
      int sec_fraction;
 {
   time_t min;
-  char abuf[INT_STRLEN_BOUND(time_t) + 1];
+  char abuf[INT_STRLEN_BOUND(time_t) + 2];
   int ind, aind;
 
   ind = 0;
   abuf[sizeof(abuf) - 1] = '\0';
 
+  if (sec < 0)
+    {
+      buf[ind++] = '-';
+      sec = -sec;
+      if (sec_fraction > 0)
+       {
+         sec_fraction = 1000 - sec_fraction;
+         sec--;
+       }
+    }
+
   /* If LNG is non-zero, we want to decompose SEC into minutes and seconds. */
   if (lng)
     {
@@ -1156,7 +1172,7 @@ mkfmt (buf, prec, lng, sec, sec_fraction)
    An occurrence of `%%' in the format string is translated to a `%'.  The
    result is printed to FP, a pointer to a FILE.  The other variables are
    the seconds and thousandths of a second of real, user, and system time,
-   resectively. */
+   respectively. */
 static void
 print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu)
      FILE *fp;
@@ -1169,7 +1185,7 @@ print_formatted_time (fp, format, rs, rsf, us, usf, ss, 
ssf, cpu)
      int ssf, cpu;
 {
   int prec, lng, len;
-  char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("mSS.FFFF")];
+  char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("-mSS.FFFF")];
   time_t sum;
   int sum_frac;
   int sindex, ssize;
diff --git a/lib/sh/timeval.c b/lib/sh/timeval.c
index 7bd9df8..8351687 100644
--- a/lib/sh/timeval.c
+++ b/lib/sh/timeval.c
@@ -37,11 +37,6 @@ difftimeval (d, t1, t2)
     {
       d->tv_usec += 1000000;
       d->tv_sec -= 1;
-      if (d->tv_sec < 0)               /* ??? -- BSD/OS does this */
-       {
-         d->tv_sec = 0;
-         d->tv_usec = 0;
-       }
     }
   return d;
 }
-- 
2.0.3




reply via email to

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