]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udevadm verify: introduce --root option
authorDmitry V. Levin <ldv@strace.io>
Thu, 9 Mar 2023 08:00:00 +0000 (08:00 +0000)
committerDmitry V. Levin <ldv@strace.io>
Fri, 10 Mar 2023 17:10:41 +0000 (17:10 +0000)
When udevadm verify is invoked without positional arguments and loads
all rules files from the system like the udev daemon does, this option
can be used to operate on files underneath the specified root path.

man/udevadm.xml
shell-completion/bash/udevadm
shell-completion/zsh/_udevadm
src/udev/udevadm-verify.c

index bafd5af0fb928466db0adda4ed55371782d14d25..503ec8109184e89019dbb8d56c71922ca2fbf214 100644 (file)
             parsed. When set to <constant>never</constant>, names will
             never be resolved.</para>
           </listitem>
+          <term><option>--root=<replaceable>PATH</replaceable></option></term>
+          <listitem>
+            <para>When looking for udev rules files located in udev/rules.d directories,
+            operate on files underneath the specified root path <replaceable>PATH</replaceable>.</para>
+          </listitem>
         </varlistentry>
 
         <xi:include href="standard-options.xml" xpointer="help" />
index b6e14e1d36e777705215a551142933c6a53e07ef..3c3c403153b821ba08922d0657191fa69accbc36 100644 (file)
@@ -64,7 +64,7 @@ _udevadm() {
         [MONITOR_ARG]='-s --subsystem-match -t --tag-match'
         [TEST]='-a --action -N --resolve-names'
         [TEST_BUILTIN]='-a --action'
-        [VERIFY]='-N --resolve-names'
+        [VERIFY]='-N --resolve-names --root'
         [WAIT]='-t --timeout --initialized=no --removed --settle'
         [LOCK]='-t --timeout -d --device -b --backing -p --print'
     )
@@ -254,6 +254,10 @@ _udevadm() {
                     -N|--resolve-names)
                         comps='early never'
                         ;;
+                    --root)
+                        comps=$(compgen -A directory -- "$cur" )
+                        compopt -o dirnames
+                        ;;
                     *)
                         comps=''
                         ;;
index 074d367a9de18115dff6e2565c1b72cce5a69064..e8414eef679378bc66912dfe58ab0c2597d006a5 100644 (file)
@@ -108,6 +108,7 @@ _udevadm_test-builtin(){
 _udevadm_verify(){
     _arguments \
         {-N+,--resolve-names=}'[When to resolve names.]:resolve:(early never)' \
+        '--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \
         {-h,--help}'[Print help text.]' \
         '*::files:_files'
 }
index f4728927312b439dd4701fcc85ba366ed4e0cb9f..26f317711e9c56750e0e982c3c7f5d37a3ba83b1 100644 (file)
 #include "conf-files.h"
 #include "constants.h"
 #include "log.h"
+#include "parse-argument.h"
 #include "pretty-print.h"
+#include "static-destruct.h"
 #include "strv.h"
 #include "udev-rules.h"
 #include "udevadm.h"
 
 static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
+static char *arg_root = NULL;
+
+STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 
 static int help(void) {
         _cleanup_free_ char *link = NULL;
@@ -30,6 +35,7 @@ static int help(void) {
                "  -h --help                            Show this help\n"
                "  -V --version                         Show package version\n"
                "  -N --resolve-names=early|never       When to resolve names\n"
+               "  --root=PATH                          Operate on an alternate filesystem root\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
                ansi_highlight(),
@@ -40,14 +46,18 @@ static int help(void) {
 }
 
 static int parse_argv(int argc, char *argv[]) {
+        enum {
+                ARG_ROOT = 0x100,
+        };
         static const struct option options[] = {
-                { "help",          no_argument,       NULL, 'h' },
-                { "version",       no_argument,       NULL, 'V' },
-                { "resolve-names", required_argument, NULL, 'N' },
+                { "help",          no_argument,       NULL, 'h'         },
+                { "version",       no_argument,       NULL, 'V'         },
+                { "resolve-names", required_argument, NULL, 'N'         },
+                { "root",          required_argument, NULL, ARG_ROOT    },
                 {}
         };
 
-        int c;
+        int r, c;
 
         assert(argc >= 0);
         assert(argv);
@@ -71,12 +81,22 @@ static int parse_argv(int argc, char *argv[]) {
                         if (arg_resolve_name_timing == RESOLVE_NAME_NEVER)
                                 arg_resolve_name_timing = RESOLVE_NAME_LATE;
                         break;
+                case ARG_ROOT:
+                        r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_root);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case '?':
                         return -EINVAL;
                 default:
                         assert_not_reached();
                 }
 
+        if (arg_root && optind < argc)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Combination of --root= and FILEs is not supported.");
+
         return 1;
 }
 
@@ -124,9 +144,12 @@ int verify_main(int argc, char *argv[], void *userdata) {
                 const char* const* rules_dirs = STRV_MAKE_CONST(CONF_PATHS("udev/rules.d"));
                 _cleanup_strv_free_ char **files = NULL;
 
-                r = conf_files_list_strv(&files, ".rules", NULL, 0, rules_dirs);
+                r = conf_files_list_strv(&files, ".rules", arg_root, 0, rules_dirs);
                 if (r < 0)
                         return log_error_errno(r, "Failed to enumerate rules files: %m");
+                if (arg_root && strv_isempty(files))
+                        return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+                                               "No rules files found in %s", arg_root);
 
                 return verify_rules(rules, files);
         }