]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/libudev/libudev-enumerate.c
systemd-analyze: added the verb unit-shell to spawn and attach shell
[thirdparty/systemd.git] / src / libudev / libudev-enumerate.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include "libudev.h"
4#include "sd-device.h"
5
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"
11
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,
17 * and return a sorted list of devices.
18 */
19
20/**
21 * udev_enumerate:
22 *
23 * Opaque object representing one device lookup/sort context.
24 */
25struct udev_enumerate {
26 struct udev *udev;
27 unsigned n_ref;
28 struct udev_list *devices_list;
29 bool devices_uptodate:1;
30
31 sd_device_enumerator *enumerator;
32};
33
34/**
35 * udev_enumerate_new:
36 * @udev: udev library context
37 *
38 * Create an enumeration context to scan /sys.
39 *
40 * Returns: an enumeration context.
41 **/
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;
46 int r;
47
48 r = sd_device_enumerator_new(&e);
49 if (r < 0)
50 return_with_errno(NULL, r);
51
52 r = sd_device_enumerator_allow_uninitialized(e);
53 if (r < 0)
54 return_with_errno(NULL, r);
55
56 list = udev_list_new(false);
57 if (!list)
58 return_with_errno(NULL, ENOMEM);
59
60 udev_enumerate = new(struct udev_enumerate, 1);
61 if (!udev_enumerate)
62 return_with_errno(NULL, ENOMEM);
63
64 *udev_enumerate = (struct udev_enumerate) {
65 .udev = udev,
66 .n_ref = 1,
67 .enumerator = TAKE_PTR(e),
68 .devices_list = TAKE_PTR(list),
69 };
70
71 return udev_enumerate;
72}
73
74static struct udev_enumerate* udev_enumerate_free(struct udev_enumerate *udev_enumerate) {
75 assert(udev_enumerate);
76
77 udev_list_free(udev_enumerate->devices_list);
78 sd_device_enumerator_unref(udev_enumerate->enumerator);
79 return mfree(udev_enumerate);
80}
81
82/**
83 * udev_enumerate_ref:
84 * @udev_enumerate: context
85 *
86 * Take a reference of an enumeration context.
87 *
88 * Returns: the passed enumeration context
89 **/
90
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.
97 *
98 * Returns: #NULL
99 **/
100DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate, udev_enumerate, udev_enumerate_free);
101
102/**
103 * udev_enumerate_get_udev:
104 * @udev_enumerate: context
105 *
106 * Get the udev library context.
107 *
108 * Returns: a pointer to the context.
109 */
110_public_ struct udev* udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
111 assert_return_errno(udev_enumerate, NULL, EINVAL);
112
113 return udev_enumerate->udev;
114}
115
116/**
117 * udev_enumerate_get_list_entry:
118 * @udev_enumerate: context
119 *
120 * Get the first entry of the sorted list of device paths.
121 *
122 * Returns: a udev_list_entry.
123 */
124_public_ struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
125 struct udev_list_entry *e;
126
127 assert_return_errno(udev_enumerate, NULL, EINVAL);
128
129 if (!udev_enumerate->devices_uptodate) {
130 sd_device *device;
131
132 udev_list_cleanup(udev_enumerate->devices_list);
133
134 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) {
135 const char *syspath;
136 int r;
137
138 r = sd_device_get_syspath(device, &syspath);
139 if (r < 0)
140 return_with_errno(NULL, r);
141
142 if (!udev_list_entry_add(udev_enumerate->devices_list, syspath, NULL))
143 return_with_errno(NULL, ENOMEM);
144 }
145
146 udev_enumerate->devices_uptodate = true;
147 }
148
149 e = udev_list_get_entry(udev_enumerate->devices_list);
150 if (!e)
151 return_with_errno(NULL, ENODATA);
152
153 return e;
154}
155
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 *
161 * Match only devices belonging to a certain kernel subsystem.
162 *
163 * Returns: 0 on success, otherwise a negative error value.
164 */
165_public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
166 int r;
167
168 assert_return(udev_enumerate, -EINVAL);
169
170 if (!subsystem)
171 return 0;
172
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;
179}
180
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 *
186 * Match only devices not belonging to a certain kernel subsystem.
187 *
188 * Returns: 0 on success, otherwise a negative error value.
189 */
190_public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
191 int r;
192
193 assert_return(udev_enumerate, -EINVAL);
194
195 if (!subsystem)
196 return 0;
197
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;
204}
205
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 *
212 * Match only devices with a certain /sys device attribute.
213 *
214 * Returns: 0 on success, otherwise a negative error value.
215 */
216_public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
217 int r;
218
219 assert_return(udev_enumerate, -EINVAL);
220
221 if (!sysattr)
222 return 0;
223
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;
230}
231
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 *
238 * Match only devices not having a certain /sys device attribute.
239 *
240 * Returns: 0 on success, otherwise a negative error value.
241 */
242_public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
243 int r;
244
245 assert_return(udev_enumerate, -EINVAL);
246
247 if (!sysattr)
248 return 0;
249
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;
256}
257
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 *
264 * Match only devices with a certain property.
265 *
266 * Returns: 0 on success, otherwise a negative error value.
267 */
268_public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
269 int r;
270
271 assert_return(udev_enumerate, -EINVAL);
272
273 if (!property)
274 return 0;
275
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;
282}
283
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 *
289 * Match only devices with a certain tag.
290 *
291 * Returns: 0 on success, otherwise a negative error value.
292 */
293_public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
294 int r;
295
296 assert_return(udev_enumerate, -EINVAL);
297
298 if (!tag)
299 return 0;
300
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;
307}
308
309/**
310 * udev_enumerate_add_match_parent:
311 * @udev_enumerate: context
312 * @parent: parent device where to start searching
313 *
314 * Return the devices on the subtree of one given device. The parent
315 * itself is included in the list.
316 *
317 * Returns: 0 on success, otherwise a negative error value.
318 */
319_public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
320 int r;
321
322 assert_return(udev_enumerate, -EINVAL);
323
324 if (!parent)
325 return 0;
326
327 r = sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, udev_device_get_sd_device(parent));
328 if (r < 0)
329 return r;
330
331 udev_enumerate->devices_uptodate = false;
332 return 0;
333}
334
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 */
353_public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
354 int r;
355
356 assert_return(udev_enumerate, -EINVAL);
357
358 r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator, MATCH_INITIALIZED_COMPAT);
359 if (r < 0)
360 return r;
361
362 udev_enumerate->devices_uptodate = false;
363 return 0;
364}
365
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 *
371 * Match only devices with a given /sys device name.
372 *
373 * Returns: 0 on success, otherwise a negative error value.
374 */
375_public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
376 int r;
377
378 assert_return(udev_enumerate, -EINVAL);
379
380 if (!sysname)
381 return 0;
382
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;
389}
390
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 */
400_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
401 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
402 int r;
403
404 assert_return(udev_enumerate, -EINVAL);
405
406 if (!syspath)
407 return 0;
408
409 r = sd_device_new_from_syspath(&device, syspath);
410 if (r < 0)
411 return r;
412
413 r = device_enumerator_add_device(udev_enumerate->enumerator, device);
414 if (r < 0)
415 return r;
416
417 udev_enumerate->devices_uptodate = false;
418 return 0;
419}
420
421/**
422 * udev_enumerate_scan_devices:
423 * @udev_enumerate: udev enumeration context
424 *
425 * Scan /sys for all devices which match the given filters. No matches
426 * will return all currently available devices.
427 *
428 * Returns: 0 on success, otherwise a negative error value.
429 **/
430_public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) {
431 assert_return(udev_enumerate, -EINVAL);
432
433 return device_enumerator_scan_devices(udev_enumerate->enumerator);
434}
435
436/**
437 * udev_enumerate_scan_subsystems:
438 * @udev_enumerate: udev enumeration context
439 *
440 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
441 *
442 * Returns: 0 on success, otherwise a negative error value.
443 **/
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);
448}