]>
Commit | Line | Data |
---|---|---|
f13467ec | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
bb051f66 | 2 | /* |
810adae9 | 3 | * Copyright © 2003-2004 Greg Kroah-Hartman <greg@kroah.com> |
bb051f66 GKH |
4 | */ |
5 | ||
bb051f66 | 6 | #include <errno.h> |
eff4a673 | 7 | #include <getopt.h> |
07630cea LP |
8 | #include <signal.h> |
9 | #include <stddef.h> | |
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
2181d30a | 12 | #include <sys/signalfd.h> |
07630cea | 13 | #include <unistd.h> |
bb051f66 | 14 | |
77ad202c YW |
15 | #include "sd-device.h" |
16 | ||
17 | #include "device-private.h" | |
18 | #include "device-util.h" | |
25f3b272 | 19 | #include "path-util.h" |
07630cea | 20 | #include "string-util.h" |
5ea78a39 | 21 | #include "strxcpyx.h" |
07a26e42 | 22 | #include "udev-builtin.h" |
25de7aa7 | 23 | #include "udev-event.h" |
3d05193e | 24 | #include "udevadm.h" |
bb051f66 | 25 | |
89e94ad3 | 26 | static const char *arg_action = "add"; |
c4d44cba | 27 | static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY; |
c8eaaf69 | 28 | static char arg_syspath[UDEV_PATH_SIZE] = {}; |
89e94ad3 YW |
29 | |
30 | static int help(void) { | |
5ac0162c | 31 | |
5639df9a YW |
32 | printf("%s test [OPTIONS] DEVPATH\n\n" |
33 | "Test an event run.\n\n" | |
5ac0162c | 34 | " -h --help Show this help\n" |
5639df9a | 35 | " -V --version Show package version\n" |
6d22bd87 | 36 | " -a --action=ACTION|help Set action string\n" |
bc556335 DDM |
37 | " -N --resolve-names=early|late|never When to resolve names\n", |
38 | program_invocation_short_name); | |
5ac0162c | 39 | |
89e94ad3 YW |
40 | return 0; |
41 | } | |
912541b0 | 42 | |
89e94ad3 | 43 | static int parse_argv(int argc, char *argv[]) { |
912541b0 | 44 | static const struct option options[] = { |
5639df9a | 45 | { "action", required_argument, NULL, 'a' }, |
912541b0 | 46 | { "resolve-names", required_argument, NULL, 'N' }, |
5639df9a YW |
47 | { "version", no_argument, NULL, 'V' }, |
48 | { "help", no_argument, NULL, 'h' }, | |
912541b0 KS |
49 | {} |
50 | }; | |
51 | ||
89e94ad3 | 52 | int c; |
912541b0 | 53 | |
5639df9a | 54 | while ((c = getopt_long(argc, argv, "a:N:Vh", options, NULL)) >= 0) |
7643ac9a | 55 | switch (c) { |
a12b87f5 | 56 | case 'a': { |
a1130022 | 57 | sd_device_action_t a; |
a12b87f5 | 58 | |
6d22bd87 YW |
59 | if (streq(optarg, "help")) { |
60 | dump_device_action_table(); | |
61 | return 0; | |
62 | } | |
63 | ||
a12b87f5 YW |
64 | a = device_action_from_string(optarg); |
65 | if (a < 0) | |
ff03bfa5 | 66 | return log_error_errno(a, "Invalid action '%s'", optarg); |
a12b87f5 | 67 | |
ff03bfa5 | 68 | arg_action = device_action_to_string(a); |
912541b0 | 69 | break; |
a12b87f5 | 70 | } |
912541b0 | 71 | case 'N': |
c4d44cba | 72 | arg_resolve_name_timing = resolve_name_timing_from_string(optarg); |
baaa35ad ZJS |
73 | if (arg_resolve_name_timing < 0) |
74 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), | |
75 | "--resolve-names= must be early, late or never"); | |
912541b0 | 76 | break; |
5639df9a | 77 | case 'V': |
51b006e1 | 78 | return print_version(); |
912541b0 | 79 | case 'h': |
89e94ad3 | 80 | return help(); |
7643ac9a | 81 | case '?': |
89e94ad3 | 82 | return -EINVAL; |
7643ac9a ZJS |
83 | default: |
84 | assert_not_reached("Unknown option"); | |
912541b0 | 85 | } |
912541b0 | 86 | |
baaa35ad ZJS |
87 | if (!argv[optind]) |
88 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), | |
89 | "syspath parameter missing."); | |
912541b0 | 90 | |
89e94ad3 | 91 | /* add /sys if needed */ |
25f3b272 | 92 | if (!path_startswith(argv[optind], "/sys")) |
89e94ad3 YW |
93 | strscpyl(arg_syspath, sizeof(arg_syspath), "/sys", argv[optind], NULL); |
94 | else | |
95 | strscpy(arg_syspath, sizeof(arg_syspath), argv[optind]); | |
96 | ||
97 | return 1; | |
98 | } | |
99 | ||
100 | int test_main(int argc, char *argv[], void *userdata) { | |
9a07157d | 101 | _cleanup_(udev_rules_freep) UdevRules *rules = NULL; |
2e088715 | 102 | _cleanup_(udev_event_freep) UdevEvent *event = NULL; |
77ad202c YW |
103 | _cleanup_(sd_device_unrefp) sd_device *dev = NULL; |
104 | const char *cmd, *key, *value; | |
89e94ad3 | 105 | sigset_t mask, sigmask_orig; |
29448498 | 106 | void *val; |
89e94ad3 YW |
107 | int r; |
108 | ||
109 | log_set_max_level(LOG_DEBUG); | |
110 | ||
111 | r = parse_argv(argc, argv); | |
112 | if (r <= 0) | |
113 | return r; | |
114 | ||
baa30fbc | 115 | printf("This program is for debugging only, it does not run any program\n" |
912541b0 KS |
116 | "specified by a RUN key. It may show incorrect results, because\n" |
117 | "some values may be different, or not available at a simulation run.\n" | |
118 | "\n"); | |
119 | ||
babdf0d3 | 120 | assert_se(sigprocmask(SIG_SETMASK, NULL, &sigmask_orig) >= 0); |
912541b0 | 121 | |
2024ed61 | 122 | udev_builtin_init(); |
912541b0 | 123 | |
c238a1f5 | 124 | r = udev_rules_load(&rules, arg_resolve_name_timing); |
1d791281 ZJS |
125 | if (r < 0) { |
126 | log_error_errno(r, "Failed to read udev rules: %m"); | |
912541b0 KS |
127 | goto out; |
128 | } | |
129 | ||
77ad202c YW |
130 | r = device_new_from_synthetic_event(&dev, arg_syspath, arg_action); |
131 | if (r < 0) { | |
132 | log_error_errno(r, "Failed to open device '%s': %m", arg_syspath); | |
912541b0 KS |
133 | goto out; |
134 | } | |
135 | ||
bf0e00ec | 136 | /* don't read info from the db */ |
77ad202c | 137 | device_seal(dev); |
912541b0 | 138 | |
1a0bd015 | 139 | event = udev_event_new(dev, 0, NULL, LOG_DEBUG); |
912541b0 | 140 | |
a3ebe5eb YW |
141 | assert_se(sigfillset(&mask) >= 0); |
142 | assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0); | |
912541b0 | 143 | |
df7ee959 | 144 | udev_event_execute_rules(event, -1, 60 * USEC_PER_SEC, SIGKILL, NULL, rules); |
912541b0 | 145 | |
77ad202c YW |
146 | FOREACH_DEVICE_PROPERTY(dev, key, value) |
147 | printf("%s=%s\n", key, value); | |
912541b0 | 148 | |
90e74a66 | 149 | ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list) { |
c8eaaf69 | 150 | char program[UDEV_PATH_SIZE]; |
912541b0 | 151 | |
5eb6ef8b | 152 | (void) udev_event_apply_format(event, cmd, program, sizeof(program), false); |
1ea97217 | 153 | printf("run: '%s'\n", program); |
912541b0 | 154 | } |
89e94ad3 YW |
155 | |
156 | r = 0; | |
2181d30a | 157 | out: |
2024ed61 | 158 | udev_builtin_exit(); |
89e94ad3 | 159 | return r; |
bb051f66 | 160 | } |