]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/gudev/gudevenumerator.c
licence: remove references to old FSF address
[thirdparty/systemd.git] / src / gudev / gudevenumerator.c
1 /* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 *
3 * Copyright (C) 2008-2010 David Zeuthen <davidz@redhat.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "gudevclient.h"
28 #include "gudevenumerator.h"
29 #include "gudevdevice.h"
30 #include "gudevmarshal.h"
31 #include "gudevprivate.h"
32
33 /**
34 * SECTION:gudevenumerator
35 * @short_description: Lookup and sort devices
36 *
37 * #GUdevEnumerator is used to lookup and sort devices.
38 *
39 * Since: 165
40 */
41
42 struct _GUdevEnumeratorPrivate
43 {
44 GUdevClient *client;
45 struct udev_enumerate *e;
46 };
47
48 enum
49 {
50 PROP_0,
51 PROP_CLIENT,
52 };
53
54 G_DEFINE_TYPE (GUdevEnumerator, g_udev_enumerator, G_TYPE_OBJECT)
55
56 /* ---------------------------------------------------------------------------------------------------- */
57
58 static void
59 g_udev_enumerator_finalize (GObject *object)
60 {
61 GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object);
62
63 if (enumerator->priv->client != NULL)
64 {
65 g_object_unref (enumerator->priv->client);
66 enumerator->priv->client = NULL;
67 }
68
69 if (enumerator->priv->e != NULL)
70 {
71 udev_enumerate_unref (enumerator->priv->e);
72 enumerator->priv->e = NULL;
73 }
74
75 if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize != NULL)
76 G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize (object);
77 }
78
79 static void
80 g_udev_enumerator_set_property (GObject *object,
81 guint prop_id,
82 const GValue *value,
83 GParamSpec *pspec)
84 {
85 GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object);
86
87 switch (prop_id)
88 {
89 case PROP_CLIENT:
90 if (enumerator->priv->client != NULL)
91 g_object_unref (enumerator->priv->client);
92 enumerator->priv->client = g_value_dup_object (value);
93 break;
94
95 default:
96 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
97 break;
98 }
99 }
100
101 static void
102 g_udev_enumerator_get_property (GObject *object,
103 guint prop_id,
104 GValue *value,
105 GParamSpec *pspec)
106 {
107 GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object);
108
109 switch (prop_id)
110 {
111 case PROP_CLIENT:
112 g_value_set_object (value, enumerator->priv->client);
113 break;
114
115 default:
116 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117 break;
118 }
119 }
120
121 static void
122 g_udev_enumerator_constructed (GObject *object)
123 {
124 GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object);
125
126 g_assert (G_UDEV_IS_CLIENT (enumerator->priv->client));
127
128 enumerator->priv->e = udev_enumerate_new (_g_udev_client_get_udev (enumerator->priv->client));
129
130 if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed != NULL)
131 G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed (object);
132 }
133
134 static void
135 g_udev_enumerator_class_init (GUdevEnumeratorClass *klass)
136 {
137 GObjectClass *gobject_class = (GObjectClass *) klass;
138
139 gobject_class->finalize = g_udev_enumerator_finalize;
140 gobject_class->set_property = g_udev_enumerator_set_property;
141 gobject_class->get_property = g_udev_enumerator_get_property;
142 gobject_class->constructed = g_udev_enumerator_constructed;
143
144 /**
145 * GUdevEnumerator:client:
146 *
147 * The #GUdevClient to enumerate devices from.
148 *
149 * Since: 165
150 */
151 g_object_class_install_property (gobject_class,
152 PROP_CLIENT,
153 g_param_spec_object ("client",
154 "The client to enumerate devices from",
155 "The client to enumerate devices from",
156 G_UDEV_TYPE_CLIENT,
157 G_PARAM_CONSTRUCT_ONLY |
158 G_PARAM_READWRITE));
159
160 g_type_class_add_private (klass, sizeof (GUdevEnumeratorPrivate));
161 }
162
163 static void
164 g_udev_enumerator_init (GUdevEnumerator *enumerator)
165 {
166 enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator,
167 G_UDEV_TYPE_ENUMERATOR,
168 GUdevEnumeratorPrivate);
169 }
170
171 /**
172 * g_udev_enumerator_new:
173 * @client: A #GUdevClient to enumerate devices from.
174 *
175 * Constructs a #GUdevEnumerator object that can be used to enumerate
176 * and sort devices. Use the add_match_*() and add_nomatch_*() methods
177 * and execute the query to get a list of devices with
178 * g_udev_enumerator_execute().
179 *
180 * Returns: A new #GUdevEnumerator object. Free with g_object_unref().
181 *
182 * Since: 165
183 */
184 GUdevEnumerator *
185 g_udev_enumerator_new (GUdevClient *client)
186 {
187 g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL);
188 return G_UDEV_ENUMERATOR (g_object_new (G_UDEV_TYPE_ENUMERATOR, "client", client, NULL));
189 }
190
191
192 /**
193 * g_udev_enumerator_add_match_subsystem:
194 * @enumerator: A #GUdevEnumerator.
195 * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'.
196 *
197 * All returned devices will match the given @subsystem.
198 *
199 * Returns: (transfer none): The passed in @enumerator.
200 *
201 * Since: 165
202 */
203 GUdevEnumerator *
204 g_udev_enumerator_add_match_subsystem (GUdevEnumerator *enumerator,
205 const gchar *subsystem)
206 {
207 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
208 g_return_val_if_fail (subsystem != NULL, NULL);
209 udev_enumerate_add_match_subsystem (enumerator->priv->e, subsystem);
210 return enumerator;
211 }
212
213 /**
214 * g_udev_enumerator_add_nomatch_subsystem:
215 * @enumerator: A #GUdevEnumerator.
216 * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'.
217 *
218 * All returned devices will not match the given @subsystem.
219 *
220 * Returns: (transfer none): The passed in @enumerator.
221 *
222 * Since: 165
223 */
224 GUdevEnumerator *
225 g_udev_enumerator_add_nomatch_subsystem (GUdevEnumerator *enumerator,
226 const gchar *subsystem)
227 {
228 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
229 g_return_val_if_fail (subsystem != NULL, NULL);
230 udev_enumerate_add_nomatch_subsystem (enumerator->priv->e, subsystem);
231 return enumerator;
232 }
233
234 /**
235 * g_udev_enumerator_add_match_sysfs_attr:
236 * @enumerator: A #GUdevEnumerator.
237 * @name: Wildcard filter for sysfs attribute key.
238 * @value: Wildcard filter for sysfs attribute value.
239 *
240 * All returned devices will have a sysfs attribute matching the given @name and @value.
241 *
242 * Returns: (transfer none): The passed in @enumerator.
243 *
244 * Since: 165
245 */
246 GUdevEnumerator *
247 g_udev_enumerator_add_match_sysfs_attr (GUdevEnumerator *enumerator,
248 const gchar *name,
249 const gchar *value)
250 {
251 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
252 g_return_val_if_fail (name != NULL, NULL);
253 g_return_val_if_fail (value != NULL, NULL);
254 udev_enumerate_add_match_sysattr (enumerator->priv->e, name, value);
255 return enumerator;
256 }
257
258 /**
259 * g_udev_enumerator_add_nomatch_sysfs_attr:
260 * @enumerator: A #GUdevEnumerator.
261 * @name: Wildcard filter for sysfs attribute key.
262 * @value: Wildcard filter for sysfs attribute value.
263 *
264 * All returned devices will not have a sysfs attribute matching the given @name and @value.
265 *
266 * Returns: (transfer none): The passed in @enumerator.
267 *
268 * Since: 165
269 */
270 GUdevEnumerator *
271 g_udev_enumerator_add_nomatch_sysfs_attr (GUdevEnumerator *enumerator,
272 const gchar *name,
273 const gchar *value)
274 {
275 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
276 g_return_val_if_fail (name != NULL, NULL);
277 g_return_val_if_fail (value != NULL, NULL);
278 udev_enumerate_add_nomatch_sysattr (enumerator->priv->e, name, value);
279 return enumerator;
280 }
281
282 /**
283 * g_udev_enumerator_add_match_property:
284 * @enumerator: A #GUdevEnumerator.
285 * @name: Wildcard filter for property name.
286 * @value: Wildcard filter for property value.
287 *
288 * All returned devices will have a property matching the given @name and @value.
289 *
290 * Returns: (transfer none): The passed in @enumerator.
291 *
292 * Since: 165
293 */
294 GUdevEnumerator *
295 g_udev_enumerator_add_match_property (GUdevEnumerator *enumerator,
296 const gchar *name,
297 const gchar *value)
298 {
299 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
300 g_return_val_if_fail (name != NULL, NULL);
301 g_return_val_if_fail (value != NULL, NULL);
302 udev_enumerate_add_match_property (enumerator->priv->e, name, value);
303 return enumerator;
304 }
305
306 /**
307 * g_udev_enumerator_add_match_name:
308 * @enumerator: A #GUdevEnumerator.
309 * @name: Wildcard filter for kernel name e.g. "sda*".
310 *
311 * All returned devices will match the given @name.
312 *
313 * Returns: (transfer none): The passed in @enumerator.
314 *
315 * Since: 165
316 */
317 GUdevEnumerator *
318 g_udev_enumerator_add_match_name (GUdevEnumerator *enumerator,
319 const gchar *name)
320 {
321 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
322 g_return_val_if_fail (name != NULL, NULL);
323 udev_enumerate_add_match_sysname (enumerator->priv->e, name);
324 return enumerator;
325 }
326
327 /**
328 * g_udev_enumerator_add_sysfs_path:
329 * @enumerator: A #GUdevEnumerator.
330 * @sysfs_path: A sysfs path, e.g. "/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda"
331 *
332 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
333 *
334 * Returns: (transfer none): The passed in @enumerator.
335 *
336 * Since: 165
337 */
338 GUdevEnumerator *
339 g_udev_enumerator_add_sysfs_path (GUdevEnumerator *enumerator,
340 const gchar *sysfs_path)
341 {
342 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
343 g_return_val_if_fail (sysfs_path != NULL, NULL);
344 udev_enumerate_add_syspath (enumerator->priv->e, sysfs_path);
345 return enumerator;
346 }
347
348 /**
349 * g_udev_enumerator_add_match_tag:
350 * @enumerator: A #GUdevEnumerator.
351 * @tag: A udev tag e.g. "udev-acl".
352 *
353 * All returned devices will match the given @tag.
354 *
355 * Returns: (transfer none): The passed in @enumerator.
356 *
357 * Since: 165
358 */
359 GUdevEnumerator *
360 g_udev_enumerator_add_match_tag (GUdevEnumerator *enumerator,
361 const gchar *tag)
362 {
363 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
364 g_return_val_if_fail (tag != NULL, NULL);
365 udev_enumerate_add_match_tag (enumerator->priv->e, tag);
366 return enumerator;
367 }
368
369 /**
370 * g_udev_enumerator_add_match_is_initialized:
371 * @enumerator: A #GUdevEnumerator.
372 *
373 * All returned devices will be initialized.
374 *
375 * Returns: (transfer none): The passed in @enumerator.
376 *
377 * Since: 165
378 */
379 GUdevEnumerator *
380 g_udev_enumerator_add_match_is_initialized (GUdevEnumerator *enumerator)
381 {
382 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
383 udev_enumerate_add_match_is_initialized (enumerator->priv->e);
384 return enumerator;
385 }
386
387 /**
388 * g_udev_enumerator_execute:
389 * @enumerator: A #GUdevEnumerator.
390 *
391 * Executes the query in @enumerator.
392 *
393 * Returns: (element-type GUdevDevice) (transfer full): A list of #GUdevDevice objects. The caller should free the result by using g_object_unref() on each element in the list and then g_list_free() on the list.
394 *
395 * Since: 165
396 */
397 GList *
398 g_udev_enumerator_execute (GUdevEnumerator *enumerator)
399 {
400 GList *ret;
401 struct udev_list_entry *l, *devices;
402
403 g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL);
404
405 ret = NULL;
406
407 /* retrieve the list */
408 udev_enumerate_scan_devices (enumerator->priv->e);
409
410 devices = udev_enumerate_get_list_entry (enumerator->priv->e);
411 for (l = devices; l != NULL; l = udev_list_entry_get_next (l))
412 {
413 struct udev_device *udevice;
414 GUdevDevice *device;
415
416 udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator->priv->e),
417 udev_list_entry_get_name (l));
418 if (udevice == NULL)
419 continue;
420
421 device = _g_udev_device_new (udevice);
422 udev_device_unref (udevice);
423 ret = g_list_prepend (ret, device);
424 }
425
426 ret = g_list_reverse (ret);
427
428 return ret;
429 }