1 /* SPDX-License-Identifier: LGPL-2.1+ */
14 #include "sd-device.h"
16 #include "alloc-util.h"
17 #include "device-enumerator-private.h"
18 #include "device-util.h"
19 #include "libudev-device-internal.h"
22 * SECTION:libudev-enumerate
23 * @short_description: lookup and sort sys devices
25 * Lookup devices in the sys filesystem, filter devices by properties,
26 * and return a sorted list of devices.
32 * Opaque object representing one device lookup/sort context.
34 struct udev_enumerate
{
37 struct udev_list
*devices_list
;
38 bool devices_uptodate
:1;
40 sd_device_enumerator
*enumerator
;
45 * @udev: udev library context
47 * Create an enumeration context to scan /sys.
49 * Returns: an enumeration context.
51 _public_
struct udev_enumerate
*udev_enumerate_new(struct udev
*udev
) {
52 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
53 _cleanup_(udev_list_freep
) struct udev_list
*list
= NULL
;
54 struct udev_enumerate
*udev_enumerate
;
57 r
= sd_device_enumerator_new(&e
);
59 return_with_errno(NULL
, r
);
61 r
= sd_device_enumerator_allow_uninitialized(e
);
63 return_with_errno(NULL
, r
);
65 list
= udev_list_new(false);
67 return_with_errno(NULL
, ENOMEM
);
69 udev_enumerate
= new(struct udev_enumerate
, 1);
71 return_with_errno(NULL
, ENOMEM
);
73 *udev_enumerate
= (struct udev_enumerate
) {
76 .enumerator
= TAKE_PTR(e
),
77 .devices_list
= TAKE_PTR(list
),
80 return udev_enumerate
;
83 static struct udev_enumerate
*udev_enumerate_free(struct udev_enumerate
*udev_enumerate
) {
84 assert(udev_enumerate
);
86 udev_list_free(udev_enumerate
->devices_list
);
87 sd_device_enumerator_unref(udev_enumerate
->enumerator
);
88 return mfree(udev_enumerate
);
93 * @udev_enumerate: context
95 * Take a reference of a enumeration context.
97 * Returns: the passed enumeration context
101 * udev_enumerate_unref:
102 * @udev_enumerate: context
104 * Drop a reference of an enumeration context. If the refcount reaches zero,
105 * all resources of the enumeration context will be released.
109 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate
, udev_enumerate
, udev_enumerate_free
);
112 * udev_enumerate_get_udev:
113 * @udev_enumerate: context
115 * Get the udev library context.
117 * Returns: a pointer to the context.
119 _public_
struct udev
*udev_enumerate_get_udev(struct udev_enumerate
*udev_enumerate
) {
120 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
122 return udev_enumerate
->udev
;
126 * udev_enumerate_get_list_entry:
127 * @udev_enumerate: context
129 * Get the first entry of the sorted list of device paths.
131 * Returns: a udev_list_entry.
133 _public_
struct udev_list_entry
*udev_enumerate_get_list_entry(struct udev_enumerate
*udev_enumerate
) {
134 struct udev_list_entry
*e
;
136 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
138 if (!udev_enumerate
->devices_uptodate
) {
141 udev_list_cleanup(udev_enumerate
->devices_list
);
143 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate
->enumerator
, device
) {
147 r
= sd_device_get_syspath(device
, &syspath
);
149 return_with_errno(NULL
, r
);
151 if (!udev_list_entry_add(udev_enumerate
->devices_list
, syspath
, NULL
))
152 return_with_errno(NULL
, ENOMEM
);
155 udev_enumerate
->devices_uptodate
= true;
158 e
= udev_list_get_entry(udev_enumerate
->devices_list
);
160 return_with_errno(NULL
, ENODATA
);
166 * udev_enumerate_add_match_subsystem:
167 * @udev_enumerate: context
168 * @subsystem: filter for a subsystem of the device to include in the list
170 * Match only devices belonging to a certain kernel subsystem.
172 * Returns: 0 on success, otherwise a negative error value.
174 _public_
int udev_enumerate_add_match_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
177 assert_return(udev_enumerate
, -EINVAL
);
182 r
= sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, true);
186 udev_enumerate
->devices_uptodate
= false;
191 * udev_enumerate_add_nomatch_subsystem:
192 * @udev_enumerate: context
193 * @subsystem: filter for a subsystem of the device to exclude from the list
195 * Match only devices not belonging to a certain kernel subsystem.
197 * Returns: 0 on success, otherwise a negative error value.
199 _public_
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
202 assert_return(udev_enumerate
, -EINVAL
);
207 r
= sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, false);
211 udev_enumerate
->devices_uptodate
= false;
216 * udev_enumerate_add_match_sysattr:
217 * @udev_enumerate: context
218 * @sysattr: filter for a sys attribute at the device to include in the list
219 * @value: optional value of the sys attribute
221 * Match only devices with a certain /sys device attribute.
223 * Returns: 0 on success, otherwise a negative error value.
225 _public_
int udev_enumerate_add_match_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
228 assert_return(udev_enumerate
, -EINVAL
);
233 r
= sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, true);
237 udev_enumerate
->devices_uptodate
= false;
242 * udev_enumerate_add_nomatch_sysattr:
243 * @udev_enumerate: context
244 * @sysattr: filter for a sys attribute at the device to exclude from the list
245 * @value: optional value of the sys attribute
247 * Match only devices not having a certain /sys device attribute.
249 * Returns: 0 on success, otherwise a negative error value.
251 _public_
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
254 assert_return(udev_enumerate
, -EINVAL
);
259 r
= sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, false);
263 udev_enumerate
->devices_uptodate
= false;
268 * udev_enumerate_add_match_property:
269 * @udev_enumerate: context
270 * @property: filter for a property of the device to include in the list
271 * @value: value of the property
273 * Match only devices with a certain property.
275 * Returns: 0 on success, otherwise a negative error value.
277 _public_
int udev_enumerate_add_match_property(struct udev_enumerate
*udev_enumerate
, const char *property
, const char *value
) {
280 assert_return(udev_enumerate
, -EINVAL
);
285 r
= sd_device_enumerator_add_match_property(udev_enumerate
->enumerator
, property
, value
);
289 udev_enumerate
->devices_uptodate
= false;
294 * udev_enumerate_add_match_tag:
295 * @udev_enumerate: context
296 * @tag: filter for a tag of the device to include in the list
298 * Match only devices with a certain tag.
300 * Returns: 0 on success, otherwise a negative error value.
302 _public_
int udev_enumerate_add_match_tag(struct udev_enumerate
*udev_enumerate
, const char *tag
) {
305 assert_return(udev_enumerate
, -EINVAL
);
310 r
= sd_device_enumerator_add_match_tag(udev_enumerate
->enumerator
, tag
);
314 udev_enumerate
->devices_uptodate
= false;
319 * udev_enumerate_add_match_parent:
320 * @udev_enumerate: context
321 * @parent: parent device where to start searching
323 * Return the devices on the subtree of one given device. The parent
324 * itself is included in the list.
326 * Returns: 0 on success, otherwise a negative error value.
328 _public_
int udev_enumerate_add_match_parent(struct udev_enumerate
*udev_enumerate
, struct udev_device
*parent
) {
331 assert_return(udev_enumerate
, -EINVAL
);
336 r
= sd_device_enumerator_add_match_parent(udev_enumerate
->enumerator
, parent
->device
);
340 udev_enumerate
->devices_uptodate
= false;
345 * udev_enumerate_add_match_is_initialized:
346 * @udev_enumerate: context
348 * Match only devices which udev has set up already. This makes
349 * sure, that the device node permissions and context are properly set
350 * and that network devices are fully renamed.
352 * Usually, devices which are found in the kernel but not already
353 * handled by udev, have still pending events. Services should subscribe
354 * to monitor events and wait for these devices to become ready, instead
355 * of using uninitialized devices.
357 * For now, this will not affect devices which do not have a device node
358 * and are not network interfaces.
360 * Returns: 0 on success, otherwise a negative error value.
362 _public_
int udev_enumerate_add_match_is_initialized(struct udev_enumerate
*udev_enumerate
) {
365 assert_return(udev_enumerate
, -EINVAL
);
367 r
= device_enumerator_add_match_is_initialized(udev_enumerate
->enumerator
);
371 udev_enumerate
->devices_uptodate
= false;
376 * udev_enumerate_add_match_sysname:
377 * @udev_enumerate: context
378 * @sysname: filter for the name of the device to include in the list
380 * Match only devices with a given /sys device name.
382 * Returns: 0 on success, otherwise a negative error value.
384 _public_
int udev_enumerate_add_match_sysname(struct udev_enumerate
*udev_enumerate
, const char *sysname
) {
387 assert_return(udev_enumerate
, -EINVAL
);
392 r
= sd_device_enumerator_add_match_sysname(udev_enumerate
->enumerator
, sysname
);
396 udev_enumerate
->devices_uptodate
= false;
401 * udev_enumerate_add_syspath:
402 * @udev_enumerate: context
403 * @syspath: path of a device
405 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
407 * Returns: 0 on success, otherwise a negative error value.
409 _public_
int udev_enumerate_add_syspath(struct udev_enumerate
*udev_enumerate
, const char *syspath
) {
410 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
413 assert_return(udev_enumerate
, -EINVAL
);
418 r
= sd_device_new_from_syspath(&device
, syspath
);
422 r
= device_enumerator_add_device(udev_enumerate
->enumerator
, device
);
426 udev_enumerate
->devices_uptodate
= false;
431 * udev_enumerate_scan_devices:
432 * @udev_enumerate: udev enumeration context
434 * Scan /sys for all devices which match the given filters. No matches
435 * will return all currently available devices.
437 * Returns: 0 on success, otherwise a negative error value.
439 _public_
int udev_enumerate_scan_devices(struct udev_enumerate
*udev_enumerate
) {
440 assert_return(udev_enumerate
, -EINVAL
);
442 return device_enumerator_scan_devices(udev_enumerate
->enumerator
);
446 * udev_enumerate_scan_subsystems:
447 * @udev_enumerate: udev enumeration context
449 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
451 * Returns: 0 on success, otherwise a negative error value.
453 _public_
int udev_enumerate_scan_subsystems(struct udev_enumerate
*udev_enumerate
) {
454 assert_return(udev_enumerate
, -EINVAL
);
456 return device_enumerator_scan_subsystems(udev_enumerate
->enumerator
);