]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libudev/libudev-enumerate.c
cryptsetup: make type-specific checks for PKCS#11 private keys
[thirdparty/systemd.git] / src / libudev / libudev-enumerate.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
eb1f0e66 2
eb1f0e66 3#include <dirent.h>
07630cea 4#include <errno.h>
c97f839e 5#include <fnmatch.h>
871a36bd 6#include <stdbool.h>
07630cea
LP
7#include <stddef.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
eb1f0e66
KS
11#include <sys/stat.h>
12
b4bbcaa9 13#include "libudev.h"
c32eb440 14#include "sd-device.h"
c32eb440 15
b5efdb8a 16#include "alloc-util.h"
07630cea
LP
17#include "device-enumerator-private.h"
18#include "device-util.h"
19#include "libudev-device-internal.h"
538bdb48 20#include "libudev-list-internal.h"
eb1f0e66 21
ce1d6d7f
KS
22/**
23 * SECTION:libudev-enumerate
24 * @short_description: lookup and sort sys devices
25 *
26 * Lookup devices in the sys filesystem, filter devices by properties,
a7c140c7 27 * and return a sorted list of devices.
ce1d6d7f
KS
28 */
29
30/**
31 * udev_enumerate:
32 *
33 * Opaque object representing one device lookup/sort context.
34 */
bf7ad0ea 35struct udev_enumerate {
912541b0 36 struct udev *udev;
3c6ac219 37 unsigned n_ref;
dcf557f7 38 struct udev_list *devices_list;
912541b0 39 bool devices_uptodate:1;
c32eb440
TG
40
41 sd_device_enumerator *enumerator;
bf7ad0ea
KS
42};
43
c97f839e
KS
44/**
45 * udev_enumerate_new:
46 * @udev: udev library context
47 *
21dbe43a
KS
48 * Create an enumeration context to scan /sys.
49 *
50 * Returns: an enumeration context.
c97f839e 51 **/
c32eb440 52_public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
60fdee32 53 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
dcf557f7 54 _cleanup_(udev_list_freep) struct udev_list *list = NULL;
60fdee32 55 struct udev_enumerate *udev_enumerate;
c32eb440
TG
56 int r;
57
60fdee32 58 r = sd_device_enumerator_new(&e);
fd05c424
YW
59 if (r < 0)
60 return_with_errno(NULL, r);
c32eb440 61
60fdee32 62 r = sd_device_enumerator_allow_uninitialized(e);
fd05c424
YW
63 if (r < 0)
64 return_with_errno(NULL, r);
dee5e0b6 65
dcf557f7
YW
66 list = udev_list_new(false);
67 if (!list)
68 return_with_errno(NULL, ENOMEM);
69
60fdee32 70 udev_enumerate = new(struct udev_enumerate, 1);
fd05c424
YW
71 if (!udev_enumerate)
72 return_with_errno(NULL, ENOMEM);
c32eb440 73
60fdee32
YW
74 *udev_enumerate = (struct udev_enumerate) {
75 .udev = udev,
76 .n_ref = 1,
77 .enumerator = TAKE_PTR(e),
dcf557f7 78 .devices_list = TAKE_PTR(list),
60fdee32 79 };
c32eb440 80
60fdee32 81 return udev_enumerate;
c97f839e
KS
82}
83
3c6ac219
YW
84static struct udev_enumerate *udev_enumerate_free(struct udev_enumerate *udev_enumerate) {
85 assert(udev_enumerate);
86
dcf557f7 87 udev_list_free(udev_enumerate->devices_list);
3c6ac219
YW
88 sd_device_enumerator_unref(udev_enumerate->enumerator);
89 return mfree(udev_enumerate);
90}
91
ce1d6d7f
KS
92/**
93 * udev_enumerate_ref:
94 * @udev_enumerate: context
95 *
387f6955 96 * Take a reference of an enumeration context.
ce1d6d7f
KS
97 *
98 * Returns: the passed enumeration context
99 **/
bf7ad0ea 100
ce1d6d7f
KS
101/**
102 * udev_enumerate_unref:
103 * @udev_enumerate: context
104 *
105 * Drop a reference of an enumeration context. If the refcount reaches zero,
106 * all resources of the enumeration context will be released.
c1959569 107 *
725d7e6c 108 * Returns: #NULL
ce1d6d7f 109 **/
3c6ac219 110DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate, udev_enumerate, udev_enumerate_free);
bf7ad0ea 111
ce1d6d7f
KS
112/**
113 * udev_enumerate_get_udev:
114 * @udev_enumerate: context
115 *
21dbe43a
KS
116 * Get the udev library context.
117 *
118 * Returns: a pointer to the context.
ce1d6d7f 119 */
c32eb440
TG
120_public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
121 assert_return_errno(udev_enumerate, NULL, EINVAL);
3bf76824 122
c32eb440 123 return udev_enumerate->udev;
3bf76824
LP
124}
125
a7c140c7
KS
126/**
127 * udev_enumerate_get_list_entry:
128 * @udev_enumerate: context
129 *
21dbe43a
KS
130 * Get the first entry of the sorted list of device paths.
131 *
132 * Returns: a udev_list_entry.
a7c140c7 133 */
c32eb440 134_public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
309f631d
LP
135 struct udev_list_entry *e;
136
c32eb440
TG
137 assert_return_errno(udev_enumerate, NULL, EINVAL);
138
912541b0 139 if (!udev_enumerate->devices_uptodate) {
c32eb440 140 sd_device *device;
912541b0 141
dcf557f7 142 udev_list_cleanup(udev_enumerate->devices_list);
912541b0 143
c32eb440
TG
144 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) {
145 const char *syspath;
146 int r;
912541b0 147
c32eb440 148 r = sd_device_get_syspath(device, &syspath);
fd05c424
YW
149 if (r < 0)
150 return_with_errno(NULL, r);
912541b0 151
dcf557f7 152 if (!udev_list_entry_add(udev_enumerate->devices_list, syspath, NULL))
3f14e721 153 return_with_errno(NULL, ENOMEM);
912541b0 154 }
912541b0
KS
155
156 udev_enumerate->devices_uptodate = true;
157 }
c32eb440 158
dcf557f7 159 e = udev_list_get_entry(udev_enumerate->devices_list);
309f631d 160 if (!e)
fd05c424 161 return_with_errno(NULL, ENODATA);
309f631d
LP
162
163 return e;
bf7ad0ea
KS
164}
165
a7c140c7
KS
166/**
167 * udev_enumerate_add_match_subsystem:
168 * @udev_enumerate: context
169 * @subsystem: filter for a subsystem of the device to include in the list
170 *
21dbe43a
KS
171 * Match only devices belonging to a certain kernel subsystem.
172 *
a7c140c7
KS
173 * Returns: 0 on success, otherwise a negative error value.
174 */
c32eb440 175_public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
56fa3682
YW
176 int r;
177
c32eb440
TG
178 assert_return(udev_enumerate, -EINVAL);
179
54f0b4d9
TG
180 if (!subsystem)
181 return 0;
182
56fa3682
YW
183 r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true);
184 if (r < 0)
185 return r;
186
187 udev_enumerate->devices_uptodate = false;
188 return 0;
c97f839e
KS
189}
190
a7c140c7
KS
191/**
192 * udev_enumerate_add_nomatch_subsystem:
193 * @udev_enumerate: context
194 * @subsystem: filter for a subsystem of the device to exclude from the list
195 *
21dbe43a
KS
196 * Match only devices not belonging to a certain kernel subsystem.
197 *
a7c140c7
KS
198 * Returns: 0 on success, otherwise a negative error value.
199 */
c32eb440 200_public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
56fa3682
YW
201 int r;
202
c32eb440
TG
203 assert_return(udev_enumerate, -EINVAL);
204
54f0b4d9
TG
205 if (!subsystem)
206 return 0;
207
56fa3682
YW
208 r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false);
209 if (r < 0)
210 return r;
211
212 udev_enumerate->devices_uptodate = false;
213 return 0;
c97f839e
KS
214}
215
a7c140c7
KS
216/**
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
221 *
21dbe43a
KS
222 * Match only devices with a certain /sys device attribute.
223 *
a7c140c7
KS
224 * Returns: 0 on success, otherwise a negative error value.
225 */
c32eb440 226_public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
56fa3682
YW
227 int r;
228
c32eb440
TG
229 assert_return(udev_enumerate, -EINVAL);
230
54f0b4d9
TG
231 if (!sysattr)
232 return 0;
233
56fa3682
YW
234 r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true);
235 if (r < 0)
236 return r;
237
238 udev_enumerate->devices_uptodate = false;
239 return 0;
c97f839e
KS
240}
241
a7c140c7
KS
242/**
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
247 *
21dbe43a
KS
248 * Match only devices not having a certain /sys device attribute.
249 *
a7c140c7
KS
250 * Returns: 0 on success, otherwise a negative error value.
251 */
c32eb440 252_public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
56fa3682
YW
253 int r;
254
c32eb440 255 assert_return(udev_enumerate, -EINVAL);
c97f839e 256
54f0b4d9
TG
257 if (!sysattr)
258 return 0;
259
56fa3682
YW
260 r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false);
261 if (r < 0)
262 return r;
263
264 udev_enumerate->devices_uptodate = false;
265 return 0;
c97f839e
KS
266}
267
a7c140c7
KS
268/**
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
273 *
21dbe43a
KS
274 * Match only devices with a certain property.
275 *
a7c140c7
KS
276 * Returns: 0 on success, otherwise a negative error value.
277 */
c32eb440 278_public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
56fa3682
YW
279 int r;
280
c32eb440
TG
281 assert_return(udev_enumerate, -EINVAL);
282
54f0b4d9
TG
283 if (!property)
284 return 0;
285
56fa3682
YW
286 r = sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value);
287 if (r < 0)
288 return r;
289
290 udev_enumerate->devices_uptodate = false;
291 return 0;
f0893502
KS
292}
293
28460195
KS
294/**
295 * udev_enumerate_add_match_tag:
296 * @udev_enumerate: context
297 * @tag: filter for a tag of the device to include in the list
298 *
21dbe43a
KS
299 * Match only devices with a certain tag.
300 *
28460195
KS
301 * Returns: 0 on success, otherwise a negative error value.
302 */
c32eb440 303_public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
56fa3682
YW
304 int r;
305
c32eb440
TG
306 assert_return(udev_enumerate, -EINVAL);
307
54f0b4d9
TG
308 if (!tag)
309 return 0;
310
56fa3682
YW
311 r = sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag);
312 if (r < 0)
313 return r;
314
315 udev_enumerate->devices_uptodate = false;
316 return 0;
28460195
KS
317}
318
b05211fa
KS
319/**
320 * udev_enumerate_add_match_parent:
321 * @udev_enumerate: context
a07e0114 322 * @parent: parent device where to start searching
b05211fa 323 *
a07e0114
KS
324 * Return the devices on the subtree of one given device. The parent
325 * itself is included in the list.
b05211fa 326 *
b05211fa
KS
327 * Returns: 0 on success, otherwise a negative error value.
328 */
c32eb440 329_public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
56fa3682
YW
330 int r;
331
c32eb440
TG
332 assert_return(udev_enumerate, -EINVAL);
333
334 if (!parent)
912541b0 335 return 0;
c32eb440 336
538bdb48 337 r = sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, udev_device_get_sd_device(parent));
56fa3682
YW
338 if (r < 0)
339 return r;
340
341 udev_enumerate->devices_uptodate = false;
342 return 0;
b05211fa
KS
343}
344
48a0170b
KS
345/**
346 * udev_enumerate_add_match_is_initialized:
347 * @udev_enumerate: context
348 *
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.
352 *
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.
357 *
358 * For now, this will not affect devices which do not have a device node
359 * and are not network interfaces.
360 *
361 * Returns: 0 on success, otherwise a negative error value.
362 */
c32eb440 363_public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
56fa3682
YW
364 int r;
365
c32eb440
TG
366 assert_return(udev_enumerate, -EINVAL);
367
d8b50e5d 368 r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator, MATCH_INITIALIZED_COMPAT);
56fa3682
YW
369 if (r < 0)
370 return r;
371
372 udev_enumerate->devices_uptodate = false;
373 return 0;
48a0170b
KS
374}
375
cf5bd040
KS
376/**
377 * udev_enumerate_add_match_sysname:
378 * @udev_enumerate: context
379 * @sysname: filter for the name of the device to include in the list
380 *
21dbe43a
KS
381 * Match only devices with a given /sys device name.
382 *
cf5bd040
KS
383 * Returns: 0 on success, otherwise a negative error value.
384 */
c32eb440 385_public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
56fa3682
YW
386 int r;
387
c32eb440 388 assert_return(udev_enumerate, -EINVAL);
c97f839e 389
54f0b4d9
TG
390 if (!sysname)
391 return 0;
392
56fa3682
YW
393 r = sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname);
394 if (r < 0)
395 return r;
396
397 udev_enumerate->devices_uptodate = false;
398 return 0;
eb1f0e66
KS
399}
400
a7c140c7
KS
401/**
402 * udev_enumerate_add_syspath:
403 * @udev_enumerate: context
404 * @syspath: path of a device
405 *
406 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
407 *
408 * Returns: 0 on success, otherwise a negative error value.
409 */
c32eb440 410_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
4afd3348 411 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
c32eb440 412 int r;
b05211fa 413
c32eb440 414 assert_return(udev_enumerate, -EINVAL);
b05211fa 415
c32eb440
TG
416 if (!syspath)
417 return 0;
6ed03d1e 418
c32eb440
TG
419 r = sd_device_new_from_syspath(&device, syspath);
420 if (r < 0)
421 return r;
6ed03d1e 422
19c9df44 423 r = device_enumerator_add_device(udev_enumerate->enumerator, device);
c32eb440
TG
424 if (r < 0)
425 return r;
b05211fa 426
56fa3682 427 udev_enumerate->devices_uptodate = false;
912541b0 428 return 0;
eb1f0e66 429}
bc8184ed 430
b05211fa
KS
431/**
432 * udev_enumerate_scan_devices:
433 * @udev_enumerate: udev enumeration context
434 *
21dbe43a
KS
435 * Scan /sys for all devices which match the given filters. No matches
436 * will return all currently available devices.
437 *
b05211fa
KS
438 * Returns: 0 on success, otherwise a negative error value.
439 **/
c32eb440
TG
440_public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) {
441 assert_return(udev_enumerate, -EINVAL);
b05211fa 442
c32eb440 443 return device_enumerator_scan_devices(udev_enumerate->enumerator);
b05211fa
KS
444}
445
438d4c3c
KS
446/**
447 * udev_enumerate_scan_subsystems:
448 * @udev_enumerate: udev enumeration context
449 *
21dbe43a
KS
450 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
451 *
a7c140c7 452 * Returns: 0 on success, otherwise a negative error value.
438d4c3c 453 **/
c32eb440
TG
454_public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) {
455 assert_return(udev_enumerate, -EINVAL);
456
457 return device_enumerator_scan_subsystems(udev_enumerate->enumerator);
bc8184ed 458}