1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <errno.h>
4 #include <getopt.h>
5 #include <stddef.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 
9 #include "log.h"
10 #include "udev-builtin.h"
11 #include "udevadm.h"
12 #include "udevadm-util.h"
13 
14 static sd_device_action_t arg_action = SD_DEVICE_ADD;
15 static const char *arg_command = NULL;
16 static const char *arg_syspath = NULL;
17 
help(void)18 static int help(void) {
19         printf("%s test-builtin [OPTIONS] COMMAND DEVPATH\n\n"
20                "Test a built-in command.\n\n"
21                "  -h --help               Print this message\n"
22                "  -V --version            Print version of the program\n\n"
23                "  -a --action=ACTION|help Set action string\n"
24                "Commands:\n",
25                program_invocation_short_name);
26 
27         udev_builtin_list();
28 
29         return 0;
30 }
31 
parse_argv(int argc,char * argv[])32 static int parse_argv(int argc, char *argv[]) {
33         static const struct option options[] = {
34                 { "action",  required_argument, NULL, 'a' },
35                 { "version", no_argument,       NULL, 'V' },
36                 { "help",    no_argument,       NULL, 'h' },
37                 {}
38         };
39 
40         int r, c;
41 
42         while ((c = getopt_long(argc, argv, "a:Vh", options, NULL)) >= 0)
43                 switch (c) {
44                 case 'a':
45                         r = parse_device_action(optarg, &arg_action);
46                         if (r < 0)
47                                 return log_error_errno(r, "Invalid action '%s'", optarg);
48                         if (r == 0)
49                                 return 0;
50                         break;
51                 case 'V':
52                         return print_version();
53                 case 'h':
54                         return help();
55                 case '?':
56                         return -EINVAL;
57                 default:
58                         assert_not_reached();
59                 }
60 
61         arg_command = argv[optind++];
62         if (!arg_command)
63                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
64                                        "Command missing.");
65 
66         arg_syspath = argv[optind++];
67         if (!arg_syspath)
68                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
69                                        "device is missing.");
70 
71         return 1;
72 }
73 
builtin_main(int argc,char * argv[],void * userdata)74 int builtin_main(int argc, char *argv[], void *userdata) {
75         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
76         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
77         UdevBuiltinCommand cmd;
78         int r;
79 
80         log_set_max_level(LOG_DEBUG);
81 
82         r = parse_argv(argc, argv);
83         if (r <= 0)
84                 return r;
85 
86         udev_builtin_init();
87 
88         cmd = udev_builtin_lookup(arg_command);
89         if (cmd < 0) {
90                 log_error("Unknown command '%s'", arg_command);
91                 r = -EINVAL;
92                 goto finish;
93         }
94 
95         r = find_device_with_action(arg_syspath, arg_action, &dev);
96         if (r < 0) {
97                 log_error_errno(r, "Failed to open device '%s': %m", arg_syspath);
98                 goto finish;
99         }
100 
101         r = udev_builtin_run(dev, &rtnl, cmd, arg_command, true);
102         if (r < 0)
103                 log_debug_errno(r, "Builtin command '%s' fails: %m", arg_command);
104 
105 finish:
106         udev_builtin_exit();
107         return r;
108 }
109