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 struct udev_enumerate
*udev_enumerate
;
56 r
= sd_device_enumerator_new(&e
);
58 return_with_errno(NULL
, r
);
60 r
= sd_device_enumerator_allow_uninitialized(e
);
62 return_with_errno(NULL
, r
);
64 udev_enumerate
= new(struct udev_enumerate
, 1);
66 return_with_errno(NULL
, ENOMEM
);
68 *udev_enumerate
= (struct udev_enumerate
) {
71 .enumerator
= TAKE_PTR(e
),
74 udev_list_init(&udev_enumerate
->devices_list
, false);
76 return udev_enumerate
;
79 static struct udev_enumerate
*udev_enumerate_free(struct udev_enumerate
*udev_enumerate
) {
80 assert(udev_enumerate
);
82 udev_list_cleanup(&udev_enumerate
->devices_list
);
83 sd_device_enumerator_unref(udev_enumerate
->enumerator
);
84 return mfree(udev_enumerate
);
89 * @udev_enumerate: context
91 * Take a reference of a enumeration context.
93 * Returns: the passed enumeration context
97 * udev_enumerate_unref:
98 * @udev_enumerate: context
100 * Drop a reference of an enumeration context. If the refcount reaches zero,
101 * all resources of the enumeration context will be released.
105 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate
, udev_enumerate
, udev_enumerate_free
);
108 * udev_enumerate_get_udev:
109 * @udev_enumerate: context
111 * Get the udev library context.
113 * Returns: a pointer to the context.
115 _public_
struct udev
*udev_enumerate_get_udev(struct udev_enumerate
*udev_enumerate
) {
116 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
118 return udev_enumerate
->udev
;
122 * udev_enumerate_get_list_entry:
123 * @udev_enumerate: context
125 * Get the first entry of the sorted list of device paths.
127 * Returns: a udev_list_entry.
129 _public_
struct udev_list_entry
*udev_enumerate_get_list_entry(struct udev_enumerate
*udev_enumerate
) {
130 struct udev_list_entry
*e
;
132 assert_return_errno(udev_enumerate
, NULL
, EINVAL
);
134 if (!udev_enumerate
->devices_uptodate
) {
137 udev_list_cleanup(&udev_enumerate
->devices_list
);
139 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate
->enumerator
, device
) {
143 r
= sd_device_get_syspath(device
, &syspath
);
145 return_with_errno(NULL
, r
);
147 if (!udev_list_entry_add(&udev_enumerate
->devices_list
, syspath
, NULL
))
148 return_with_errno(NULL
, ENOMEM
);
151 udev_enumerate
->devices_uptodate
= true;
154 e
= udev_list_get_entry(&udev_enumerate
->devices_list
);
156 return_with_errno(NULL
, ENODATA
);
162 * udev_enumerate_add_match_subsystem:
163 * @udev_enumerate: context
164 * @subsystem: filter for a subsystem of the device to include in the list
166 * Match only devices belonging to a certain kernel subsystem.
168 * Returns: 0 on success, otherwise a negative error value.
170 _public_
int udev_enumerate_add_match_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
171 assert_return(udev_enumerate
, -EINVAL
);
176 return sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, true);
180 * udev_enumerate_add_nomatch_subsystem:
181 * @udev_enumerate: context
182 * @subsystem: filter for a subsystem of the device to exclude from the list
184 * Match only devices not belonging to a certain kernel subsystem.
186 * Returns: 0 on success, otherwise a negative error value.
188 _public_
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate
*udev_enumerate
, const char *subsystem
) {
189 assert_return(udev_enumerate
, -EINVAL
);
194 return sd_device_enumerator_add_match_subsystem(udev_enumerate
->enumerator
, subsystem
, false);
198 * udev_enumerate_add_match_sysattr:
199 * @udev_enumerate: context
200 * @sysattr: filter for a sys attribute at the device to include in the list
201 * @value: optional value of the sys attribute
203 * Match only devices with a certain /sys device attribute.
205 * Returns: 0 on success, otherwise a negative error value.
207 _public_
int udev_enumerate_add_match_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
208 assert_return(udev_enumerate
, -EINVAL
);
213 return sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, true);
217 * udev_enumerate_add_nomatch_sysattr:
218 * @udev_enumerate: context
219 * @sysattr: filter for a sys attribute at the device to exclude from the list
220 * @value: optional value of the sys attribute
222 * Match only devices not having a certain /sys device attribute.
224 * Returns: 0 on success, otherwise a negative error value.
226 _public_
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate
*udev_enumerate
, const char *sysattr
, const char *value
) {
227 assert_return(udev_enumerate
, -EINVAL
);
232 return sd_device_enumerator_add_match_sysattr(udev_enumerate
->enumerator
, sysattr
, value
, false);
236 * udev_enumerate_add_match_property:
237 * @udev_enumerate: context
238 * @property: filter for a property of the device to include in the list
239 * @value: value of the property
241 * Match only devices with a certain property.
243 * Returns: 0 on success, otherwise a negative error value.
245 _public_
int udev_enumerate_add_match_property(struct udev_enumerate
*udev_enumerate
, const char *property
, const char *value
) {
246 assert_return(udev_enumerate
, -EINVAL
);
251 return sd_device_enumerator_add_match_property(udev_enumerate
->enumerator
, property
, value
);
255 * udev_enumerate_add_match_tag:
256 * @udev_enumerate: context
257 * @tag: filter for a tag of the device to include in the list
259 * Match only devices with a certain tag.
261 * Returns: 0 on success, otherwise a negative error value.
263 _public_
int udev_enumerate_add_match_tag(struct udev_enumerate
*udev_enumerate
, const char *tag
) {
264 assert_return(udev_enumerate
, -EINVAL
);
269 return sd_device_enumerator_add_match_tag(udev_enumerate
->enumerator
, tag
);
273 * udev_enumerate_add_match_parent:
274 * @udev_enumerate: context
275 * @parent: parent device where to start searching
277 * Return the devices on the subtree of one given device. The parent
278 * itself is included in the list.
280 * Returns: 0 on success, otherwise a negative error value.
282 _public_
int udev_enumerate_add_match_parent(struct udev_enumerate
*udev_enumerate
, struct udev_device
*parent
) {
283 assert_return(udev_enumerate
, -EINVAL
);
288 return sd_device_enumerator_add_match_parent(udev_enumerate
->enumerator
, parent
->device
);
292 * udev_enumerate_add_match_is_initialized:
293 * @udev_enumerate: context
295 * Match only devices which udev has set up already. This makes
296 * sure, that the device node permissions and context are properly set
297 * and that network devices are fully renamed.
299 * Usually, devices which are found in the kernel but not already
300 * handled by udev, have still pending events. Services should subscribe
301 * to monitor events and wait for these devices to become ready, instead
302 * of using uninitialized devices.
304 * For now, this will not affect devices which do not have a device node
305 * and are not network interfaces.
307 * Returns: 0 on success, otherwise a negative error value.
309 _public_
int udev_enumerate_add_match_is_initialized(struct udev_enumerate
*udev_enumerate
) {
310 assert_return(udev_enumerate
, -EINVAL
);
312 return device_enumerator_add_match_is_initialized(udev_enumerate
->enumerator
);
316 * udev_enumerate_add_match_sysname:
317 * @udev_enumerate: context
318 * @sysname: filter for the name of the device to include in the list
320 * Match only devices with a given /sys device name.
322 * Returns: 0 on success, otherwise a negative error value.
324 _public_
int udev_enumerate_add_match_sysname(struct udev_enumerate
*udev_enumerate
, const char *sysname
) {
325 assert_return(udev_enumerate
, -EINVAL
);
330 return sd_device_enumerator_add_match_sysname(udev_enumerate
->enumerator
, sysname
);
334 * udev_enumerate_add_syspath:
335 * @udev_enumerate: context
336 * @syspath: path of a device
338 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
340 * Returns: 0 on success, otherwise a negative error value.
342 _public_
int udev_enumerate_add_syspath(struct udev_enumerate
*udev_enumerate
, const char *syspath
) {
343 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
346 assert_return(udev_enumerate
, -EINVAL
);
351 r
= sd_device_new_from_syspath(&device
, syspath
);
355 r
= device_enumerator_add_device(udev_enumerate
->enumerator
, device
);
363 * udev_enumerate_scan_devices:
364 * @udev_enumerate: udev enumeration context
366 * Scan /sys for all devices which match the given filters. No matches
367 * will return all currently available devices.
369 * Returns: 0 on success, otherwise a negative error value.
371 _public_
int udev_enumerate_scan_devices(struct udev_enumerate
*udev_enumerate
) {
372 assert_return(udev_enumerate
, -EINVAL
);
374 return device_enumerator_scan_devices(udev_enumerate
->enumerator
);
378 * udev_enumerate_scan_subsystems:
379 * @udev_enumerate: udev enumeration context
381 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
383 * Returns: 0 on success, otherwise a negative error value.
385 _public_
int udev_enumerate_scan_subsystems(struct udev_enumerate
*udev_enumerate
) {
386 assert_return(udev_enumerate
, -EINVAL
);
388 return device_enumerator_scan_subsystems(udev_enumerate
->enumerator
);