]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libudev/libudev-enumerate.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libudev / libudev-enumerate.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
88a6477e
KS
2/***
3 This file is part of systemd.
4
5 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
c32eb440 6 Copyright 2015 Tom Gundersen <teg@jklm.no>
88a6477e
KS
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
eb1f0e66 21
eb1f0e66 22#include <dirent.h>
07630cea 23#include <errno.h>
c97f839e 24#include <fnmatch.h>
871a36bd 25#include <stdbool.h>
07630cea
LP
26#include <stddef.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
eb1f0e66
KS
30#include <sys/stat.h>
31
b4bbcaa9 32#include "libudev.h"
c32eb440 33#include "sd-device.h"
c32eb440 34
b5efdb8a 35#include "alloc-util.h"
07630cea
LP
36#include "device-enumerator-private.h"
37#include "device-util.h"
38#include "libudev-device-internal.h"
eb1f0e66 39
ce1d6d7f
KS
40/**
41 * SECTION:libudev-enumerate
42 * @short_description: lookup and sort sys devices
43 *
44 * Lookup devices in the sys filesystem, filter devices by properties,
a7c140c7 45 * and return a sorted list of devices.
ce1d6d7f
KS
46 */
47
48/**
49 * udev_enumerate:
50 *
51 * Opaque object representing one device lookup/sort context.
52 */
bf7ad0ea 53struct udev_enumerate {
912541b0
KS
54 struct udev *udev;
55 int refcount;
912541b0 56 struct udev_list devices_list;
912541b0 57 bool devices_uptodate:1;
c32eb440
TG
58
59 sd_device_enumerator *enumerator;
bf7ad0ea
KS
60};
61
c97f839e
KS
62/**
63 * udev_enumerate_new:
64 * @udev: udev library context
65 *
21dbe43a
KS
66 * Create an enumeration context to scan /sys.
67 *
68 * Returns: an enumeration context.
c97f839e 69 **/
c32eb440 70_public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
dee5e0b6
TG
71 _cleanup_free_ struct udev_enumerate *udev_enumerate = NULL;
72 struct udev_enumerate *ret;
c32eb440
TG
73 int r;
74
75 assert_return_errno(udev, NULL, EINVAL);
c97f839e 76
955d98c9 77 udev_enumerate = new0(struct udev_enumerate, 1);
c32eb440
TG
78 if (!udev_enumerate) {
79 errno = ENOMEM;
80 return NULL;
81 }
82
83 r = sd_device_enumerator_new(&udev_enumerate->enumerator);
84 if (r < 0) {
dee5e0b6
TG
85 errno = -r;
86 return NULL;
87 }
88
89 r = sd_device_enumerator_allow_uninitialized(udev_enumerate->enumerator);
90 if (r < 0) {
c32eb440 91 errno = -r;
912541b0 92 return NULL;
c32eb440
TG
93 }
94
912541b0
KS
95 udev_enumerate->refcount = 1;
96 udev_enumerate->udev = udev;
c32eb440 97
912541b0 98 udev_list_init(udev, &udev_enumerate->devices_list, false);
c32eb440 99
dee5e0b6
TG
100 ret = udev_enumerate;
101 udev_enumerate = NULL;
102
103 return ret;
c97f839e
KS
104}
105
ce1d6d7f
KS
106/**
107 * udev_enumerate_ref:
108 * @udev_enumerate: context
109 *
110 * Take a reference of a enumeration context.
111 *
112 * Returns: the passed enumeration context
113 **/
c32eb440
TG
114_public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) {
115 if (udev_enumerate)
313cefa1 116 udev_enumerate->refcount++;
c32eb440 117
912541b0 118 return udev_enumerate;
bf7ad0ea
KS
119}
120
ce1d6d7f
KS
121/**
122 * udev_enumerate_unref:
123 * @udev_enumerate: context
124 *
125 * Drop a reference of an enumeration context. If the refcount reaches zero,
126 * all resources of the enumeration context will be released.
c1959569 127 *
725d7e6c 128 * Returns: #NULL
ce1d6d7f 129 **/
c32eb440
TG
130_public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) {
131 if (udev_enumerate && (-- udev_enumerate->refcount) == 0) {
132 udev_list_cleanup(&udev_enumerate->devices_list);
133 sd_device_enumerator_unref(udev_enumerate->enumerator);
134 free(udev_enumerate);
135 }
912541b0 136
20bbd54f 137 return NULL;
bf7ad0ea
KS
138}
139
ce1d6d7f
KS
140/**
141 * udev_enumerate_get_udev:
142 * @udev_enumerate: context
143 *
21dbe43a
KS
144 * Get the udev library context.
145 *
146 * Returns: a pointer to the context.
ce1d6d7f 147 */
c32eb440
TG
148_public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
149 assert_return_errno(udev_enumerate, NULL, EINVAL);
3bf76824 150
c32eb440 151 return udev_enumerate->udev;
3bf76824
LP
152}
153
a7c140c7
KS
154/**
155 * udev_enumerate_get_list_entry:
156 * @udev_enumerate: context
157 *
21dbe43a
KS
158 * Get the first entry of the sorted list of device paths.
159 *
160 * Returns: a udev_list_entry.
a7c140c7 161 */
c32eb440 162_public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
309f631d
LP
163 struct udev_list_entry *e;
164
c32eb440
TG
165 assert_return_errno(udev_enumerate, NULL, EINVAL);
166
912541b0 167 if (!udev_enumerate->devices_uptodate) {
c32eb440 168 sd_device *device;
912541b0
KS
169
170 udev_list_cleanup(&udev_enumerate->devices_list);
912541b0 171
c32eb440
TG
172 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) {
173 const char *syspath;
174 int r;
912541b0 175
c32eb440
TG
176 r = sd_device_get_syspath(device, &syspath);
177 if (r < 0) {
178 errno = -r;
179 return NULL;
912541b0
KS
180 }
181
c32eb440 182 udev_list_entry_add(&udev_enumerate->devices_list, syspath, NULL);
912541b0 183 }
912541b0
KS
184
185 udev_enumerate->devices_uptodate = true;
186 }
c32eb440 187
309f631d
LP
188 e = udev_list_get_entry(&udev_enumerate->devices_list);
189 if (!e)
190 errno = ENODATA;
191
192 return e;
bf7ad0ea
KS
193}
194
a7c140c7
KS
195/**
196 * udev_enumerate_add_match_subsystem:
197 * @udev_enumerate: context
198 * @subsystem: filter for a subsystem of the device to include in the list
199 *
21dbe43a
KS
200 * Match only devices belonging to a certain kernel subsystem.
201 *
a7c140c7
KS
202 * Returns: 0 on success, otherwise a negative error value.
203 */
c32eb440
TG
204_public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
205 assert_return(udev_enumerate, -EINVAL);
206
54f0b4d9
TG
207 if (!subsystem)
208 return 0;
209
c32eb440 210 return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true);
c97f839e
KS
211}
212
a7c140c7
KS
213/**
214 * udev_enumerate_add_nomatch_subsystem:
215 * @udev_enumerate: context
216 * @subsystem: filter for a subsystem of the device to exclude from the list
217 *
21dbe43a
KS
218 * Match only devices not belonging to a certain kernel subsystem.
219 *
a7c140c7
KS
220 * Returns: 0 on success, otherwise a negative error value.
221 */
c32eb440
TG
222_public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
223 assert_return(udev_enumerate, -EINVAL);
224
54f0b4d9
TG
225 if (!subsystem)
226 return 0;
227
c32eb440 228 return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false);
c97f839e
KS
229}
230
a7c140c7
KS
231/**
232 * udev_enumerate_add_match_sysattr:
233 * @udev_enumerate: context
234 * @sysattr: filter for a sys attribute at the device to include in the list
235 * @value: optional value of the sys attribute
236 *
21dbe43a
KS
237 * Match only devices with a certain /sys device attribute.
238 *
a7c140c7
KS
239 * Returns: 0 on success, otherwise a negative error value.
240 */
c32eb440
TG
241_public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
242 assert_return(udev_enumerate, -EINVAL);
243
54f0b4d9
TG
244 if (!sysattr)
245 return 0;
246
c32eb440 247 return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true);
c97f839e
KS
248}
249
a7c140c7
KS
250/**
251 * udev_enumerate_add_nomatch_sysattr:
252 * @udev_enumerate: context
253 * @sysattr: filter for a sys attribute at the device to exclude from the list
254 * @value: optional value of the sys attribute
255 *
21dbe43a
KS
256 * Match only devices not having a certain /sys device attribute.
257 *
a7c140c7
KS
258 * Returns: 0 on success, otherwise a negative error value.
259 */
c32eb440
TG
260_public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
261 assert_return(udev_enumerate, -EINVAL);
c97f839e 262
54f0b4d9
TG
263 if (!sysattr)
264 return 0;
265
c32eb440 266 return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false);
c97f839e
KS
267}
268
a7c140c7
KS
269/**
270 * udev_enumerate_add_match_property:
271 * @udev_enumerate: context
272 * @property: filter for a property of the device to include in the list
273 * @value: value of the property
274 *
21dbe43a
KS
275 * Match only devices with a certain property.
276 *
a7c140c7
KS
277 * Returns: 0 on success, otherwise a negative error value.
278 */
c32eb440
TG
279_public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
280 assert_return(udev_enumerate, -EINVAL);
281
54f0b4d9
TG
282 if (!property)
283 return 0;
284
c32eb440 285 return sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value);
f0893502
KS
286}
287
28460195
KS
288/**
289 * udev_enumerate_add_match_tag:
290 * @udev_enumerate: context
291 * @tag: filter for a tag of the device to include in the list
292 *
21dbe43a
KS
293 * Match only devices with a certain tag.
294 *
28460195
KS
295 * Returns: 0 on success, otherwise a negative error value.
296 */
c32eb440
TG
297_public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
298 assert_return(udev_enumerate, -EINVAL);
299
54f0b4d9
TG
300 if (!tag)
301 return 0;
302
c32eb440 303 return sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag);
28460195
KS
304}
305
b05211fa
KS
306/**
307 * udev_enumerate_add_match_parent:
308 * @udev_enumerate: context
a07e0114 309 * @parent: parent device where to start searching
b05211fa 310 *
a07e0114
KS
311 * Return the devices on the subtree of one given device. The parent
312 * itself is included in the list.
b05211fa
KS
313 *
314 * A reference for the device is held until the udev_enumerate context
315 * is cleaned up.
316 *
317 * Returns: 0 on success, otherwise a negative error value.
318 */
c32eb440
TG
319_public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
320 assert_return(udev_enumerate, -EINVAL);
321
322 if (!parent)
912541b0 323 return 0;
c32eb440
TG
324
325 return sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, parent->device);
b05211fa
KS
326}
327
48a0170b
KS
328/**
329 * udev_enumerate_add_match_is_initialized:
330 * @udev_enumerate: context
331 *
332 * Match only devices which udev has set up already. This makes
333 * sure, that the device node permissions and context are properly set
334 * and that network devices are fully renamed.
335 *
336 * Usually, devices which are found in the kernel but not already
337 * handled by udev, have still pending events. Services should subscribe
338 * to monitor events and wait for these devices to become ready, instead
339 * of using uninitialized devices.
340 *
341 * For now, this will not affect devices which do not have a device node
342 * and are not network interfaces.
343 *
344 * Returns: 0 on success, otherwise a negative error value.
345 */
c32eb440
TG
346_public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
347 assert_return(udev_enumerate, -EINVAL);
348
dee5e0b6 349 return device_enumerator_add_match_is_initialized(udev_enumerate->enumerator);
48a0170b
KS
350}
351
cf5bd040
KS
352/**
353 * udev_enumerate_add_match_sysname:
354 * @udev_enumerate: context
355 * @sysname: filter for the name of the device to include in the list
356 *
21dbe43a
KS
357 * Match only devices with a given /sys device name.
358 *
cf5bd040
KS
359 * Returns: 0 on success, otherwise a negative error value.
360 */
c32eb440
TG
361_public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
362 assert_return(udev_enumerate, -EINVAL);
c97f839e 363
54f0b4d9
TG
364 if (!sysname)
365 return 0;
366
c32eb440 367 return sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname);
eb1f0e66
KS
368}
369
a7c140c7
KS
370/**
371 * udev_enumerate_add_syspath:
372 * @udev_enumerate: context
373 * @syspath: path of a device
374 *
375 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
376 *
377 * Returns: 0 on success, otherwise a negative error value.
378 */
c32eb440 379_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
4afd3348 380 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
c32eb440 381 int r;
b05211fa 382
c32eb440 383 assert_return(udev_enumerate, -EINVAL);
b05211fa 384
c32eb440
TG
385 if (!syspath)
386 return 0;
6ed03d1e 387
c32eb440
TG
388 r = sd_device_new_from_syspath(&device, syspath);
389 if (r < 0)
390 return r;
6ed03d1e 391
19c9df44 392 r = device_enumerator_add_device(udev_enumerate->enumerator, device);
c32eb440
TG
393 if (r < 0)
394 return r;
b05211fa 395
912541b0 396 return 0;
eb1f0e66 397}
bc8184ed 398
b05211fa
KS
399/**
400 * udev_enumerate_scan_devices:
401 * @udev_enumerate: udev enumeration context
402 *
21dbe43a
KS
403 * Scan /sys for all devices which match the given filters. No matches
404 * will return all currently available devices.
405 *
b05211fa
KS
406 * Returns: 0 on success, otherwise a negative error value.
407 **/
c32eb440
TG
408_public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) {
409 assert_return(udev_enumerate, -EINVAL);
b05211fa 410
c32eb440 411 return device_enumerator_scan_devices(udev_enumerate->enumerator);
b05211fa
KS
412}
413
438d4c3c
KS
414/**
415 * udev_enumerate_scan_subsystems:
416 * @udev_enumerate: udev enumeration context
417 *
21dbe43a
KS
418 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
419 *
a7c140c7 420 * Returns: 0 on success, otherwise a negative error value.
438d4c3c 421 **/
c32eb440
TG
422_public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) {
423 assert_return(udev_enumerate, -EINVAL);
424
425 return device_enumerator_scan_subsystems(udev_enumerate->enumerator);
bc8184ed 426}