ecbff1
From add02d6e5934100f023b45584d0227be90a297e8 Mon Sep 17 00:00:00 2001
ecbff1
From: Jan Synacek <jsynacek@redhat.com>
ecbff1
Date: Thu, 19 Oct 2017 09:53:56 +0200
ecbff1
Subject: [PATCH] timedatectl: stop using xstrftime
ecbff1
MIME-Version: 1.0
ecbff1
Content-Type: text/plain; charset=UTF-8
ecbff1
Content-Transfer-Encoding: 8bit
ecbff1
ecbff1
When using strftime in arbitrary locales, we cannot really say how big the
ecbff1
buffer should be. Let's make the buffer "large", which will work fine pretty
ecbff1
much always, and just print n/a if the timestamp does not fit. strftime returns
ecbff1
0 if the buffer is too small and a NUL-terminated string otherwise, so we
ecbff1
can drop the size specifications in string formatting.
ecbff1
ecbff1
$ export LANG=fa_IR.UTF-8
ecbff1
$ date
ecbff1
چهارشنبه ۱۸ اكتبر ۱۷، ساعت ۱۰:۵۴:۲۴ (+0330)
ecbff1
$ timedatectl
ecbff1
Assertion 'xstrftime: a[] must be big enough' failed at ../src/timedate/timedatectl.c:105, function print_status_info(). Aborting.
ecbff1
ecbff1
now:
ecbff1
ecbff1
$ timedatectl
ecbff1
        Local time: چهارشنبه 2017-10-18 16:29:40 CEST
ecbff1
    Universal time: چهارشنبه 2017-10-18 14:29:40 UTC
ecbff1
          RTC time: چهارشنبه 2017-10-18 14:29:40
ecbff1
ecbff1
ecbff1
(cherry picked from commit 14ce0c25c28ba58e80084e28b4f23884199900e4)
ecbff1
Resolves: #1503942
ecbff1
---
ecbff1
 src/shared/time-util.h     |  2 --
de8967
 src/timedate/timedatectl.c | 49 ++++++++++++++++++++------------------
ecbff1
 2 files changed, 26 insertions(+), 25 deletions(-)
ecbff1
ecbff1
diff --git a/src/shared/time-util.h b/src/shared/time-util.h
ecbff1
index f2789142f..32e90902a 100644
ecbff1
--- a/src/shared/time-util.h
ecbff1
+++ b/src/shared/time-util.h
ecbff1
@@ -108,5 +108,3 @@ int get_timezones(char ***l);
ecbff1
 bool timezone_is_valid(const char *name);
ecbff1
 
ecbff1
 clockid_t clock_boottime_or_monotonic(void);
ecbff1
-
ecbff1
-#define xstrftime(buf, fmt, tm) assert_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0)
ecbff1
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
ecbff1
index 1accccb68..3e9b657bc 100644
ecbff1
--- a/src/timedate/timedatectl.c
ecbff1
+++ b/src/timedate/timedatectl.c
ecbff1
@@ -93,8 +93,8 @@ static const char *jump_str(int delta_minutes, char *s, size_t size) {
ecbff1
 }
ecbff1
 
