]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libudev/libudev-enumerate.c
ci: enable arm64 runner for build/unit jobs
[thirdparty/systemd.git] / src / libudev / libudev-enumerate.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
eb1f0e66 2
b4bbcaa9 3#include "libudev.h"
c32eb440 4#include "sd-device.h"
c32eb440 5
b5efdb8a 6#include "alloc-util.h"
07630cea 7#include "device-enumerator-private.h"
3b7d3320 8#include "errno-util.h"
07630cea 9#include "libudev-device-internal.h"
538bdb48 10#include "libudev-list-internal.h"
eb1f0e66 11
ce1d6d7f
KS
12/**
13 * SECTION:libudev-enumerate
14 * @short_description: lookup and sort sys devices
15 *
16 * Lookup devices in the sys filesystem, filter devices by properties,
a7c140c7 17 * and return a sorted list of devices.
ce1d6d7f
KS
18 */
19
20/**
21 * udev_enumerate:
22 *
23 * Opaque object representing one device lookup/sort context.
24 */
bf7ad0ea 25struct udev_enumerate {
912541b0 26 struct udev *udev;
3c6ac219 27 unsigned n_ref;
dcf557f7 28 struct udev_list *devices_list;
912541b0 29 bool devices_uptodate:1;
c32eb440
TG
30
31 sd_device_enumerator *enumerator;
bf7ad0ea
KS
32};
33
c97f839e
KS
34/**
35 * udev_enumerate_new:
36 * @udev: udev library context
37 *
21dbe43a
KS
38 * Create an enumeration context to scan /sys.
39 *
40 * Returns: an enumeration context.
c97f839e 41 **/
9ee08c8d 42_public_ struct udev_enumerate* udev_enumerate_new(struct udev *udev) {
60fdee32 43 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
dcf557f7 44 _cleanup_(udev_list_freep) struct udev_list *list = NULL;
60fdee32 45 struct udev_enumerate *udev_enumerate;
c32eb440
TG
46 int r;
47
60fdee32 48 r = sd_device_enumerator_new(&e);
fd05c424
YW
49 if (r < 0)
50 return_with_errno(NULL, r);
c32eb440 51
60fdee32 52 r = sd_device_enumerator_allow_uninitialized(e);
fd05c424
YW
53 if (r < 0)
54 return_with_errno(NULL, r);
dee5e0b6 55
dcf557f7
YW
56 list = udev_list_new(false);
57 if (!list)
58 return_with_errno(NULL, ENOMEM);
59
60fdee32 60 udev_enumerate = new(struct udev_enumerate, 1);
fd05c424
YW
61 if (!udev_enumerate)
62 return_with_errno(NULL, ENOMEM);
c32eb440 63
60fdee32
YW
64 *udev_enumerate = (struct udev_enumerate) {
65 .udev = udev,
66 .n_ref = 1,
67 .enumerator = TAKE_PTR(e),
dcf557f7 68 .devices_list = TAKE_PTR(list),
60fdee32 69 };
c32eb440 70
60fdee32 71 return udev_enumerate;
c97f839e
KS
72}
73
9ee08c8d 74static struct udev_enumerate* udev_enumerate_free(struct udev_enumerate *udev_enumerate) {
3c6ac219
YW
75 assert(udev_enumerate);
76
dcf557f7 77 udev_list_free(udev_enumerate->devices_list);
3c6ac219
YW
78 sd_device_enumerator_unref(udev_enumerate->enumerator);
79 return mfree(udev_enumerate);
80}
81
ce1d6d7f
KS
82/**
83 * udev_enumerate_ref:
84 * @udev_enumerate: context
85 *
387f6955 86 * Take a reference of an enumeration context.
ce1d6d7f
KS
87 *
88 * Returns: the passed enumeration context
89 **/
bf7ad0ea 90
ce1d6d7f
KS
91/**
92 * udev_enumerate_unref:
93 * @udev_enumerate: context
94 *
95 * Drop a reference of an enumeration context. If the refcount reaches zero,
96 * all resources of the enumeration context will be released.
c1959569 97 *
725d7e6c 98 * Returns: #NULL
ce1d6d7f 99 **/
3c6ac219 100DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate, udev_enumerate, udev_enumerate_free);
bf7ad0ea 101
ce1d6d7f
KS
102/**
103 * udev_enumerate_get_udev:
104 * @udev_enumerate: context
105 *
21dbe43a
KS
106 * Get the udev library context.
107 *
108 * Returns: a pointer to the context.
ce1d6d7f 109 */
9ee08c8d 110_public_ struct udev* udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
c32eb440 111 assert_return_errno(udev_enumerate, NULL, EINVAL);
3bf76824 112
c32eb440 113 return udev_enumerate->udev;
3bf76824
LP
114}
115
a7c140c7
KS
116/**
117 * udev_enumerate_get_list_entry:
118 * @udev_enumerate: context
119 *
21dbe43a
KS
120 * Get the first entry of the sorted list of device paths.
121 *
122 * Returns: a udev_list_entry.
a7c140c7 123 */
9ee08c8d 124_public_ struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
309f631d
LP
125 struct udev_list_entry *e;
126
c32eb440
TG
127 assert_return_errno(udev_enumerate, NULL, EINVAL);
128
912541b0 129 if (!udev_enumerate->devices_uptodate) {
c32eb440 130 sd_device *device;
912541b0 131
dcf557f7 132 udev_list_cleanup(udev_enumerate->devices_list);
912541b0 133
c32eb440
TG
134 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) {
135 const char *syspath;
136 int r;
912541b0 137
c32eb440 138 r = sd_device_get_syspath(device, &syspath);
fd05c424
YW
139 if (r < 0)
140 return_with_errno(NULL, r);
912541b0 141
dcf557f7 142 if (!udev_list_entry_add(udev_enumerate->devices_list, syspath, NULL))
3f14e721 143 return_with_errno(NULL, ENOMEM);
912541b0 144 }
912541b0
KS
145
146 udev_enumerate->devices_uptodate = true;
147 }
c32eb440 148
dcf557f7 149 e = udev_list_get_entry(udev_enumerate->devices_list);
309f631d 150 if (!e)
fd05c424 151 return_with_errno(NULL, ENODATA);
309f631d
LP
152
153 return e;
bf7ad0ea
KS
154}
155
a7c140c7
KS
156/**
157 * udev_enumerate_add_match_subsystem:
158 * @udev_enumerate: context
159 * @subsystem: filter for a subsystem of the device to include in the list
160 *
21dbe43a
KS
161 * Match only devices belonging to a certain kernel subsystem.
162 *
a7c140c7
KS
163 * Returns: 0 on success, otherwise a negative error value.
164 */
c32eb440 165_public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
56fa3682
YW
166 int r;
167
c32eb440
TG
168 assert_return(udev_enumerate, -EINVAL);
169
54f0b4d9
TG
170 if (!subsystem)
171 return 0;
172
56fa3682
YW
173 r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true);
174 if (r < 0)
175 return r;
176
177 udev_enumerate->devices_uptodate = false;
178 return 0;
c97f839e
KS
179}
180
a7c140c7
KS
181/**
182 * udev_enumerate_add_nomatch_subsystem:
183 * @udev_enumerate: context
184 * @subsystem: filter for a subsystem of the device to exclude from the list
185 *
21dbe43a
KS
186 * Match only devices not belonging to a certain kernel subsystem.
187 *
a7c140c7
KS
188 * Returns: 0 on success, otherwise a negative error value.
189 */
c32eb440 190_public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
56fa3682
YW
191 int r;
192
c32eb440
TG
193 assert_return(udev_enumerate, -EINVAL);
194
54f0b4d9
TG
195 if (!subsystem)
196 return 0;
197
56fa3682
YW
198 r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false);
199 if (r < 0)
200 return r;
201
202 udev_enumerate->devices_uptodate = false;
203 return 0;
c97f839e
KS
204}
205
a7c140c7
KS
206/**
207 * udev_enumerate_add_match_sysattr:
208 * @udev_enumerate: context
209 * @sysattr: filter for a sys attribute at the device to include in the list
210 * @value: optional value of the sys attribute
211 *
21dbe43a
KS
212 * Match only devices with a certain /sys device attribute.
213 *
a7c140c7
KS
214 * Returns: 0 on success, otherwise a negative error value.
215 */
c32eb440 216_public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
56fa3682
YW
217 int r;
218
c32eb440
TG
219 assert_return(udev_enumerate, -EINVAL);
220
54f0b4d9
TG
221 if (!sysattr)
222 return 0;
223
56fa3682
YW
224 r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true);
225 if (r < 0)
226 return r;
227
228 udev_enumerate->devices_uptodate = false;
229 return 0;
c97f839e
KS
230}
231
a7c140c7
KS
232/**
233 * udev_enumerate_add_nomatch_sysattr:
234 * @udev_enumerate: context
235 * @sysattr: filter for a sys attribute at the device to exclude from the list
236 * @value: optional value of the sys attribute
237 *
21dbe43a
KS
238 * Match only devices not having a certain /sys device attribute.
239 *
a7c140c7
KS
240 * Returns: 0 on success, otherwise a negative error value.
241 */
c32eb440 242_public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
56fa3682
YW
243 int r;
244
c32eb440 245 assert_return(udev_enumerate, -EINVAL);
c97f839e 246
54f0b4d9
TG
247 if (!sysattr)
248 return 0;
249
56fa3682
YW
250 r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false);
251 if (r < 0)
252 return r;
253
254 udev_enumerate->devices_uptodate = false;
255 return 0;
c97f839e
KS
256}
257
a7c140c7
KS
258/**
259 * udev_enumerate_add_match_property:
260 * @udev_enumerate: context
261 * @property: filter for a property of the device to include in the list
262 * @value: value of the property
263 *
21dbe43a
KS
264 * Match only devices with a certain property.
265 *
a7c140c7
KS
266 * Returns: 0 on success, otherwise a negative error value.
267 */
c32eb440 268_public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
56fa3682
YW
269 int r;
270
c32eb440
TG
271 assert_return(udev_enumerate, -EINVAL);
272
54f0b4d9
TG
273 if (!property)
274 return 0;
275
56fa3682
YW
276 r = sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value);
277 if (r < 0)
278 return r;
279
280 udev_enumerate->devices_uptodate = false;
281 return 0;
f0893502
KS
282}
283
28460195
KS
284/**
285 * udev_enumerate_add_match_tag:
286 * @udev_enumerate: context
287 * @tag: filter for a tag of the device to include in the list
288 *
21dbe43a
KS
289 * Match only devices with a certain tag.
290 *
28460195
KS
291 * Returns: 0 on success, otherwise a negative error value.
292 */
c32eb440 293_public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
56fa3682
YW
294 int r;
295
c32eb440
TG
296 assert_return(udev_enumerate, -EINVAL);
297
54f0b4d9
TG
298 if (!tag)
299 return 0;
300
56fa3682
YW
301 r = sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag);
302 if (r < 0)
303 return r;
304
305 udev_enumerate->devices_uptodate = false;
306 return 0;
28460195
KS
307}
308
b05211fa
KS
309/**
310 * udev_enumerate_add_match_parent:
311 * @udev_enumerate: context
a07e0114 312 * @parent: parent device where to start searching
b05211fa 313 *
a07e0114
KS
314 * Return the devices on the subtree of one given device. The parent
315 * itself is included in the list.
b05211fa 316 *
b05211fa
KS
317 * Returns: 0 on success, otherwise a negative error value.
318 */
c32eb440 319_public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
56fa3682
YW
320 int r;
321
c32eb440
TG
322 assert_return(udev_enumerate, -EINVAL);
323
324 if (!parent)
912541b0 325 return 0;
c32eb440 326
538bdb48 327 r = sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, udev_device_get_sd_device(parent));
56fa3682
YW
328 if (r < 0)
329 return r;
330
331 udev_enumerate->devices_uptodate = false;
332 return 0;
b05211fa
KS
333}
334
48a0170b
KS
335/**
336 * udev_enumerate_add_match_is_initialized:
337 * @udev_enumerate: context
338 *
339 * Match only devices which udev has set up already. This makes
340 * sure, that the device node permissions and context are properly set
341 * and that network devices are fully renamed.
342 *
343 * Usually, devices which are found in the kernel but not already
344 * handled by udev, have still pending events. Services should subscribe
345 * to monitor events and wait for these devices to become ready, instead
346 * of using uninitialized devices.
347 *
348 * For now, this will not affect devices which do not have a device node
349 * and are not network interfaces.
350 *
351 * Returns: 0 on success, otherwise a negative error value.
352 */
c32eb440 353_public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
56fa3682
YW
354 int r;
355
c32eb440
TG
356 assert_return(udev_enumerate, -EINVAL);
357
d8b50e5d 358 r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator, MATCH_INITIALIZED_COMPAT);
56fa3682
YW
359 if (r < 0)
360 return r;
361
362 udev_enumerate->devices_uptodate = false;
363 return 0;
48a0170b
KS
364}
365
cf5bd040
KS
366/**
367 * udev_enumerate_add_match_sysname:
368 * @udev_enumerate: context
369 * @sysname: filter for the name of the device to include in the list
370 *
21dbe43a
KS
371 * Match only devices with a given /sys device name.
372 *
cf5bd040
KS
373 * Returns: 0 on success, otherwise a negative error value.
374 */
c32eb440 375_public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
56fa3682
YW
376 int r;
377
c32eb440 378 assert_return(udev_enumerate, -EINVAL);
c97f839e 379
54f0b4d9
TG
380 if (!sysname)
381 return 0;
382
56fa3682
YW
383 r = sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname);
384 if (r < 0)
385 return r;
386
387 udev_enumerate->devices_uptodate = false;
388 return 0;
eb1f0e66
KS
389}
390
a7c140c7
KS
391/**
392 * udev_enumerate_add_syspath:
393 * @udev_enumerate: context
394 * @syspath: path of a device
395 *
396 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
397 *
398 * Returns: 0 on success, otherwise a negative error value.
399 */
c32eb440 400_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
4afd3348 401 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
c32eb440 402 int r;
b05211fa 403
c32eb440 404 assert_return(udev_enumerate, -EINVAL);
b05211fa 405
c32eb440
TG
406 if (!syspath)
407 return 0;
6ed03d1e 408
c32eb440
TG
409 r = sd_device_new_from_syspath(&device, syspath);
410 if (r < 0)
411 return r;
6ed03d1e 412
19c9df44 413 r = device_enumerator_add_device(udev_enumerate->enumerator, device);
c32eb440
TG
414 if (r < 0)
415 return r;
b05211fa 416
56fa3682 417 udev_enumerate->devices_uptodate = false;
912541b0 418 return 0;
eb1f0e66 419}
bc8184ed 420
b05211fa
KS
421/**
422 * udev_enumerate_scan_devices:
423 * @udev_enumerate: udev enumeration context
424 *
21dbe43a
KS
425 * Scan /sys for all devices which match the given filters. No matches
426 * will return all currently available devices.
427 *
b05211fa
KS
428 * Returns: 0 on success, otherwise a negative error value.
429 **/
c32eb440
TG
430_public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) {
431 assert_return(udev_enumerate, -EINVAL);
b05211fa 432
c32eb440 433 return device_enumerator_scan_devices(udev_enumerate->enumerator);
b05211fa
KS
434}
435
438d4c3c
KS
436/**
437 * udev_enumerate_scan_subsystems:
438 * @udev_enumerate: udev enumeration context
439 *
21dbe43a
KS
440 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
441 *
a7c140c7 442 * Returns: 0 on success, otherwise a negative error value.
438d4c3c 443 **/
c32eb440
TG
444_public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) {
445 assert_return(udev_enumerate, -EINVAL);
446
447 return device_enumerator_scan_subsystems(udev_enumerate->enumerator);
bc8184ed 448}