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"
20 #include "libudev-list-internal.h"
23 * SECTION:libudev-enumerate
24 * @short_description: lookup and sort sys devices
26 * Lookup devices in the sys filesystem, filter devices by properties,
27 * and return a sorted list of devices.
33 * Opaque object representing one device lookup/sort context.
35 struct udev_enumerate
{
38 struct udev_list
*devices_list
;
39 bool devices_uptodate
:1;
41 sd_device_enumerator
*enumerator
;
46 * @udev: udev library context
48 * Create an enumeration context to scan /sys.
50 * Returns: an enumeration context.
52 _public_
struct udev_enumerate
*udev_enumerate_new(struct udev
*udev
) {
53 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
54 _cleanup_(udev_list_freep
) struct udev_list
*list
= NULL
;
55 struct udev_enumerate
*udev_enumerate
;
58 r
= sd_device_enumerator_new(&e
);
60 return_with_errno(NULL
, r
);
62 r
= sd_device_enumerator_allow_uninitialized(e
);
64 return_with_errno(NULL
, r
);
66 list
= udev_list_new(false);
68 return_with_errno(NULL
, ENOMEM
);
70 udev_enumerate
= new(struct udev_enumerate
, 1);
72 return_with_errno(NULL
, ENOMEM
);
74 *udev_enumerate
= (struct udev_enumerate
) {
77 .enumerator
= TAKE_PTR(e
),
78 .devices_list
= TAKE_PTR(list
),
81 return udev_enumerate
;
84 static struct udev_enumerate
*udev_enumerate_free(struct udev_enumerate
*udev_enumerate
) {
85 assert(udev_enumerate
);
87 udev_list_free(udev_enumerate
->devices_list
);
88 sd_device_enumerator_unref(udev_enumerate
->enumerator
);
89 return mfree(udev_enumerate
);
94 * @udev_enumerate: context
96 * Take a reference of a enumeration context.
98 * Returns: the passed enumeration context
102 * udev_enumerate_unref:
103 * @udev_enumerate: context
105 * Drop a reference of an enumeration context. If the refcount reaches zero,
106 * all resources of the enumeration context will be released.
110 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate
, udev_enumerate
, udev_enumerate_free
);
113 * udev_enumerate_get_udev:
114 * @udev_enumerate: context
116 * Get the udev library context.
118 * Returns: a pointer to the context.
120 _public_
struct udev
*udev_enumerate_get_udev(struct udev_enumerate
*udev_enumerate
) {
121 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
123 return udev_enumerate
->udev
;
127 * udev_enumerate_get_list_entry:
128 * @udev_enumerate: context
130 * Get the first entry of the sorted list of device paths.
132 * Returns: a udev_list_entry.
134 _public_
struct udev_list_entry
*udev_enumerate_get_list_entry(struct udev_enumerate
*udev_enumerate
) {
135 struct udev_list_entry
*e
;
137 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
139 if (!udev_enumerate
->devices_uptodate
) {
142 udev_list_cleanup(udev_enumerate
->devices_list
);
144 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate
->enumerator
, device
) {
148 r
= sd_device_get_syspath(device
, &syspath
);
150 return_with_errno(NULL
, r
);
152 if (!udev_list_entry_add(udev_enumerate
->devices_list
, syspath
, NULL
))
153 return_with_errno(NULL
, ENOMEM
);
156 udev_enumerate
->devices_uptodate
= true;
159 e
= udev_list_get_entry(udev_enumerate
->devices_list
);
161 return_with_errno(NULL
, ENODATA
);
167 * udev_enumerate_add_match_subsystem:
168 * @udev_enumerate: context
169 * @subsystem: filter for a subsystem of the device to include in the list
171 * Match only devices belonging to a certain kernel subsystem.
173 * Returns: 0 on success, otherwise a negative error value.
175 _public_
int udev_enumerate_add_match_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
178 assert_return(udev_enumerate
, -EINVAL
);
183 r
= sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, true);
187 udev_enumerate
->devices_uptodate
= false;
192 * udev_enumerate_add_nomatch_subsystem:
193 * @udev_enumerate: context
194 * @subsystem: filter for a subsystem of the device to exclude from the list
196 * Match only devices not belonging to a certain kernel subsystem.
198 * Returns: 0 on success, otherwise a negative error value.
200 _public_
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
203 assert_return(udev_enumerate
, -EINVAL
);
208 r
= sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, false);
212 udev_enumerate
->devices_uptodate
= false;
217 * udev_enumerate_add_match_sysattr:
218 * @udev_enumerate: context
219 * @sysattr: filter for a sys attribute at the device to include in the list
220 * @value: optional value of the sys attribute
222 * Match only devices with a certain /sys device attribute.
224 * Returns: 0 on success, otherwise a negative error value.
226 _public_
int udev_enumerate_add_match_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
229 assert_return(udev_enumerate
, -EINVAL
);
234 r
= sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, true);
238 udev_enumerate
->devices_uptodate
= false;
243 * udev_enumerate_add_nomatch_sysattr:
244 * @udev_enumerate: context
245 * @sysattr: filter for a sys attribute at the device to exclude from the list
246 * @value: optional value of the sys attribute
248 * Match only devices not having a certain /sys device attribute.
250 * Returns: 0 on success, otherwise a negative error value.
252 _public_
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
255 assert_return(udev_enumerate
, -EINVAL
);
260 r
= sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, false);
264 udev_enumerate
->devices_uptodate
= false;
269 * udev_enumerate_add_match_property:
270 * @udev_enumerate: context
271 * @property: filter for a property of the device to include in the list
272 * @value: value of the property
274 * Match only devices with a certain property.
276 * Returns: 0 on success, otherwise a negative error value.
278 _public_
int udev_enumerate_add_match_property(struct udev_enumerate
*udev_enumerate
, const char *property
, const char *value
) {
281 assert_return(udev_enumerate
, -EINVAL
);
286 r
= sd_device_enumerator_add_match_property(udev_enumerate
->enumerator
, property
, value
);
290 udev_enumerate
->devices_uptodate
= false;
295 * udev_enumerate_add_match_tag:
296 * @udev_enumerate: context
297 * @tag: filter for a tag of the device to include in the list
299 * Match only devices with a certain tag.
301 * Returns: 0 on success, otherwise a negative error value.
303 _public_
int udev_enumerate_add_match_tag(struct udev_enumerate
*udev_enumerate
, const char *tag
) {
306 assert_return(udev_enumerate
, -EINVAL
);
311 r
= sd_device_enumerator_add_match_tag(udev_enumerate
->enumerator
, tag
);
315 udev_enumerate
->devices_uptodate
= false;
320 * udev_enumerate_add_match_parent:
321 * @udev_enumerate: context
322 * @parent: parent device where to start searching
324 * Return the devices on the subtree of one given device. The parent
325 * itself is included in the list.
327 * Returns: 0 on success, otherwise a negative error value.
329 _public_
int udev_enumerate_add_match_parent(struct udev_enumerate
*udev_enumerate
, struct udev_device
*parent
) {
332 assert_return(udev_enumerate
, -EINVAL
);
337 r
= sd_device_enumerator_add_match_parent(udev_enumerate
->enumerator
, udev_device_get_sd_device(parent
));
341 udev_enumerate
->devices_uptodate
= false;
346 * udev_enumerate_add_match_is_initialized:
347 * @udev_enumerate: context
349 * Match only devices which udev has set up already. This makes
350 * sure, that the device node permissions and context are properly set
351 * and that network devices are fully renamed.
353 * Usually, devices which are found in the kernel but not already
354 * handled by udev, have still pending events. Services should subscribe
355 * to monitor events and wait for these devices to become ready, instead
356 * of using uninitialized devices.
358 * For now, this will not affect devices which do not have a device node
359 * and are not network interfaces.
361 * Returns: 0 on success, otherwise a negative error value.
363 _public_
int udev_enumerate_add_match_is_initialized(struct udev_enumerate
*udev_enumerate
) {
366 assert_return(udev_enumerate
, -EINVAL
);
368 r
= device_enumerator_add_match_is_initialized(udev_enumerate
->enumerator
);
372 udev_enumerate
->devices_uptodate
= false;
377 * udev_enumerate_add_match_sysname:
378 * @udev_enumerate: context
379 * @sysname: filter for the name of the device to include in the list
381 * Match only devices with a given /sys device name.
383 * Returns: 0 on success, otherwise a negative error value.
385 _public_
int udev_enumerate_add_match_sysname(struct udev_enumerate
*udev_enumerate
, const char *sysname
) {
388 assert_return(udev_enumerate
, -EINVAL
);
393 r
= sd_device_enumerator_add_match_sysname(udev_enumerate
->enumerator
, sysname
);
397 udev_enumerate
->devices_uptodate
= false;
402 * udev_enumerate_add_syspath:
403 * @udev_enumerate: context
404 * @syspath: path of a device
406 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
408 * Returns: 0 on success, otherwise a negative error value.
410 _public_
int udev_enumerate_add_syspath(struct udev_enumerate
*udev_enumerate
, const char *syspath
) {
411 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
414 assert_return(udev_enumerate
, -EINVAL
);
419 r
= sd_device_new_from_syspath(&device
, syspath
);
423 r
= device_enumerator_add_device(udev_enumerate
->enumerator
, device
);
427 udev_enumerate
->devices_uptodate
= false;
432 * udev_enumerate_scan_devices:
433 * @udev_enumerate: udev enumeration context
435 * Scan /sys for all devices which match the given filters. No matches
436 * will return all currently available devices.
438 * Returns: 0 on success, otherwise a negative error value.
440 _public_
int udev_enumerate_scan_devices(struct udev_enumerate
*udev_enumerate
) {
441 assert_return(udev_enumerate
, -EINVAL
);
443 return device_enumerator_scan_devices(udev_enumerate
->enumerator
);
447 * udev_enumerate_scan_subsystems:
448 * @udev_enumerate: udev enumeration context
450 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
452 * Returns: 0 on success, otherwise a negative error value.
454 _public_
int udev_enumerate_scan_subsystems(struct udev_enumerate
*udev_enumerate
) {
455 assert_return(udev_enumerate
, -EINVAL
);
457 return device_enumerator_scan_subsystems(udev_enumerate
->enumerator
);