ecbff1
 static void print_status_info(const StatusInfo *i) {
ecbff1
-        char a[FORMAT_TIMESTAMP_MAX];
ecbff1
-        char b[FORMAT_TIMESTAMP_MAX];
ecbff1
+        char a[LINE_MAX];
ecbff1
+        char b[LINE_MAX];
ecbff1
         char s[32];
ecbff1
         struct tm tm;
ecbff1
         time_t sec;
ecbff1
@@ -104,6 +104,7 @@ static void print_status_info(const StatusInfo *i) {
ecbff1
         int dn = 0;
ecbff1
         bool is_dstc = false, is_dstn = false;
ecbff1
         int r;
ecbff1
+        size_t n;
ecbff1
 
ecbff1
         assert(i);
ecbff1
 
ecbff1
@@ -123,11 +124,11 @@ static void print_status_info(const StatusInfo *i) {
ecbff1
                 fprintf(stderr, "Warning: Could not get time from timedated and not operating locally.\n\n");
ecbff1
 
ecbff1
         if (have_time) {
ecbff1
-                xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
ecbff1
-                printf("      Local time: %.*s\n", (int) sizeof(a), a);
ecbff1
+                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
ecbff1
+                printf("      Local time: %s\n", n > 0 ? a : "n/a");
ecbff1
 
ecbff1
-                xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
ecbff1
-                printf("  Universal time: %.*s\n", (int) sizeof(a), a);
ecbff1
+                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
ecbff1
+                printf("  Universal time: %s\n", n > 0 ? a : "n/a");
ecbff1
         } else {
ecbff1
                 printf("      Local time: %s\n", "n/a");
ecbff1
                 printf("  Universal time: %s\n", "n/a");
ecbff1
@@ -137,24 +138,26 @@ static void print_status_info(const StatusInfo *i) {
ecbff1
                 time_t rtc_sec;
ecbff1
 
ecbff1
                 rtc_sec = (time_t)(i->rtc_time / USEC_PER_SEC);
ecbff1
-                xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
ecbff1
-                printf("        RTC time: %.*s\n", (int) sizeof(a), a);
ecbff1
+                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
ecbff1
+                printf("        RTC time: %s\n", n > 0 ? a : "n/a");
ecbff1
         } else
ecbff1
                 printf("        RTC time: %s\n", "n/a");
ecbff1
 
ecbff1
         if (have_time)
ecbff1
-                xstrftime(a, "%Z, %z", localtime_r(&sec, &tm));
ecbff1
+                n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm));
ecbff1
 
ecbff1
-        printf("       Time zone: %s (%.*s)\n"
ecbff1
+        printf("       Time zone: %s (%s)\n"
ecbff1
                "     NTP enabled: %s\n"
ecbff1
                "NTP synchronized: %s\n"
ecbff1
                " RTC in local TZ: %s\n",
ecbff1
-               strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a",
ecbff1
+               strna(i->timezone), have_time && n > 0 ? a : "n/a",
ecbff1
                i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
ecbff1
                yes_no(i->ntp_synced),
ecbff1
                yes_no(i->rtc_local));
ecbff1
 
ecbff1
         if (have_time) {
ecbff1
+                size_t m;
ecbff1
+
ecbff1
                 r = time_get_dst(sec, "/etc/localtime",
ecbff1
                                  &tc, &zc, &is_dstc,
ecbff1
                                  &tn, &dn, &zn, &is_dstn);
ecbff1
@@ -164,26 +167,26 @@ static void print_status_info(const StatusInfo *i) {
ecbff1
                         printf("      DST active: %s\n", yes_no(is_dstc));
ecbff1
 
ecbff1
                         t = tc - 1;
ecbff1
-                        xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
ecbff1
+                        n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
ecbff1
 
ecbff1
-                        xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm));
ecbff1
+                        m = strftime(b, sizeof b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm));
ecbff1
                         printf(" Last DST change: DST %s at\n"
ecbff1
-                               "                  %.*s\n"
ecbff1
-                               "                  %.*s\n",
ecbff1
+                               "                  %s\n"
ecbff1
+                               "                  %s\n",
ecbff1
                                is_dstc ? "began" : "ended",
ecbff1
-                               (int) sizeof(a), a,
ecbff1
-                               (int) sizeof(b), b);
ecbff1
+                               n > 0 ? a : "n/a",
ecbff1
+                               m > 0 ? b : "n/a");
ecbff1
 
ecbff1
                         t = tn - 1;
ecbff1
-                        xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
ecbff1
-                        xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm));
ecbff1
+                        n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
ecbff1
+                        m = strftime(b, sizeof b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm));
ecbff1
                         printf(" Next DST change: DST %s (the clock jumps %s) at\n"
ecbff1
-                               "                  %.*s\n"
ecbff1
-                               "                  %.*s\n",
ecbff1
+                               "                  %s\n"
ecbff1
+                               "                  %s\n",
ecbff1
                                is_dstn ? "begins" : "ends",
ecbff1
                                jump_str(dn, s, sizeof(s)),
ecbff1
-                               (int) sizeof(a), a,
ecbff1
-                               (int) sizeof(b), b);
ecbff1
+                               n > 0 ? a : "n/a",
ecbff1
+                               m > 0 ? b : "n/a");
ecbff1
                 }
ecbff1
         } else
ecbff1
                 printf("      DST active: %s\n", yes_no(is_dstc));