diff options
author | Eric Blake <eblake@redhat.com> | 2010-09-30 16:42:13 -0600 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2010-10-01 10:43:41 -0600 |
commit | 9069af45e691d1252c727da66aa4f3f3c7f1ea29 (patch) | |
tree | 09371cf730f26806f6a45703e3b4989afff0f439 | |
parent | abe5c1f9bc09753fd79e7a121c8ecfa917dfaddb (diff) | |
download | coreutils-9069af45e691d1252c727da66aa4f3f3c7f1ea29.tar.xz |
stat: print timestamps to full resolution
* src/stat.c (epoch_time): New function.
(print_stat): Use it for %[WXYZ].
* NEWS: Document this.
* tests/touch/60-seconds: Adjust test to match.
* tests/misc/stat-birthtime: Likewise.
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | src/stat.c | 39 | ||||
-rwxr-xr-x | tests/misc/stat-birthtime | 3 | ||||
-rwxr-xr-x | tests/touch/60-seconds | 2 |
4 files changed, 31 insertions, 18 deletions
@@ -75,6 +75,11 @@ GNU coreutils NEWS -*- outline -*- merely accepted and ignored, for compatibility. Starting two years ago, with coreutils-7.0, its use evoked a warning. + stat now outputs the full sub-second resolution for the atime, + mtime, and ctime values since the Epoch, when using the %X, %Y, and + %Z directives of the --format option. This matches the fact that + %x, %y, and %z were already doing so for the human-readable variant. + touch's --file option is no longer recognized. Use --reference=F (-r) instead. --file has not been documented for 15 years, and its use has elicited a warning since coreutils-7.1. diff --git a/src/stat.c b/src/stat.c index e1d68a556..6b2e99b77 100644 --- a/src/stat.c +++ b/src/stat.c @@ -461,6 +461,26 @@ human_time (struct timespec t) return str; } +static char * ATTRIBUTE_WARN_UNUSED_RESULT +epoch_time (struct timespec t) +{ + static char str[INT_STRLEN_BOUND (time_t) + sizeof ".NNNNNNNNN"]; + /* Note that time_t can technically be a floating point value, such + that casting to [u]intmax_t could lose a fractional value or + suffer from overflow. However, most porting targets have an + integral time_t; also, we know of no file systems that store + valid time values outside the bounds of intmax_t even if that + value were represented as a floating point. Besides, the cost of + converting to struct tm just to use nstrftime (str, len, "%s.%N", + tm, 0, t.tv_nsec) is pointless, since nstrftime would have to + convert back to seconds as time_t. */ + if (TYPE_SIGNED (time_t)) + sprintf (str, "%" PRIdMAX ".%09ld", (intmax_t) t.tv_sec, t.tv_nsec); + else + sprintf (str, "%" PRIuMAX ".%09ld", (uintmax_t) t.tv_sec, t.tv_nsec); + return str; +} + static void out_string (char *pformat, size_t prefix_len, char const *arg) { @@ -802,38 +822,27 @@ print_stat (char *pformat, size_t prefix_len, char m, struct timespec t = get_stat_birthtime (statbuf); if (t.tv_nsec < 0) out_string (pformat, prefix_len, "-"); - else if (TYPE_SIGNED (time_t)) - out_int (pformat, prefix_len, t.tv_sec); else - out_uint (pformat, prefix_len, t.tv_sec); + out_string (pformat, prefix_len, epoch_time (t)); } break; case 'x': out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf))); break; case 'X': - if (TYPE_SIGNED (time_t)) - out_int (pformat, prefix_len, statbuf->st_atime); - else - out_uint (pformat, prefix_len, statbuf->st_atime); + out_string (pformat, prefix_len, epoch_time (get_stat_atime (statbuf))); break; case 'y': out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf))); break; case 'Y': - if (TYPE_SIGNED (time_t)) - out_int (pformat, prefix_len, statbuf->st_mtime); - else - out_uint (pformat, prefix_len, statbuf->st_mtime); + out_string (pformat, prefix_len, epoch_time (get_stat_mtime (statbuf))); break; case 'z': out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf))); break; case 'Z': - if (TYPE_SIGNED (time_t)) - out_int (pformat, prefix_len, statbuf->st_ctime); - else - out_uint (pformat, prefix_len, statbuf->st_ctime); + out_string (pformat, prefix_len, epoch_time (get_stat_ctime (statbuf))); break; case 'C': fail |= out_file_context (filename, pformat, prefix_len); diff --git a/tests/misc/stat-birthtime b/tests/misc/stat-birthtime index b54268c11..38e5d5947 100755 --- a/tests/misc/stat-birthtime +++ b/tests/misc/stat-birthtime @@ -28,8 +28,7 @@ ctime=$(stat --format %Z a) || fail=1 case $(stat --format %x a) in *.000000000*) sleep 2;; # worst case file system is FAT - *) # FIXME: sleep .1 would be sufficient if %X is fixed to show nanoseconds - sleep 1;; + *) sleep .02;; # should be adequate for any system with subsecond resolution esac touch a || fail=1 diff --git a/tests/touch/60-seconds b/tests/touch/60-seconds index f858a309a..f98f0c5d1 100755 --- a/tests/touch/60-seconds +++ b/tests/touch/60-seconds @@ -23,7 +23,7 @@ fi . $srcdir/test-lib.sh -echo 60 > exp || framework_failure +echo 60.000000000 > exp || framework_failure # Before coreutils-7.7, this would fail, complaining of |