]>
Commit | Line | Data |
---|---|---|
e7145211 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
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" | |
5ea78a39 | 19 | #include "libudev-util.h" |
07630cea | 20 | #include "string-util.h" |
5ea78a39 | 21 | #include "strxcpyx.h" |
07a26e42 | 22 | #include "udev-builtin.h" |
07630cea | 23 | #include "udev.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; |
89e94ad3 YW |
28 | static char arg_syspath[UTIL_PATH_SIZE] = {}; |
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" |
5ac0162c LP |
36 | " -a --action=ACTION Set action string\n" |
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) { |
912541b0 | 56 | case 'a': |
89e94ad3 | 57 | arg_action = optarg; |
912541b0 KS |
58 | break; |
59 | case 'N': | |
c4d44cba | 60 | arg_resolve_name_timing = resolve_name_timing_from_string(optarg); |
baaa35ad ZJS |
61 | if (arg_resolve_name_timing < 0) |
62 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), | |
63 | "--resolve-names= must be early, late or never"); | |
912541b0 | 64 | break; |
5639df9a | 65 | case 'V': |
51b006e1 | 66 | return print_version(); |
912541b0 | 67 | case 'h': |
89e94ad3 | 68 | return help(); |
7643ac9a | 69 | case '?': |
89e94ad3 | 70 | return -EINVAL; |
7643ac9a ZJS |
71 | default: |
72 | assert_not_reached("Unknown option"); | |
912541b0 | 73 | } |
912541b0 | 74 | |
baaa35ad ZJS |
75 | if (!argv[optind]) |
76 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), | |
77 | "syspath parameter missing."); | |
912541b0 | 78 | |
89e94ad3 YW |
79 | /* add /sys if needed */ |
80 | if (!startswith(argv[optind], "/sys")) | |
81 | strscpyl(arg_syspath, sizeof(arg_syspath), "/sys", argv[optind], NULL); | |
82 | else | |
83 | strscpy(arg_syspath, sizeof(arg_syspath), argv[optind]); | |
84 | ||
85 | return 1; | |
86 | } | |
87 | ||
88 | int test_main(int argc, char *argv[], void *userdata) { | |
9a07157d | 89 | _cleanup_(udev_rules_freep) UdevRules *rules = NULL; |
2e088715 | 90 | _cleanup_(udev_event_freep) UdevEvent *event = NULL; |
77ad202c YW |
91 | _cleanup_(sd_device_unrefp) sd_device *dev = NULL; |
92 | const char *cmd, *key, *value; | |
89e94ad3 | 93 | sigset_t mask, sigmask_orig; |
29448498 YW |
94 | Iterator i; |
95 | void *val; | |
89e94ad3 YW |
96 | int r; |
97 | ||
98 | log_set_max_level(LOG_DEBUG); | |
99 | ||
100 | r = parse_argv(argc, argv); | |
101 | if (r <= 0) | |
102 | return r; | |
103 | ||
baa30fbc | 104 | printf("This program is for debugging only, it does not run any program\n" |
912541b0 KS |
105 | "specified by a RUN key. It may show incorrect results, because\n" |
106 | "some values may be different, or not available at a simulation run.\n" | |
107 | "\n"); | |
108 | ||
babdf0d3 | 109 | assert_se(sigprocmask(SIG_SETMASK, NULL, &sigmask_orig) >= 0); |
912541b0 | 110 | |
2024ed61 | 111 | udev_builtin_init(); |
912541b0 | 112 | |
1d791281 ZJS |
113 | r = udev_rules_new(&rules, arg_resolve_name_timing); |
114 | if (r < 0) { | |
115 | log_error_errno(r, "Failed to read udev rules: %m"); | |
912541b0 KS |
116 | goto out; |
117 | } | |
118 | ||
77ad202c YW |
119 | r = device_new_from_synthetic_event(&dev, arg_syspath, arg_action); |
120 | if (r < 0) { | |
121 | log_error_errno(r, "Failed to open device '%s': %m", arg_syspath); | |
912541b0 KS |
122 | goto out; |
123 | } | |
124 | ||
bf0e00ec | 125 | /* don't read info from the db */ |
77ad202c | 126 | device_seal(dev); |
912541b0 | 127 | |
77ad202c | 128 | event = udev_event_new(dev, 0, NULL); |
912541b0 | 129 | |
a3ebe5eb YW |
130 | assert_se(sigfillset(&mask) >= 0); |
131 | assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0); | |
912541b0 | 132 | |
66f737b4 | 133 | udev_event_execute_rules(event, 60 * USEC_PER_SEC, NULL, rules); |
912541b0 | 134 | |
77ad202c YW |
135 | FOREACH_DEVICE_PROPERTY(dev, key, value) |
136 | printf("%s=%s\n", key, value); | |
912541b0 | 137 | |
29448498 | 138 | HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) { |
1ea97217 | 139 | char program[UTIL_PATH_SIZE]; |
912541b0 | 140 | |
29448498 | 141 | udev_event_apply_format(event, cmd, program, sizeof(program), false); |
1ea97217 | 142 | printf("run: '%s'\n", program); |
912541b0 | 143 | } |
89e94ad3 YW |
144 | |
145 | r = 0; | |
2181d30a | 146 | out: |
2024ed61 | 147 | udev_builtin_exit(); |
89e94ad3 | 148 | return r; |
bb051f66 | 149 | } |