Fix timestamp outputs for TAI timezone. Bug 2530
authorArne Wörner <arne_woerner@yahoo.com>
Mon, 24 Feb 2020 17:07:22 +0000 (17:07 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 24 Feb 2020 17:07:22 +0000 (17:07 +0000)
doc/doc-txt/ChangeLog
src/src/tod.c

index 116df90d06203425630a5ef19e9078beb25e2026..8f583e21af9b1bc8d1c493c96d0b93f46685c5e4 100644 (file)
@@ -131,6 +131,11 @@ JH/26 Fix use of the SIZE parameter on MAIL commands, on continued connections.
       only the first would provide a SIZE.  This was due to the size information
       not being properly tracked.
 
+JH/27 Bug 2530: When operating in a timezone with sub-minute offset, such as
+      TAI (at 37 seconds currently), pretend to be in UTC for time-related
+      expansion and logging.  Previously, spurious values such as a future
+      minute could be seen.
+
 
 Exim version 4.93
 -----------------
index e7123f9eb90d89a22ec07fee07b01dc1f1079045..cdfd1231278d3ca2f44283b79ded67adc9e60381 100644 (file)
@@ -148,7 +148,8 @@ switch(type)
       {
       int diff_hour, diff_min;
       struct tm local;
-      memcpy(&local, t, sizeof(struct tm));
+      struct tm * lp = &local;
+      memcpy(lp, t, sizeof(struct tm));
 
       if (f.timestamps_utc)
        diff_hour = diff_min = 0;
@@ -156,13 +157,22 @@ switch(type)
        {
        struct tm * gmt = gmtime(&now.tv_sec);
 
-       diff_min = 60*(local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
-       if (local.tm_year != gmt->tm_year)
-         diff_min += (local.tm_year > gmt->tm_year)? 1440 : -1440;
-       else if (local.tm_yday != gmt->tm_yday)
-         diff_min += (local.tm_yday > gmt->tm_yday)? 1440 : -1440;
-       diff_hour = diff_min/60;
-       diff_min  = abs(diff_min - diff_hour*60);
+       if (local.tm_sec == gmt->tm_sec)        /* usual case */
+         {
+         diff_min = 60 * (local.tm_hour - gmt->tm_hour)
+                   + local.tm_min - gmt->tm_min;
+         if (local.tm_year != gmt->tm_year)
+           diff_min += (local.tm_year > gmt->tm_year) ? 1440 : -1440;
+         else if (local.tm_yday != gmt->tm_yday)
+           diff_min += (local.tm_yday > gmt->tm_yday) ? 1440 : -1440;
+         diff_hour = diff_min/60;
+         diff_min  = abs(diff_min - diff_hour*60);
+         }
+       else                                    /* subminute offset, eg. TAI */
+         {
+         lp = gmt;                             /* pretend we're in UTC */
+         diff_min = diff_hour = 0;
+         }
        }
 
       switch(type)
@@ -172,15 +182,15 @@ switch(type)
          if (LOGGING(millisec))
            (void) snprintf(CS timebuf, sizeof(timebuf),
              "%04u-%02u-%02u %02u:%02u:%02u.%03u %+03d%02d",
-             1900 + (uint)local.tm_year, 1 + (uint)local.tm_mon, (uint)local.tm_mday,
-             (uint)local.tm_hour, (uint)local.tm_min, (uint)local.tm_sec, (uint)(now.tv_usec/1000),
+             1900 + (uint)lp->tm_year, 1 + (uint)lp->tm_mon, (uint)lp->tm_mday,
+             (uint)lp->tm_hour, (uint)lp->tm_min, (uint)lp->tm_sec, (uint)(now.tv_usec/1000),
              diff_hour, diff_min);
          else
 #endif
            (void) snprintf(CS timebuf, sizeof(timebuf),
              "%04u-%02u-%02u %02u:%02u:%02u %+03d%02d",
-             1900 + (uint)local.tm_year, 1 + (uint)local.tm_mon, (uint)local.tm_mday,
-             (uint)local.tm_hour, (uint)local.tm_min, (uint)local.tm_sec,
+             1900 + (uint)lp->tm_year, 1 + (uint)lp->tm_mon, (uint)lp->tm_mday,
+             (uint)lp->tm_hour, (uint)lp->tm_min, (uint)lp->tm_sec,
              diff_hour, diff_min);
          break;
 
@@ -190,31 +200,32 @@ switch(type)
 
        /* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */
 
-         #ifdef SUPPORT_MBX
+#ifdef SUPPORT_MBX
        case tod_mbx:
-           {
-           int len;
-           (void) snprintf(CS timebuf, sizeof(timebuf), "%02u-", (uint)local.tm_mday);
-           len = Ustrlen(timebuf);
-           len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b-%Y %H:%M:%S",
-             &local);
-           (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, " %+03d%02d", diff_hour, diff_min);
-           }
+         {
+         int len = snprintf(CS timebuf, sizeof(timebuf),
+           "%02u-", (uint)lp->tm_mday);
+         len += Ustrftime(timebuf + len, sizeof(timebuf) - len,
+           "%b-%Y %H:%M:%S", lp);
+         (void) snprintf(CS timebuf + len, sizeof(timebuf)-len,
+           " %+03d%02d", diff_hour, diff_min);
+         }
          break;
-         #endif
+#endif
 
        /* tod_full: format used in Received: headers (use as default just in case
        called with a junk type value) */
 
        default:
-           {
-           int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local);
-           (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, "%02u ", (uint)local.tm_mday);
-           len += Ustrlen(timebuf + len);
-           len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b %Y %H:%M:%S",
-             &local);
-           (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, " %+03d%02d", diff_hour, diff_min);
-           }
+         {
+         int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", lp);
+         len += snprintf(CS timebuf + len, sizeof(timebuf)-len,
+           "%02u ", (uint)lp->tm_mday);
+         len += Ustrftime(timebuf + len, sizeof(timebuf) - len,
+           "%b %Y %H:%M:%S", lp);
+         (void) snprintf(CS timebuf + len, sizeof(timebuf)-len,
+           " %+03d%02d", diff_hour, diff_min);
+         }
          break;
        }
       }