]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udevadm-verify: add support for directory arguments 27676/head
authorDmitry V. Levin <ldv@strace.io>
Wed, 17 May 2023 14:00:00 +0000 (14:00 +0000)
committerDmitry V. Levin <ldv@strace.io>
Thu, 18 May 2023 17:00:00 +0000 (17:00 +0000)
When an argument specified to udevadm verify is a directory,
verify all *.rules files in that directory.

Suggested-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
src/udev/udevadm-verify.c
test/units/testsuite-17.11.sh

index 48aeb8f7e75daa8f2e9424b56e754b2cd7bf40b1..37c477da6a5c2f4ea96921d852bff6cfae2c499e 100644 (file)
@@ -12,6 +12,7 @@
 #include "log.h"
 #include "parse-argument.h"
 #include "pretty-print.h"
+#include "stat-util.h"
 #include "static-destruct.h"
 #include "strv.h"
 #include "udev-rules.h"
@@ -119,20 +120,58 @@ static int verify_rules_file(UdevRules *rules, const char *fname) {
         return 0;
 }
 
-static int verify_rules(UdevRules *rules, char **files) {
-        size_t fail_count = 0, success_count = 0;
+static int verify_rules_filelist(UdevRules *rules, char **files, size_t *fail_count, size_t *success_count, bool walk_dirs);
+
+static int verify_rules_dir(UdevRules *rules, const char *dir, size_t *fail_count, size_t *success_count) {
+        int r;
+        _cleanup_strv_free_ char **files = NULL;
+
+        assert(rules);
+        assert(dir);
+        assert(fail_count);
+        assert(success_count);
+
+        r = conf_files_list(&files, ".rules", NULL, 0, dir);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enumerate rules files: %m");
+
+        return verify_rules_filelist(rules, files, fail_count, success_count, /* walk_dirs */ false);
+}
+
+static int verify_rules_filelist(UdevRules *rules, char **files, size_t *fail_count, size_t *success_count, bool walk_dirs) {
         int r, rv = 0;
 
+        assert(rules);
+        assert(files);
+        assert(fail_count);
+        assert(success_count);
+
         STRV_FOREACH(fp, files) {
-                r = verify_rules_file(rules, *fp);
-                if (r < 0) {
-                        fail_count++;
-                        if (rv >= 0)
-                                rv = r;
-                } else
-                        success_count++;
+                if (walk_dirs && is_dir(*fp, /* follow = */ true) > 0)
+                        r = verify_rules_dir(rules, *fp, fail_count, success_count);
+                else {
+                        r = verify_rules_file(rules, *fp);
+                        if (r < 0)
+                                ++(*fail_count);
+                        else
+                                ++(*success_count);
+                }
+                if (r < 0 && rv >= 0)
+                        rv = r;
         }
 
+        return rv;
+}
+
+static int verify_rules(UdevRules *rules, char **files) {
+        size_t fail_count = 0, success_count = 0;
+        int r;
+
+        assert(rules);
+        assert(files);
+
+        r = verify_rules_filelist(rules, files, &fail_count, &success_count, /* walk_dirs */ true);
+
         printf("\n%s%zu udev rules files have been checked.%s\n"
                "  Success: %zu\n"
                "%s  Fail:    %zu%s\n",
@@ -144,7 +183,7 @@ static int verify_rules(UdevRules *rules, char **files) {
                fail_count,
                fail_count > 0 ? ansi_normal() : "");
 
-        return rv;
+        return r;
 }
 
 int verify_main(int argc, char *argv[], void *userdata) {
index 4b9e188b22c0e868df4d0786bd6233b836bef091..d70a93b74f10381bcf6c1be351a67b5145e6367a 100755 (executable)
@@ -31,6 +31,12 @@ cat >"${workdir}/default_output_1_fail" <<EOF
   Success: 0
   Fail:    1
 EOF
+cat >"${workdir}/output_0_files" <<EOF
+
+0 udev rules files have been checked.
+  Success: 0
+  Fail:    0
+EOF
 
 test_number=0
 rules=
@@ -52,8 +58,10 @@ next_test_number() {
 
 assert_0() {
     udevadm verify "$@" >"${out}"
-    if [ -f "${rules}" ]; then
-       diff -u "${workdir}/default_output_1_success" "${out}"
+    if [ -f "${exo}" ]; then
+        diff -u "${exo}" "${out}"
+    elif [ -f "${rules}" ]; then
+        diff -u "${workdir}/default_output_1_success" "${out}"
     fi
 
     next_test_number
@@ -97,28 +105,40 @@ assert_1 -N now
 assert_1 --resolve-names
 # --resolve-names= takes "early" or "never"
 assert_1 --resolve-names=now
-# Failed to parse rules file .: Is a directory
-cp "${workdir}/default_output_1_fail" "${exo}"
-assert_1 .
 # Failed to parse rules file ./nosuchfile: No such file or directory
 assert_1 ./nosuchfile
-# Failed to parse rules file .: Is a directory
+# Failed to parse rules file ./nosuchfile: No such file or directory
 cat >"${exo}" <<EOF
 
 3 udev rules files have been checked.
   Success: 2
   Fail:    1
 EOF
-assert_1 /dev/null . /dev/null
+assert_1 /dev/null ./nosuchfile /dev/null
 
 rules_dir='etc/udev/rules.d'
 mkdir -p "${rules_dir}"
 # No rules files found in $PWD
 assert_1 --root="${workdir}"
 
+# Directory without rules.
+cp "${workdir}/output_0_files" "${exo}"
+assert_0 "${rules_dir}"
+
+# Directory with a loop.
+ln -s . "${rules_dir}/loop.rules"
+cp "${workdir}/default_output_1_fail" "${exo}"
+assert_1 "${rules_dir}"
+rm "${rules_dir}/loop.rules"
+
+# Empty rules.
 touch "${rules_dir}/empty.rules"
 assert_0 --root="${workdir}"
 
+# Directory with a single *.rules file.
+cp "${workdir}/default_output_1_success" "${exo}"
+assert_0 "${rules_dir}"
+
 # Combination of --root= and FILEs is not supported.
 assert_1 --root="${workdir}" /dev/null
 # No rules files found in nosuchdir
@@ -396,5 +416,12 @@ assert_1 "${rules}"
 sed "s|sample-[0-9]*.rules|${workdir}/${rules_dir}/&|" sample-*.exp >"${workdir}/${exp}"
 cd -
 assert_1 --root="${workdir}"
+cd -
+
+# udevadm verify path/
+sed "s|sample-[0-9]*.rules|${workdir}/${rules_dir}/&|" sample-*.exp >"${workdir}/${exp}"
+cd -
+assert_1 "${rules_dir}"
+cd -
 
 exit 0