1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
7 #include "device-enumerator-private.h"
8 #include "errno-util.h"
9 #include "libudev-device-internal.h"
10 #include "libudev-list-internal.h"
13 * SECTION:libudev-enumerate
14 * @short_description: lookup and sort sys devices
16 * Lookup devices in the sys filesystem, filter devices by properties,
17 * and return a sorted list of devices.
23 * Opaque object representing one device lookup/sort context.
25 struct udev_enumerate
{
28 struct udev_list
*devices_list
;
29 bool devices_uptodate
:1;
31 sd_device_enumerator
*enumerator
;
36 * @udev: udev library context
38 * Create an enumeration context to scan /sys.
40 * Returns: an enumeration context.
42 _public_
struct udev_enumerate
* udev_enumerate_new(struct udev
*udev
) {
43 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
44 _cleanup_(udev_list_freep
) struct udev_list
*list
= NULL
;
45 struct udev_enumerate
*udev_enumerate
;
48 r
= sd_device_enumerator_new(&e
);
50 return_with_errno(NULL
, r
);
52 r
= sd_device_enumerator_allow_uninitialized(e
);
54 return_with_errno(NULL
, r
);
56 list
= udev_list_new(false);
58 return_with_errno(NULL
, ENOMEM
);
60 udev_enumerate
= new(struct udev_enumerate
, 1);
62 return_with_errno(NULL
, ENOMEM
);
64 *udev_enumerate
= (struct udev_enumerate
) {
67 .enumerator
= TAKE_PTR(e
),
68 .devices_list
= TAKE_PTR(list
),
71 return udev_enumerate
;
74 static struct udev_enumerate
* udev_enumerate_free(struct udev_enumerate
*udev_enumerate
) {
75 assert(udev_enumerate
);
77 udev_list_free(udev_enumerate
->devices_list
);
78 sd_device_enumerator_unref(udev_enumerate
->enumerator
);
79 return mfree(udev_enumerate
);
84 * @udev_enumerate: context
86 * Take a reference of an enumeration context.
88 * Returns: the passed enumeration context
92 * udev_enumerate_unref:
93 * @udev_enumerate: context
95 * Drop a reference of an enumeration context. If the refcount reaches zero,
96 * all resources of the enumeration context will be released.
100 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate
, udev_enumerate
, udev_enumerate_free
);
103 * udev_enumerate_get_udev:
104 * @udev_enumerate: context
106 * Get the udev library context.
108 * Returns: a pointer to the context.
110 _public_
struct udev
* udev_enumerate_get_udev(struct udev_enumerate
*udev_enumerate
) {
111 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
113 return udev_enumerate
->udev
;
117 * udev_enumerate_get_list_entry:
118 * @udev_enumerate: context
120 * Get the first entry of the sorted list of device paths.
122 * Returns: a udev_list_entry.
124 _public_
struct udev_list_entry
* udev_enumerate_get_list_entry(struct udev_enumerate
*udev_enumerate
) {
125 struct udev_list_entry
*e
;
127 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
129 if (!udev_enumerate
->devices_uptodate
) {
132 udev_list_cleanup(udev_enumerate
->devices_list
);
134 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate
->enumerator
, device
) {
138 r
= sd_device_get_syspath(device
, &syspath
);
140 return_with_errno(NULL
, r
);
142 if (!udev_list_entry_add(udev_enumerate
->devices_list
, syspath
, NULL
))
143 return_with_errno(NULL
, ENOMEM
);
146 udev_enumerate
->devices_uptodate
= true;
149 e
= udev_list_get_entry(udev_enumerate
->devices_list
);
151 return_with_errno(NULL
, ENODATA
);
157 * udev_enumerate_add_match_subsystem:
158 * @udev_enumerate: context
159 * @subsystem: filter for a subsystem of the device to include in the list
161 * Match only devices belonging to a certain kernel subsystem.
163 * Returns: 0 on success, otherwise a negative error value.
165 _public_
int udev_enumerate_add_match_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
168 assert_return(udev_enumerate
, -EINVAL
);
173 r
= sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, true);
177 udev_enumerate
->devices_uptodate
= false;
182 * udev_enumerate_add_nomatch_subsystem:
183 * @udev_enumerate: context
184 * @subsystem: filter for a subsystem of the device to exclude from the list
186 * Match only devices not belonging to a certain kernel subsystem.
188 * Returns: 0 on success, otherwise a negative error value.
190 _public_
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
193 assert_return(udev_enumerate
, -EINVAL
);
198 r
= sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, false);
202 udev_enumerate
->devices_uptodate
= false;
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
212 * Match only devices with a certain /sys device attribute.
214 * Returns: 0 on success, otherwise a negative error value.
216 _public_
int udev_enumerate_add_match_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
219 assert_return(udev_enumerate
, -EINVAL
);
224 r
= sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, true);
228 udev_enumerate
->devices_uptodate
= false;
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
238 * Match only devices not having a certain /sys device attribute.
240 * Returns: 0 on success, otherwise a negative error value.
242 _public_
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
245 assert_return(udev_enumerate
, -EINVAL
);
250 r
= sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, false);
254 udev_enumerate
->devices_uptodate
= false;
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
264 * Match only devices with a certain property.
266 * Returns: 0 on success, otherwise a negative error value.
268 _public_
int udev_enumerate_add_match_property(struct udev_enumerate
*udev_enumerate
, const char *property
, const char *value
) {
271 assert_return(udev_enumerate
, -EINVAL
);
276 r
= sd_device_enumerator_add_match_property(udev_enumerate
->enumerator
, property
, value
);
280 udev_enumerate
->devices_uptodate
= false;
285 * udev_enumerate_add_match_tag:
286 * @udev_enumerate: context
287 * @tag: filter for a tag of the device to include in the list
289 * Match only devices with a certain tag.
291 * Returns: 0 on success, otherwise a negative error value.
293 _public_
int udev_enumerate_add_match_tag(struct udev_enumerate
*udev_enumerate
, const char *tag
) {
296 assert_return(udev_enumerate
, -EINVAL
);
301 r
= sd_device_enumerator_add_match_tag(udev_enumerate
->enumerator
, tag
);
305 udev_enumerate
->devices_uptodate
= false;
310 * udev_enumerate_add_match_parent:
311 * @udev_enumerate: context
312 * @parent: parent device where to start searching
314 * Return the devices on the subtree of one given device. The parent
315 * itself is included in the list.
317 * Returns: 0 on success, otherwise a negative error value.
319 _public_
int udev_enumerate_add_match_parent(struct udev_enumerate
*udev_enumerate
, struct udev_device
*parent
) {
322 assert_return(udev_enumerate
, -EINVAL
);
327 r
= sd_device_enumerator_add_match_parent(udev_enumerate
->enumerator
, udev_device_get_sd_device(parent
));
331 udev_enumerate
->devices_uptodate
= false;
336 * udev_enumerate_add_match_is_initialized:
337 * @udev_enumerate: context
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.
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.
348 * For now, this will not affect devices which do not have a device node
349 * and are not network interfaces.
351 * Returns: 0 on success, otherwise a negative error value.
353 _public_
int udev_enumerate_add_match_is_initialized(struct udev_enumerate
*udev_enumerate
) {
356 assert_return(udev_enumerate
, -EINVAL
);
358 r
= device_enumerator_add_match_is_initialized(udev_enumerate
->enumerator
, MATCH_INITIALIZED_COMPAT
);
362 udev_enumerate
->devices_uptodate
= false;
367 * udev_enumerate_add_match_sysname:
368 * @udev_enumerate: context
369 * @sysname: filter for the name of the device to include in the list
371 * Match only devices with a given /sys device name.
373 * Returns: 0 on success, otherwise a negative error value.
375 _public_
int udev_enumerate_add_match_sysname(struct udev_enumerate
*udev_enumerate
, const char *sysname
) {
378 assert_return(udev_enumerate
, -EINVAL
);
383 r
= sd_device_enumerator_add_match_sysname(udev_enumerate
->enumerator
, sysname
);
387 udev_enumerate
->devices_uptodate
= false;
392 * udev_enumerate_add_syspath:
393 * @udev_enumerate: context
394 * @syspath: path of a device
396 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
398 * Returns: 0 on success, otherwise a negative error value.
400 _public_
int udev_enumerate_add_syspath(struct udev_enumerate
*udev_enumerate
, const char *syspath
) {
401 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
404 assert_return(udev_enumerate
, -EINVAL
);
409 r
= sd_device_new_from_syspath(&device
, syspath
);
413 r
= device_enumerator_add_device(udev_enumerate
->enumerator
, device
);
417 udev_enumerate
->devices_uptodate
= false;
422 * udev_enumerate_scan_devices:
423 * @udev_enumerate: udev enumeration context
425 * Scan /sys for all devices which match the given filters. No matches
426 * will return all currently available devices.
428 * Returns: 0 on success, otherwise a negative error value.
430 _public_
int udev_enumerate_scan_devices(struct udev_enumerate
*udev_enumerate
) {
431 assert_return(udev_enumerate
, -EINVAL
);
433 return device_enumerator_scan_devices(udev_enumerate
->enumerator
);
437 * udev_enumerate_scan_subsystems:
438 * @udev_enumerate: udev enumeration context
440 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
442 * Returns: 0 on success, otherwise a negative error value.
444 _public_
int udev_enumerate_scan_subsystems(struct udev_enumerate
*udev_enumerate
) {
445 assert_return(udev_enumerate
, -EINVAL
);
447 return device_enumerator_scan_subsystems(udev_enumerate
->enumerator
);