]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #19164 from mmatsuya/main
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 11 Apr 2021 07:46:25 +0000 (16:46 +0900)
committerGitHub <noreply@github.com>
Sun, 11 Apr 2021 07:46:25 +0000 (16:46 +0900)
tmpfiles: use a entry in hashmap as ItemArray in read_config_file()

man/tmpfiles.d.xml
src/tmpfiles/tmpfiles.c
test/units/testsuite-22.11.sh [new file with mode: 0755]

index 55b763e26d587f504f5047ac38592b7e94def5c6..35b762ca3f7c7d3b6d2d79cc844f64e4275e9d41 100644 (file)
@@ -58,8 +58,8 @@ 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                        -    -    -     -           /source/to/copy
-x     /path-or-glob/to/ignore                  -    -    -     -           -
-X     /path-or-glob/to/ignore/recursively      -    -    -     -           -
+x     /path-or-glob/to/ignore/recursively      -    -    -     -           -
+X     /path-or-glob/to/ignore                  -    -    -     -           -
 r     /empty/dir/to/remove                     -    -    -     -           -
 R     /dir/to/remove/recursively               -    -    -     -           -
 z     /path-or-glob/to/adjust/mode             mode user group -           -
index 6b26dc8b9c333a65a195959b60f04235c056f8a6..b6de1e74b210d2a692693ad1588f7371fa5bdc5d 100644 (file)
@@ -3187,7 +3187,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
         _cleanup_fclose_ FILE *_f = NULL;
         unsigned v = 0;
         FILE *f;
-        Item *i;
+        ItemArray *ia;
         int r = 0;
 
         assert(fn);
@@ -3240,31 +3240,41 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
         }
 
         /* we have to determine age parameter for each entry of type X */
-        ORDERED_HASHMAP_FOREACH(i, globs) {
-                Item *j, *candidate_item = NULL;
+        ORDERED_HASHMAP_FOREACH(ia, globs)
+                for (size_t ni = 0; ni < ia->n_items; ni++) {
+                        ItemArray *ja;
+                        Item *i = ia->items + ni, *candidate_item = NULL;
 
-                if (i->type != IGNORE_DIRECTORY_PATH)
-                        continue;
-
-                ORDERED_HASHMAP_FOREACH(j, items) {
-                        if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA))
+                        if (i->type != IGNORE_DIRECTORY_PATH)
                                 continue;
 
-                        if (path_equal(j->path, i->path)) {
-                                candidate_item = j;
-                                break;
-                        }
+                        ORDERED_HASHMAP_FOREACH(ja, items)
+                                for (size_t nj = 0; nj < ja->n_items; nj++) {
+                                        Item *j = ja->items + nj;
 
-                        if ((!candidate_item && path_startswith(i->path, j->path)) ||
-                            (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
-                                candidate_item = j;
-                }
+                                        if (!IN_SET(j->type, CREATE_DIRECTORY,
+                                                             TRUNCATE_DIRECTORY,
+                                                             CREATE_SUBVOLUME,
+                                                             CREATE_SUBVOLUME_INHERIT_QUOTA,
+                                                             CREATE_SUBVOLUME_NEW_QUOTA))
+                                                continue;
 
-                if (candidate_item && candidate_item->age_set) {
-                        i->age = candidate_item->age;
-                        i->age_set = true;
+                                        if (path_equal(j->path, i->path)) {
+                                                candidate_item = j;
+                                                break;
+                                        }
+
+                                        if (candidate_item
+                                            ? (path_startswith(j->path, candidate_item->path) && fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)
+                                            : path_startswith(i->path, j->path) != NULL)
+                                                candidate_item = j;
+                                }
+
+                        if (candidate_item && candidate_item->age_set) {
+                                i->age = candidate_item->age;
+                                i->age_set = true;
+                        }
                 }
-        }
 
         if (ferror(f)) {
                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
diff --git a/test/units/testsuite-22.11.sh b/test/units/testsuite-22.11.sh
new file mode 100755 (executable)
index 0000000..21ef210
--- /dev/null
@@ -0,0 +1,141 @@
+#! /bin/bash
+
+set -e
+set -x
+
+rm -fr /tmp/x
+mkdir  /tmp/x
+
+#
+# 'x'
+#
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+x /tmp/x/1
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test -f /tmp/x/1/x1
+test -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test ! -f /tmp/x/z1
+test ! -f /tmp/x/z2
+
+#
+# 'X'
+#
+
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+X /tmp/x/1
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test ! -f /tmp/x/1/x1
+test ! -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test ! -f /tmp/x/z1
+test ! -f /tmp/x/z2
+
+#
+# 'x' with glob
+#
+
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+x /tmp/x/[1345]
+x /tmp/x/z*
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test -f /tmp/x/1/x1
+test -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test -f /tmp/x/z1
+test -f /tmp/x/z2
+
+#
+# 'X' with glob
+#
+
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+X /tmp/x/[1345]
+X /tmp/x/?[12]
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test ! -f /tmp/x/1/x1
+test ! -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test -f /tmp/x/z1
+test -f /tmp/x/z2
+
+#
+# 'x' with 'r'
+#
+
+mkdir -p /tmp/x/{1,2}/a
+touch /tmp/x/1/a/{x1,x2} /tmp/x/2/a/{y1,y2}
+
+systemd-tmpfiles --clean - <<EOF
+# x/X is not supposed to influence r
+x /tmp/x/1/a
+X /tmp/x/2/a
+r /tmp/x/1
+r /tmp/x/2
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test -d /tmp/x/1/a
+test -f /tmp/x/1/a/x1
+test -f /tmp/x/1/a/x2
+test -f /tmp/x/2/a/y1
+test -f /tmp/x/2/a/y2
+
+#
+# 'x' with 'R'
+#
+
+mkdir -p /tmp/x/{1,2}/a
+touch /tmp/x/1/a/{x1,x2} /tmp/x/2/a/{y1,y2}
+
+systemd-tmpfiles --remove - <<EOF
+# X is not supposed to influence R
+X /tmp/x/1/a
+X /tmp/x/2/a
+R /tmp/x/1
+EOF
+
+find /tmp/x | sort
+test ! -d /tmp/x/1
+test ! -d /tmp/x/1/a
+test ! -f /tmp/x/1/a/x1
+test ! -f /tmp/x/1/a/x2
+test -f /tmp/x/2/a/y1
+test -f /tmp/x/2/a/y2