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