diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/date.c | 24 | ||||
-rw-r--r-- | src/du.c | 17 | ||||
-rw-r--r-- | src/ls.c | 23 | ||||
-rw-r--r-- | src/pr.c | 23 | ||||
-rw-r--r-- | src/stat.c | 26 |
5 files changed, 62 insertions, 51 deletions
diff --git a/src/date.c b/src/date.c index 269570b1a..e73196b96 100644 --- a/src/date.c +++ b/src/date.c @@ -559,23 +559,23 @@ main (int argc, char **argv) static bool show_date (const char *format, struct timespec when, timezone_t tz) { - struct tm *tm; + struct tm tm; - tm = localtime (&when.tv_sec); - if (! tm) + if (localtime_rz (tz, &when.tv_sec, &tm)) + { + if (format == rfc_2822_format) + setlocale (LC_TIME, "C"); + fprintftime (stdout, format, &tm, tz, when.tv_nsec); + if (format == rfc_2822_format) + setlocale (LC_TIME, ""); + fputc ('\n', stdout); + return true; + } + else { char buf[INT_BUFSIZE_BOUND (intmax_t)]; error (0, 0, _("time %s is out of range"), quote (timetostr (when.tv_sec, buf))); return false; } - - if (format == rfc_2822_format) - setlocale (LC_TIME, "C"); - fprintftime (stdout, format, tm, tz, when.tv_nsec); - fputc ('\n', stdout); - if (format == rfc_2822_format) - setlocale (LC_TIME, ""); - - return true; } @@ -182,6 +182,9 @@ static char const *time_style = NULL; /* Format used to display date / time. Controlled by --time-style */ static char const *time_format = NULL; +/* The local time zone rules, as per the TZ environment variable. */ +static timezone_t localtz; + /* The units to use when printing sizes. */ static uintmax_t output_block_size; @@ -372,19 +375,18 @@ hash_ins (struct di_set *di_set, ino_t ino, dev_t dev) in FORMAT. */ static void -show_date (const char *format, struct timespec when) +show_date (const char *format, struct timespec when, timezone_t tz) { - struct tm *tm = localtime (&when.tv_sec); - if (! tm) + struct tm tm; + if (localtime_rz (tz, &when.tv_sec, &tm)) + fprintftime (stdout, format, &tm, tz, when.tv_nsec); + else { char buf[INT_BUFSIZE_BOUND (intmax_t)]; char *when_str = timetostr (when.tv_sec, buf); error (0, 0, _("time %s is out of range"), quote (when_str)); fputs (when_str, stdout); - return; } - - fprintftime (stdout, format, tm, 0, when.tv_nsec); } /* Print N_BYTES. Convert it to a readable value before printing. */ @@ -412,7 +414,7 @@ print_size (const struct duinfo *pdui, const char *string) if (opt_time) { putchar ('\t'); - show_date (time_format, pdui->tmax); + show_date (time_format, pdui->tmax, localtz); } printf ("\t%s%c", string, opt_nul_terminate_output ? '\0' : '\n'); fflush (stdout); @@ -905,6 +907,7 @@ main (int argc, char **argv) (optarg ? XARGMATCH ("--time", optarg, time_args, time_types) : time_mtime); + localtz = tzalloc (getenv ("TZ")); break; case TIME_STYLE_OPTION: @@ -3720,20 +3720,20 @@ long_time_expected_width (void) if (width < 0) { time_t epoch = 0; - struct tm const *tm = localtime (&epoch); + struct tm tm; char buf[TIME_STAMP_LEN_MAXIMUM + 1]; - /* In case you're wondering if localtime can fail with an input time_t + /* In case you're wondering if localtime_rz can fail with an input time_t value of 0, let's just say it's very unlikely, but not inconceivable. The TZ environment variable would have to specify a time zone that is 2**31-1900 years or more ahead of UTC. This could happen only on a 64-bit system that blindly accepts e.g., TZ=UTC+20000000000000. However, this is not possible with Solaris 10 or glibc-2.3.5, since their implementations limit the offset to 167:59 and 24:00, resp. */ - if (tm) + if (localtime_rz (localtz, &epoch, &tm)) { size_t len = - align_nstrftime (buf, sizeof buf, long_time_format[0], tm, + align_nstrftime (buf, sizeof buf, long_time_format[0], &tm, localtz, 0); if (len != 0) width = mbsnwidth (buf, len, 0); @@ -3856,7 +3856,7 @@ print_long_format (const struct fileinfo *f) size_t s; char *p; struct timespec when_timespec; - struct tm *when_local; + struct tm when_local; /* Compute the mode string, except remove the trailing space if no file in this directory has an ACL or security context. */ @@ -3983,11 +3983,10 @@ print_long_format (const struct fileinfo *f) p[-1] = ' '; } - when_local = localtime (&when_timespec.tv_sec); s = 0; *p = '\1'; - if (f->stat_ok && when_local) + if (f->stat_ok && localtime_rz (localtz, &when_timespec.tv_sec, &when_local)) { struct timespec six_months_ago; bool recent; @@ -3997,13 +3996,7 @@ print_long_format (const struct fileinfo *f) time, in case the file happens to have been modified since the last time we checked the clock. */ if (timespec_cmp (current_time, when_timespec) < 0) - { - /* Note that gettime may call gettimeofday which, on some non- - compliant systems, clobbers the buffer used for localtime's result. - But it's ok here, because we use a gettimeofday wrapper that - saves and restores the buffer around the gettimeofday call. */ - gettime (¤t_time); - } + gettime (¤t_time); /* Consider a time to be recent if it is within the past six months. A Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds @@ -4019,7 +4012,7 @@ print_long_format (const struct fileinfo *f) /* We assume here that all time zones are offset from UTC by a whole number of seconds. */ s = align_nstrftime (p, TIME_STAMP_LEN_MAXIMUM + 1, fmt, - when_local, localtz, when_timespec.tv_nsec); + &when_local, localtz, when_timespec.tv_nsec); } if (s || !*p) @@ -710,6 +710,9 @@ static char *custom_header; /* (-D) Date format for the header. */ static char const *date_format; +/* The local time zone rules, as per the TZ environment variable. */ +static timezone_t localtz; + /* Date and file name for the header. */ static char *date_text; static char const *file_text; @@ -1049,6 +1052,8 @@ main (int argc, char **argv) ? "%b %e %H:%M %Y" : "%Y-%m-%d %H:%M"); + localtz = tzalloc (getenv ("TZ")); + /* Now we can set a reasonable initial value: */ if (first_page_number == 0) first_page_number = 1; @@ -1611,7 +1616,7 @@ init_header (char const *filename, int desc) struct stat st; struct timespec t; int ns; - struct tm *tm; + struct tm tm; /* If parallel files or standard input, use current date. */ if (STREQ (filename, "-")) @@ -1627,18 +1632,18 @@ init_header (char const *filename, int desc) } ns = t.tv_nsec; - tm = localtime (&t.tv_sec); - if (tm == NULL) + if (localtime_rz (localtz, &t.tv_sec, &tm)) { - buf = xmalloc (INT_BUFSIZE_BOUND (long int) - + MAX (10, INT_BUFSIZE_BOUND (int))); - sprintf (buf, "%ld.%09d", (long int) t.tv_sec, ns); + size_t bufsize + = nstrftime (NULL, SIZE_MAX, date_format, &tm, localtz, ns) + 1; + buf = xmalloc (bufsize); + nstrftime (buf, bufsize, date_format, &tm, localtz, ns); } else { - size_t bufsize = nstrftime (NULL, SIZE_MAX, date_format, tm, 0, ns) + 1; - buf = xmalloc (bufsize); - nstrftime (buf, bufsize, date_format, tm, 0, ns); + char secbuf[INT_BUFSIZE_BOUND (intmax_t)]; + buf = xmalloc (sizeof secbuf + MAX (10, INT_BUFSIZE_BOUND (int))); + sprintf (buf, "%s.%09d", timetostr (t.tv_sec, secbuf), ns); } free (date_text); 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; } |