mirror of
https://github.com/systemd/systemd.git
synced 2025-03-30 10:50:15 +03:00
udevadm-test: allow to specify extra directories to load udev rules files
This adds -D/--extra-rules-dir=DIR switch for 'udevadm test' command. When specified, udev rules files in the specified directory will be also loaded. This may be useful for debugging udev rules by copying some udev rules files to a temporary directory.
This commit is contained in:
parent
4fd81d03e2
commit
c1b7db56e5
@ -888,6 +888,21 @@
|
||||
<xi:include href="version-info.xml" xpointer="v209"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-D <replaceable>DIR</replaceable></option></term>
|
||||
<term><option>--extra-rules-dir=<replaceable>DIR</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>Also load udev rules files from the specified directory. This option can be specified
|
||||
multiple times. It may be useful for debugging udev rules by copying some udev rules files to a
|
||||
temporary directory, editing them, and specifying the directory with this option. Files found in
|
||||
the specified directories have a higher priority than rules files in the default
|
||||
<filename>udev/rules.d</filename> directories used by <command>systemd-udevd</command>. See
|
||||
<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more
|
||||
details about the search paths.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<term><option>--verbose</option></term>
|
||||
|
@ -70,7 +70,7 @@ _udevadm() {
|
||||
[MONITOR_STANDALONE]='-k --kernel -u --udev -p --property'
|
||||
[MONITOR_ARG]='-s --subsystem-match -t --tag-match'
|
||||
[TEST_STANDALONE]='-v --verbose'
|
||||
[TEST_ARG]='-a --action -N --resolve-names'
|
||||
[TEST_ARG]='-a --action -N --resolve-names -D --extra-rules-dir'
|
||||
[TEST_BUILTIN]='-a --action'
|
||||
[VERIFY]='-N --resolve-names --root --no-summary --no-style'
|
||||
[WAIT]='-t --timeout --initialized=no --removed --settle'
|
||||
@ -228,6 +228,9 @@ _udevadm() {
|
||||
-N|--resolve-names)
|
||||
comps='early late never'
|
||||
;;
|
||||
-D|--extra-rules-dir)
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
esac
|
||||
elif [[ $cur = -* ]]; then
|
||||
comps="${OPTS[COMMON]} ${OPTS[TEST_ARG]} ${OPTS[TEST_STANDALONE]}"
|
||||
|
@ -89,6 +89,7 @@ _udevadm_test(){
|
||||
'(-)'{-V,--version}'[Show package version]' \
|
||||
'--action=[The action string.]:actions:(add change remove move online offline bind unbind)' \
|
||||
'--subsystem=[The subsystem string.]' \
|
||||
'(-D --extra-rules-dir=)'{-D,--extra-rules-dir=}'[Also load rules from the directory.]' \
|
||||
'(-v --verbose)'{-v,--verbose}'[Show verbose logs.]' \
|
||||
'*::devpath:_files -P /sys/ -W /sys'
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ static int run(int argc, char *argv[]) {
|
||||
usleep_safe(us);
|
||||
}
|
||||
|
||||
assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY) == 0);
|
||||
assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY, /* extra = */ NULL) == 0);
|
||||
|
||||
const char *syspath = strjoina("/sys", devpath);
|
||||
r = device_new_from_synthetic_event(&dev, syspath, action);
|
||||
|
@ -284,7 +284,7 @@ void manager_reload(Manager *manager, bool force) {
|
||||
udev_builtin_reload(flags);
|
||||
|
||||
if (FLAGS_SET(flags, UDEV_RELOAD_RULES)) {
|
||||
r = udev_rules_load(&rules, manager->config.resolve_name_timing);
|
||||
r = udev_rules_load(&rules, manager->config.resolve_name_timing, /* extra = */ NULL);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
|
||||
else
|
||||
@ -1316,7 +1316,7 @@ int manager_main(Manager *manager) {
|
||||
|
||||
udev_builtin_init();
|
||||
|
||||
r = udev_rules_load(&manager->rules, manager->config.resolve_name_timing);
|
||||
r = udev_rules_load(&manager->rules, manager->config.resolve_name_timing, /* extra = */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read udev rules: %m");
|
||||
|
||||
|
@ -1778,16 +1778,26 @@ UdevRules* udev_rules_new(ResolveNameTiming resolve_name_timing) {
|
||||
return rules;
|
||||
}
|
||||
|
||||
int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing) {
|
||||
int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing, char * const *extra) {
|
||||
_cleanup_(udev_rules_freep) UdevRules *rules = NULL;
|
||||
_cleanup_strv_free_ char **files = NULL;
|
||||
_cleanup_strv_free_ char **files = NULL, **directories = NULL;
|
||||
int r;
|
||||
|
||||
rules = udev_rules_new(resolve_name_timing);
|
||||
if (!rules)
|
||||
return -ENOMEM;
|
||||
|
||||
r = conf_files_list_strv(&files, ".rules", NULL, 0, RULES_DIRS);
|
||||
if (!strv_isempty(extra)) {
|
||||
directories = strv_copy(extra);
|
||||
if (!directories)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = strv_extend_strv(&directories, CONF_PATHS_STRV("udev/rules.d"), /* filter_duplicates = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = conf_files_list_strv(&files, ".rules", NULL, 0, (const char* const*) directories);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to enumerate rules files: %m");
|
||||
|
||||
|
@ -14,7 +14,7 @@ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos, bool *
|
||||
int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_checks, UdevRuleFile **ret);
|
||||
unsigned udev_rule_file_get_issues(UdevRuleFile *rule_file);
|
||||
UdevRules* udev_rules_new(ResolveNameTiming resolve_name_timing);
|
||||
int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing);
|
||||
int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing, char * const *extra);
|
||||
UdevRules* udev_rules_free(UdevRules *rules);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRules*, udev_rules_free);
|
||||
#define udev_rules_free_and_replace(a, b) free_and_replace_full(a, b, udev_rules_free)
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "sd-device.h"
|
||||
|
||||
#include "device-private.h"
|
||||
#include "parse-argument.h"
|
||||
#include "static-destruct.h"
|
||||
#include "strv.h"
|
||||
#include "udev-builtin.h"
|
||||
#include "udev-dump.h"
|
||||
#include "udev-event.h"
|
||||
@ -20,8 +23,11 @@
|
||||
static sd_device_action_t arg_action = SD_DEVICE_ADD;
|
||||
static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
|
||||
static const char *arg_syspath = NULL;
|
||||
static char **arg_extra_rules_dir = NULL;
|
||||
static bool arg_verbose = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_extra_rules_dir, strv_freep);
|
||||
|
||||
static int help(void) {
|
||||
|
||||
printf("%s test [OPTIONS] DEVPATH\n\n"
|
||||
@ -30,6 +36,7 @@ static int help(void) {
|
||||
" -V --version Show package version\n"
|
||||
" -a --action=ACTION|help Set action string\n"
|
||||
" -N --resolve-names=early|late|never When to resolve names\n"
|
||||
" -D --extra-rules-dir=DIR Also load rules from the directory\n"
|
||||
" -v --verbose Show verbose logs\n",
|
||||
program_invocation_short_name);
|
||||
|
||||
@ -38,17 +45,18 @@ static int help(void) {
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
static const struct option options[] = {
|
||||
{ "action", required_argument, NULL, 'a' },
|
||||
{ "resolve-names", required_argument, NULL, 'N' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "action", required_argument, NULL, 'a' },
|
||||
{ "resolve-names", required_argument, NULL, 'N' },
|
||||
{ "extra-rules-dir", required_argument, NULL, 'D' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{}
|
||||
};
|
||||
|
||||
int r, c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "a:N:vVh", options, NULL)) >= 0)
|
||||
while ((c = getopt_long(argc, argv, "a:N:D:vVh", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
case 'a':
|
||||
r = parse_device_action(optarg, &arg_action);
|
||||
@ -63,6 +71,18 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"--resolve-names= must be early, late or never");
|
||||
break;
|
||||
case 'D': {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
r = parse_path_argument(optarg, /* suppress_root = */ false, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strv_consume(&arg_extra_rules_dir, TAKE_PTR(p));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
break;
|
||||
}
|
||||
case 'v':
|
||||
arg_verbose = true;
|
||||
break;
|
||||
@ -108,7 +128,7 @@ int test_main(int argc, char *argv[], void *userdata) {
|
||||
puts("Loading builtins done.");
|
||||
|
||||
puts("\nLoading udev rules files...");
|
||||
r = udev_rules_load(&rules, arg_resolve_name_timing);
|
||||
r = udev_rules_load(&rules, arg_resolve_name_timing, arg_extra_rules_dir);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to read udev rules: %m");
|
||||
goto out;
|
||||
|
Loading…
x
Reference in New Issue
Block a user