diff options
Diffstat (limited to 'src/stat.c')
-rw-r--r-- | src/stat.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/src/stat.c b/src/stat.c index e11e4318f..1742ff128 100644 --- a/src/stat.c +++ b/src/stat.c @@ -557,17 +557,27 @@ human_access (struct stat const *statbuf) static char * ATTRIBUTE_WARN_UNUSED_RESULT human_time (struct timespec t) { - static char str[MAX (INT_BUFSIZE_BOUND (intmax_t), - (INT_STRLEN_BOUND (int) /* YYYY */ - + 1 /* because YYYY might equal INT_MAX + 1900 */ - + sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +ZZZZ"))]; + /* STR must be at least this big, either because localtime_rz fails, + or because the time zone is truly outlandish so that %z expands + to a long string. */ + enum { intmax_bufsize = INT_BUFSIZE_BOUND (intmax_t) }; + + static char str[intmax_bufsize + + INT_STRLEN_BOUND (int) /* YYYY */ + + 1 /* because YYYY might equal INT_MAX + 1900 */ + + sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +"]; static timezone_t tz; if (!tz) tz = tzalloc (getenv ("TZ")); - struct tm const *tm = localtime (&t.tv_sec); - if (tm == NULL) - return timetostr (t.tv_sec, str); - nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", tm, tz, t.tv_nsec); + struct tm tm; + int ns = t.tv_nsec; + if (localtime_rz (tz, &t.tv_sec, &tm)) + nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", &tm, tz, ns); + else + { + char secbuf[INT_BUFSIZE_BOUND (intmax_t)]; + sprintf (str, "%s.%09d", timetostr (t.tv_sec, secbuf), ns); + } return str; } |