summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/ask-password-api.c2
-rw-r--r--src/shared/condition.c42
-rw-r--r--src/shared/install.c3
3 files changed, 44 insertions, 3 deletions
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index 65151b19a6..2597cfc648 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -484,7 +484,7 @@ int ask_password_agent(
(void) mkdir_p_label("/run/systemd/ask-password", 0755);
- fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
+ fd = mkostemp_safe(temp);
if (fd < 0) {
r = fd;
goto finish;
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", &timestamp_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, &timestamp);
+ 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) {
diff --git a/src/shared/install.c b/src/shared/install.c
index 11770d887f..5f12fb447f 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -403,6 +403,9 @@ static bool chroot_symlinks_same(const char *root, const char *wd, const char *a
/* This will give incorrect results if the paths are relative and go outside
* of the chroot. False negatives are possible. */
+ if (!root)
+ root = "/";
+
a = strjoina(path_is_absolute(a) ? root : wd, "/", a);
b = strjoina(path_is_absolute(b) ? root : wd, "/", b);
return path_equal_or_files_same(a, b);