]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
hardlink: preserve timestamps when reflinking files
authorLiu Zheng <liuzheng@uniontech.com>
Tue, 2 Jun 2026 06:26:28 +0000 (14:26 +0800)
committerLiu Zheng <liuzheng@uniontech.com>
Tue, 2 Jun 2026 06:31:03 +0000 (14:31 +0800)
When using --reflink=always, the destination file gets the current
timestamp instead of preserving the original file's atime and mtime.
This differs from both hardlink behavior and "cp -p --reflink=always".

Add futimens() call after successful reflink to restore the original
timestamps from the target file's stat data.

Fixes #2340

misc-utils/hardlink.c

index bbfac951fddfcbf63325a54f8ea122cd04210826..07be3e1afeaee45859f59ea683e1606f568596a0 100644 (file)
@@ -701,6 +701,7 @@ static inline int do_link(struct file *a, struct file *b,
 {
        if (reflink) {
                int dest = -1, src = -1;
+               struct timespec times[2];
 
                dest = open(new_name, O_CREAT|O_WRONLY|O_TRUNC, 0600);
                if (dest < 0)
@@ -714,6 +715,10 @@ static inline int do_link(struct file *a, struct file *b,
                        goto fallback;
                if (ioctl(dest, FICLONE, src) != 0)
                        goto fallback;
+               times[0] = b->st.st_atim;
+               times[1] = b->st.st_mtim;
+               if (futimens(dest, times) != 0)
+                       goto fallback;
                close(dest);
                close(src);
                return 0;