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