diff options
author | Jim Meyering <jim@meyering.net> | 2001-01-03 21:02:08 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2001-01-03 21:02:08 +0000 |
commit | 550edf90b21ef96fccc4e91bf799bf2d6df15053 (patch) | |
tree | e2bd29c572c9028a1be57962313bb9be8e2106c9 /src/ls.c | |
parent | f3aa9892056918da39e6873f051d4b02523d3209 (diff) | |
download | coreutils-550edf90b21ef96fccc4e91bf799bf2d6df15053.tar.xz |
Use the more precise algorithm of GNU "make" to decide whether
a file is in the future, by looking at high-resolution time
stamps if available.
(TIMESPEC_NS): New macro.
(current_time): Initialize to the minimum value.
(current_time_ns): New var.
(main): Do not bother to initialize current_time;
it's no longer needed.
(get_current_time): New function.
(print_long_format): Use it when a file appears to be in the future.
Get the nanoseconds of the file's time stamp, if available,
and use that to decide whether the file appears to be in the future.
Diffstat (limited to 'src/ls.c')
-rw-r--r-- | src/ls.c | 76 |
1 files changed, 65 insertions, 11 deletions
@@ -205,6 +205,12 @@ int rpl_lstat PARAMS((const char *, struct stat *)); # define DT_INIT(Val) /* empty */ #endif +#ifdef ST_MTIM_NSEC +# define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC) +#else +# define TIMESPEC_NS(timespec) 0 +#endif + enum filetype { unknown DT_INIT (DT_UNKNOWN), @@ -383,10 +389,11 @@ struct pending static struct pending *pending_dirs; -/* Current time (seconds since 1970). When we are printing a file's time, - include the year if it is more than 6 months before this time. */ +/* Current time in seconds and nanoseconds since 1970, updated as + needed when deciding whether a file is recent. */ -static time_t current_time; +static time_t current_time = TYPE_MINIMUM (time_t); +static int current_time_ns = -1; /* The number of digits to use for block sizes. 4, or more if needed for bigger numbers. */ @@ -866,7 +873,6 @@ main (int argc, char **argv) dir_defaulted = 1; print_dir_name = 1; pending_dirs = 0; - current_time = time ((time_t *) 0); i = decode_switches (argc, argv); @@ -2379,6 +2385,45 @@ long_time_expected_width (void) return width; } +/* Get the current time. */ + +static void +get_current_time (void) +{ +#if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME + { + struct timespec timespec; + if (clock_gettime (CLOCK_REALTIME, ×pec) == 0) + { + current_time = timespec.tv_sec; + current_time_ns = timespec.tv_nsec; + return; + } + } +#endif + + /* The clock does not have nanosecond resolution, so get the maximum + possible value for the current time that is consistent with the + reported clock. That way, files are not considered to be in the + future merely because their time stamps have higher resolution + than the clock resolution. */ + +#if HAVE_GETTIMEOFDAY + { + struct timeval timeval; + if (gettimeofday (&timeval, NULL) == 0) + { + current_time = timeval.tv_sec; + current_time_ns = timeval.tv_usec * 1000 + 999; + return; + } + } +#endif + + current_time = time (NULL); + current_time_ns = 999999999; +} + static void print_long_format (const struct fileinfo *f) { @@ -2398,6 +2443,7 @@ print_long_format (const struct fileinfo *f) size_t s; char *p; time_t when; + int when_ns IF_LINT (= 0); struct tm *when_local; char *user_name; @@ -2415,12 +2461,15 @@ print_long_format (const struct fileinfo *f) { case time_ctime: when = f->stat.st_ctime; + when_ns = TIMESPEC_NS (f->stat.st_ctim); break; case time_mtime: when = f->stat.st_mtime; + when_ns = TIMESPEC_NS (f->stat.st_mtim); break; case time_atime: when = f->stat.st_atime; + when_ns = TIMESPEC_NS (f->stat.st_atim); break; } @@ -2481,21 +2530,26 @@ print_long_format (const struct fileinfo *f) if ((when_local = localtime (&when))) { + time_t six_months_ago; + int recent; + char const *fmt; + /* If the file appears to be in the future, update the current time, in case the file happens to have been modified since the last time we checked the clock. */ - time_t now = (current_time < when - ? (current_time = time (NULL)) - : current_time); + if (current_time < when + || (current_time == when && current_time_ns < when_ns)) + get_current_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 on the average. Write this value as an integer constant to avoid floating point hassles. */ - time_t six_months_ago = now - 31556952 / 2; - int recent = six_months_ago <= when && when <= now; - - char const *fmt = long_time_format[recent]; + six_months_ago = current_time - 31556952 / 2; + recent = (six_months_ago <= when + && (when < current_time + || (when == current_time && when_ns <= current_time_ns))); + fmt = long_time_format[recent]; for (;;) { |