summaryrefslogtreecommitdiff
path: root/src/stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stat.c')
-rw-r--r--src/stat.c26
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;
}