]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libudev/libudev-enumerate.c
libudev: accept NULL as the argument 'struct udev*' for udev_monitor_new() or friends
[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
KS
35 struct udev *udev;
36 int refcount;
912541b0 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) {
dee5e0b6 52 _cleanup_free_ struct udev_enumerate *udev_enumerate = NULL;
c32eb440
TG
53 int r;
54
955d98c9 55 udev_enumerate = new0(struct udev_enumerate, 1);
c32eb440
TG
56 if (!udev_enumerate) {
57 errno = ENOMEM;
58 return NULL;
59 }
60
61 r = sd_device_enumerator_new(&udev_enumerate->enumerator);
62 if (r < 0) {
dee5e0b6
TG
63 errno = -r;
64 return NULL;
65 }
66
67 r = sd_device_enumerator_allow_uninitialized(udev_enumerate->enumerator);
68 if (r < 0) {
c32eb440 69 errno = -r;
912541b0 70 return NULL;
c32eb440
TG
71 }
72
912541b0
KS
73 udev_enumerate->refcount = 1;
74 udev_enumerate->udev = udev;
c32eb440 75
912541b0 76 udev_list_init(udev, &udev_enumerate->devices_list, false);
c32eb440 77
ae2a15bc 78 return TAKE_PTR(udev_enumerate);
c97f839e
KS
79}
80
ce1d6d7f
KS
81/**
82 * udev_enumerate_ref:
83 * @udev_enumerate: context
84 *
85 * Take a reference of a enumeration context.
86 *
87 * Returns: the passed enumeration context
88 **/
c32eb440
TG
89_public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) {
90 if (udev_enumerate)
313cefa1 91 udev_enumerate->refcount++;
c32eb440 92
912541b0 93 return udev_enumerate;
bf7ad0ea
KS
94}
95
ce1d6d7f
KS
96/**
97 * udev_enumerate_unref:
98 * @udev_enumerate: context
99 *
100 * Drop a reference of an enumeration context. If the refcount reaches zero,
101 * all resources of the enumeration context will be released.
c1959569 102 *
725d7e6c 103 * Returns: #NULL
ce1d6d7f 104 **/
c32eb440
TG
105_public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) {
106 if (udev_enumerate && (-- udev_enumerate->refcount) == 0) {
107 udev_list_cleanup(&udev_enumerate->devices_list);
108 sd_device_enumerator_unref(udev_enumerate->enumerator);
109 free(udev_enumerate);
110 }
912541b0 111
20bbd54f 112 return NULL;
bf7ad0ea
KS
113}
114
ce1d6d7f
KS
115/**
116 * udev_enumerate_get_udev:
117 * @udev_enumerate: context
118 *
21dbe43a
KS
119 * Get the udev library context.
120 *
121 * Returns: a pointer to the context.
ce1d6d7f 122 */
c32eb440
TG
123_public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
124 assert_return_errno(udev_enumerate, NULL, EINVAL);
3bf76824 125
c32eb440 126 return udev_enumerate->udev;
3bf76824
LP
127}
128
a7c140c7
KS
129/**
130 * udev_enumerate_get_list_entry:
131 * @udev_enumerate: context
132 *
21dbe43a
KS
133 * Get the first entry of the sorted list of device paths.
134 *
135 * Returns: a udev_list_entry.
a7c140c7 136 */
c32eb440 137_public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
309f631d
LP
138 struct udev_list_entry *e;
139
c32eb440
TG
140 assert_return_errno(udev_enumerate, NULL, EINVAL);
141
912541b0 142 if (!udev_enumerate->devices_uptodate) {
c32eb440 143 sd_device *device;
912541b0
KS
144
145 udev_list_cleanup(&udev_enumerate->devices_list);
912541b0 146
c32eb440
TG
147 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) {
148 const char *syspath;
149 int r;
912541b0 150
c32eb440
TG
151 r = sd_device_get_syspath(device, &syspath);
152 if (r < 0) {
153 errno = -r;
154 return NULL;
912541b0
KS
155 }
156
c32eb440 157 udev_list_entry_add(&udev_enumerate->devices_list, syspath, NULL);
912541b0 158 }
912541b0
KS
159
160 udev_enumerate->devices_uptodate = true;
161 }
c32eb440 162
309f631d
LP
163 e = udev_list_get_entry(&udev_enumerate->devices_list);
164 if (!e)
165 errno = ENODATA;
166
167 return e;
bf7ad0ea
KS
168}
169
a7c140c7
KS
170/**
171 * udev_enumerate_add_match_subsystem:
172 * @udev_enumerate: context
173 * @subsystem: filter for a subsystem of the device to include in the list
174 *
21dbe43a
KS
175 * Match only devices belonging to a certain kernel subsystem.
176 *
a7c140c7
KS
177 * Returns: 0 on success, otherwise a negative error value.
178 */
c32eb440
TG
179_public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
180 assert_return(udev_enumerate, -EINVAL);
181
54f0b4d9
TG
182 if (!subsystem)
183 return 0;
184
c32eb440 185 return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true);
c97f839e
KS
186}
187
a7c140c7
KS
188/**
189 * udev_enumerate_add_nomatch_subsystem:
190 * @udev_enumerate: context
191 * @subsystem: filter for a subsystem of the device to exclude from the list
192 *
21dbe43a
KS
193 * Match only devices not belonging to a certain kernel subsystem.
194 *
a7c140c7
KS
195 * Returns: 0 on success, otherwise a negative error value.
196 */
c32eb440
TG
197_public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
198 assert_return(udev_enumerate, -EINVAL);
199
54f0b4d9
TG
200 if (!subsystem)
201 return 0;
202
c32eb440 203 return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false);
c97f839e
KS
204}
205
a7c140c7
KS
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 *
21dbe43a
KS
212 * Match only devices with a certain /sys device attribute.
213 *
a7c140c7
KS
214 * Returns: 0 on success, otherwise a negative error value.
215 */
c32eb440
TG
216_public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
217 assert_return(udev_enumerate, -EINVAL);
218
54f0b4d9
TG
219 if (!sysattr)
220 return 0;
221
c32eb440 222 return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true);
c97f839e
KS
223}
224
a7c140c7
KS
225/**
226 * udev_enumerate_add_nomatch_sysattr:
227 * @udev_enumerate: context
228 * @sysattr: filter for a sys attribute at the device to exclude from the list
229 * @value: optional value of the sys attribute
230 *
21dbe43a
KS
231 * Match only devices not having a certain /sys device attribute.
232 *
a7c140c7
KS
233 * Returns: 0 on success, otherwise a negative error value.
234 */
c32eb440
TG
235_public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
236 assert_return(udev_enumerate, -EINVAL);
c97f839e 237
54f0b4d9
TG
238 if (!sysattr)
239 return 0;
240
c32eb440 241 return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false);
c97f839e
KS
242}
243
a7c140c7
KS
244/**
245 * udev_enumerate_add_match_property:
246 * @udev_enumerate: context
247 * @property: filter for a property of the device to include in the list
248 * @value: value of the property
249 *
21dbe43a
KS
250 * Match only devices with a certain property.
251 *
a7c140c7
KS
252 * Returns: 0 on success, otherwise a negative error value.
253 */
c32eb440
TG
254_public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
255 assert_return(udev_enumerate, -EINVAL);
256
54f0b4d9
TG
257 if (!property)
258 return 0;
259
c32eb440 260 return sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value);
f0893502
KS
261}
262
28460195
KS
263/**
264 * udev_enumerate_add_match_tag:
265 * @udev_enumerate: context
266 * @tag: filter for a tag of the device to include in the list
267 *
21dbe43a
KS
268 * Match only devices with a certain tag.
269 *
28460195
KS
270 * Returns: 0 on success, otherwise a negative error value.
271 */
c32eb440
TG
272_public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
273 assert_return(udev_enumerate, -EINVAL);
274
54f0b4d9
TG
275 if (!tag)
276 return 0;
277
c32eb440 278 return sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag);
28460195
KS
279}
280
b05211fa
KS
281/**
282 * udev_enumerate_add_match_parent:
283 * @udev_enumerate: context
a07e0114 284 * @parent: parent device where to start searching
b05211fa 285 *
a07e0114
KS
286 * Return the devices on the subtree of one given device. The parent
287 * itself is included in the list.
b05211fa
KS
288 *
289 * A reference for the device is held until the udev_enumerate context
290 * is cleaned up.
291 *
292 * Returns: 0 on success, otherwise a negative error value.
293 */
c32eb440
TG
294_public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
295 assert_return(udev_enumerate, -EINVAL);
296
297 if (!parent)
912541b0 298 return 0;
c32eb440
TG
299
300 return sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, parent->device);
b05211fa
KS
301}
302
48a0170b
KS
303/**
304 * udev_enumerate_add_match_is_initialized:
305 * @udev_enumerate: context
306 *
307 * Match only devices which udev has set up already. This makes
308 * sure, that the device node permissions and context are properly set
309 * and that network devices are fully renamed.
310 *
311 * Usually, devices which are found in the kernel but not already
312 * handled by udev, have still pending events. Services should subscribe
313 * to monitor events and wait for these devices to become ready, instead
314 * of using uninitialized devices.
315 *
316 * For now, this will not affect devices which do not have a device node
317 * and are not network interfaces.
318 *
319 * Returns: 0 on success, otherwise a negative error value.
320 */
c32eb440
TG
321_public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
322 assert_return(udev_enumerate, -EINVAL);
323
dee5e0b6 324 return device_enumerator_add_match_is_initialized(udev_enumerate->enumerator);
48a0170b
KS
325}
326
cf5bd040
KS
327/**
328 * udev_enumerate_add_match_sysname:
329 * @udev_enumerate: context
330 * @sysname: filter for the name of the device to include in the list
331 *
21dbe43a
KS
332 * Match only devices with a given /sys device name.
333 *
cf5bd040
KS
334 * Returns: 0 on success, otherwise a negative error value.
335 */
c32eb440
TG
336_public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
337 assert_return(udev_enumerate, -EINVAL);
c97f839e 338
54f0b4d9
TG
339 if (!sysname)
340 return 0;
341
c32eb440 342 return sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname);
eb1f0e66
KS
343}
344
a7c140c7
KS
345/**
346 * udev_enumerate_add_syspath:
347 * @udev_enumerate: context
348 * @syspath: path of a device
349 *
350 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
351 *
352 * Returns: 0 on success, otherwise a negative error value.
353 */
c32eb440 354_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
4afd3348 355 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
c32eb440 356 int r;
b05211fa 357
c32eb440 358 assert_return(udev_enumerate, -EINVAL);
b05211fa 359
c32eb440
TG
360 if (!syspath)
361 return 0;
6ed03d1e 362
c32eb440
TG
363 r = sd_device_new_from_syspath(&device, syspath);
364 if (r < 0)
365 return r;
6ed03d1e 366
19c9df44 367 r = device_enumerator_add_device(udev_enumerate->enumerator, device);
c32eb440
TG
368 if (r < 0)
369 return r;
b05211fa 370
912541b0 371 return 0;
eb1f0e66 372}
bc8184ed 373
b05211fa
KS
374/**
375 * udev_enumerate_scan_devices:
376 * @udev_enumerate: udev enumeration context
377 *
21dbe43a
KS
378 * Scan /sys for all devices which match the given filters. No matches
379 * will return all currently available devices.
380 *
b05211fa
KS
381 * Returns: 0 on success, otherwise a negative error value.
382 **/
c32eb440
TG
383_public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) {
384 assert_return(udev_enumerate, -EINVAL);
b05211fa 385
c32eb440 386 return device_enumerator_scan_devices(udev_enumerate->enumerator);
b05211fa
KS
387}
388
438d4c3c
KS
389/**
390 * udev_enumerate_scan_subsystems:
391 * @udev_enumerate: udev enumeration context
392 *
21dbe43a
KS
393 * Scan /sys for all kernel subsystems, including buses, classes, drivers.
394 *
a7c140c7 395 * Returns: 0 on success, otherwise a negative error value.
438d4c3c 396 **/
c32eb440
TG
397_public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) {
398 assert_return(udev_enumerate, -EINVAL);
399
400 return device_enumerator_scan_subsystems(udev_enumerate->enumerator);
bc8184ed 401}