File: | build-scan/../src/libsystemd/sd-device/device-enumerator.c |
Warning: | line 141, column 33 Potential leak of memory pointed to by 'sysattr' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
18 | typedef 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 | ||||
25 | struct 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); | |||
| ||||
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); | |||
124 | ||||
125 | if (match) | |||
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) | |||
132 | return r; | |||
133 | ||||
134 | sysattr = strdup(_sysattr); | |||
135 | if (!sysattr) | |||
136 | return -ENOMEM12; | |||
137 | ||||
138 | if (_value) { | |||
139 | value = strdup(_value); | |||
140 | if (!value) | |||
141 | return -ENOMEM12; | |||
| ||||
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 | ||||
249 | int 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 | ||||
259 | static 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 | ||||
309 | int 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 | ||||
328 | static 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 | ||||
348 | static 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 | ||||
367 | static 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 | ||||
399 | static 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 | ||||
413 | static 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 | ||||
432 | static 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 | ||||
449 | static 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 | ||||
546 | static 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 | ||||
569 | static 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 | ||||
600 | static 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 | ||||
675 | static 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 | ||||
693 | static 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 | ||||
734 | static 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 | ||||
770 | static 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 | ||||
789 | static 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 | ||||
818 | int 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 | ||||
876 | int 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 | ||||
953 | sd_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 | ||||
959 | sd_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 | } |