diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2016-09-15 22:53:00 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-15 22:53:00 -0400 |
commit | e77e0f51fee8780941690176cb88bdffb80e7adc (patch) | |
tree | 2c3e06bc18ef7daacfcbfabb9f2d502df77a3dea /src/shared | |
parent | 7dabbb55a8744a43ec869839ef371b184c8d2ffe (diff) | |
parent | fb8b0869a7bc30e23be175cf978df23192d59118 (diff) |
Merge pull request #4131 from intelfx/update-done-timestamps-precision
condition: ignore nanoseconds in timestamps for ConditionNeedsUpdate=
Fixes #4130.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/condition.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/src/shared/condition.c b/src/shared/condition.c index 6bb42c0692..f13fa6a9fd 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -37,6 +37,7 @@ #include "condition.h" #include "extract-word.h" #include "fd-util.h" +#include "fileio.h" #include "glob-util.h" #include "hostname-util.h" #include "ima-util.h" @@ -309,8 +310,45 @@ static int condition_test_needs_update(Condition *c) { if (lstat("/usr/", &usr) < 0) return true; - return usr.st_mtim.tv_sec > other.st_mtim.tv_sec || - (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec); + /* + * First, compare seconds as they are always accurate... + */ + if (usr.st_mtim.tv_sec != other.st_mtim.tv_sec) + return usr.st_mtim.tv_sec > other.st_mtim.tv_sec; + + /* + * ...then compare nanoseconds. + * + * A false positive is only possible when /usr's nanoseconds > 0 + * (otherwise /usr cannot be strictly newer than the target file) + * AND the target file's nanoseconds == 0 + * (otherwise the filesystem supports nsec timestamps, see stat(2)). + */ + if (usr.st_mtim.tv_nsec > 0 && other.st_mtim.tv_nsec == 0) { + _cleanup_free_ char *timestamp_str = NULL; + uint64_t timestamp; + int r; + + r = parse_env_file(p, NULL, "TimestampNSec", ×tamp_str, NULL); + if (r < 0) { + log_error_errno(-r, "Failed to parse timestamp file '%s', using mtime: %m", p); + return true; + } else if (r == 0) { + log_debug("No data in timestamp file '%s', using mtime", p); + return true; + } + + r = safe_atou64(timestamp_str, ×tamp); + if (r < 0) { + log_error_errno(-r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", + timestamp_str, p); + return true; + } + + other.st_mtim.tv_nsec = timestamp % NSEC_PER_SEC; + } + + return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec; } static int condition_test_first_boot(Condition *c) { |