1 /*
2 * g-udisks-volume-monitor.c
3 *
4 * Copyright 2010 PCMan <pcman.tw@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "dbus-utils.h"
27 #include "udisks.h"
28
29 #include "g-udisks-volume-monitor.h"
30 #include "g-udisks-device.h"
31 #include "g-udisks-drive.h"
32 #include "g-udisks-volume.h"
33
34 /* FIXME: later we need to remove this when gio-udisks becomes an
35 * independent gio module. */
36 #include "fm-config.h"
37
38 static guint sig_drive_changed;
39 static guint sig_drive_connected;
40 static guint sig_drive_disconnected;
41 static guint sig_drive_eject_button;
42 static guint sig_mount_added;
43 static guint sig_mount_changed;
44 static guint sig_mount_premount;
45 static guint sig_mount_removed;
46 static guint sig_volume_added;
47 static guint sig_volume_changed;
48 static guint sig_volume_removed;
49
50 static void g_udisks_device_added(GUDisksDevice* dev, GUDisksVolumeMonitor* mon);
51 static void g_udisks_device_changed(GUDisksDevice* dev, GUDisksVolumeMonitor* mon);
52 static void g_udisks_device_removed(GUDisksDevice* dev, GUDisksVolumeMonitor* mon);
53
54 typedef void (*GUDisksDeviceEventHandler)(GUDisksDevice*, GUDisksVolumeMonitor*);
55
56 typedef struct
57 {
58 GUDisksDevice* dev;
59 GUDisksDeviceEventHandler func;
60 }QueuedEvent;
61
62 static void g_udisks_volume_monitor_finalize (GObject *object);
63 static GMount* get_mount_for_mount_path(const char *mount_path, GCancellable *cancellable);
64
65 static gboolean is_supported(void);
66 static GList* get_connected_drives(GVolumeMonitor *mon);
67 static GList* get_volumes(GVolumeMonitor *mon);
68 static GList* get_mounts(GVolumeMonitor *mon);
69 static GVolume *get_volume_for_uuid(GVolumeMonitor *mon, const char *uuid);
70 static GMount *get_mount_for_uuid(GVolumeMonitor *mon, const char *uuid);
71 static void drive_eject_button(GVolumeMonitor *mon, GDrive *drive);
72
73 static void add_device(GUDisksVolumeMonitor* mon, DBusGProxy* proxy, const char* obj_path, gboolean emit_signal);
74 static void on_device_added(DBusGProxy* proxy, const char* obj_path, gpointer user_data);
75 static void on_device_removed(DBusGProxy* proxy, const char* obj_path, gpointer user_data);
76 static void on_device_changed(DBusGProxy* proxy, const char* obj_path, gpointer user_data);
77
78 static GList* find_device_l(GUDisksVolumeMonitor* mon, const char* obj_path);
79 static GList* find_drive_l(GUDisksVolumeMonitor* mon, GUDisksDevice* dev);
80 static GList* find_volume_l(GUDisksVolumeMonitor* mon, GUDisksDevice* dev);
81
find_device(GUDisksVolumeMonitor * mon,const char * obj_path)82 static inline GUDisksDevice* find_device(GUDisksVolumeMonitor* mon, const char* obj_path)
83 {
84 GList* l = find_device_l(mon, obj_path);
85 return l ? G_UDISKS_DEVICE(l->data) : NULL;
86 }
87
find_drive(GUDisksVolumeMonitor * mon,GUDisksDevice * dev)88 static inline GUDisksDrive* find_drive(GUDisksVolumeMonitor* mon, GUDisksDevice* dev)
89 {
90 GList* l = find_drive_l(mon, dev);
91 return l ? G_UDISKS_DRIVE(l->data) : NULL;
92 }
93
find_volume(GUDisksVolumeMonitor * mon,GUDisksDevice * dev)94 static inline GUDisksVolume* find_volume(GUDisksVolumeMonitor* mon, GUDisksDevice* dev)
95 {
96 GList* l = find_volume_l(mon, dev);
97 return l ? G_UDISKS_VOLUME(l->data) : NULL;
98 }
99
100
101 G_DEFINE_TYPE(GUDisksVolumeMonitor, g_udisks_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR);
102
103
g_udisks_volume_monitor_class_init(GUDisksVolumeMonitorClass * klass)104 static void g_udisks_volume_monitor_class_init(GUDisksVolumeMonitorClass *klass)
105 {
106 GObjectClass *g_object_class = G_OBJECT_CLASS(klass);
107 GNativeVolumeMonitorClass *parent_class = G_NATIVE_VOLUME_MONITOR_CLASS(klass);
108 GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
109
110 g_object_class->finalize = g_udisks_volume_monitor_finalize;
111 parent_class->get_mount_for_mount_path = get_mount_for_mount_path;
112
113 monitor_class->get_mounts = get_mounts;
114 monitor_class->get_volumes = get_volumes;
115 monitor_class->get_connected_drives = get_connected_drives;
116 monitor_class->get_volume_for_uuid = get_volume_for_uuid;
117 monitor_class->get_mount_for_uuid = get_mount_for_uuid;
118 monitor_class->is_supported = is_supported;
119 monitor_class->drive_eject_button = drive_eject_button;
120
121 sig_drive_changed = g_signal_lookup("drive-changed", G_TYPE_VOLUME_MONITOR);
122 sig_drive_connected = g_signal_lookup("drive-connected", G_TYPE_VOLUME_MONITOR);
123 sig_drive_disconnected = g_signal_lookup("drive-disconnected", G_TYPE_VOLUME_MONITOR);
124 sig_drive_eject_button = g_signal_lookup("drive-eject-button", G_TYPE_VOLUME_MONITOR);
125 sig_mount_added = g_signal_lookup("mount-added", G_TYPE_VOLUME_MONITOR);
126 sig_mount_changed = g_signal_lookup("mount-changed", G_TYPE_VOLUME_MONITOR);
127 sig_mount_premount = g_signal_lookup("mount-premount", G_TYPE_VOLUME_MONITOR);
128 sig_mount_removed = g_signal_lookup("mount-removed", G_TYPE_VOLUME_MONITOR);
129 sig_volume_added = g_signal_lookup("volume-added", G_TYPE_VOLUME_MONITOR);
130 sig_volume_changed = g_signal_lookup("volume-changed", G_TYPE_VOLUME_MONITOR);
131 sig_volume_removed = g_signal_lookup("volume-removed", G_TYPE_VOLUME_MONITOR);
132 }
133
134
g_udisks_volume_monitor_finalize(GObject * object)135 static void g_udisks_volume_monitor_finalize(GObject *object)
136 {
137 GUDisksVolumeMonitor *self;
138
139 g_return_if_fail(object != NULL);
140 g_return_if_fail(G_IS_UDISKS_VOLUME_MONITOR(object));
141
142 self = G_UDISKS_VOLUME_MONITOR(object);
143
144 if(self->idle_handler)
145 {
146 GList* l;
147 g_source_remove(self->idle_handler);
148 for(l = self->queued_events; l; l=l->next)
149 {
150 QueuedEvent* q = (QueuedEvent*)l->data;
151 g_object_unref(q->dev);
152 g_slice_free(QueuedEvent, q);
153 }
154 g_list_free(self->queued_events);
155 }
156
157 if(self->udisks_proxy)
158 {
159 dbus_g_proxy_disconnect_signal(self->udisks_proxy, "DeviceAdded", G_CALLBACK(on_device_added), self);
160 dbus_g_proxy_disconnect_signal(self->udisks_proxy, "DeviceRemoved", G_CALLBACK(on_device_removed), self);
161 dbus_g_proxy_disconnect_signal(self->udisks_proxy, "DeviceChanged", G_CALLBACK(on_device_changed), self);
162 g_object_unref(self->udisks_proxy);
163 }
164
165 if(self->devices)
166 {
167 g_list_foreach(self->devices, (GFunc)g_object_unref, NULL);
168 g_list_free(self->devices);
169 }
170
171 if(self->drives)
172 {
173 g_list_foreach(self->drives, (GFunc)g_object_unref, NULL);
174 g_list_free(self->drives);
175 }
176
177 if(self->volumes)
178 {
179 g_list_foreach(self->volumes, (GFunc)g_object_unref, NULL);
180 g_list_free(self->volumes);
181 }
182
183 G_OBJECT_CLASS(g_udisks_volume_monitor_parent_class)->finalize(object);
184 }
185
update_volume_drive(GUDisksVolume * vol,GUDisksVolumeMonitor * mon)186 static void update_volume_drive(GUDisksVolume* vol, GUDisksVolumeMonitor* mon)
187 {
188 /* set association between drive and volumes here */
189 GUDisksDevice* dev;
190 if(vol->dev->is_drive) /* it's a drive itself (cdrom is an example) */
191 dev = vol->dev;
192 else if(vol->dev->partition_slave)
193 dev = find_device(mon, vol->dev->partition_slave);
194 else
195 dev = NULL;
196
197 /* no ref_count handling is needed. volume manager owns all the objects. */
198 if(dev)
199 {
200 GUDisksDrive* drv = find_drive(mon, dev);
201 vol->drive = drv;
202 }
203 else
204 vol->drive = NULL;
205 }
206
g_udisks_volume_monitor_init(GUDisksVolumeMonitor * self)207 static void g_udisks_volume_monitor_init(GUDisksVolumeMonitor *self)
208 {
209 self->con = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
210 if(self->con)
211 {
212 GPtrArray* ret;
213 /* FIXME: handle disconnecting from dbus */
214 self->udisks_proxy = dbus_g_proxy_new_for_name(self->con, "org.freedesktop.UDisks", "/org/freedesktop/UDisks", "org.freedesktop.UDisks");
215
216 if(org_freedesktop_UDisks_enumerate_devices(self->udisks_proxy, &ret, NULL))
217 {
218 guint i;
219 char** paths = (char**)ret->pdata;
220 for(i=0; i<ret->len;++i)
221 add_device(self, self->udisks_proxy, paths[i], FALSE);
222 g_ptr_array_free(ret, TRUE);
223 }
224
225 dbus_g_proxy_add_signal(self->udisks_proxy, "DeviceAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
226 dbus_g_proxy_add_signal(self->udisks_proxy, "DeviceRemoved", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
227 dbus_g_proxy_add_signal(self->udisks_proxy, "DeviceChanged", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
228
229 dbus_g_proxy_connect_signal(self->udisks_proxy, "DeviceAdded", G_CALLBACK(on_device_added), self, NULL);
230 dbus_g_proxy_connect_signal(self->udisks_proxy, "DeviceRemoved", G_CALLBACK(on_device_removed), self, NULL);
231 dbus_g_proxy_connect_signal(self->udisks_proxy, "DeviceChanged", G_CALLBACK(on_device_changed), self, NULL);
232
233 /* find drives for volumes */
234 if(self->volumes && self->drives)
235 g_list_foreach(self->volumes, (GFunc)update_volume_drive, self);
236 }
237 }
238
239
g_udisks_volume_monitor_new(void)240 GNativeVolumeMonitor *g_udisks_volume_monitor_new(void)
241 {
242 return g_object_new(G_UDISKS_VOLUME_MONITOR_TYPE, NULL);
243 }
244
get_mount_for_mount_path(const char * mount_path,GCancellable * cancellable)245 GMount* get_mount_for_mount_path(const char *mount_path, GCancellable *cancellable)
246 {
247 /* TODO */
248
249 return NULL;
250 }
251
252
is_supported(void)253 gboolean is_supported(void)
254 {
255 return TRUE;
256 }
257
get_connected_drives(GVolumeMonitor * mon)258 GList* get_connected_drives(GVolumeMonitor *mon)
259 {
260 GUDisksVolumeMonitor* umon = G_UDISKS_VOLUME_MONITOR(mon);
261 GList* drvs = g_list_copy(umon->drives);
262 g_list_foreach(drvs, (GFunc)g_object_ref, NULL);
263 return drvs;
264 }
265
get_volumes(GVolumeMonitor * mon)266 GList* get_volumes(GVolumeMonitor *mon)
267 {
268 GUDisksVolumeMonitor* umon = G_UDISKS_VOLUME_MONITOR(mon);
269 GList* vols = g_list_copy(umon->volumes);
270 g_list_foreach(vols, (GFunc)g_object_ref, NULL);
271 return vols;
272 }
273
get_mounts(GVolumeMonitor * mon)274 GList* get_mounts(GVolumeMonitor *mon)
275 {
276 GUDisksVolumeMonitor* umon = G_UDISKS_VOLUME_MONITOR(mon);
277 GList* l;
278 GList* mnts = NULL;
279 for(l = umon->volumes; l; l=l->next)
280 {
281 GUDisksVolume* vol = G_UDISKS_VOLUME(l->data);
282 if(vol->mount)
283 mnts = g_list_prepend(mnts, g_object_ref(vol->mount));
284 }
285 return mnts;
286 }
287
get_volume_for_uuid(GVolumeMonitor * mon,const char * uuid)288 GVolume *get_volume_for_uuid(GVolumeMonitor *mon, const char *uuid)
289 {
290 GUDisksVolumeMonitor* umon = G_UDISKS_VOLUME_MONITOR(mon);
291 GList* l;
292 for(l = umon->volumes; l; l=l->next)
293 {
294 GUDisksVolume* vol = G_UDISKS_VOLUME(l->data);
295 if(g_strcmp0(vol->dev->uuid, uuid) == 0)
296 return (GVolume*)g_object_ref(vol);
297 }
298 return NULL;
299 }
300
get_mount_for_uuid(GVolumeMonitor * mon,const char * uuid)301 GMount *get_mount_for_uuid(GVolumeMonitor *mon, const char *uuid)
302 {
303 GUDisksVolumeMonitor* umon = G_UDISKS_VOLUME_MONITOR(mon);
304 GList* l;
305 for(l = umon->volumes; l; l=l->next)
306 {
307 GUDisksVolume* vol = G_UDISKS_VOLUME(l->data);
308 if(g_strcmp0(vol->dev->uuid, uuid) == 0)
309 return g_volume_get_mount(G_VOLUME(vol));
310 }
311 return NULL;
312 }
313
314 /* signal added in 2.17 */
drive_eject_button(GVolumeMonitor * mon,GDrive * drive)315 void drive_eject_button(GVolumeMonitor *mon, GDrive *drive)
316 {
317 /* TODO */
318 //GUDisksVolumeMonitor* umon = G_UDISKS_VOLUME_MONITOR(mon);
319
320 }
321
find_device_l(GUDisksVolumeMonitor * mon,const char * obj_path)322 GList* find_device_l(GUDisksVolumeMonitor* mon, const char* obj_path)
323 {
324 GList* l;
325 for(l = mon->devices; l; l=l->next)
326 {
327 GUDisksDevice* dev = G_UDISKS_DEVICE(l->data);
328 if(g_strcmp0(dev->obj_path, obj_path) == 0)
329 return l;
330 }
331 return NULL;
332 }
333
find_drive_l(GUDisksVolumeMonitor * mon,GUDisksDevice * dev)334 GList* find_drive_l(GUDisksVolumeMonitor* mon, GUDisksDevice* dev)
335 {
336 GList* l;
337 for(l = mon->drives; l; l=l->next)
338 {
339 GUDisksDrive* drv = G_UDISKS_DRIVE(l->data);
340 if(G_UNLIKELY(drv->dev == dev))
341 return l;
342 }
343 return NULL;
344 }
345
find_volume_l(GUDisksVolumeMonitor * mon,GUDisksDevice * dev)346 GList* find_volume_l(GUDisksVolumeMonitor* mon, GUDisksDevice* dev)
347 {
348 GList* l;
349 for(l = mon->volumes; l; l=l->next)
350 {
351 GUDisksVolume* vol = G_UDISKS_VOLUME(l->data);
352 if(G_UNLIKELY(vol->dev == dev))
353 return l;
354 }
355 return NULL;
356 }
357
add_drive(GUDisksVolumeMonitor * mon,GUDisksDevice * dev,gboolean emit_signal)358 static void add_drive(GUDisksVolumeMonitor* mon, GUDisksDevice* dev, gboolean emit_signal)
359 {
360 if(!find_drive(mon, dev))
361 {
362 GUDisksDrive* drv = g_udisks_drive_new(mon, dev);
363 mon->drives = g_list_prepend(mon->drives, drv);
364 if(emit_signal)
365 g_signal_emit(mon, sig_drive_connected, 0, drv);
366 }
367 }
368
add_volume(GUDisksVolumeMonitor * mon,GUDisksDevice * dev,gboolean emit_signal)369 static void add_volume(GUDisksVolumeMonitor* mon, GUDisksDevice* dev, gboolean emit_signal)
370 {
371 if(!find_volume(mon, dev))
372 {
373 GUDisksVolume* vol = g_udisks_volume_new(mon, dev);
374 mon->volumes = g_list_prepend(mon->volumes, vol);
375 if(emit_signal)
376 g_signal_emit(mon, sig_volume_added, 0, vol);
377 }
378 }
379
remove_drive(GUDisksVolumeMonitor * mon,GUDisksDevice * dev)380 static void remove_drive(GUDisksVolumeMonitor* mon, GUDisksDevice* dev)
381 {
382 GList* l = find_drive_l(mon, dev);
383 if(l)
384 {
385 GUDisksDrive* drv = G_UDISKS_DRIVE(l->data);
386 mon->drives = g_list_delete_link(mon->drives, l);
387 g_signal_emit(mon, sig_drive_disconnected, 0, drv);
388 g_udisks_drive_disconnected(drv);
389 drv->mon = NULL;
390 for(l = mon->volumes; l; l=l->next)
391 {
392 GUDisksVolume* vol = G_UDISKS_VOLUME(l->data);
393 if(vol->drive == drv)
394 {
395 vol->drive = NULL;
396 /* FIXME: emit sigal for volume change */
397 }
398 }
399 g_object_unref(drv);
400 }
401 }
402
remove_volume(GUDisksVolumeMonitor * mon,GUDisksDevice * dev)403 static void remove_volume(GUDisksVolumeMonitor* mon, GUDisksDevice* dev)
404 {
405 GList* l = find_volume_l(mon, dev);
406 if(l)
407 {
408 GUDisksVolume* vol = G_UDISKS_VOLUME(l->data);
409 mon->volumes = g_list_delete_link(mon->volumes, l);
410 g_signal_emit(mon, sig_volume_removed, 0, vol);
411 g_udisks_volume_removed(vol);
412 vol->mon = NULL;
413 vol->drive = NULL;
414 g_object_unref(vol);
415 }
416 }
417
_g_udisks_device_added(GUDisksDevice * dev,GUDisksVolumeMonitor * mon,gboolean emit_signal)418 static void _g_udisks_device_added(GUDisksDevice* dev, GUDisksVolumeMonitor* mon, gboolean emit_signal)
419 {
420 /* FIXME: how should we treat sys internal devices?
421 * make this optional */
422 if(!dev->is_hidden && (!dev->is_sys_internal || fm_config->show_internal_volumes) )
423 {
424 if(dev->is_drive)
425 add_drive(mon, dev, emit_signal);
426
427 if(g_udisks_device_is_volume(dev))
428 add_volume(mon, dev, emit_signal);
429 }
430 }
431
g_udisks_device_added(GUDisksDevice * dev,GUDisksVolumeMonitor * mon)432 static void g_udisks_device_added(GUDisksDevice* dev, GUDisksVolumeMonitor* mon)
433 {
434 g_debug("g_udisks_device_added");
435 _g_udisks_device_added(dev, mon, TRUE);
436 }
437
g_udisks_device_changed(GUDisksDevice * dev,GUDisksVolumeMonitor * mon)438 static void g_udisks_device_changed(GUDisksDevice* dev, GUDisksVolumeMonitor* mon)
439 {
440 GUDisksDrive* drv = find_drive(mon, dev);
441 GUDisksVolume* vol = find_volume(mon, dev);
442 /*
443 gboolean is_drive = dev->is_drive;
444 char* usage = g_strdup(dev->usage);
445 */
446 g_debug("g_udisks_device_changed");
447 if(drv)
448 {
449 g_signal_emit(mon, sig_drive_changed, 0, drv);
450 g_udisks_drive_changed(drv);
451 /* it's no longer a drive */
452 if(!dev->is_drive)
453 remove_drive(mon, dev);
454 }
455 else
456 {
457 if(dev->is_drive)
458 add_drive(mon, dev, TRUE);
459 }
460
461 if(vol)
462 {
463 update_volume_drive(vol, mon);
464 g_signal_emit(mon, sig_volume_changed, 0, vol);
465 g_udisks_volume_changed(vol);
466
467 /* it's no longer a volume */
468 if(!g_udisks_device_is_volume(dev))
469 remove_volume(mon, dev);
470 }
471 else
472 {
473 /* we got a usable volume now */
474 if(g_udisks_device_is_volume(dev))
475 add_volume(mon, dev, TRUE);
476 }
477 }
478
g_udisks_device_removed(GUDisksDevice * dev,GUDisksVolumeMonitor * mon)479 static void g_udisks_device_removed(GUDisksDevice* dev, GUDisksVolumeMonitor* mon)
480 {
481 g_debug("g_udisks_device_removed");
482
483 if(dev->is_drive)
484 remove_drive(mon, dev);
485
486 remove_volume(mon, dev);
487 }
488
on_idle(GUDisksVolumeMonitor * mon)489 static gboolean on_idle(GUDisksVolumeMonitor* mon)
490 {
491 GList* l;
492 g_debug("on_idle: %d", g_list_length(mon->queued_events));
493 for(l = mon->queued_events; l; l=l->next)
494 {
495 QueuedEvent* q = (QueuedEvent*)l->data;
496 q->func(q->dev, mon);
497 g_object_unref(q->dev);
498 g_slice_free(QueuedEvent, q);
499 }
500 g_list_free(mon->queued_events);
501 mon->queued_events = NULL;
502 mon->idle_handler = 0;
503 return FALSE;
504 }
505
g_udisks_device_queue_event(GUDisksDevice * dev,GUDisksDeviceEventHandler func,GUDisksVolumeMonitor * mon)506 static void g_udisks_device_queue_event(GUDisksDevice* dev, GUDisksDeviceEventHandler func, GUDisksVolumeMonitor* mon)
507 {
508 QueuedEvent* q = g_slice_new(QueuedEvent);
509 q->dev = g_object_ref(dev);
510 q->func = func;
511 mon->queued_events = g_list_append(mon->queued_events, q);
512
513 if(0 == mon->idle_handler)
514 mon->idle_handler = g_idle_add_full(G_PRIORITY_HIGH, (GSourceFunc)on_idle, mon, NULL);
515 }
516
add_device(GUDisksVolumeMonitor * mon,DBusGProxy * proxy,const char * obj_path,gboolean emit_signal)517 static void add_device(GUDisksVolumeMonitor* mon, DBusGProxy* proxy, const char* obj_path, gboolean emit_signal)
518 {
519 if(!find_device(mon, obj_path))
520 {
521 DBusGProxy *dev_proxy = dbus_g_proxy_new_for_name(mon->con,
522 "org.freedesktop.UDisks",
523 obj_path,
524 "org.freedesktop.DBus.Properties");
525 GError* err = NULL;
526 GHashTable* props = dbus_get_all_props(dev_proxy, "org.freedesktop.UDisks.Device", &err);
527 if(props)
528 {
529 GUDisksDevice* dev = g_udisks_device_new(obj_path, props);
530 g_hash_table_destroy(props);
531
532 mon->devices = g_list_prepend(mon->devices, dev);
533 if(emit_signal)
534 g_udisks_device_queue_event(dev, g_udisks_device_added, mon);
535 else
536 _g_udisks_device_added(dev, mon, FALSE);
537 }
538 else
539 {
540 g_debug("%s", err->message);
541 g_error_free(err);
542 }
543 g_object_unref(dev_proxy);
544 }
545 g_debug("device_added: %s", obj_path);
546 }
547
on_device_added(DBusGProxy * proxy,const char * obj_path,gpointer user_data)548 void on_device_added(DBusGProxy* proxy, const char* obj_path, gpointer user_data)
549 {
550 GUDisksVolumeMonitor* mon = G_UDISKS_VOLUME_MONITOR(user_data);
551 add_device(mon, proxy, obj_path, TRUE);
552 }
553
554
on_device_removed(DBusGProxy * proxy,const char * obj_path,gpointer user_data)555 void on_device_removed(DBusGProxy* proxy, const char* obj_path, gpointer user_data)
556 {
557 GUDisksVolumeMonitor* mon = G_UDISKS_VOLUME_MONITOR(user_data);
558 GList* l;
559 l = find_device_l(mon, obj_path);
560 if(l)
561 {
562 GUDisksDevice* dev = G_UDISKS_DEVICE(l->data);
563 mon->devices = g_list_delete_link(mon->devices, l);
564
565 g_udisks_device_queue_event(dev, g_udisks_device_removed, mon);
566 g_object_unref(dev);
567 }
568 g_debug("device_removed: %s", obj_path);
569
570 }
571
on_device_changed(DBusGProxy * proxy,const char * obj_path,gpointer user_data)572 void on_device_changed(DBusGProxy* proxy, const char* obj_path, gpointer user_data)
573 {
574 GUDisksVolumeMonitor* mon = G_UDISKS_VOLUME_MONITOR(user_data);
575 GUDisksDevice* dev = find_device(mon, obj_path);
576 if(dev)
577 {
578 DBusGProxy *dev_proxy = dbus_g_proxy_new_for_name(mon->con,
579 "org.freedesktop.UDisks",
580 obj_path,
581 "org.freedesktop.DBus.Properties");
582
583 GError* err = NULL;
584 GHashTable* props = dbus_get_all_props(dev_proxy, "org.freedesktop.UDisks.Device", &err);
585 if(props)
586 {
587 g_udisks_device_update(dev, props);
588 g_hash_table_destroy(props);
589
590 g_udisks_device_queue_event(dev, g_udisks_device_changed, mon);
591 }
592 g_object_unref(dev_proxy);
593 }
594 g_debug("device_changed: %s", obj_path);
595 }
596
597