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