Coverage Report

Created: 2025-11-16 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/systemd/src/udev/udev-builtin.c
Line
Count
Source
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3
#include <getopt.h>
4
#include <stdio.h>
5
6
#include "alloc-util.h"
7
#include "bitfield.h"
8
#include "device-private.h"
9
#include "device-util.h"
10
#include "extract-word.h"
11
#include "string-util.h"
12
#include "strv.h"
13
#include "udev-builtin.h"
14
15
static const UdevBuiltin *const builtins[_UDEV_BUILTIN_MAX] = {
16
#if HAVE_BLKID
17
        [UDEV_BUILTIN_BLKID]         = &udev_builtin_blkid,
18
#endif
19
        [UDEV_BUILTIN_BTRFS]         = &udev_builtin_btrfs,
20
        [UDEV_BUILTIN_DISSECT_IMAGE] = &udev_builtin_dissect_image,
21
        [UDEV_BUILTIN_FACTORY_RESET] = &udev_builtin_factory_reset,
22
        [UDEV_BUILTIN_HWDB]          = &udev_builtin_hwdb,
23
        [UDEV_BUILTIN_INPUT_ID]      = &udev_builtin_input_id,
24
        [UDEV_BUILTIN_KEYBOARD]      = &udev_builtin_keyboard,
25
#if HAVE_KMOD
26
        [UDEV_BUILTIN_KMOD]          = &udev_builtin_kmod,
27
#endif
28
        [UDEV_BUILTIN_NET_DRIVER]    = &udev_builtin_net_driver,
29
        [UDEV_BUILTIN_NET_ID]        = &udev_builtin_net_id,
30
        [UDEV_BUILTIN_NET_LINK]      = &udev_builtin_net_setup_link,
31
        [UDEV_BUILTIN_PATH_ID]       = &udev_builtin_path_id,
32
#if HAVE_ACL
33
        [UDEV_BUILTIN_UACCESS]       = &udev_builtin_uaccess,
34
#endif
35
        [UDEV_BUILTIN_USB_ID]        = &udev_builtin_usb_id,
36
};
37
38
0
void udev_builtin_init(void) {
39
0
        FOREACH_ELEMENT(b, builtins)
40
0
                if (*b && (*b)->init)
41
0
                        (*b)->init();
42
0
}
43
44
0
void udev_builtin_exit(void) {
45
0
        FOREACH_ELEMENT(b, builtins)
46
0
                if (*b && (*b)->exit)
47
0
                        (*b)->exit();
48
0
}
49
50
0
UdevReloadFlags udev_builtin_should_reload(void) {
51
0
        UdevReloadFlags flags = 0;
52
53
0
        for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++)
54
0
                if (builtins[i] && builtins[i]->should_reload && builtins[i]->should_reload())
55
0
                        flags |= 1u << i;
56
57
0
        if (flags != 0)
58
0
                flags |= UDEV_RELOAD_KILL_WORKERS;
59
60
0
        return flags;
61
0
}
62
63
0
void udev_builtin_reload(UdevReloadFlags flags) {
64
0
        for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++) {
65
0
                if (!BIT_SET(flags, i) || !builtins[i])
66
0
                        continue;
67
0
                if (builtins[i]->exit)
68
0
                        builtins[i]->exit();
69
0
                if (builtins[i]->init)
70
0
                        builtins[i]->init();
71
0
        }
72
0
}
73
74
0
void udev_builtin_list(void) {
75
0
        FOREACH_ELEMENT(b, builtins)
76
0
                if (*b)
77
0
                        fprintf(stderr, "  %-14s  %s\n", (*b)->name, (*b)->help);
78
0
}
79
80
0
const char* udev_builtin_name(UdevBuiltinCommand cmd) {
81
0
        assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX);
82
83
0
        if (!builtins[cmd])
84
0
                return NULL;
85
86
0
        return builtins[cmd]->name;
87
0
}
88
89
0
bool udev_builtin_run_once(UdevBuiltinCommand cmd) {
90
0
        assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX);
91
92
0
        if (!builtins[cmd])
93
0
                return false;
94
95
0
        return builtins[cmd]->run_once;
96
0
}
97
98
1.41k
UdevBuiltinCommand udev_builtin_lookup(const char *command) {
99
1.41k
        size_t n;
100
101
1.41k
        assert(command);
102
103
1.41k
        command += strspn(command, WHITESPACE);
104
1.41k
        n = strcspn(command, WHITESPACE);
105
10.1k
        for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++)
106
9.38k
                if (builtins[i] && strneq(builtins[i]->name, command, n))
107
629
                        return i;
108
109
787
        return _UDEV_BUILTIN_INVALID;
110
1.41k
}
111
112
0
int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command) {
113
0
        _cleanup_strv_free_ char **argv = NULL;
114
0
        int r;
115
116
0
        assert(event);
117
0
        assert(event->dev);
118
0
        assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX);
119
0
        assert(command);
120
121
0
        if (!builtins[cmd])
122
0
                return -EOPNOTSUPP;
123
124
0
        r = strv_split_full(&argv, command, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE);
125
0
        if (r < 0)
126
0
                return r;
127
128
        /* we need '0' here to reset the internal state */
129
0
        optind = 0;
130
0
        return builtins[cmd]->cmd(event, strv_length(argv), argv);
131
0
}
132
133
0
int udev_builtin_add_property(UdevEvent *event, const char *key, const char *val) {
134
0
        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
135
0
        int r;
136
137
0
        assert(key);
138
139
0
        r = device_add_property(dev, key, val);
140
0
        if (r < 0)
141
0
                return log_device_debug_errno(dev, r, "Failed to add property '%s%s%s'",
142
0
                                              key, val ? "=" : "", strempty(val));
143
144
0
        if (event->event_mode == EVENT_UDEVADM_TEST_BUILTIN)
145
0
                printf("%s=%s\n", key, strempty(val));
146
147
0
        return 0;
148
0
}
149
150
0
int udev_builtin_add_propertyf(UdevEvent *event, const char *key, const char *valf, ...) {
151
0
        _cleanup_free_ char *val = NULL;
152
0
        va_list ap;
153
0
        int r;
154
155
0
        assert(event);
156
0
        assert(key);
157
0
        assert(valf);
158
159
0
        va_start(ap, valf);
160
0
        r = vasprintf(&val, valf, ap);
161
0
        va_end(ap);
162
0
        if (r < 0)
163
0
                return log_oom_debug();
164
165
0
        return udev_builtin_add_property(event, key, val);
166
0
}
167
168
0
int udev_builtin_import_property(UdevEvent *event, const char *key) {
169
0
        const char *val;
170
0
        int r;
171
172
0
        assert(event);
173
0
        assert(event->dev);
174
175
0
        if (!event->dev_db_clone)
176
0
                return 0;
177
178
0
        r = sd_device_get_property_value(event->dev_db_clone, key, &val);
179
0
        if (r == -ENOENT)
180
0
                return 0;
181
0
        if (r < 0)
182
0
                return log_device_debug_errno(event->dev_db_clone, r, "Failed to get property \"%s\", ignoring: %m", key);
183
184
0
        r = udev_builtin_add_property(event, key, val);
185
0
        if (r < 0)
186
0
                return r;
187
188
0
        return 1;
189
0
}