]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
copy: Invoke hardlink context cleanup before restoring timestamps
authorAndreas Stührk <andreas.stuehrk@yaxi.tech>
Tue, 25 Feb 2025 23:05:41 +0000 (00:05 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 26 Feb 2025 08:07:26 +0000 (09:07 +0100)
When hardlink recreation is requested, it creates temporary files that
will be deleted once the context is destroyed. The deletion
(potentially) updates the directory's timestamps, so it's crucial that
the deletion happens before the directory timestamps are restored when
`COPY_RESTORE_DIRECTORY_TIMESTAMPS` is requested.

src/shared/copy.c

index 17c027a9e89e6c8c9f754fc811643621de4010b2..6a008f2dbe88063332efc06b1bd0b33cd812c68e 100644 (file)
@@ -1178,11 +1178,16 @@ finish:
                 if (fchmod(fdt, st->st_mode & 07777) < 0)
                         r = -errno;
 
+                /* Run hardlink context cleanup now because it potentially changes timestamps */
+                hardlink_context_destroy(&our_hardlink_context);
                 (void) copy_xattr(dirfd(d), NULL, fdt, NULL, copy_flags);
                 (void) futimens(fdt, (struct timespec[]) { st->st_atim, st->st_mtim });
-        } else if (FLAGS_SET(copy_flags, COPY_RESTORE_DIRECTORY_TIMESTAMPS))
+        } else if (FLAGS_SET(copy_flags, COPY_RESTORE_DIRECTORY_TIMESTAMPS)) {
+                /* Run hardlink context cleanup now because it potentially changes timestamps */
+                hardlink_context_destroy(&our_hardlink_context);
                 /* If the directory already exists, make sure the timestamps stay the same as before. */
                 (void) futimens(fdt, (struct timespec[]) { dt_st.st_atim, dt_st.st_mtim });
+        }
 
         if (copy_flags & COPY_FSYNC_FULL) {
                 if (fsync(fdt) < 0)