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