Bug Summary

File:build-scan/../src/libsystemd/sd-device/device-enumerator.c
Warning:line 141, column 33
Potential leak of memory pointed to by 'sysattr'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name device-enumerator.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/libsystemd/libsystemd_static.a.p -I src/libsystemd -I ../src/libsystemd -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/libsystemd/sd-device/device-enumerator.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include "sd-device.h"
4
5#include "alloc-util.h"
6#include "device-enumerator-private.h"
7#include "device-util.h"
8#include "dirent-util.h"
9#include "fd-util.h"
10#include "prioq.h"
11#include "set.h"
12#include "string-util.h"
13#include "strv.h"
14#include "util.h"
15
16#define DEVICE_ENUMERATE_MAX_DEPTH256 256
17
18typedef enum DeviceEnumerationType {
19 DEVICE_ENUMERATION_TYPE_DEVICES,
20 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS,
21 _DEVICE_ENUMERATION_TYPE_MAX,
22 _DEVICE_ENUMERATION_TYPE_INVALID = -1,
23} DeviceEnumerationType;
24
25struct sd_device_enumerator {
26 unsigned n_ref;
27
28 DeviceEnumerationType type;
29 Prioq *devices;
30 bool_Bool scan_uptodate;
31
32 Set *match_subsystem;
33 Set *nomatch_subsystem;
34 Hashmap *match_sysattr;
35 Hashmap *nomatch_sysattr;
36 Hashmap *match_property;
37 Set *match_sysname;
38 Set *match_tag;
39 sd_device *match_parent;
40 bool_Bool match_allow_uninitialized;
41};
42
43_public___attribute__ ((visibility("default"))) int sd_device_enumerator_new(sd_device_enumerator **ret) {
44 _cleanup_(sd_device_enumerator_unrefp)__attribute__((cleanup(sd_device_enumerator_unrefp))) sd_device_enumerator *enumerator = NULL((void*)0);
45
46 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-device/device-enumerator.c"
, 46, __PRETTY_FUNCTION__); } while (0)
;
47
48 enumerator = new0(sd_device_enumerator, 1)((sd_device_enumerator*) calloc((1), sizeof(sd_device_enumerator
)))
;
49 if (!enumerator)
50 return -ENOMEM12;
51
52 enumerator->n_ref = 1;
53 enumerator->type = _DEVICE_ENUMERATION_TYPE_INVALID;
54
55 *ret = TAKE_PTR(enumerator)({ typeof(enumerator) _ptr_ = (enumerator); (enumerator) = ((
void*)0); _ptr_; })
;
56
57 return 0;
58}
59
60_public___attribute__ ((visibility("default"))) sd_device_enumerator *sd_device_enumerator_ref(sd_device_enumerator *enumerator) {
61 assert_return(enumerator, NULL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 61, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
62
63 assert_se((++ enumerator->n_ref) >= 2)do { if ((__builtin_expect(!!(!((++ enumerator->n_ref) >=
2)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("(++ enumerator->n_ref) >= 2"
), "../src/libsystemd/sd-device/device-enumerator.c", 63, __PRETTY_FUNCTION__
); } while (0)
;
64
65 return enumerator;
66}
67
68_public___attribute__ ((visibility("default"))) sd_device_enumerator *sd_device_enumerator_unref(sd_device_enumerator *enumerator) {
69 if (enumerator && (-- enumerator->n_ref) == 0) {
70 sd_device *device;
71
72 while ((device = prioq_pop(enumerator->devices)))
73 sd_device_unref(device);
74
75 prioq_free(enumerator->devices);
76
77 set_free_free(enumerator->match_subsystem);
78 set_free_free(enumerator->nomatch_subsystem);
79 hashmap_free_free_free(enumerator->match_sysattr);
80 hashmap_free_free_free(enumerator->nomatch_sysattr);
81 hashmap_free_free_free(enumerator->match_property);
82 set_free_free(enumerator->match_sysname);
83 set_free_free(enumerator->match_tag);
84 sd_device_unref(enumerator->match_parent);
85
86 free(enumerator);
87 }
88
89 return NULL((void*)0);
90}
91
92_public___attribute__ ((visibility("default"))) int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) {
93 Set **set;
94 int r;
95
96 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 96, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
97 assert_return(subsystem, -EINVAL)do { if (!(((__builtin_expect(!!(subsystem),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("subsystem"), "../src/libsystemd/sd-device/device-enumerator.c"
, 97, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
98
99 if (match)
100 set = &enumerator->match_subsystem;
101 else
102 set = &enumerator->nomatch_subsystem;
103
104 r = set_ensure_allocated(set, NULL)internal_set_ensure_allocated(set, ((void*)0) );
105 if (r < 0)
106 return r;
107
108 r = set_put_strdup(*set, subsystem);
109 if (r < 0)
110 return r;
111
112 enumerator->scan_uptodate = false0;
113
114 return 0;
115}
116
117_public___attribute__ ((visibility("default"))) int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *_sysattr, const char *_value, int match) {
118 _cleanup_free___attribute__((cleanup(freep))) char *sysattr = NULL((void*)0), *value = NULL((void*)0);
119 Hashmap **hashmap;
120 int r;
121
122 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 122, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1
Assuming 'enumerator' is non-null
2
'?' condition is true
3
Taking false branch
4
Loop condition is false. Exiting loop
123 assert_return(_sysattr, -EINVAL)do { if (!(((__builtin_expect(!!(_sysattr),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("_sysattr"), "../src/libsystemd/sd-device/device-enumerator.c"
, 123, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5
Assuming '_sysattr' is non-null
6
'?' condition is true
7
Taking false branch
8
Loop condition is false. Exiting loop
124
125 if (match)
9
Assuming 'match' is 0
10
Taking false branch
126 hashmap = &enumerator->match_sysattr;
127 else
128 hashmap = &enumerator->nomatch_sysattr;
129
130 r = hashmap_ensure_allocated(hashmap, NULL)internal_hashmap_ensure_allocated(hashmap, ((void*)0) );
131 if (r < 0)
11
Assuming 'r' is >= 0
12
Taking false branch
132 return r;
133
134 sysattr = strdup(_sysattr);
13
Memory is allocated
135 if (!sysattr)
14
Assuming 'sysattr' is non-null
15
Taking false branch
136 return -ENOMEM12;
137
138 if (_value) {
16
Assuming '_value' is non-null
17
Taking true branch
139 value = strdup(_value);
140 if (!value)
18
Assuming 'value' is null
19
Taking true branch
141 return -ENOMEM12;
20
Potential leak of memory pointed to by 'sysattr'
142 }
143
144 r = hashmap_put(*hashmap, sysattr, value);
145 if (r < 0)
146 return r;
147
148 sysattr = NULL((void*)0);
149 value = NULL((void*)0);
150
151 enumerator->scan_uptodate = false0;
152
153 return 0;
154}
155
156_public___attribute__ ((visibility("default"))) int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *_property, const char *_value) {
157 _cleanup_free___attribute__((cleanup(freep))) char *property = NULL((void*)0), *value = NULL((void*)0);
158 int r;
159
160 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 160, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
161 assert_return(_property, -EINVAL)do { if (!(((__builtin_expect(!!(_property),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("_property"), "../src/libsystemd/sd-device/device-enumerator.c"
, 161, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
162
163 r = hashmap_ensure_allocated(&enumerator->match_property, NULL)internal_hashmap_ensure_allocated(&enumerator->match_property
, ((void*)0) )
;
164 if (r < 0)
165 return r;
166
167 property = strdup(_property);
168 if (!property)
169 return -ENOMEM12;
170
171 if (_value) {
172 value = strdup(_value);
173 if (!value)
174 return -ENOMEM12;
175 }
176
177 r = hashmap_put(enumerator->match_property, property, value);
178 if (r < 0)
179 return r;
180
181 property = NULL((void*)0);
182 value = NULL((void*)0);
183
184 enumerator->scan_uptodate = false0;
185
186 return 0;
187}
188
189_public___attribute__ ((visibility("default"))) int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
190 int r;
191
192 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 192, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
193 assert_return(sysname, -EINVAL)do { if (!(((__builtin_expect(!!(sysname),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("sysname"), "../src/libsystemd/sd-device/device-enumerator.c"
, 193, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
194
195 r = set_ensure_allocated(&enumerator->match_sysname, NULL)internal_set_ensure_allocated(&enumerator->match_sysname
, ((void*)0) )
;
196 if (r < 0)
197 return r;
198
199 r = set_put_strdup(enumerator->match_sysname, sysname);
200 if (r < 0)
201 return r;
202
203 enumerator->scan_uptodate = false0;
204
205 return 0;
206}
207
208_public___attribute__ ((visibility("default"))) int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) {
209 int r;
210
211 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 211, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
212 assert_return(tag, -EINVAL)do { if (!(((__builtin_expect(!!(tag),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("tag"), "../src/libsystemd/sd-device/device-enumerator.c"
, 212, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
213
214 r = set_ensure_allocated(&enumerator->match_tag, NULL)internal_set_ensure_allocated(&enumerator->match_tag, (
(void*)0) )
;
215 if (r < 0)
216 return r;
217
218 r = set_put_strdup(enumerator->match_tag, tag);
219 if (r < 0)
220 return r;
221
222 enumerator->scan_uptodate = false0;
223
224 return 0;
225}
226
227_public___attribute__ ((visibility("default"))) int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent) {
228 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 228, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
229 assert_return(parent, -EINVAL)do { if (!(((__builtin_expect(!!(parent),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("parent"), "../src/libsystemd/sd-device/device-enumerator.c"
, 229, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
230
231 sd_device_unref(enumerator->match_parent);
232 enumerator->match_parent = sd_device_ref(parent);
233
234 enumerator->scan_uptodate = false0;
235
236 return 0;
237}
238
239_public___attribute__ ((visibility("default"))) int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) {
240 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 240, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
241
242 enumerator->match_allow_uninitialized = true1;
243
244 enumerator->scan_uptodate = false0;
245
246 return 0;
247}
248
249int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) {
250 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 250, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
251
252 enumerator->match_allow_uninitialized = false0;
253
254 enumerator->scan_uptodate = false0;
255
256 return 0;
257}
258
259static int device_compare(const void *_a, const void *_b) {
260 sd_device *a = (sd_device *)_a, *b = (sd_device *)_b;
261 const char *devpath_a, *devpath_b, *sound_a;
262 bool_Bool delay_a, delay_b;
263
264 assert_se(sd_device_get_devpath(a, &devpath_a) >= 0)do { if ((__builtin_expect(!!(!(sd_device_get_devpath(a, &
devpath_a) >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("sd_device_get_devpath(a, &devpath_a) >= 0"), "../src/libsystemd/sd-device/device-enumerator.c"
, 264, __PRETTY_FUNCTION__); } while (0)
;
265 assert_se(sd_device_get_devpath(b, &devpath_b) >= 0)do { if ((__builtin_expect(!!(!(sd_device_get_devpath(b, &
devpath_b) >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("sd_device_get_devpath(b, &devpath_b) >= 0"), "../src/libsystemd/sd-device/device-enumerator.c"
, 265, __PRETTY_FUNCTION__); } while (0)
;
266
267 sound_a = strstr(devpath_a, "/sound/card");
268 if (sound_a) {
269 /* For sound cards the control device must be enumerated last to
270 * make sure it's the final device node that gets ACLs applied.
271 * Applications rely on this fact and use ACL changes on the
272 * control node as an indicator that the ACL change of the
273 * entire sound card completed. The kernel makes this guarantee
274 * when creating those devices, and hence we should too when
275 * enumerating them. */
276 sound_a += STRLEN("/sound/card")(sizeof("""/sound/card""") - 1);
277 sound_a = strchr(sound_a, '/');
278
279 if (sound_a) {
280 unsigned prefix_len;
281
282 prefix_len = sound_a - devpath_a;
283
284 if (strncmp(devpath_a, devpath_b, prefix_len) == 0) {
285 const char *sound_b;
286
287 sound_b = devpath_b + prefix_len;
288
289 if (startswith(sound_a, "/controlC") &&
290 !startswith(sound_b, "/contolC"))
291 return 1;
292
293 if (!startswith(sound_a, "/controlC") &&
294 startswith(sound_b, "/controlC"))
295 return -1;
296 }
297 }
298 }
299
300 /* md and dm devices are enumerated after all other devices */
301 delay_a = strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-");
302 delay_b = strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-");
303 if (delay_a != delay_b)
304 return delay_a - delay_b;
305
306 return strcmp(devpath_a, devpath_b);
307}
308
309int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
310 int r;
311
312 assert_return(enumerator, -EINVAL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 312, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
313 assert_return(device, -EINVAL)do { if (!(((__builtin_expect(!!(device),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("device"), "../src/libsystemd/sd-device/device-enumerator.c"
, 313, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
314
315 r = prioq_ensure_allocated(&enumerator->devices, device_compare);
316 if (r < 0)
317 return r;
318
319 r = prioq_put(enumerator->devices, device, NULL((void*)0));
320 if (r < 0)
321 return r;
322
323 sd_device_ref(device);
324
325 return 0;
326}
327
328static bool_Bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
329 const char *value;
330 int r;
331
332 assert(device)do { if ((__builtin_expect(!!(!(device)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("device"), "../src/libsystemd/sd-device/device-enumerator.c"
, 332, __PRETTY_FUNCTION__); } while (0)
;
333 assert(sysattr)do { if ((__builtin_expect(!!(!(sysattr)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sysattr"), "../src/libsystemd/sd-device/device-enumerator.c"
, 333, __PRETTY_FUNCTION__); } while (0)
;
334
335 r = sd_device_get_sysattr_value(device, sysattr, &value);
336 if (r < 0)
337 return false0;
338
339 if (!match_value)
340 return true1;
341
342 if (fnmatch(match_value, value, 0) == 0)
343 return true1;
344
345 return false0;
346}
347
348static bool_Bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) {
349 const char *sysattr;
350 const char *value;
351 Iterator i;
352
353 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 353, __PRETTY_FUNCTION__); } while (0)
;
354 assert(device)do { if ((__builtin_expect(!!(!(device)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("device"), "../src/libsystemd/sd-device/device-enumerator.c"
, 354, __PRETTY_FUNCTION__); } while (0)
;
355
356 HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((enumerator->nomatch_sysattr
), &(i), (void**)&(value), (const void**) &(sysattr
)); )
357 if (match_sysattr_value(device, sysattr, value))
358 return false0;
359
360 HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((enumerator->match_sysattr
), &(i), (void**)&(value), (const void**) &(sysattr
)); )
361 if (!match_sysattr_value(device, sysattr, value))
362 return false0;
363
364 return true1;
365}
366
367static bool_Bool match_property(sd_device_enumerator *enumerator, sd_device *device) {
368 const char *property;
369 const char *value;
370 Iterator i;
371
372 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 372, __PRETTY_FUNCTION__); } while (0)
;
373 assert(device)do { if ((__builtin_expect(!!(!(device)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("device"), "../src/libsystemd/sd-device/device-enumerator.c"
, 373, __PRETTY_FUNCTION__); } while (0)
;
374
375 if (hashmap_isempty(enumerator->match_property))
376 return true1;
377
378 HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((enumerator->match_property
), &(i), (void**)&(value), (const void**) &(property
)); )
{
379 const char *property_dev, *value_dev;
380
381 FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev)for (property_dev = sd_device_get_property_first(device, &
(value_dev)); property_dev; property_dev = sd_device_get_property_next
(device, &(value_dev)))
{
382 if (fnmatch(property, property_dev, 0) != 0)
383 continue;
384
385 if (!value && !value_dev)
386 return true1;
387
388 if (!value || !value_dev)
389 continue;
390
391 if (fnmatch(value, value_dev, 0) == 0)
392 return true1;
393 }
394 }
395
396 return false0;
397}
398
399static bool_Bool match_tag(sd_device_enumerator *enumerator, sd_device *device) {
400 const char *tag;
401 Iterator i;
402
403 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 403, __PRETTY_FUNCTION__); } while (0)
;
404 assert(device)do { if ((__builtin_expect(!!(!(device)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("device"), "../src/libsystemd/sd-device/device-enumerator.c"
, 404, __PRETTY_FUNCTION__); } while (0)
;
405
406 SET_FOREACH(tag, enumerator->match_tag, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((enumerator->match_tag
), &(i), (void**)&(tag)); )
407 if (!sd_device_has_tag(device, tag))
408 return false0;
409
410 return true1;
411}
412
413static bool_Bool match_parent(sd_device_enumerator *enumerator, sd_device *device) {
414 const char *devpath, *devpath_dev;
415 int r;
416
417 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 417, __PRETTY_FUNCTION__); } while (0)
;
418 assert(device)do { if ((__builtin_expect(!!(!(device)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("device"), "../src/libsystemd/sd-device/device-enumerator.c"
, 418, __PRETTY_FUNCTION__); } while (0)
;
419
420 if (!enumerator->match_parent)
421 return true1;
422
423 r = sd_device_get_devpath(enumerator->match_parent, &devpath);
424 assert(r >= 0)do { if ((__builtin_expect(!!(!(r >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r >= 0"), "../src/libsystemd/sd-device/device-enumerator.c"
, 424, __PRETTY_FUNCTION__); } while (0)
;
425
426 r = sd_device_get_devpath(device, &devpath_dev);
427 assert(r >= 0)do { if ((__builtin_expect(!!(!(r >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r >= 0"), "../src/libsystemd/sd-device/device-enumerator.c"
, 427, __PRETTY_FUNCTION__); } while (0)
;
428
429 return startswith(devpath_dev, devpath);
430}
431
432static bool_Bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
433 const char *sysname_match;
434 Iterator i;
435
436 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 436, __PRETTY_FUNCTION__); } while (0)
;
437 assert(sysname)do { if ((__builtin_expect(!!(!(sysname)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sysname"), "../src/libsystemd/sd-device/device-enumerator.c"
, 437, __PRETTY_FUNCTION__); } while (0)
;
438
439 if (set_isempty(enumerator->match_sysname))
440 return true1;
441
442 SET_FOREACH(sysname_match, enumerator->match_sysname, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((enumerator->match_sysname
), &(i), (void**)&(sysname_match)); )
443 if (fnmatch(sysname_match, sysname, 0) == 0)
444 return true1;
445
446 return false0;
447}
448
449static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) {
450 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *dir = NULL((void*)0);
451 char *path;
452 struct dirent *dent;
453 int r = 0;
454
455 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 455, __PRETTY_FUNCTION__); } while (0)
;
456 assert(basedir)do { if ((__builtin_expect(!!(!(basedir)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("basedir"), "../src/libsystemd/sd-device/device-enumerator.c"
, 456, __PRETTY_FUNCTION__); } while (0)
;
457
458 path = strjoina("/sys/", basedir, "/")({ const char *_appendees_[] = { "/sys/", basedir, "/" }; char
*_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
459
460 if (subdir1)
461 path = strjoina(path, subdir1, "/")({ const char *_appendees_[] = { path, subdir1, "/" }; char *
_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
462
463 if (subdir2)
464 path = strjoina(path, subdir2, "/")({ const char *_appendees_[] = { path, subdir2, "/" }; char *
_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
465
466 dir = opendir(path);
467 if (!dir)
468 return -errno(*__errno_location ());
469
470 FOREACH_DIRENT_ALL(dent, dir, return -errno)for ((*__errno_location ()) = 0, dent = readdir(dir);; (*__errno_location
()) = 0, dent = readdir(dir)) if (!dent) { if ((*__errno_location
()) > 0) { return -(*__errno_location ()); } break; } else
{
471 _cleanup_(sd_device_unrefp)__attribute__((cleanup(sd_device_unrefp))) sd_device *device = NULL((void*)0);
472 char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1];
473 dev_t devnum;
474 int ifindex, initialized, k;
475
476 if (dent->d_name[0] == '.')
477 continue;
478
479 if (!match_sysname(enumerator, dent->d_name))
480 continue;
481
482 (void)sprintf(syspath, "%s%s", path, dent->d_name);
483
484 k = sd_device_new_from_syspath(&device, syspath);
485 if (k < 0) {
486 if (k != -ENODEV19)
487 /* this is necessarily racey, so ignore missing devices */
488 r = k;
489
490 continue;
491 }
492
493 k = sd_device_get_devnum(device, &devnum);
494 if (k < 0) {
495 r = k;
496 continue;
497 }
498
499 k = sd_device_get_ifindex(device, &ifindex);
500 if (k < 0) {
501 r = k;
502 continue;
503 }
504
505 k = sd_device_get_is_initialized(device, &initialized);
506 if (k < 0) {
507 r = k;
508 continue;
509 }
510
511 /*
512 * All devices with a device node or network interfaces
513 * possibly need udev to adjust the device node permission
514 * or context, or rename the interface before it can be
515 * reliably used from other processes.
516 *
517 * For now, we can only check these types of devices, we
518 * might not store a database, and have no way to find out
519 * for all other types of devices.
520 */
521 if (!enumerator->match_allow_uninitialized &&
522 !initialized &&
523 (major(devnum)gnu_dev_major (devnum) > 0 || ifindex > 0))
524 continue;
525
526 if (!match_parent(enumerator, device))
527 continue;
528
529 if (!match_tag(enumerator, device))
530 continue;
531
532 if (!match_property(enumerator, device))
533 continue;
534
535 if (!match_sysattr(enumerator, device))
536 continue;
537
538 k = device_enumerator_add_device(enumerator, device);
539 if (k < 0)
540 r = k;
541 }
542
543 return r;
544}
545
546static bool_Bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
547 const char *subsystem_match;
548 Iterator i;
549
550 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 550, __PRETTY_FUNCTION__); } while (0)
;
551
552 if (!subsystem)
553 return false0;
554
555 SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((enumerator->nomatch_subsystem
), &(i), (void**)&(subsystem_match)); )
556 if (fnmatch(subsystem_match, subsystem, 0) == 0)
557 return false0;
558
559 if (set_isempty(enumerator->match_subsystem))
560 return true1;
561
562 SET_FOREACH(subsystem_match, enumerator->match_subsystem, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((enumerator->match_subsystem
), &(i), (void**)&(subsystem_match)); )
563 if (fnmatch(subsystem_match, subsystem, 0) == 0)
564 return true1;
565
566 return false0;
567}
568
569static int enumerator_scan_dir(sd_device_enumerator *enumerator, const char *basedir, const char *subdir, const char *subsystem) {
570 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *dir = NULL((void*)0);
571 char *path;
572 struct dirent *dent;
573 int r = 0;
574
575 path = strjoina("/sys/", basedir)({ const char *_appendees_[] = { "/sys/", basedir }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
576
577 dir = opendir(path);
578 if (!dir)
579 return -errno(*__errno_location ());
580
581 log_debug(" device-enumerator: scanning %s", path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 581, __func__
, " device-enumerator: scanning %s", path) : -abs(_e); })
;
582
583 FOREACH_DIRENT_ALL(dent, dir, return -errno)for ((*__errno_location ()) = 0, dent = readdir(dir);; (*__errno_location
()) = 0, dent = readdir(dir)) if (!dent) { if ((*__errno_location
()) > 0) { return -(*__errno_location ()); } break; } else
{
584 int k;
585
586 if (dent->d_name[0] == '.')
587 continue;
588
589 if (!match_subsystem(enumerator, subsystem ? : dent->d_name))
590 continue;
591
592 k = enumerator_scan_dir_and_add_devices(enumerator, basedir, dent->d_name, subdir);
593 if (k < 0)
594 r = k;
595 }
596
597 return r;
598}
599
600static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const char *tag) {
601 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *dir = NULL((void*)0);
602 char *path;
603 struct dirent *dent;
604 int r = 0;
605
606 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 606, __PRETTY_FUNCTION__); } while (0)
;
607 assert(tag)do { if ((__builtin_expect(!!(!(tag)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("tag"), "../src/libsystemd/sd-device/device-enumerator.c"
, 607, __PRETTY_FUNCTION__); } while (0)
;
608
609 path = strjoina("/run/udev/tags/", tag)({ const char *_appendees_[] = { "/run/udev/tags/", tag }; char
*_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
610
611 dir = opendir(path);
612 if (!dir) {
613 if (errno(*__errno_location ()) == ENOENT2)
614 return 0;
615 else
616 return log_error_errno(errno, "sd-device-enumerator: could not open tags directory %s: %m", path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/libsystemd/sd-device/device-enumerator.c"
, 616, __func__, "sd-device-enumerator: could not open tags directory %s: %m"
, path) : -abs(_e); })
;
617 }
618
619 /* TODO: filter away subsystems? */
620
621 FOREACH_DIRENT_ALL(dent, dir, return -errno)for ((*__errno_location ()) = 0, dent = readdir(dir);; (*__errno_location
()) = 0, dent = readdir(dir)) if (!dent) { if ((*__errno_location
()) > 0) { return -(*__errno_location ()); } break; } else
{
622 _cleanup_(sd_device_unrefp)__attribute__((cleanup(sd_device_unrefp))) sd_device *device = NULL((void*)0);
623 const char *subsystem, *sysname;
624 int k;
625
626 if (dent->d_name[0] == '.')
627 continue;
628
629 k = sd_device_new_from_device_id(&device, dent->d_name);
630 if (k < 0) {
631 if (k != -ENODEV19)
632 /* this is necessarily racy, so ignore missing devices */
633 r = k;
634
635 continue;
636 }
637
638 k = sd_device_get_subsystem(device, &subsystem);
639 if (k < 0) {
640 r = k;
641 continue;
642 }
643
644 if (!match_subsystem(enumerator, subsystem))
645 continue;
646
647 k = sd_device_get_sysname(device, &sysname);
648 if (k < 0) {
649 r = k;
650 continue;
651 }
652
653 if (!match_sysname(enumerator, sysname))
654 continue;
655
656 if (!match_parent(enumerator, device))
657 continue;
658
659 if (!match_property(enumerator, device))
660 continue;
661
662 if (!match_sysattr(enumerator, device))
663 continue;
664
665 k = device_enumerator_add_device(enumerator, device);
666 if (k < 0) {
667 r = k;
668 continue;
669 }
670 }
671
672 return r;
673}
674
675static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) {
676 const char *tag;
677 Iterator i;
678 int r = 0;
679
680 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 680, __PRETTY_FUNCTION__); } while (0)
;
681
682 SET_FOREACH(tag, enumerator->match_tag, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((enumerator->match_tag
), &(i), (void**)&(tag)); )
{
683 int k;
684
685 k = enumerator_scan_devices_tag(enumerator, tag);
686 if (k < 0)
687 r = k;
688 }
689
690 return r;
691}
692
693static int parent_add_child(sd_device_enumerator *enumerator, const char *path) {
694 _cleanup_(sd_device_unrefp)__attribute__((cleanup(sd_device_unrefp))) sd_device *device = NULL((void*)0);
695 const char *subsystem, *sysname;
696 int r;
697
698 r = sd_device_new_from_syspath(&device, path);
699 if (r == -ENODEV19)
700 /* this is necessarily racy, so ignore missing devices */
701 return 0;
702 else if (r < 0)
703 return r;
704
705 r = sd_device_get_subsystem(device, &subsystem);
706 if (r == -ENOENT2)
707 return 0;
708 if (r < 0)
709 return r;
710
711 if (!match_subsystem(enumerator, subsystem))
712 return 0;
713
714 r = sd_device_get_sysname(device, &sysname);
715 if (r < 0)
716 return r;
717
718 if (!match_sysname(enumerator, sysname))
719 return 0;
720
721 if (!match_property(enumerator, device))
722 return 0;
723
724 if (!match_sysattr(enumerator, device))
725 return 0;
726
727 r = device_enumerator_add_device(enumerator, device);
728 if (r < 0)
729 return r;
730
731 return 1;
732}
733
734static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) {
735 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *dir = NULL((void*)0);
736 struct dirent *dent;
737 int r = 0;
738
739 dir = opendir(path);
740 if (!dir)
741 return log_debug_errno(errno, "sd-device-enumerate: could not open parent directory %s: %m", path)({ int _level = ((7)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/libsystemd/sd-device/device-enumerator.c"
, 741, __func__, "sd-device-enumerate: could not open parent directory %s: %m"
, path) : -abs(_e); })
;
742
743 FOREACH_DIRENT_ALL(dent, dir, return -errno)for ((*__errno_location ()) = 0, dent = readdir(dir);; (*__errno_location
()) = 0, dent = readdir(dir)) if (!dent) { if ((*__errno_location
()) > 0) { return -(*__errno_location ()); } break; } else
{
744 _cleanup_free___attribute__((cleanup(freep))) char *child = NULL((void*)0);
745 int k;
746
747 if (dent->d_name[0] == '.')
748 continue;
749
750 if (dent->d_type != DT_DIRDT_DIR)
751 continue;
752
753 child = strjoin(path, "/", dent->d_name)strjoin_real((path), "/", dent->d_name, ((void*)0));
754 if (!child)
755 return -ENOMEM12;
756
757 k = parent_add_child(enumerator, child);
758 if (k < 0)
759 r = k;
760
761 if (maxdepth > 0)
762 parent_crawl_children(enumerator, child, maxdepth - 1);
763 else
764 log_debug("device-enumerate: max depth reached, %s: ignoring devices", child)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 764, __func__
, "device-enumerate: max depth reached, %s: ignoring devices"
, child) : -abs(_e); })
;
765 }
766
767 return r;
768}
769
770static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) {
771 const char *path;
772 int r = 0, k;
773
774 r = sd_device_get_syspath(enumerator->match_parent, &path);
775 if (r < 0)
776 return r;
777
778 k = parent_add_child(enumerator, path);
779 if (k < 0)
780 r = k;
781
782 k = parent_crawl_children(enumerator, path, DEVICE_ENUMERATE_MAX_DEPTH256);
783 if (k < 0)
784 r = k;
785
786 return r;
787}
788
789static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
790 int r = 0;
791
792 log_debug("device-enumerator: scan all dirs")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 792, __func__
, "device-enumerator: scan all dirs") : -abs(_e); })
;
793
794 if (access("/sys/subsystem", F_OK0) >= 0) {
795 /* we have /subsystem/, forget all the old stuff */
796 r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL((void*)0));
797 if (r < 0)
798 return log_debug_errno(r, "device-enumerator: failed to scan /sys/subsystem: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 798, __func__
, "device-enumerator: failed to scan /sys/subsystem: %m") : -
abs(_e); })
;
799 } else {
800 int k;
801
802 k = enumerator_scan_dir(enumerator, "bus", "devices", NULL((void*)0));
803 if (k < 0) {
804 log_debug_errno(k, "device-enumerator: failed to scan /sys/bus: %m")({ int _level = ((7)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 804, __func__
, "device-enumerator: failed to scan /sys/bus: %m") : -abs(_e
); })
;
805 r = k;
806 }
807
808 k = enumerator_scan_dir(enumerator, "class", NULL((void*)0), NULL((void*)0));
809 if (k < 0) {
810 log_debug_errno(k, "device-enumerator: failed to scan /sys/class: %m")({ int _level = ((7)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 810, __func__
, "device-enumerator: failed to scan /sys/class: %m") : -abs(
_e); })
;
811 r = k;
812 }
813 }
814
815 return r;
816}
817
818int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
819 sd_device *device;
820 int r = 0, k;
821
822 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 822, __PRETTY_FUNCTION__); } while (0)
;
823
824 if (enumerator->scan_uptodate &&
825 enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES)
826 return 0;
827
828 while ((device = prioq_pop(enumerator->devices)))
829 sd_device_unref(device);
830
831 if (!set_isempty(enumerator->match_tag)) {
832 k = enumerator_scan_devices_tags(enumerator);
833 if (k < 0)
834 r = k;
835 } else if (enumerator->match_parent) {
836 k = enumerator_scan_devices_children(enumerator);
837 if (k < 0)
838 r = k;
839 } else {
840 k = enumerator_scan_devices_all(enumerator);
841 if (k < 0)
842 r = k;
843 }
844
845 enumerator->scan_uptodate = true1;
846
847 return r;
848}
849
850_public___attribute__ ((visibility("default"))) sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) {
851 int r;
852
853 assert_return(enumerator, NULL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 853, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
854
855 r = device_enumerator_scan_devices(enumerator);
856 if (r < 0)
857 return NULL((void*)0);
858
859 enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES;
860
861 return prioq_peek(enumerator->devices);
862}
863
864_public___attribute__ ((visibility("default"))) sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) {
865 assert_return(enumerator, NULL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 865, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
866
867 if (!enumerator->scan_uptodate ||
868 enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES)
869 return NULL((void*)0);
870
871 sd_device_unref(prioq_pop(enumerator->devices));
872
873 return prioq_peek(enumerator->devices);
874}
875
876int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
877 sd_device *device;
878 const char *subsysdir;
879 int r = 0, k;
880
881 assert(enumerator)do { if ((__builtin_expect(!!(!(enumerator)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 881, __PRETTY_FUNCTION__); } while (0)
;
882
883 if (enumerator->scan_uptodate &&
884 enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
885 return 0;
886
887 while ((device = prioq_pop(enumerator->devices)))
888 sd_device_unref(device);
889
890 /* modules */
891 if (match_subsystem(enumerator, "module")) {
892 k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL((void*)0), NULL((void*)0));
893 if (k < 0) {
894 log_debug_errno(k, "device-enumerator: failed to scan modules: %m")({ int _level = ((7)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 894, __func__
, "device-enumerator: failed to scan modules: %m") : -abs(_e)
; })
;
895 r = k;
896 }
897 }
898
899 if (access("/sys/subsystem", F_OK0) >= 0)
900 subsysdir = "subsystem";
901 else
902 subsysdir = "bus";
903
904 /* subsystems (only buses support coldplug) */
905 if (match_subsystem(enumerator, "subsystem")) {
906 k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL((void*)0), NULL((void*)0));
907 if (k < 0) {
908 log_debug_errno(k, "device-enumerator: failed to scan subsystems: %m")({ int _level = ((7)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 908, __func__
, "device-enumerator: failed to scan subsystems: %m") : -abs(
_e); })
;
909 r = k;
910 }
911 }
912
913 /* subsystem drivers */
914 if (match_subsystem(enumerator, "drivers")) {
915 k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers");
916 if (k < 0) {
917 log_debug_errno(k, "device-enumerator: failed to scan drivers: %m")({ int _level = ((7)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-device/device-enumerator.c", 917, __func__
, "device-enumerator: failed to scan drivers: %m") : -abs(_e)
; })
;
918 r = k;
919 }
920 }
921
922 enumerator->scan_uptodate = true1;
923
924 return r;
925}
926
927_public___attribute__ ((visibility("default"))) sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) {
928 int r;
929
930 assert_return(enumerator, NULL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 930, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
931
932 r = device_enumerator_scan_subsystems(enumerator);
933 if (r < 0)
934 return NULL((void*)0);
935
936 enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS;
937
938 return prioq_peek(enumerator->devices);
939}
940
941_public___attribute__ ((visibility("default"))) sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) {
942 assert_return(enumerator, NULL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 942, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
943
944 if (enumerator->scan_uptodate ||
945 enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
946 return NULL((void*)0);
947
948 sd_device_unref(prioq_pop(enumerator->devices));
949
950 return prioq_peek(enumerator->devices);
951}
952
953sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) {
954 assert_return(enumerator, NULL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 954, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
955
956 return prioq_peek(enumerator->devices);
957}
958
959sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) {
960 assert_return(enumerator, NULL)do { if (!(((__builtin_expect(!!(enumerator),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("enumerator"), "../src/libsystemd/sd-device/device-enumerator.c"
, 960, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
961
962 sd_device_unref(prioq_pop(enumerator->devices));
963
964 return prioq_peek(enumerator->devices);
965}