1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3 /* GIO - GLib Input, Output and Streaming Library
5 * Copyright (C) 2006-2007 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but 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.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307, USA.
22 * Author: Alexander Larsson <alexl@redhat.com>
23 * David Zeuthen <davidz@redhat.com>
31 #include "gunixvolumemonitor.h"
32 #include "gunixmounts.h"
33 #include "gunixmount.h"
34 #include "gunixvolume.h"
36 #include "gmountprivate.h"
37 #include "giomodule.h"
42 struct _GUnixVolumeMonitor
{
43 GNativeVolumeMonitor parent
;
45 GUnixMountMonitor
*mount_monitor
;
47 GList
*last_mountpoints
;
54 static void mountpoints_changed (GUnixMountMonitor
*mount_monitor
,
56 static void mounts_changed (GUnixMountMonitor
*mount_monitor
,
58 static void update_volumes (GUnixVolumeMonitor
*monitor
);
59 static void update_mounts (GUnixVolumeMonitor
*monitor
);
61 #define g_unix_volume_monitor_get_type _g_unix_volume_monitor_get_type
62 G_DEFINE_TYPE_WITH_CODE (GUnixVolumeMonitor
, g_unix_volume_monitor
, G_TYPE_NATIVE_VOLUME_MONITOR
,
63 g_io_extension_point_implement (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME
,
69 g_unix_volume_monitor_finalize (GObject
*object
)
71 GUnixVolumeMonitor
*monitor
;
73 monitor
= G_UNIX_VOLUME_MONITOR (object
);
75 g_signal_handlers_disconnect_by_func (monitor
->mount_monitor
, mountpoints_changed
, monitor
);
76 g_signal_handlers_disconnect_by_func (monitor
->mount_monitor
, mounts_changed
, monitor
);
78 g_object_unref (monitor
->mount_monitor
);
80 g_list_foreach (monitor
->last_mountpoints
, (GFunc
)g_unix_mount_point_free
, NULL
);
81 g_list_free (monitor
->last_mountpoints
);
82 g_list_foreach (monitor
->last_mounts
, (GFunc
)g_unix_mount_free
, NULL
);
83 g_list_free (monitor
->last_mounts
);
85 g_list_foreach (monitor
->volumes
, (GFunc
)g_object_unref
, NULL
);
86 g_list_free (monitor
->volumes
);
87 g_list_foreach (monitor
->mounts
, (GFunc
)g_object_unref
, NULL
);
88 g_list_free (monitor
->mounts
);
90 G_OBJECT_CLASS (g_unix_volume_monitor_parent_class
)->finalize (object
);
94 get_mounts (GVolumeMonitor
*volume_monitor
)
96 GUnixVolumeMonitor
*monitor
;
99 monitor
= G_UNIX_VOLUME_MONITOR (volume_monitor
);
101 l
= g_list_copy (monitor
->mounts
);
102 g_list_foreach (l
, (GFunc
)g_object_ref
, NULL
);
108 get_volumes (GVolumeMonitor
*volume_monitor
)
110 GUnixVolumeMonitor
*monitor
;
113 monitor
= G_UNIX_VOLUME_MONITOR (volume_monitor
);
115 l
= g_list_copy (monitor
->volumes
);
116 g_list_foreach (l
, (GFunc
)g_object_ref
, NULL
);
122 get_connected_drives (GVolumeMonitor
*volume_monitor
)
128 get_volume_for_uuid (GVolumeMonitor
*volume_monitor
, const char *uuid
)
134 get_mount_for_uuid (GVolumeMonitor
*volume_monitor
, const char *uuid
)
146 get_mount_for_mount_path (const char *mount_path
,
147 GCancellable
*cancellable
)
149 GUnixMountEntry
*mount_entry
;
152 mount_entry
= g_unix_mount_at (mount_path
, NULL
);
157 /* TODO: Set mountable volume? */
158 mount
= _g_unix_mount_new (NULL
, mount_entry
, NULL
);
160 g_unix_mount_free (mount_entry
);
162 return G_MOUNT (mount
);
166 g_unix_volume_monitor_class_init (GUnixVolumeMonitorClass
*klass
)
168 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
169 GVolumeMonitorClass
*monitor_class
= G_VOLUME_MONITOR_CLASS (klass
);
170 GNativeVolumeMonitorClass
*native_class
= G_NATIVE_VOLUME_MONITOR_CLASS (klass
);
172 gobject_class
->finalize
= g_unix_volume_monitor_finalize
;
174 monitor_class
->get_mounts
= get_mounts
;
175 monitor_class
->get_volumes
= get_volumes
;
176 monitor_class
->get_connected_drives
= get_connected_drives
;
177 monitor_class
->get_volume_for_uuid
= get_volume_for_uuid
;
178 monitor_class
->get_mount_for_uuid
= get_mount_for_uuid
;
179 monitor_class
->is_supported
= is_supported
;
181 native_class
->get_mount_for_mount_path
= get_mount_for_mount_path
;
185 mountpoints_changed (GUnixMountMonitor
*mount_monitor
,
188 GUnixVolumeMonitor
*unix_monitor
= user_data
;
190 /* Update both to make sure volumes are created before mounts */
191 update_volumes (unix_monitor
);
192 update_mounts (unix_monitor
);
196 mounts_changed (GUnixMountMonitor
*mount_monitor
,
199 GUnixVolumeMonitor
*unix_monitor
= user_data
;
201 /* Update both to make sure volumes are created before mounts */
202 update_volumes (unix_monitor
);
203 update_mounts (unix_monitor
);
207 g_unix_volume_monitor_init (GUnixVolumeMonitor
*unix_monitor
)
210 unix_monitor
->mount_monitor
= g_unix_mount_monitor_new ();
212 g_signal_connect (unix_monitor
->mount_monitor
,
213 "mounts-changed", G_CALLBACK (mounts_changed
),
216 g_signal_connect (unix_monitor
->mount_monitor
,
217 "mountpoints-changed", G_CALLBACK (mountpoints_changed
),
220 update_volumes (unix_monitor
);
221 update_mounts (unix_monitor
);
225 * g_unix_volume_monitor_new:
227 * Returns: a new #GVolumeMonitor.
230 _g_unix_volume_monitor_new (void)
232 GUnixVolumeMonitor
*monitor
;
234 monitor
= g_object_new (G_TYPE_UNIX_VOLUME_MONITOR
, NULL
);
236 return G_VOLUME_MONITOR (monitor
);
240 diff_sorted_lists (GList
*list1
,
242 GCompareFunc compare
,
248 *added
= *removed
= NULL
;
250 while (list1
!= NULL
&&
253 order
= (*compare
) (list1
->data
, list2
->data
);
256 *removed
= g_list_prepend (*removed
, list1
->data
);
261 *added
= g_list_prepend (*added
, list2
->data
);
271 while (list1
!= NULL
)
273 *removed
= g_list_prepend (*removed
, list1
->data
);
276 while (list2
!= NULL
)
278 *added
= g_list_prepend (*added
, list2
->data
);
284 * _g_unix_volume_monitor_lookup_volume_for_mount_path:
288 * Returns: #GUnixVolume for the given @mount_path.
291 _g_unix_volume_monitor_lookup_volume_for_mount_path (GUnixVolumeMonitor
*monitor
,
292 const char *mount_path
)
296 for (l
= monitor
->volumes
; l
!= NULL
; l
= l
->next
)
298 GUnixVolume
*volume
= l
->data
;
300 if (_g_unix_volume_has_mount_path (volume
, mount_path
))
308 find_mount_by_mountpath (GUnixVolumeMonitor
*monitor
,
309 const char *mount_path
)
313 for (l
= monitor
->mounts
; l
!= NULL
; l
= l
->next
)
315 GUnixMount
*mount
= l
->data
;
317 if (_g_unix_mount_has_mount_path (mount
, mount_path
))
325 update_volumes (GUnixVolumeMonitor
*monitor
)
327 GList
*new_mountpoints
;
328 GList
*removed
, *added
;
332 new_mountpoints
= g_unix_mount_points_get (NULL
);
334 new_mountpoints
= g_list_sort (new_mountpoints
, (GCompareFunc
) g_unix_mount_point_compare
);
336 diff_sorted_lists (monitor
->last_mountpoints
,
337 new_mountpoints
, (GCompareFunc
) g_unix_mount_point_compare
,
340 for (l
= removed
; l
!= NULL
; l
= l
->next
)
342 GUnixMountPoint
*mountpoint
= l
->data
;
344 volume
= _g_unix_volume_monitor_lookup_volume_for_mount_path (monitor
,
345 g_unix_mount_point_get_mount_path (mountpoint
));
348 _g_unix_volume_disconnected (volume
);
349 monitor
->volumes
= g_list_remove (monitor
->volumes
, volume
);
350 g_signal_emit_by_name (monitor
, "volume-removed", volume
);
351 g_signal_emit_by_name (volume
, "removed");
352 g_object_unref (volume
);
356 for (l
= added
; l
!= NULL
; l
= l
->next
)
358 GUnixMountPoint
*mountpoint
= l
->data
;
360 volume
= _g_unix_volume_new (G_VOLUME_MONITOR (monitor
), mountpoint
);
363 monitor
->volumes
= g_list_prepend (monitor
->volumes
, volume
);
364 g_signal_emit_by_name (monitor
, "volume-added", volume
);
369 g_list_free (removed
);
370 g_list_foreach (monitor
->last_mountpoints
,
371 (GFunc
)g_unix_mount_point_free
, NULL
);
372 g_list_free (monitor
->last_mountpoints
);
373 monitor
->last_mountpoints
= new_mountpoints
;
377 update_mounts (GUnixVolumeMonitor
*monitor
)
380 GList
*removed
, *added
;
384 const char *mount_path
;
386 new_mounts
= g_unix_mounts_get (NULL
);
388 new_mounts
= g_list_sort (new_mounts
, (GCompareFunc
) g_unix_mount_compare
);
390 diff_sorted_lists (monitor
->last_mounts
,
391 new_mounts
, (GCompareFunc
) g_unix_mount_compare
,
394 for (l
= removed
; l
!= NULL
; l
= l
->next
)
396 GUnixMountEntry
*mount_entry
= l
->data
;
398 mount
= find_mount_by_mountpath (monitor
, g_unix_mount_get_mount_path (mount_entry
));
401 _g_unix_mount_unmounted (mount
);
402 monitor
->mounts
= g_list_remove (monitor
->mounts
, mount
);
403 g_signal_emit_by_name (monitor
, "mount-removed", mount
);
404 g_signal_emit_by_name (mount
, "unmounted");
405 g_object_unref (mount
);
409 for (l
= added
; l
!= NULL
; l
= l
->next
)
411 GUnixMountEntry
*mount_entry
= l
->data
;
413 mount_path
= g_unix_mount_get_mount_path (mount_entry
);
415 volume
= _g_unix_volume_monitor_lookup_volume_for_mount_path (monitor
, mount_path
);
416 mount
= _g_unix_mount_new (G_VOLUME_MONITOR (monitor
), mount_entry
, volume
);
419 monitor
->mounts
= g_list_prepend (monitor
->mounts
, mount
);
420 g_signal_emit_by_name (monitor
, "mount-added", mount
);
425 g_list_free (removed
);
426 g_list_foreach (monitor
->last_mounts
,
427 (GFunc
)g_unix_mount_free
, NULL
);
428 g_list_free (monitor
->last_mounts
);
429 monitor
->last_mounts
= new_mounts
;