From b3e823e43c45b6233405d62e5f095c11130e638f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 18 Oct 2017 16:15:09 +0200
Subject: [PATCH] timedatectl: stop using xstrftime
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When using strftime in arbitrary locales, we cannot really say how big the
buffer should be. Let's make the buffer "large", which will work fine pretty
much always, and just print n/a if the timestamp does not fit. strftime returns
0 if the buffer is too small and a NUL-terminated string otherwise, so we
can drop the size specifications in string formatting.
$ export LANG=fa_IR.UTF-8
$ date
چهارشنبه ۱۸ اكتبر ۱۷، ساعت ۱۰:۵۴:۲۴ (+0330)
$ timedatectl
Assertion 'xstrftime: a[] must be big enough' failed at ../src/timedate/timedatectl.c:105, function print_status_info(). Aborting.
now:
$ timedatectl
Local time: چهارشنبه 2017-10-18 16:29:40 CEST
Universal time: چهارشنبه 2017-10-18 14:29:40 UTC
RTC time: چهارشنبه 2017-10-18 14:29:40
…
https://bugzilla.redhat.com/show_bug.cgi?id=1503452
(cherry picked from commit 14ce0c25c28ba58e80084e28b4f23884199900e4)
---
src/basic/time-util.h | 4 ----
src/timedate/timedatectl.c | 21 +++++++++++----------
2 files changed, 11 insertions(+), 14 deletions(-)
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index 3b7f0e99c0..73f7e40066 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -148,10 +148,6 @@ clockid_t clock_boottime_or_monotonic(void);
usec_t usec_shift_clock(usec_t, clockid_t from, clockid_t to);
-#define xstrftime(buf, fmt, tm) \
- assert_message_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0, \
- "xstrftime: " #buf "[] must be big enough")
-
int get_timezone(char **timezone);
time_t mktime_or_timegm(struct tm *tm, bool utc);
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index a30e783c09..716675aa1d 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -72,12 +72,13 @@ static void status_info_clear(StatusInfo *info) {
}
static void print_status_info(const StatusInfo *i) {
- char a[FORMAT_TIMESTAMP_MAX];
+ char a[LINE_MAX];
struct tm tm;
time_t sec;
bool have_time = false;
const char *old_tz = NULL, *tz;
int r;
+ size_t n;
assert(i);
@@ -102,11 +103,11 @@ static void print_status_info(const StatusInfo *i) {
log_warning("Could not get time from timedated and not operating locally, ignoring.");
if (have_time) {
- xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
- printf(" Local time: %.*s\n", (int) sizeof(a), a);
+ n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
+ printf(" Local time: %s\n", n > 0 ? a : "n/a");
- xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
- printf(" Universal time: %.*s\n", (int) sizeof(a), a);
+ n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
+ printf(" Universal time: %s\n", n > 0 ? a : "n/a");
} else {
printf(" Local time: %s\n", "n/a");
printf(" Universal time: %s\n", "n/a");
@@ -116,13 +117,13 @@ static void print_status_info(const StatusInfo *i) {
time_t rtc_sec;
rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC);
- xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
- printf(" RTC time: %.*s\n", (int) sizeof(a), a);
+ n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
+ printf(" RTC time: %s\n", n > 0 ? a : "n/a");
} else
printf(" RTC time: %s\n", "n/a");
if (have_time)
- xstrftime(a, "%Z, %z", localtime_r(&sec, &tm));
+ n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm));
/* Restore the $TZ */
if (old_tz)
@@ -134,11 +135,11 @@ static void print_status_info(const StatusInfo *i) {
else
tzset();
- printf(" Time zone: %s (%.*s)\n"
+ printf(" Time zone: %s (%s)\n"
" System clock synchronized: %s\n"
"systemd-timesyncd.service active: %s\n"
" RTC in local TZ: %s\n",
- strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a",
+ strna(i->timezone), have_time && n > 0 ? a : "n/a",
i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
yes_no(i->ntp_synced),
yes_no(i->rtc_local));