]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tmpfiles: Add merge support for copy files action
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 9 May 2023 11:45:16 +0000 (13:45 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 10 May 2023 16:08:07 +0000 (18:08 +0200)
If '+' is specified with 'C', let's merge the tree with any existing
tree.

man/tmpfiles.d.xml
src/tmpfiles/tmpfiles.c
test/units/testsuite-22.02.sh

index 54f3c501cb0bf43021ee027500abccfc140610df..a105b8af394accd9986b3e12c84303900fd55b23 100644 (file)
@@ -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</programlisting>
 
         <varlistentry>
           <term><varname>C</varname></term>
-          <listitem><para>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
-          <filename>/usr/share/factory/</filename> 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.
+          <term><varname>C+</varname></term>
+          <listitem><para>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 <varname>+</varname>. Instead, the entire copy operation is skipped. If the argument
+          is omitted, files from the source directory <filename>/usr/share/factory/</filename> 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.
           </para></listitem>
         </varlistentry>
 
index de72df29087395576833dabbe1fe9c7ac80f7dc5..382fa8b56a082921c3bb1ce7706a82b7e4102035 100644 (file)
@@ -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);
index de28fa70446a1ab7a1cd9d50919624de0bf1e5dd..b883a9672ecee03a65117e621a3a6786d046f1d5 100755 (executable)
@@ -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 - <<EOF
+C+     /tmp/C/3    0755 daemon daemon - /tmp/C/3-origin
+EOF
+
+# Test that the trees got merged, even though /tmp/C/3 already exists.
+test -e /tmp/C/3/f1
+test -e /tmp/C/3/f2
+test -e /tmp/C/3/f3
+test -e /tmp/C/3/f4
+
+# Test that /tmp/C/3/f1 did not get overwritten.
+test "$(cat /tmp/C/3/f1)" = "ABC"
+
 # Check that %U expands to 0, both in the path and in the argument.
 home='/tmp/C'
 systemd-tmpfiles --create - <<EOF