]>
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" | |
03b6879f | 19 | #include "format-util.h" |
25f3b272 | 20 | #include "path-util.h" |
07630cea | 21 | #include "string-util.h" |
03b6879f | 22 | #include "strv.h" |
5ea78a39 | 23 | #include "strxcpyx.h" |
03b6879f | 24 | #include "terminal-util.h" |
07a26e42 | 25 | #include "udev-builtin.h" |
25de7aa7 | 26 | #include "udev-event.h" |
0b76cc2f | 27 | #include "udev-format.h" |
d1429d8f | 28 | #include "udevadm-util.h" |
3d05193e | 29 | #include "udevadm.h" |
03b6879f | 30 | #include "user-util.h" |
bb051f66 | 31 | |
d1429d8f | 32 | static sd_device_action_t arg_action = SD_DEVICE_ADD; |
c4d44cba | 33 | static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY; |
d1429d8f | 34 | static const char *arg_syspath = NULL; |
89e94ad3 YW |
35 | |
36 | static int help(void) { | |
5ac0162c | 37 | |
5639df9a YW |
38 | printf("%s test [OPTIONS] DEVPATH\n\n" |
39 | "Test an event run.\n\n" | |
5ac0162c | 40 | " -h --help Show this help\n" |
5639df9a | 41 | " -V --version Show package version\n" |
6d22bd87 | 42 | " -a --action=ACTION|help Set action string\n" |
bc556335 DDM |
43 | " -N --resolve-names=early|late|never When to resolve names\n", |
44 | program_invocation_short_name); | |
5ac0162c | 45 | |
89e94ad3 YW |
46 | return 0; |
47 | } | |
912541b0 | 48 | |
89e94ad3 | 49 | static int parse_argv(int argc, char *argv[]) { |
912541b0 | 50 | static const struct option options[] = { |
5639df9a | 51 | { "action", required_argument, NULL, 'a' }, |
912541b0 | 52 | { "resolve-names", required_argument, NULL, 'N' }, |
5639df9a YW |
53 | { "version", no_argument, NULL, 'V' }, |
54 | { "help", no_argument, NULL, 'h' }, | |
912541b0 KS |
55 | {} |
56 | }; | |
57 | ||
6de7fa87 | 58 | int r, c; |
912541b0 | 59 | |
5639df9a | 60 | while ((c = getopt_long(argc, argv, "a:N:Vh", options, NULL)) >= 0) |
7643ac9a | 61 | switch (c) { |
6de7fa87 YW |
62 | case 'a': |
63 | r = parse_device_action(optarg, &arg_action); | |
64 | if (r < 0) | |
65 | return log_error_errno(r, "Invalid action '%s'", optarg); | |
66 | if (r == 0) | |
6d22bd87 | 67 | return 0; |
912541b0 KS |
68 | break; |
69 | case 'N': | |
c4d44cba | 70 | arg_resolve_name_timing = resolve_name_timing_from_string(optarg); |
baaa35ad ZJS |
71 | if (arg_resolve_name_timing < 0) |
72 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), | |
73 | "--resolve-names= must be early, late or never"); | |
912541b0 | 74 | break; |
5639df9a | 75 | case 'V': |
51b006e1 | 76 | return print_version(); |
912541b0 | 77 | case 'h': |
89e94ad3 | 78 | return help(); |
7643ac9a | 79 | case '?': |
89e94ad3 | 80 | return -EINVAL; |
7643ac9a | 81 | default: |
04499a70 | 82 | assert_not_reached(); |
912541b0 | 83 | } |
912541b0 | 84 | |
d1429d8f YW |
85 | arg_syspath = argv[optind]; |
86 | if (!arg_syspath) | |
87 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "syspath parameter missing."); | |
89e94ad3 YW |
88 | |
89 | return 1; | |
90 | } | |
91 | ||
92 | int test_main(int argc, char *argv[], void *userdata) { | |
9a07157d | 93 | _cleanup_(udev_rules_freep) UdevRules *rules = NULL; |
2e088715 | 94 | _cleanup_(udev_event_freep) UdevEvent *event = NULL; |
77ad202c | 95 | _cleanup_(sd_device_unrefp) sd_device *dev = NULL; |
89e94ad3 YW |
96 | sigset_t mask, sigmask_orig; |
97 | int r; | |
98 | ||
aa976d87 | 99 | log_setup(); |
89e94ad3 YW |
100 | |
101 | r = parse_argv(argc, argv); | |
102 | if (r <= 0) | |
103 | return r; | |
104 | ||
baa30fbc | 105 | printf("This program is for debugging only, it does not run any program\n" |
912541b0 KS |
106 | "specified by a RUN key. It may show incorrect results, because\n" |
107 | "some values may be different, or not available at a simulation run.\n" | |
108 | "\n"); | |
109 | ||
babdf0d3 | 110 | assert_se(sigprocmask(SIG_SETMASK, NULL, &sigmask_orig) >= 0); |
912541b0 | 111 | |
2024ed61 | 112 | udev_builtin_init(); |
912541b0 | 113 | |
c238a1f5 | 114 | r = udev_rules_load(&rules, arg_resolve_name_timing); |
1d791281 ZJS |
115 | if (r < 0) { |
116 | log_error_errno(r, "Failed to read udev rules: %m"); | |
912541b0 KS |
117 | goto out; |
118 | } | |
119 | ||
d1429d8f | 120 | r = find_device_with_action(arg_syspath, arg_action, &dev); |
77ad202c YW |
121 | if (r < 0) { |
122 | log_error_errno(r, "Failed to open device '%s': %m", arg_syspath); | |
912541b0 KS |
123 | goto out; |
124 | } | |
125 | ||
bf0e00ec | 126 | /* don't read info from the db */ |
77ad202c | 127 | device_seal(dev); |
912541b0 | 128 | |
089bef66 | 129 | event = udev_event_new(dev, NULL, EVENT_UDEVADM_TEST); |
912541b0 | 130 | |
a3ebe5eb YW |
131 | assert_se(sigfillset(&mask) >= 0); |
132 | assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0); | |
912541b0 | 133 | |
eb1a51b8 | 134 | udev_event_execute_rules(event, rules); |
912541b0 | 135 | |
03b6879f | 136 | printf("%sProperties:%s\n", ansi_highlight(), ansi_normal()); |
77ad202c | 137 | FOREACH_DEVICE_PROPERTY(dev, key, value) |
03b6879f | 138 | printf(" %s=%s\n", key, value); |
912541b0 | 139 | |
03b6879f YW |
140 | if (sd_device_get_tag_first(dev)) { |
141 | printf("%sTags:%s\n", ansi_highlight(), ansi_normal()); | |
142 | FOREACH_DEVICE_TAG(dev, tag) | |
143 | printf(" %s\n", tag); | |
144 | } | |
145 | ||
146 | if (sd_device_get_devnum(dev, NULL) >= 0) { | |
147 | ||
148 | if (sd_device_get_devlink_first(dev)) { | |
149 | int prio; | |
150 | device_get_devlink_priority(dev, &prio); | |
151 | printf("%sDevice node symlinks:%s (priority=%i)\n", ansi_highlight(), ansi_normal(), prio); | |
152 | FOREACH_DEVICE_DEVLINK(dev, devlink) | |
153 | printf(" %s\n", devlink); | |
154 | } | |
155 | ||
156 | printf("%sInotify watch:%s\n %s\n", ansi_highlight(), ansi_normal(), enabled_disabled(event->inotify_watch)); | |
157 | ||
158 | uid_t uid = event->uid; | |
159 | if (!uid_is_valid(uid)) | |
160 | (void) device_get_devnode_uid(dev, &uid); | |
161 | if (uid_is_valid(uid)) { | |
162 | _cleanup_free_ char *user = uid_to_name(uid); | |
163 | printf("%sDevice node owner:%s\n %s (uid="UID_FMT")\n", ansi_highlight(), ansi_normal(), strna(user), uid); | |
164 | } | |
165 | ||
166 | gid_t gid = event->gid; | |
167 | if (!gid_is_valid(uid)) | |
168 | (void) device_get_devnode_gid(dev, &gid); | |
169 | if (gid_is_valid(gid)) { | |
170 | _cleanup_free_ char *group = gid_to_name(gid); | |
171 | printf("%sDevice node group:%s\n %s (gid="GID_FMT")\n", ansi_highlight(), ansi_normal(), strna(group), gid); | |
172 | } | |
173 | ||
174 | mode_t mode = event->mode; | |
175 | if (mode == MODE_INVALID) | |
176 | (void) device_get_devnode_mode(dev, &mode); | |
177 | if (mode != MODE_INVALID) | |
178 | printf("%sDevice node permission:%s\n %04o\n", ansi_highlight(), ansi_normal(), mode); | |
e17e438e YW |
179 | |
180 | if (!ordered_hashmap_isempty(event->seclabel_list)) { | |
181 | const char *name, *label; | |
182 | printf("%sDevice node security label:%s\n", ansi_highlight(), ansi_normal()); | |
183 | ORDERED_HASHMAP_FOREACH_KEY(label, name, event->seclabel_list) | |
184 | printf(" %s : %s\n", name, label); | |
185 | } | |
03b6879f YW |
186 | } |
187 | ||
188 | if (sd_device_get_ifindex(dev, NULL) >= 0) { | |
189 | if (!isempty(event->name)) | |
6a363a83 | 190 | printf("%sNetwork interface name:%s\n %s\n", ansi_highlight(), ansi_normal(), event->name); |
912541b0 | 191 | |
03b6879f YW |
192 | if (!strv_isempty(event->altnames)) { |
193 | bool space = true; | |
194 | printf("%sAlternative interface names:%s", ansi_highlight(), ansi_normal()); | |
195 | fputstrv(stdout, event->altnames, "\n ", &space); | |
196 | puts(""); | |
197 | } | |
198 | } | |
199 | ||
200 | if (!ordered_hashmap_isempty(event->run_list)) { | |
201 | void *val; | |
202 | const char *command; | |
203 | printf("%sQueued commands:%s\n", ansi_highlight(), ansi_normal()); | |
204 | ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list) { | |
205 | UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val); | |
206 | ||
207 | if (builtin_cmd != _UDEV_BUILTIN_INVALID) | |
208 | printf(" RUN{builtin} : %s\n", command); | |
209 | else | |
210 | printf(" RUN{program} : %s\n", command); | |
211 | } | |
912541b0 | 212 | } |
89e94ad3 YW |
213 | |
214 | r = 0; | |
2181d30a | 215 | out: |
2024ed61 | 216 | udev_builtin_exit(); |
89e94ad3 | 217 | return r; |
bb051f66 | 218 | } |