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