tmpfiles: use NSEC_INFINITY consistently in dir_cleanup()
Correctness analysis ==================== The *time_nsec variables are used for a total of 2 or 3 times: - twice in needs_cleanup() (lines 788, 839) - once in a recursive dir_cleanup() (line 764) as self_*time_nsec In needs_cleanup(), all passed timestamps are guarded against NSEC_INFINITY (this does not fix any real bugs as a 0 value is also older than any cutoff point and thus would not cause any deletions). Recursively in dir_cleanup(), the self_* variables are used to reset the toplevel directory utimes, where they are superficially compared against NSEC_INFINITY as a guard, but subsequently mishandled in the case when only one of the times is NSEC_INFINITY: in this case, it will be a) logged as a bogus value and b) passed through directly to timespec_store_nsec(), which does special-case it, but in a way that is invalid for futimens(). This is further fixed up by explicitly mapping NSEC_INFINITY to TIMESPEC_OMIT. This constitutes a bugfix in theory, as a ~STATX_ATIME return from statx() would have previously caused the corresponding utime to be reset to 0 epoch) rather than being omitted from being set. However, in a directory with ~STATX_ATIME, attempts to set atime would likely be ignored as well. Mostly this is a self-consistency fix that establishes that dir_cleanup() should be called with NSEC_INFINITY in place of absent timestamps.
This commit is contained in:
+16
-8
@@ -710,10 +710,10 @@ static int dir_cleanup(
|
||||
continue;
|
||||
}
|
||||
|
||||
atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? statx_timestamp_load_nsec(&sx.stx_atime) : 0;
|
||||
mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? statx_timestamp_load_nsec(&sx.stx_mtime) : 0;
|
||||
ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? statx_timestamp_load_nsec(&sx.stx_ctime) : 0;
|
||||
btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? statx_timestamp_load_nsec(&sx.stx_btime) : 0;
|
||||
atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? statx_timestamp_load_nsec(&sx.stx_atime) : NSEC_INFINITY;
|
||||
mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? statx_timestamp_load_nsec(&sx.stx_mtime) : NSEC_INFINITY;
|
||||
ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? statx_timestamp_load_nsec(&sx.stx_ctime) : NSEC_INFINITY;
|
||||
btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? statx_timestamp_load_nsec(&sx.stx_btime) : NSEC_INFINITY;
|
||||
|
||||
sub_path = path_join(p, de->d_name);
|
||||
if (!sub_path) {
|
||||
@@ -867,11 +867,19 @@ finish:
|
||||
log_action("Would restore", "Restoring",
|
||||
"%s access and modification time on \"%s\": %s, %s",
|
||||
p,
|
||||
FORMAT_TIMESTAMP_STYLE(self_atime_nsec / NSEC_PER_USEC, TIMESTAMP_US),
|
||||
FORMAT_TIMESTAMP_STYLE(self_mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US));
|
||||
self_atime_nsec != NSEC_INFINITY
|
||||
? FORMAT_TIMESTAMP_STYLE(self_atime_nsec / NSEC_PER_USEC, TIMESTAMP_US)
|
||||
: "(omitted)",
|
||||
self_mtime_nsec != NSEC_INFINITY
|
||||
? FORMAT_TIMESTAMP_STYLE(self_mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US)
|
||||
: "(omitted)");
|
||||
|
||||
timespec_store_nsec(ts + 0, self_atime_nsec);
|
||||
timespec_store_nsec(ts + 1, self_mtime_nsec);
|
||||
ts[0] = self_atime_nsec != NSEC_INFINITY
|
||||
? *TIMESPEC_STORE_NSEC(self_atime_nsec)
|
||||
: TIMESPEC_OMIT;
|
||||
ts[1] = self_mtime_nsec != NSEC_INFINITY
|
||||
? *TIMESPEC_STORE_NSEC(self_mtime_nsec)
|
||||
: TIMESPEC_OMIT;
|
||||
|
||||
/* Restore original directory timestamps */
|
||||
if (!arg_dry_run &&
|
||||
|
||||
Reference in New Issue
Block a user