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