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