diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index 54f3c501cb..a105b8af39 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -58,6 +58,7 @@ c+ /dev/char-device-to-[re]create mode user group - major b /dev/block-device-to-create mode user group - major:minor b+ /dev/block-device-to-[re]create mode user group - major:minor C /target/to/create - - - cleanup-age /source/to/copy +C+ /target/to/create - - - cleanup-age /source/to/copy x /path-or-glob/to/ignore/recursively - - - cleanup-age - X /path-or-glob/to/ignore - - - cleanup-age - r /path-or-glob/to/remove - - - - - @@ -326,15 +327,14 @@ L /tmp/foobar - - - - /dev/null C - Recursively copy a file or directory, if the - destination files or directories do not exist yet or the - destination directory is empty. Note that this command will not - descend into subdirectories if the destination directory already - exists and is not empty. Instead, the entire copy operation is - skipped. If the argument is omitted, files from the source directory - /usr/share/factory/ with the same name - are copied. Does not follow symlinks. Contents of the directories - are subject to time-based cleanup if the age argument is specified. + C+ + Recursively copy a file or directory, if the destination files or directories do + not exist yet or the destination directory is empty. Note that this command will not descend into + subdirectories if the destination directory already exists and is not empty, unless the action is + suffixed with +. Instead, the entire copy operation is skipped. If the argument + is omitted, files from the source directory /usr/share/factory/ with the same + name are copied. Does not follow symlinks. Contents of the directories are subject to time-based + cleanup if the age argument is specified. diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index de72df2908..382fa8b56a 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1803,7 +1803,7 @@ static int copy_files(Item *i) { dfd, bn, i->uid_set ? i->uid : UID_INVALID, i->gid_set ? i->gid : GID_INVALID, - COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE | COPY_HARDLINKS, + COPY_REFLINK | ((i->append_or_force) ? COPY_MERGE : COPY_MERGE_EMPTY) | COPY_MAC_CREATE | COPY_HARDLINKS, NULL); fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH); diff --git a/test/units/testsuite-22.02.sh b/test/units/testsuite-22.02.sh index de28fa7044..b883a9672e 100755 --- a/test/units/testsuite-22.02.sh +++ b/test/units/testsuite-22.02.sh @@ -122,6 +122,22 @@ EOF test "$(stat -c %U:%G:%a /tmp/C/3/f1)" = "root:root:644" test ! -e /tmp/C/4 +touch /tmp/C/3-origin/f{2,3,4} +echo -n ABC > /tmp/C/3/f1 + +systemd-tmpfiles --create - <