Rework how volumes, drives and volume monitoring is done. Previosly the
authorDavid Zeuthen <davidz@redhat.com>
Tue, 11 Dec 2007 21:23:55 +0000 (21:23 +0000)
committerDavid Zeuthen <davidz@src.gnome.org>
Tue, 11 Dec 2007 21:23:55 +0000 (21:23 +0000)
2007-12-11  David Zeuthen  <davidz@redhat.com>

Rework how volumes, drives and volume monitoring is
done. Previosly the model was

 GDrive <1-1> GVolume

where a GDrive instance represented a mount point and a GVolume
instance represented a mounted file system. This patch changes it
the model to

GDrive <1-N> GVolume <1-1> GMount

where GMount now serves the purpose of the old GVolume and the new
GVolume serves the purpose of the old GDrive. In addition the new
GDrive interface is used to represent a collection of GVolume
instances (typically partitions) and also contains utility to query
the state of the physical drive the GDrive object represents (such
as checking for media, polling the drive, ejecting the media etc.).

Also implement mounting and unmounting in the Unix volume monitor
backend. A subquent patch will introduce GDrive support for ejection
of media.

* Makefile.am:
* gdrive.c: (g_drive_is_media_check_automatic),
(g_drive_is_media_removable), (g_drive_has_media),
(g_drive_can_poll_for_media), (g_drive_eject),
(g_drive_eject_finish), (g_drive_poll_for_media),
(g_drive_poll_for_media_finish):
* gdrive.h:
* gfile.c: (g_file_find_enclosing_mount):
* gfile.h:
* gio.symbols:
* glocaldirectorymonitor.c:
(g_local_directory_monitor_constructor), (mounts_changed):
* glocalfile.c: (get_mount_info),
(g_local_file_find_enclosing_mount),
(g_local_file_file_iface_init):
* gnativevolumemonitor.h:
* gunionvolumemonitor.c: (get_mounts), (get_volumes),
(get_connected_drives), (g_union_volume_monitor_class_init),
(child_volume_added), (child_volume_removed),
(child_volume_changed), (child_mount_added), (child_mount_removed),
(child_mount_pre_unmount), (child_mount_changed),
(child_drive_changed), (g_union_volume_monitor_add_monitor),
(g_union_volume_monitor_remove_monitor),
(_g_mount_get_for_mount_path):
* gunixmounts.c: (g_unix_is_mount_path_system_internal),
(guess_system_internal), (_g_get_unix_mounts),
(_g_get_unix_mount_points), (g_get_unix_mount_at),
(g_unix_mount_free), (g_unix_mount_compare),
(g_unix_mount_get_mount_path), (g_unix_mount_get_device_path),
(g_unix_mount_get_fs_type), (g_unix_mount_is_readonly),
(g_unix_mount_is_system_internal), (g_unix_mount_guess_type),
(type_to_icon), (g_unix_mount_guess_name),
(g_unix_mount_guess_icon), (g_unix_mount_point_guess_name),
(g_unix_mount_point_guess_icon), (_canonicalize_filename),
(_resolve_symlink), (_resolve_dev_root):
* gunixmounts.h:
* gunixvolume.c: (g_unix_volume_finalize), (_g_unix_volume_new),
(_g_unix_volume_disconnected), (_g_unix_volume_set_mount),
(_g_unix_volume_unset_mount), (g_unix_volume_get_icon),
(g_unix_volume_get_name), (g_unix_volume_can_mount),
(g_unix_volume_get_drive), (g_unix_volume_get_mount),
(_g_unix_volume_has_mount_path), (mount_cb), (mount_read_error),
(g_unix_volume_mount), (g_unix_volume_mount_finish),
(g_unix_volume_volume_iface_init):
* gunixvolume.h:
* gunixvolumemonitor.c: (g_unix_volume_monitor_finalize),
(get_mounts), (get_volumes), (get_connected_drives),
(get_mount_for_mount_path), (g_unix_volume_monitor_class_init),
(mountpoints_changed), (mounts_changed),
(g_unix_volume_monitor_init),
(_g_unix_volume_monitor_lookup_volume_for_mount_path),
(find_mount_by_mountpath), (update_volumes), (update_mounts):
* gunixvolumemonitor.h:
* gvolume.c: (g_volume_get_mount), (g_volume_can_mount),
(g_volume_mount), (g_volume_mount_finish):
* gvolume.h:
* gvolumemonitor.c: (g_volume_monitor_class_init),
(g_volume_monitor_get_connected_drives),
(g_volume_monitor_get_volumes), (g_volume_monitor_get_mounts):
* gvolumemonitor.h:

svn path=/trunk/; revision=6095

29 files changed:
gio/ChangeLog
gio/Makefile.am
gio/gdrive.c
gio/gdrive.h
gio/gfile.c
gio/gfile.h
gio/gio.symbols
gio/glocaldirectorymonitor.c
gio/glocalfile.c
gio/gmount.c [new file with mode: 0644]
gio/gmount.h [new file with mode: 0644]
gio/gmountprivate.h [moved from gio/gvolumeprivate.h with 94% similarity]
gio/gnativevolumemonitor.h
gio/gunionvolumemonitor.c
gio/gunionvolumemonitor.h
gio/gunixdrive.c [deleted file]
gio/gunixdrive.h [deleted file]
gio/gunixmount.c [new file with mode: 0644]
gio/gunixmount.h [new file with mode: 0644]
gio/gunixmounts.c
gio/gunixmounts.h
gio/gunixvolume.c
gio/gunixvolume.h
gio/gunixvolumemonitor.c
gio/gunixvolumemonitor.h
gio/gvolume.c
gio/gvolume.h
gio/gvolumemonitor.c
gio/gvolumemonitor.h

index e37d575..f195252 100644 (file)
@@ -1,3 +1,88 @@
+2007-12-11  David Zeuthen  <davidz@redhat.com>
+
+       Rework how volumes, drives and volume monitoring is
+       done. Previosly the model was
+
+        GDrive <1-1> GVolume
+
+       where a GDrive instance represented a mount point and a GVolume
+       instance represented a mounted file system. This patch changes it
+       the model to
+
+               GDrive <1-N> GVolume <1-1> GMount
+
+       where GMount now serves the purpose of the old GVolume and the new
+       GVolume serves the purpose of the old GDrive. In addition the new
+       GDrive interface is used to represent a collection of GVolume
+       instances (typically partitions) and also contains utility to query
+       the state of the physical drive the GDrive object represents (such
+       as checking for media, polling the drive, ejecting the media etc.).
+
+       Also implement mounting and unmounting in the Unix volume monitor
+       backend. A subquent patch will introduce GDrive support for ejection
+       of media.
+
+       * Makefile.am:
+       * gdrive.c: (g_drive_is_media_check_automatic),
+       (g_drive_is_media_removable), (g_drive_has_media),
+       (g_drive_can_poll_for_media), (g_drive_eject),
+       (g_drive_eject_finish), (g_drive_poll_for_media),
+       (g_drive_poll_for_media_finish):
+       * gdrive.h:
+       * gfile.c: (g_file_find_enclosing_mount):
+       * gfile.h:
+       * gio.symbols:
+       * glocaldirectorymonitor.c:
+       (g_local_directory_monitor_constructor), (mounts_changed):
+       * glocalfile.c: (get_mount_info),
+       (g_local_file_find_enclosing_mount),
+       (g_local_file_file_iface_init):
+       * gnativevolumemonitor.h:
+       * gunionvolumemonitor.c: (get_mounts), (get_volumes),
+       (get_connected_drives), (g_union_volume_monitor_class_init),
+       (child_volume_added), (child_volume_removed),
+       (child_volume_changed), (child_mount_added), (child_mount_removed),
+       (child_mount_pre_unmount), (child_mount_changed),
+       (child_drive_changed), (g_union_volume_monitor_add_monitor),
+       (g_union_volume_monitor_remove_monitor),
+       (_g_mount_get_for_mount_path):
+       * gunixmounts.c: (g_unix_is_mount_path_system_internal),
+       (guess_system_internal), (_g_get_unix_mounts),
+       (_g_get_unix_mount_points), (g_get_unix_mount_at),
+       (g_unix_mount_free), (g_unix_mount_compare),
+       (g_unix_mount_get_mount_path), (g_unix_mount_get_device_path),
+       (g_unix_mount_get_fs_type), (g_unix_mount_is_readonly),
+       (g_unix_mount_is_system_internal), (g_unix_mount_guess_type),
+       (type_to_icon), (g_unix_mount_guess_name),
+       (g_unix_mount_guess_icon), (g_unix_mount_point_guess_name),
+       (g_unix_mount_point_guess_icon), (_canonicalize_filename),
+       (_resolve_symlink), (_resolve_dev_root):
+       * gunixmounts.h:
+       * gunixvolume.c: (g_unix_volume_finalize), (_g_unix_volume_new),
+       (_g_unix_volume_disconnected), (_g_unix_volume_set_mount),
+       (_g_unix_volume_unset_mount), (g_unix_volume_get_icon),
+       (g_unix_volume_get_name), (g_unix_volume_can_mount),
+       (g_unix_volume_get_drive), (g_unix_volume_get_mount),
+       (_g_unix_volume_has_mount_path), (mount_cb), (mount_read_error),
+       (g_unix_volume_mount), (g_unix_volume_mount_finish),
+       (g_unix_volume_volume_iface_init):
+       * gunixvolume.h:
+       * gunixvolumemonitor.c: (g_unix_volume_monitor_finalize),
+       (get_mounts), (get_volumes), (get_connected_drives),
+       (get_mount_for_mount_path), (g_unix_volume_monitor_class_init),
+       (mountpoints_changed), (mounts_changed),
+       (g_unix_volume_monitor_init),
+       (_g_unix_volume_monitor_lookup_volume_for_mount_path),
+       (find_mount_by_mountpath), (update_volumes), (update_mounts):
+       * gunixvolumemonitor.h:
+       * gvolume.c: (g_volume_get_mount), (g_volume_can_mount),
+       (g_volume_mount), (g_volume_mount_finish):
+       * gvolume.h:
+       * gvolumemonitor.c: (g_volume_monitor_class_init),
+       (g_volume_monitor_get_connected_drives),
+       (g_volume_monitor_get_volumes), (g_volume_monitor_get_mounts):
+       * gvolumemonitor.h:
+
 2007-12-10  Matthias Clasen  <mclasen@redhat.com>
 
        * gmountoperation.h (GPasswordFlags): Close the gap
index 3516aaf..07c9e8c 100644 (file)
@@ -90,8 +90,8 @@ if OS_UNIX
 appinfo_sources += gdesktopappinfo.c gdesktopappinfo.h
 platform_libadd += xdgmime/libxdgmime.la
 unix_sources = \
-       gunixdrive.c            \
-       gunixdrive.h            \
+       gunixmount.c            \
+       gunixmount.h            \
        gunixmounts.c           \
        gunixmounts.h           \
        gunixvolume.c           \
@@ -102,6 +102,7 @@ unix_sources = \
        gunixoutputstream.c     \
        $(NULL)
 
+
 giounixincludedir=$(includedir)/gio-unix-2.0/gio
 giounixinclude_HEADERS = \
        gdesktopappinfo.h       \
@@ -150,6 +151,7 @@ libgio_2_0_la_SOURCES =             \
        giomodule-priv.h        \
        gioscheduler.c          \
        gloadableicon.c         \
+       gmount.c                \
        gmemoryinputstream.c    \
        gmemoryoutputstream.c   \
        gmountoperation.c       \
@@ -166,7 +168,7 @@ libgio_2_0_la_SOURCES =             \
        gvfs.c                  \
        gvolume.c               \
        gvolumemonitor.c        \
-       gvolumeprivate.h        \
+       gmountprivate.h         \
        gioenumtypes.h          \
        gioenumtypes.c          \
        $(appinfo_sources)      \
@@ -222,6 +224,7 @@ gio_headers =                       \
        giomodule.h             \
        gioscheduler.h          \
        gloadableicon.h         \
+       gmount.h                \
        gmemoryinputstream.h    \
        gmemoryoutputstream.h   \
        gmountoperation.h       \
index 41e5171..06d9097 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #include <config.h>
  * @short_description: Virtual File System drive management
  * @include: gio/gdrive.h
  * 
- * #GDrive manages drive operations from GVFS, including volume mounting
- * and ejecting, and getting the drive's name and icon. 
- * 
+ * #GDrive is a container class for #GVolume objects that stem from
+ * the same piece of media. As such, #GDrive abstracts a drive with
+ * (or without) removable media and provides operations for querying
+ * whether media is available, determing whether media change is
+ * automatically detected and ejecting the media.
+ *
+ * If the #GDrive reports that media isn't automatically detected, one
+ * can poll for media; typically one should not do this periodically
+ * as a poll for media operation is potententially expensive and may
+ * spin up the drive creating noise.
+ *
+ * For porting from GnomeVFS note that there is no equivalent of
+ * #GDrive in that API.
  **/
 
 static void g_drive_base_init (gpointer g_class);
@@ -148,9 +159,9 @@ g_drive_get_icon (GDrive *drive)
  * g_drive_has_volumes:
  * @drive: a #GDrive.
  * 
- * Checks if a drive has any volumes.
+ * Check if @drive has any mountable volumes.
  * 
- * Returns: %TRUE if @drive contains volumes, %FALSE otherwise.
+ * Returns: %TRUE if the @drive contains volumes, %FALSE otherwise.
  **/
 gboolean
 g_drive_has_volumes (GDrive *drive)
@@ -168,10 +179,9 @@ g_drive_has_volumes (GDrive *drive)
  * g_drive_get_volumes:
  * @drive: a #GDrive.
  * 
- * Gets a list of volumes for a drive.
+ * Get a list of mountable volumes for @drive.
  * 
  * Returns: #GList containing any #GVolume<!---->s on the given @drive.
- * <!-- NOTE: Fact-check this. -->
  **/
 GList *
 g_drive_get_volumes (GDrive *drive)
@@ -186,15 +196,15 @@ g_drive_get_volumes (GDrive *drive)
 }
 
 /**
- * g_drive_is_automounted:
+ * g_drive_is_media_check_automatic:
  * @drive: a #GDrive.
  * 
- * Checks if a drive was automatically mounted, e.g. by HAL.
+ * Checks if @drive is capabable of automatically detecting media changes.
  * 
- * Returns: %TRUE if the drive was automounted. %FALSE otherwise.
+ * Returns: %TRUE if the @drive is capabable of automatically detecting media changes, %FALSE otherwise.
  **/
 gboolean
-g_drive_is_automounted (GDrive *drive)
+g_drive_is_media_check_automatic (GDrive *drive)
 {
   GDriveIface *iface;
 
@@ -202,19 +212,19 @@ g_drive_is_automounted (GDrive *drive)
 
   iface = G_DRIVE_GET_IFACE (drive);
 
-  return (* iface->is_automounted) (drive);
+  return (* iface->is_media_check_automatic) (drive);
 }
 
 /**
- * g_drive_can_mount:
+ * g_drive_is_media_removable:
  * @drive: a #GDrive.
  * 
- * Checks if a drive can be mounted.
+ * Checks if the @drive supports removable media.
  * 
- * Returns: %TRUE if the @drive can be mounted. %FALSE otherwise.
+ * Returns: %TRUE if @drive supports removable media, %FALSE otherwise.
  **/
 gboolean
-g_drive_can_mount (GDrive *drive)
+g_drive_is_media_removable (GDrive *drive)
 {
   GDriveIface *iface;
 
@@ -222,10 +232,29 @@ g_drive_can_mount (GDrive *drive)
 
   iface = G_DRIVE_GET_IFACE (drive);
 
-  if (iface->can_mount == NULL)
-    return FALSE;
+  return (* iface->is_media_removable) (drive);
+}
 
-  return (* iface->can_mount) (drive);
+/**
+ * g_drive_has_media:
+ * @drive: a #GDrive.
+ * 
+ * Checks if the @drive has media. Note that the OS may not be polling
+ * the drive for media changes; see g_drive_is_media_check_automatic()
+ * for more details.
+ * 
+ * Returns: %TRUE if @drive has media, %FALSE otherwise.
+ **/
+gboolean
+g_drive_has_media (GDrive *drive)
+{
+  GDriveIface *iface;
+
+  g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
+
+  iface = G_DRIVE_GET_IFACE (drive);
+
+  return (* iface->has_media) (drive);
 }
 
 /**
@@ -252,18 +281,40 @@ g_drive_can_eject (GDrive *drive)
 }
 
 /**
- * g_drive_mount:
+ * g_drive_can_poll_for_media:
+ * @drive: a #GDrive.
+ * 
+ * Checks if a drive can be polled for media changes.
+ * 
+ * Returns: %TRUE if the @drive can be polled for media changes. %FALSE otherwise.
+ **/
+gboolean
+g_drive_can_poll_for_media (GDrive *drive)
+{
+  GDriveIface *iface;
+
+  g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
+
+  iface = G_DRIVE_GET_IFACE (drive);
+
+  if (iface->poll_for_media == NULL)
+    return FALSE;
+
+  return (* iface->can_poll_for_media) (drive);
+}
+
+/**
+ * g_drive_eject:
  * @drive: a #GDrive.
- * @mount_operation: a #GMountOperation.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @callback: a #GAsyncReadyCallback.
  * @user_data: a #gpointer.
  * 
- * Mounts a drive.
+ * Ejects a drive.
+ * 
  **/
 void
-g_drive_mount (GDrive              *drive,
-              GMountOperation     *mount_operation,
+g_drive_eject (GDrive              *drive,
               GCancellable        *cancellable,
               GAsyncReadyCallback  callback,
               gpointer             user_data)
@@ -271,38 +322,34 @@ g_drive_mount (GDrive              *drive,
   GDriveIface *iface;
 
   g_return_if_fail (G_IS_DRIVE (drive));
-  g_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
 
   iface = G_DRIVE_GET_IFACE (drive);
 
-  if (iface->mount_fn == NULL)
+  if (iface->eject == NULL)
     {
       g_simple_async_report_error_in_idle (G_OBJECT (drive), callback, user_data,
                                           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                                          _("drive doesn't implement mount"));
+                                          _("drive doesn't implement eject"));
       
       return;
     }
   
-  (* iface->mount_fn) (drive, mount_operation, cancellable, callback, user_data);
+  (* iface->eject) (drive, cancellable, callback, user_data);
 }
 
 /**
- * g_drive_mount_finish:
+ * g_drive_eject_finish
  * @drive: a #GDrive.
  * @result: a #GAsyncResult.
  * @error: a #GError.
  * 
- * Finishes mounting a drive. 
- *
- * If the @drive's interface does not implement the mount operation, @error will 
- * be set to %G_IO_ERROR_NOT_SUPPORTED and %FALSE will be returned.
+ * Finishes ejecting a drive.
  * 
- * Returns: %TRUE if the mount was finished successfully, 
- *     %FALSE if operation failed.
+ * Returns: %TRUE if the drive has been ejected successfully,
+ * %FALSE otherwise.
  **/
 gboolean
-g_drive_mount_finish (GDrive        *drive,
+g_drive_eject_finish (GDrive        *drive,
                      GAsyncResult  *result,
                      GError       **error)
 {
@@ -319,24 +366,25 @@ g_drive_mount_finish (GDrive        *drive,
     }
   
   iface = G_DRIVE_GET_IFACE (drive);
-  return (* iface->mount_finish) (drive, result, error);
+  
+  return (* iface->eject_finish) (drive, result, error);
 }
 
 /**
- * g_drive_eject:
+ * g_drive_poll_for_media:
  * @drive: a #GDrive.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @callback: a #GAsyncReadyCallback.
  * @user_data: a #gpointer.
  * 
- * Ejects a drive.
+ * Polls @drive to see if media has been inserted or removed.
  * 
  **/
 void
-g_drive_eject (GDrive              *drive,
-              GCancellable        *cancellable,
-              GAsyncReadyCallback  callback,
-              gpointer             user_data)
+g_drive_poll_for_media (GDrive              *drive,
+                        GCancellable        *cancellable,
+                        GAsyncReadyCallback  callback,
+                        gpointer             user_data)
 {
   GDriveIface *iface;
 
@@ -344,36 +392,33 @@ g_drive_eject (GDrive              *drive,
 
   iface = G_DRIVE_GET_IFACE (drive);
 
-  if (iface->eject == NULL)
+  if (iface->poll_for_media == NULL)
     {
       g_simple_async_report_error_in_idle (G_OBJECT (drive), callback, user_data,
                                           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                                          _("drive doesn't implement eject"));
+                                          _("drive doesn't implement polling for media"));
       
       return;
     }
   
-  (* iface->eject) (drive, cancellable, callback, user_data);
+  (* iface->poll_for_media) (drive, cancellable, callback, user_data);
 }
 
 /**
- * g_drive_eject_finish
+ * g_drive_poll_for_media_finish
  * @drive: a #GDrive.
  * @result: a #GAsyncResult.
  * @error: a #GError.
  * 
- * Finishes ejecting a drive.
- *
- * If @drive's interface does not implement the eject operation, @error will 
- * be set to %G_IO_ERROR_NOT_SUPPORTED and %FALSE will be returned.
+ * Finishes poll_for_mediaing a drive.
  * 
- * Returns: %TRUE if the drive has been ejected successfully,
+ * Returns: %TRUE if the drive has been poll_for_mediaed successfully,
  * %FALSE otherwise.
  **/
 gboolean
-g_drive_eject_finish (GDrive        *drive,
-                     GAsyncResult  *result,
-                     GError       **error)
+g_drive_poll_for_media_finish (GDrive        *drive,
+                               GAsyncResult  *result,
+                               GError       **error)
 {
   GDriveIface *iface;
 
@@ -389,7 +434,7 @@ g_drive_eject_finish (GDrive        *drive,
   
   iface = G_DRIVE_GET_IFACE (drive);
   
-  return (* iface->mount_finish) (drive, result, error);
+  return (* iface->poll_for_media_finish) (drive, result, error);
 }
 
 #define __G_DRIVE_C__
index f81339c..53de230 100644 (file)
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #ifndef __G_DRIVE_H__
 #define __G_DRIVE_H__
 
 #include <glib-object.h>
+#include <gio/gmount.h>
 #include <gio/gvolume.h>
 #include <gio/gmountoperation.h>
 
@@ -41,14 +43,16 @@ G_BEGIN_DECLS
  * @get_name: Returns the name for the given #GDrive.
  * @get_icon: Returns a #GIcon for the given #GDrive.
  * @has_volumes: Returns %TRUE if the #GDrive has mountable volumes.
- * @get_volumes: Returns a #GList of volumes for the #GDrive.
- * @is_automounted: returns %TRUE if the #GDrive was automounted.
- * @can_mount: Returns %TRUE if the #GDrive can be mounted.
- * @can_eject: Returns %TRUE if the #GDrive can be ejected.
- * @mount_fn: Mounts a given #GDrive.
- * @mount_finish: Finishes a mount operation.
+ * @get_volumes: Returns a list #GList of #GVolume for the #GDrive.
+ * @is_media_removable: Returns %TRUE if the #GDrive supports removal and insertion of media.
+ * @has_media: Returns %TRUE if the #GDrive has media inserted.
+ * @is_media_check_automatic: Returns %TRUE if the #GDrive is capabable of automatically detecting media changes.
+ * @can_poll_for_media: Returns %TRUE if the #GDrive is capable of manually polling for media change.
+ * @can_eject: Returns %TRUE if the #GDrive can eject media.
  * @eject: Ejects a #GDrive.
  * @eject_finish: Finishes an eject operation.
+ * @poll_for_media: Poll for media insertion/removal on a #GDrive.
+ * @poll_for_media_finish: Finishes a media poll operation.
  * 
  * Interface for creating #GDrive implementations.
  */ 
@@ -59,58 +63,70 @@ struct _GDriveIface
   GTypeInterface g_iface;
 
   /* signals */
-  void (*changed)            (GVolume *volume);
+  void (*changed)                      (GDrive              *drive);
   
   /* Virtual Table */
-  
-  char *   (*get_name)    (GDrive         *drive);
-  GIcon *  (*get_icon)    (GDrive         *drive);
-  gboolean (*has_volumes) (GDrive         *drive);
-  GList *  (*get_volumes) (GDrive         *drive);
-  gboolean (*is_automounted)(GDrive       *drive);
-  gboolean (*can_mount)   (GDrive         *drive);
-  gboolean (*can_eject)   (GDrive         *drive);
-  void     (*mount_fn)    (GDrive         *drive,
-                          GMountOperation *mount_operation,
-                          GCancellable   *cancellable,
-                          GAsyncReadyCallback callback,
-                          gpointer        user_data);
-  gboolean (*mount_finish)(GDrive         *drive,
-                          GAsyncResult   *result,
-                          GError        **error);
-  void     (*eject)       (GDrive         *drive,
-                          GCancellable   *cancellable,
-                          GAsyncReadyCallback callback,
-                          gpointer        user_data);
-  gboolean (*eject_finish)(GDrive         *drive,
-                          GAsyncResult   *result,
-                          GError        **error);
+  char *   (*get_name)                 (GDrive              *drive);
+  GIcon *  (*get_icon)                 (GDrive              *drive);
+  gboolean (*has_volumes)              (GDrive              *drive);
+  GList *  (*get_volumes)              (GDrive              *drive);
+  gboolean (*is_media_removable)       (GDrive              *drive);
+  gboolean (*has_media)                (GDrive              *drive);
+  gboolean (*is_media_check_automatic) (GDrive              *drive);
+  gboolean (*can_eject)                (GDrive              *drive);
+  gboolean (*can_poll_for_media)       (GDrive              *drive);
+  void     (*eject)                    (GDrive              *drive,
+                                        GCancellable        *cancellable,
+                                        GAsyncReadyCallback  callback,
+                                        gpointer             user_data);
+  gboolean (*eject_finish)             (GDrive              *drive,
+                                        GAsyncResult        *result,
+                                        GError             **error);
+  void     (*poll_for_media)           (GDrive              *drive,
+                                        GCancellable        *cancellable,
+                                        GAsyncReadyCallback  callback,
+                                        gpointer             user_data);
+  gboolean (*poll_for_media_finish)    (GDrive              *drive,
+                                        GAsyncResult        *result,
+                                        GError             **error);
+
+  /*< private >*/
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+  void (*_g_reserved6) (void);
+  void (*_g_reserved7) (void);
+  void (*_g_reserved8) (void);
 };
 
-GType g_drive_get_type (void) G_GNUC_CONST;
+GType g_drive_get_type                    (void) G_GNUC_CONST;
 
-char *   g_drive_get_name       (GDrive               *drive);
-GIcon *  g_drive_get_icon       (GDrive               *drive);
-gboolean g_drive_has_volumes    (GDrive               *drive);
-GList  * g_drive_get_volumes    (GDrive               *drive);
-gboolean g_drive_is_automounted (GDrive               *drive);
-gboolean g_drive_can_mount      (GDrive               *drive);
-gboolean g_drive_can_eject      (GDrive               *drive);
-void     g_drive_mount          (GDrive               *drive,
-                                GMountOperation      *mount_operation,
-                                GCancellable         *cancellable,
-                                GAsyncReadyCallback   callback,
-                                gpointer              user_data);
-gboolean g_drive_mount_finish   (GDrive               *drive,
-                                GAsyncResult         *result,
-                                GError              **error);
-void     g_drive_eject          (GDrive               *drive,
-                                GCancellable         *cancellable,
-                                GAsyncReadyCallback   callback,
-                                gpointer              user_data);
-gboolean g_drive_eject_finish   (GDrive               *drive,
-                                GAsyncResult         *result,
-                                GError              **error);
+char *   g_drive_get_name                 (GDrive               *drive);
+GIcon *  g_drive_get_icon                 (GDrive               *drive);
+gboolean g_drive_has_volumes              (GDrive               *drive);
+GList *  g_drive_get_volumes              (GDrive               *drive);
+gboolean g_drive_is_media_removable       (GDrive               *drive);
+gboolean g_drive_has_media                (GDrive               *drive);
+gboolean g_drive_is_media_check_automatic (GDrive               *drive);
+gboolean g_drive_can_poll_for_media       (GDrive               *drive);
+gboolean g_drive_can_eject                (GDrive               *drive);
+void     g_drive_eject                    (GDrive               *drive,
+                                           GCancellable         *cancellable,
+                                           GAsyncReadyCallback   callback,
+                                           gpointer              user_data);
+gboolean g_drive_eject_finish             (GDrive               *drive,
+                                           GAsyncResult         *result,
+                                           GError              **error);
+void     g_drive_poll_for_media           (GDrive               *drive,
+                                           GCancellable         *cancellable,
+                                           GAsyncReadyCallback   callback,
+                                           gpointer              user_data);
+gboolean g_drive_poll_for_media_finish    (GDrive               *drive,
+                                           GAsyncResult         *result,
+                                           GError              **error);
 
 G_END_DECLS
 
index 5ddc7fd..0cbd91f 100644 (file)
@@ -929,14 +929,14 @@ g_file_query_filesystem_info (GFile         *file,
 }
 
 /**
- * g_file_find_enclosing_volume:
+ * g_file_find_enclosing_mount:
  * @file: input #GFile.
  * @cancellable: optional #GCancellable object, %NULL to ignore. 
  * @error: a #GError. 
  *
- * Gets a #GVolume for the #GFile. 
+ * Gets a #GMount for the #GFile. 
  *
- * If the #GFileIface for @file does not have a volume (e.g. possibly a 
+ * If the #GFileIface for @file does not have a mount (e.g. possibly a 
  * remote share), @error will be set to %G_IO_ERROR_NOT_FOUND and %NULL
  * will be returned.
  * 
@@ -944,10 +944,10 @@ g_file_query_filesystem_info (GFile         *file,
  * triggering the cancellable object from another thread. If the operation
  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
  * 
- * Returns: a #GVolume where the @file is located or %NULL on error.
+ * Returns: a #GMount where the @file is located or %NULL on error.
  **/
-GVolume *
-g_file_find_enclosing_volume (GFile         *file,
+GMount *
+g_file_find_enclosing_mount (GFile         *file,
                              GCancellable  *cancellable,
                              GError       **error)
 {
@@ -959,15 +959,15 @@ g_file_find_enclosing_volume (GFile         *file,
     return NULL;
 
   iface = G_FILE_GET_IFACE (file);
-  if (iface->find_enclosing_volume == NULL)
+  if (iface->find_enclosing_mount == NULL)
     {
       g_set_error (error, G_IO_ERROR,
                   G_IO_ERROR_NOT_FOUND,
-                  _("Containing volume does not exist"));
+                  _("Containing mount does not exist"));
       return NULL;
     }
   
-  return (* iface->find_enclosing_volume) (file, cancellable, error);
+  return (* iface->find_enclosing_mount) (file, cancellable, error);
 }
 
 /**
index 67dce7a..49e24cb 100644 (file)
@@ -105,11 +105,11 @@ typedef struct _GDirectoryMonitor       GDirectoryMonitor;
 typedef struct _GFileMonitor            GFileMonitor;
 
 /**
- * GVolume:
+ * GMount:
  * 
- * A handle to an object implementing the #GVolumeIface interface.
+ * A handle to an object implementing the #GMountIface interface.
  **/
-typedef struct _GVolume         GVolume; /* Dummy typedef */
+typedef struct _GMount         GMount; /* Dummy typedef */
 
 /**
  * GFileProgressCallback:
@@ -169,9 +169,9 @@ typedef gboolean (* GFileReadMoreCallback) (const char *file_contents,
  * @query_filesystem_info: Gets a #GFileInfo for the file system #GFile is on.
  * @_query_filesystem_info_async: Asynchronously gets a #GFileInfo for the file system #GFile is on.
  * @_query_filesystem_info_finish: Finishes asynchronously getting the file system info.
- * @find_enclosing_volume: Gets a #GVolume for the #GFile.
- * @find_enclosing_volume_async: Asynchronously gets the #GVolume for a #GFile.
- * @find_enclosing_volume_finish: Finishes asynchronously getting the volume.
+ * @find_enclosing_mount: Gets a #GMount for the #GFile.
+ * @find_enclosing_mount_async: Asynchronously gets the #GMount for a #GFile.
+ * @find_enclosing_mount_finish: Finishes asynchronously getting the volume.
  * @set_display_name: Sets the display name for a #GFile.
  * @set_display_name_async: Asynchronously sets a #GFile's display name.
  * @set_display_name_finish: Finishes asynchronously setting a #GFile's display name.
@@ -296,17 +296,17 @@ struct _GFileIface
   void                (*_query_filesystem_info_async) (void);
   void                (*_query_filesystem_info_finish) (void);
   
-  GVolume *           (*find_enclosing_volume)(GFile              *file,
+  GMount *            (*find_enclosing_mount)(GFile              *file,
                                               GCancellable       *cancellable,
                                               GError            **error);
-  void                (*find_enclosing_volume_async)(GFile              *file,
-                                                    int                   io_priority,
-                                                    GCancellable         *cancellable,
-                                                    GAsyncReadyCallback   callback,
-                                                    gpointer              user_data);
-  GVolume *           (*find_enclosing_volume_finish)(GFile              *file,
-                                                     GAsyncResult         *res,
-                                                     GError            **error);
+  void                (*find_enclosing_mount_async)(GFile              *file,
+                                                    int                   io_priority,
+                                                    GCancellable         *cancellable,
+                                                    GAsyncReadyCallback   callback,
+                                                    gpointer              user_data);
+  GMount *            (*find_enclosing_mount_finish)(GFile              *file,
+                                                     GAsyncResult         *res,
+                                                     GError            **error);
   
   GFile *             (*set_display_name)         (GFile                *file,
                                                   const char           *display_name,
@@ -608,9 +608,9 @@ GFileInfo *             g_file_query_filesystem_info      (GFile
                                                           const char                 *attributes,
                                                           GCancellable               *cancellable,
                                                           GError                    **error);
-GVolume *               g_file_find_enclosing_volume      (GFile                      *file,
-                                                          GCancellable               *cancellable,
-                                                          GError                    **error);
+GMount *                g_file_find_enclosing_mount      (GFile                      *file,
+                                                          GCancellable               *cancellable,
+                                                          GError                    **error);
 GFileEnumerator *       g_file_enumerate_children         (GFile                      *file,
                                                           const char                 *attributes,
                                                           GFileQueryInfoFlags         flags,
index 0fe7456..d185ddb 100644 (file)
@@ -190,13 +190,15 @@ g_drive_get_name
 g_drive_get_icon
 g_drive_has_volumes
 g_drive_get_volumes
-g_drive_is_automounted
-g_drive_can_mount
+g_drive_is_media_removable
+g_drive_has_media
+g_drive_is_media_check_automatic
+g_drive_can_poll_for_media
 g_drive_can_eject
-g_drive_mount
-g_drive_mount_finish
 g_drive_eject
 g_drive_eject_finish
+g_drive_poll_for_media
+g_drive_poll_for_media_finish
 #endif
 #endif
 
@@ -272,7 +274,7 @@ g_file_query_info
 g_file_query_info_async
 g_file_query_info_finish
 g_file_query_filesystem_info
-g_file_find_enclosing_volume
+g_file_find_enclosing_mount
 g_file_enumerate_children
 g_file_enumerate_children_async
 g_file_enumerate_children_finish
@@ -650,7 +652,8 @@ g_unix_mount_get_device_path
 g_unix_mount_get_fs_type 
 g_unix_mount_is_readonly 
 g_unix_mount_is_system_internal 
-g_unix_mount_guess_type 
+g_unix_mount_guess_name 
+g_unix_mount_guess_icon
 g_unix_mount_point_compare 
 g_unix_mount_point_get_mount_path 
 g_unix_mount_point_get_device_path 
@@ -658,7 +661,8 @@ g_unix_mount_point_get_fs_type
 g_unix_mount_point_is_readonly 
 g_unix_mount_point_is_user_mountable 
 g_unix_mount_point_is_loopback 
-g_unix_mount_point_guess_type 
+g_unix_mount_point_guess_name 
+g_unix_mount_point_guess_icon
 g_get_unix_mount_points 
 g_get_unix_mounts 
 g_get_unix_mount_at 
@@ -666,6 +670,7 @@ g_unix_mounts_changed_since
 g_unix_mount_points_changed_since 
 g_unix_mount_monitor_get_type  G_GNUC_CONST
 g_unix_mount_monitor_new 
+g_unix_is_mount_path_system_internal
 #endif /* G_OS_UNIX */
 #endif
 #endif
@@ -688,27 +693,39 @@ g_unix_output_stream_new
 #endif
 #endif
 
+#if IN_HEADER(__G_MOUNT_H__)
+#if IN_FILE(__G_MOUNT_C__)
+g_mount_get_type  G_GNUC_CONST
+g_mount_get_root 
+g_mount_get_name 
+g_mount_get_icon 
+g_mount_get_volume
+g_mount_get_drive 
+g_mount_can_unmount 
+g_mount_unmount 
+g_mount_unmount_finish 
+#endif
+#endif
+
 #if IN_HEADER(__G_VOLUME_H__)
 #if IN_FILE(__G_VOLUME_C__)
 g_volume_get_type  G_GNUC_CONST
-g_volume_get_root 
 g_volume_get_name 
 g_volume_get_icon 
 g_volume_get_drive 
-g_volume_can_unmount 
-g_volume_can_eject 
-g_volume_unmount 
-g_volume_unmount_finish 
-g_volume_eject 
-g_volume_eject_finish 
+g_volume_get_mount
+g_volume_can_mount
+g_volume_mount 
+g_volume_mount_finish 
 #endif
 #endif
 
 #if IN_HEADER(__G_VOLUME_MONITOR_H__)
 #if IN_FILE(__G_VOLUME_MONITOR_C__)
 g_volume_monitor_get_type  G_GNUC_CONST
-g_volume_monitor_get_mounted_volumes 
 g_volume_monitor_get_connected_drives 
+g_volume_monitor_get_volumes 
+g_volume_monitor_get_mounts
 #endif
 #if IN_FILE(__G_UNION_VOLUME_MONITOR_C__)
 g_volume_monitor_get 
index d620afc..5047067 100644 (file)
@@ -115,7 +115,7 @@ g_local_directory_monitor_constructor (GType                  type,
 #ifdef G_OS_WIN32
       g_warning ("G_OS_WIN32: no mount emulation");
 #else
-      GUnixMount *mount;
+      GUnixMountEntry *mount;
       
       /* Emulate unmount detection */
       
@@ -164,7 +164,7 @@ mounts_changed (GUnixMountMonitor *mount_monitor,
                 gpointer           user_data)
 {
   GLocalDirectoryMonitor *local_monitor = user_data;
-  GUnixMount *mount;
+  GUnixMountEntry *mount;
   gboolean is_mounted;
   GFile *file;
   
index cb1e443..1afa66e 100644 (file)
@@ -75,7 +75,7 @@
 #include "glocalfileoutputstream.h"
 #include "glocaldirectorymonitor.h"
 #include "glocalfilemonitor.h"
-#include "gvolumeprivate.h"
+#include "gmountprivate.h"
 #include <glib/gstdio.h>
 #include "glibintl.h"
 
@@ -697,7 +697,7 @@ get_mount_info (GFileInfo             *fs_info,
   guint mount_info;
   char *mountpoint;
   dev_t *dev;
-  GUnixMount *mount;
+  GUnixMountEntry *mount;
   guint64 cache_time;
 
   if (g_lstat (path, &buf) != 0)
@@ -871,21 +871,21 @@ g_local_file_query_filesystem_info (GFile         *file,
   return info;
 }
 
-static GVolume *
-g_local_file_find_enclosing_volume (GFile         *file,
-                                   GCancellable  *cancellable,
-                                   GError       **error)
+static GMount *
+g_local_file_find_enclosing_mount (GFile         *file,
+                                   GCancellable  *cancellable,
+                                   GError       **error)
 {
   GLocalFile *local = G_LOCAL_FILE (file);
   struct stat buf;
   char *mountpoint;
-  GVolume *volume;
+  GMount *mount;
 
   if (g_lstat (local->filename, &buf) != 0)
     {
       g_set_error (error, G_IO_ERROR,
                   G_IO_ERROR_NOT_FOUND,
-                  _("Containing volume does not exist"));
+                  _("Containing mount does not exist"));
       return NULL;
     }
 
@@ -894,18 +894,18 @@ g_local_file_find_enclosing_volume (GFile         *file,
     {
       g_set_error (error, G_IO_ERROR,
                   G_IO_ERROR_NOT_FOUND,
-                  _("Containing volume does not exist"));
+                  _("Containing mount does not exist"));
       return NULL;
     }
 
-  volume = _g_volume_get_for_mount_path (mountpoint);
+  mount = _g_mount_get_for_mount_path (mountpoint);
   g_free (mountpoint);
-  if (volume)
-    return volume;
+  if (mount)
+    return mount;
 
   g_set_error (error, G_IO_ERROR,
               G_IO_ERROR_NOT_FOUND,
-              _("Containing volume does not exist"));
+              _("Containing mount does not exist"));
   return NULL;
 }
 
@@ -1889,7 +1889,7 @@ g_local_file_file_iface_init (GFileIface *iface)
   iface->enumerate_children = g_local_file_enumerate_children;
   iface->query_info = g_local_file_query_info;
   iface->query_filesystem_info = g_local_file_query_filesystem_info;
-  iface->find_enclosing_volume = g_local_file_find_enclosing_volume;
+  iface->find_enclosing_mount = g_local_file_find_enclosing_mount;
   iface->query_settable_attributes = g_local_file_query_settable_attributes;
   iface->query_writable_namespaces = g_local_file_query_writable_namespaces;
   iface->set_attribute = g_local_file_set_attribute;
diff --git a/gio/gmount.c b/gio/gmount.c
new file mode 100644 (file)
index 0000000..49f9175
--- /dev/null
@@ -0,0 +1,312 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+#include "gmount.h"
+#include "gmountprivate.h"
+#include "gsimpleasyncresult.h"
+#include "glibintl.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:gmount
+ * @short_description: mount management
+ * 
+ * The #GMount interface represents user-visible mounts. Note, when
+ * porting from GnomeVFS, #GMount is the moral equivalent of
+ * #GnomeVFSVolume.
+ * 
+ * Unmounting a #GMount instance is an asynchronous operation. For
+ * more information about asynchronous operations, see #GAsyncReady
+ * and #GSimpleAsyncReady. To unmount a #GMount instance, first call
+ * g_mount_unmount() with (at least) the #GMount instance and a
+ * #GAsyncReadyCallback.  The callback will be fired when the
+ * operation has resolved (either with success or failure), and a
+ * #GAsyncReady structure will be passed to the callback.  That
+ * callback should then call g_mount_unmount_finish() with the #GMount
+ * and the #GAsyncReady data to see if the operation was completed
+ * successfully.  If an @error is present when
+ * g_mount_unmount_finish() is called, then it will be filled with any
+ * error information.
+ **/
+
+static void g_mount_base_init (gpointer g_class);
+static void g_mount_class_init (gpointer g_class,
+                                gpointer class_data);
+
+GType
+g_mount_get_type (void)
+{
+  static GType mount_type = 0;
+
+  if (! mount_type)
+    {
+      static const GTypeInfo mount_info =
+      {
+        sizeof (GMountIface), /* class_size */
+       g_mount_base_init,   /* base_init */
+       NULL,           /* base_finalize */
+       g_mount_class_init,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+       0,
+       0,              /* n_preallocs */
+       NULL
+      };
+
+      mount_type =
+       g_type_register_static (G_TYPE_INTERFACE, I_("GMount"),
+                               &mount_info, 0);
+
+      g_type_interface_add_prerequisite (mount_type, G_TYPE_OBJECT);
+    }
+
+  return mount_type;
+}
+
+static void
+g_mount_class_init (gpointer g_class,
+                    gpointer class_data)
+{
+}
+
+static void
+g_mount_base_init (gpointer g_class)
+{
+  static gboolean initialized = FALSE;
+
+  if (! initialized)
+    {
+     /**
+      * GMount::changed:
+      * 
+      * Emitted when the mount has been changed.
+      **/
+      g_signal_new (I_("changed"),
+                    G_TYPE_MOUNT,
+                    G_SIGNAL_RUN_LAST,
+                    G_STRUCT_OFFSET (GMountIface, changed),
+                    NULL, NULL,
+                    g_cclosure_marshal_VOID__VOID,
+                    G_TYPE_NONE, 0);
+
+      initialized = TRUE;
+    }
+}
+
+/**
+ * g_mount_get_root:
+ * @mount: a #GMount.
+ * 
+ * Gets the root directory on @mount.
+ * 
+ * Returns: a #GFile.
+ **/
+GFile *
+g_mount_get_root (GMount *mount)
+{
+  GMountIface *iface;
+
+  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
+
+  iface = G_MOUNT_GET_IFACE (mount);
+
+  return (* iface->get_root) (mount);
+}
+
+/**
+ * g_mount_get_name:
+ * @mount: a #GMount.
+ * 
+ * Gets the name of @mount.
+ * 
+ * Returns: the name for the given @mount. The returned string should 
+ * be freed when no longer needed.
+ **/
+char *
+g_mount_get_name (GMount *mount)
+{
+  GMountIface *iface;
+
+  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
+
+  iface = G_MOUNT_GET_IFACE (mount);
+
+  return (* iface->get_name) (mount);
+}
+
+/**
+ * g_mount_get_icon:
+ * @mount: a #GMount.
+ * 
+ * Gets the icon for @mount.
+ * 
+ * Returns: a #GIcon.
+ **/
+GIcon *
+g_mount_get_icon (GMount *mount)
+{
+  GMountIface *iface;
+
+  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
+
+  iface = G_MOUNT_GET_IFACE (mount);
+
+  return (* iface->get_icon) (mount);
+}
+  
+/**
+ * g_mount_get_volume:
+ * @mount: a #GMount.
+ * 
+ * Gets the volume for the @mount.
+ * 
+ * Returns: a #GVolume or %NULL if @mount is not associated with a volume.
+ **/
+GVolume *
+g_mount_get_volume (GMount *mount)
+{
+  GMountIface *iface;
+
+  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
+
+  iface = G_MOUNT_GET_IFACE (mount);
+
+  return (* iface->get_volume) (mount);
+}
+
+/**
+ * g_mount_get_drive:
+ * @mount: a #GMount.
+ * 
+ * Gets the drive for the @mount.
+ *
+ * This is a convenience method for getting the #GVolume and then
+ * using that object to get the #GDrive.
+ * 
+ * Returns: a #GDrive or %NULL if @mount is not associated with a volume or a drive.
+ **/
+GDrive *
+g_mount_get_drive (GMount *mount)
+{
+  GMountIface *iface;
+
+  g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
+
+  iface = G_MOUNT_GET_IFACE (mount);
+
+  return (* iface->get_drive) (mount);
+}
+
+/**
+ * g_mount_can_unmount: 
+ * @mount: a #GMount.
+ * 
+ * Checks if @mount can be mounted.
+ * 
+ * Returns: %TRUE if the @mount can be unmounted.
+ **/
+gboolean
+g_mount_can_unmount (GMount *mount)
+{
+  GMountIface *iface;
+
+  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
+
+  iface = G_MOUNT_GET_IFACE (mount);
+
+  return (* iface->can_unmount) (mount);
+}
+
+/**
+ * g_mount_unmount:
+ * @mount: a #GMount.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: a #GAsyncReadyCallback.
+ * @user_data: user data passed to @callback.
+ * 
+ * Unmounts a mount. This is an asynchronous operation, and is 
+ * finished by calling g_mount_unmount_finish() with the @mount 
+ * and #GAsyncResults data returned in the @callback.
+ **/
+void
+g_mount_unmount (GMount             *mount,
+                 GCancellable        *cancellable,
+                 GAsyncReadyCallback  callback,
+                 gpointer             user_data)
+{
+  GMountIface *iface;
+
+  g_return_if_fail (G_IS_MOUNT (mount));
+  
+  iface = G_MOUNT_GET_IFACE (mount);
+
+  if (iface->unmount == NULL)
+    {
+      g_simple_async_report_error_in_idle (G_OBJECT (mount),
+                                          callback, user_data,
+                                          G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                                          _("mount doesn't implement unmount"));
+      
+      return;
+    }
+  
+  (* iface->unmount) (mount, cancellable, callback, user_data);
+}
+
+/**
+ * g_mount_unmount_finish:
+ * @mount: a #GMount.
+ * @result: a #GAsyncResult.
+ * @error: a #GError location to store the error occuring, or %NULL to 
+ * ignore.
+ * 
+ * Finishes unmounting a mount. If any errors occured during the operation, 
+ * @error will be set to contain the errors and %FALSE will be returned.
+ * 
+ * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
+ **/
+gboolean
+g_mount_unmount_finish (GMount       *mount,
+                        GAsyncResult  *result,
+                        GError       **error)
+{
+  GMountIface *iface;
+
+  g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+        return FALSE;
+    }
+  
+  iface = G_MOUNT_GET_IFACE (mount);
+  return (* iface->unmount_finish) (mount, result, error);
+}
+
+#define __G_MOUNT_C__
+#include "gioaliasdef.c"
diff --git a/gio/gmount.h b/gio/gmount.h
new file mode 100644 (file)
index 0000000..ed413e1
--- /dev/null
@@ -0,0 +1,123 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_MOUNT_H__
+#define __G_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gfile.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_MOUNT            (g_mount_get_type ())
+#define G_MOUNT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_MOUNT, GMount))
+#define G_IS_MOUNT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_MOUNT))
+#define G_MOUNT_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_MOUNT, GMountIface))
+
+/* GMount typedef is in gfile.h due to include order issues */
+/**
+ * GVolume:
+ * 
+ * Opaque mountable volume object.
+ **/
+typedef struct _GVolume GVolume; /* Dummy typedef */
+
+/**
+ * GDrive:
+ * 
+ * Opaque drive object.
+ **/
+typedef struct _GDrive          GDrive; /* Dummy typedef */
+
+typedef struct _GMountIface    GMountIface;
+
+/**
+ * GMountIface:
+ * @g_iface: The parent interface.
+ * @changed: Changed signal that is emitted when the mount's state has changed.
+ * @get_root: Gets a #GFile to the root directory of the #GMount.
+ * @get_name: Gets a string containing the name of the #GMount.
+ * @get_icon: Gets a #GIcon for the #GMount.
+ * @get_volume: Gets a #GVolume the mount is located on. Returns %NULL if the #GMount is not associated with a #GVolume.
+ * @get_drive: Gets a #GDrive the volume of the mount is located on. Returns %NULL if the #GMount is not associated with a #GDrive or a #GVolume. This is convenience method for getting the #GVolume and using that to get the #GDrive.
+ * @can_unmount: Checks if a #GMount can be unmounted.
+ * @unmount: Starts unmounting a #GMount.
+ * @unmount_finish: Finishes an unmounting operation.
+ * 
+ * Interface for implementing operations for mounts.
+ **/
+struct _GMountIface
+{
+  GTypeInterface g_iface;
+
+  /* signals */
+
+  void (*changed) (GMount *mount);
+  
+  /* Virtual Table */
+
+  GFile *            (*get_root)             (GMount         *mount);
+  char *             (*get_name)             (GMount         *mount);
+  GIcon *            (*get_icon)             (GMount         *mount);
+  GVolume *          (*get_volume)           (GMount         *mount);
+  GDrive *           (*get_drive)            (GMount         *mount);
+  gboolean           (*can_unmount)          (GMount         *mount);
+  void               (*unmount)              (GMount         *mount,
+                                              GCancellable    *cancellable,
+                                              GAsyncReadyCallback callback,
+                                              gpointer         user_data);
+  gboolean           (*unmount_finish)       (GMount         *mount,
+                                              GAsyncResult    *result,
+                                              GError         **error);
+
+  /*< private >*/
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+  void (*_g_reserved6) (void);
+  void (*_g_reserved7) (void);
+  void (*_g_reserved8) (void);
+};
+
+GType g_mount_get_type (void) G_GNUC_CONST;
+
+GFile *            g_mount_get_root             (GMount              *mount);
+char *             g_mount_get_name             (GMount              *mount);
+GIcon *            g_mount_get_icon             (GMount              *mount);
+GVolume *          g_mount_get_volume           (GMount              *mount);
+GDrive *           g_mount_get_drive            (GMount              *mount);
+gboolean           g_mount_can_unmount          (GMount              *mount);
+void               g_mount_unmount              (GMount              *mount,
+                                                 GCancellable         *cancellable,
+                                                 GAsyncReadyCallback   callback,
+                                                 gpointer              user_data);
+gboolean           g_mount_unmount_finish       (GMount              *mount,
+                                                 GAsyncResult         *result,
+                                                 GError              **error);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_H__ */
similarity index 94%
rename from gio/gvolumeprivate.h
rename to gio/gmountprivate.h
index 43c9c1f..836613e 100644 (file)
@@ -27,7 +27,7 @@
 
 G_BEGIN_DECLS
 
-GVolume *_g_volume_get_for_mount_path (const char *mountpoint);
+GMount *_g_mount_get_for_mount_path (const char *mount_path);
 
 G_END_DECLS
 
index c3ccca2..688e98e 100644 (file)
@@ -22,7 +22,7 @@ struct _GNativeVolumeMonitor {
 struct _GNativeVolumeMonitorClass {
   GVolumeMonitorClass parent_class;
 
-  GVolume * (*get_volume_for_mountpoint) (const char *mountpoint);
+  GMount * (*get_mount_for_mount_path) (const char *mount_path);
   
   int priority;
 };
index 63afd0c..37e48cd 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #include <config.h>
@@ -26,7 +27,7 @@
 
 #include <glib.h>
 #include "gunionvolumemonitor.h"
-#include "gvolumeprivate.h"
+#include "gmountprivate.h"
 #include "giomodule-priv.h"
 #ifdef G_OS_UNIX
 #include "gunixvolumemonitor.h"
@@ -85,7 +86,7 @@ g_union_volume_monitor_dispose (GObject *object)
 }
 
 static GList *
-get_mounted_volumes (GVolumeMonitor *volume_monitor)
+get_mounts (GVolumeMonitor *volume_monitor)
 {
   GUnionVolumeMonitor *monitor;
   GVolumeMonitor *child_monitor;
@@ -102,8 +103,33 @@ get_mounted_volumes (GVolumeMonitor *volume_monitor)
     {
       child_monitor = l->data;
 
-      res = g_list_concat (res,
-                          g_volume_monitor_get_mounted_volumes (child_monitor));
+      res = g_list_concat (res, g_volume_monitor_get_mounts (child_monitor));
+    }
+  
+  G_UNLOCK (the_volume_monitor);
+
+  return res;
+}
+
+static GList *
+get_volumes (GVolumeMonitor *volume_monitor)
+{
+  GUnionVolumeMonitor *monitor;
+  GVolumeMonitor *child_monitor;
+  GList *res;
+  GList *l;
+  
+  monitor = G_UNION_VOLUME_MONITOR (volume_monitor);
+
+  res = NULL;
+  
+  G_LOCK (the_volume_monitor);
+
+  for (l = monitor->monitors; l != NULL; l = l->next)
+    {
+      child_monitor = l->data;
+
+      res = g_list_concat (res, g_volume_monitor_get_volumes (child_monitor));
     }
   
   G_UNLOCK (the_volume_monitor);
@@ -129,8 +155,7 @@ get_connected_drives (GVolumeMonitor *volume_monitor)
     {
       child_monitor = l->data;
 
-      res = g_list_concat (res,
-                          g_volume_monitor_get_connected_drives (child_monitor));
+      res = g_list_concat (res, g_volume_monitor_get_connected_drives (child_monitor));
     }
   
   G_UNLOCK (the_volume_monitor);
@@ -147,41 +172,83 @@ g_union_volume_monitor_class_init (GUnionVolumeMonitorClass *klass)
   gobject_class->finalize = g_union_volume_monitor_finalize;
   gobject_class->dispose = g_union_volume_monitor_dispose;
 
-  monitor_class->get_mounted_volumes = get_mounted_volumes;
   monitor_class->get_connected_drives = get_connected_drives;
+  monitor_class->get_volumes = get_volumes;
+  monitor_class->get_mounts = get_mounts;
 }
 
 static void
-child_volume_mounted (GVolumeMonitor      *child_monitor,
-                      GVolume             *child_volume,
-                      GUnionVolumeMonitor *union_monitor)
+child_volume_added (GVolumeMonitor      *child_monitor,
+                    GVolume    *child_volume,
+                    GUnionVolumeMonitor *union_monitor)
 {
   g_signal_emit_by_name (union_monitor,
-                        "volume_mounted",
+                        "volume_added",
                         child_volume);
 }
 
 static void
-child_volume_pre_unmount (GVolumeMonitor      *child_monitor,
-                          GVolume             *child_volume,
-                          GUnionVolumeMonitor *union_monitor)
+child_volume_removed (GVolumeMonitor      *child_monitor,
+                      GVolume    *child_volume,
+                      GUnionVolumeMonitor *union_monitor)
 {
   g_signal_emit_by_name (union_monitor,
-                        "volume_pre_unmount",
+                        "volume_removed",
                         child_volume);
 }
 
 static void
-child_volume_unmounted (GVolumeMonitor      *child_monitor,
-                        GVolume             *child_volume,
-                        GUnionVolumeMonitor *union_monitor)
+child_volume_changed (GVolumeMonitor      *child_monitor,
+                      GVolume    *child_volume,
+                      GUnionVolumeMonitor *union_monitor)
 {
   g_signal_emit_by_name (union_monitor,
-                        "volume_unmounted",
+                        "volume_changed",
                         child_volume);
 }
 
 static void
+child_mount_added (GVolumeMonitor      *child_monitor,
+                   GMount              *child_mount,
+                   GUnionVolumeMonitor *union_monitor)
+{
+  g_signal_emit_by_name (union_monitor,
+                         "mount_added",
+                         child_mount);
+}
+
+static void
+child_mount_removed (GVolumeMonitor      *child_monitor,
+                     GMount              *child_mount,
+                     GUnionVolumeMonitor *union_monitor)
+{
+  g_signal_emit_by_name (union_monitor,
+                        "mount_removed",
+                        child_mount);
+}
+
+static void
+child_mount_pre_unmount (GVolumeMonitor       *child_monitor,
+                          GMount              *child_mount,
+                          GUnionVolumeMonitor *union_monitor)
+{
+  g_signal_emit_by_name (union_monitor,
+                        "mount_pre_unmount",
+                        child_mount);
+}
+
+
+static void
+child_mount_changed (GVolumeMonitor       *child_monitor,
+                      GMount              *child_mount,
+                      GUnionVolumeMonitor *union_monitor)
+{
+  g_signal_emit_by_name (union_monitor,
+                        "mount_changed",
+                        child_mount);
+}
+
+static void
 child_drive_connected (GVolumeMonitor      *child_monitor,
                        GDrive              *child_drive,
                        GUnionVolumeMonitor *union_monitor)
@@ -202,6 +269,16 @@ child_drive_disconnected (GVolumeMonitor      *child_monitor,
 }
 
 static void
+child_drive_changed (GVolumeMonitor      *child_monitor,
+                     GDrive             *child_drive,
+                     GUnionVolumeMonitor *union_monitor)
+{
+  g_signal_emit_by_name (union_monitor,
+                         "drive_changed",
+                         child_drive);
+}
+
+static void
 g_union_volume_monitor_add_monitor (GUnionVolumeMonitor *union_monitor,
                                     GVolumeMonitor      *volume_monitor)
 {
@@ -212,11 +289,16 @@ g_union_volume_monitor_add_monitor (GUnionVolumeMonitor *union_monitor,
     g_list_prepend (union_monitor->monitors,
                    g_object_ref (volume_monitor));
 
-  g_signal_connect (volume_monitor, "volume_mounted", (GCallback)child_volume_mounted, union_monitor);
-  g_signal_connect (volume_monitor, "volume_pre_unmount", (GCallback)child_volume_pre_unmount, union_monitor);
-  g_signal_connect (volume_monitor, "volume_unmounted", (GCallback)child_volume_unmounted, union_monitor);
+  g_signal_connect (volume_monitor, "volume_added", (GCallback)child_volume_added, union_monitor);
+  g_signal_connect (volume_monitor, "volume_removed", (GCallback)child_volume_removed, union_monitor);
+  g_signal_connect (volume_monitor, "volume_changed", (GCallback)child_volume_changed, union_monitor);
+  g_signal_connect (volume_monitor, "mount_added", (GCallback)child_mount_added, union_monitor);
+  g_signal_connect (volume_monitor, "mount_removed", (GCallback)child_mount_removed, union_monitor);
+  g_signal_connect (volume_monitor, "mount_pre_unmount", (GCallback)child_mount_pre_unmount, union_monitor);
+  g_signal_connect (volume_monitor, "mount_changed", (GCallback)child_mount_changed, union_monitor);
   g_signal_connect (volume_monitor, "drive_connected", (GCallback)child_drive_connected, union_monitor);
   g_signal_connect (volume_monitor, "drive_disconnected", (GCallback)child_drive_disconnected, union_monitor);
+  g_signal_connect (volume_monitor, "drive_changed", (GCallback)child_drive_changed, union_monitor);
 }
 
 static void
@@ -231,11 +313,16 @@ g_union_volume_monitor_remove_monitor (GUnionVolumeMonitor *union_monitor,
 
   union_monitor->monitors = g_list_delete_link (union_monitor->monitors, l);
 
-  g_signal_handlers_disconnect_by_func (child_monitor, child_volume_mounted, union_monitor);
-  g_signal_handlers_disconnect_by_func (child_monitor, child_volume_pre_unmount, union_monitor);
-  g_signal_handlers_disconnect_by_func (child_monitor, child_volume_unmounted, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_volume_added, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_volume_removed, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_volume_changed, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_mount_added, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_mount_removed, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_mount_pre_unmount, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_mount_changed, union_monitor);
   g_signal_handlers_disconnect_by_func (child_monitor, child_drive_connected, union_monitor);
   g_signal_handlers_disconnect_by_func (child_monitor, child_drive_disconnected, union_monitor);
+  g_signal_handlers_disconnect_by_func (child_monitor, child_drive_changed, union_monitor);
 }
 
 static gpointer
@@ -369,32 +456,32 @@ g_volume_monitor_get (void)
 }
 
 /**
- * g_volume_get_for_mount_path:
+ * _g_mount_get_for_mount_path:
  * @mountpoint: a string.
  * 
- * Returns: a #GVolume for given @mountpoint or %NULL.  
+ * Returns: a #GMount for given @mount_path or %NULL.  
  **/
-GVolume *
-_g_volume_get_for_mount_path (const char *mountpoint)
+GMount *
+_g_mount_get_for_mount_path (const char *mount_path)
 {
   GType native_type;
   GNativeVolumeMonitorClass *klass;
-  GVolume *volume;
+  GMount *mount;
   
   native_type = get_native_type ();
 
   if (native_type == G_TYPE_INVALID)
     return NULL;
 
-  volume = NULL;
+  mount = NULL;
   
   klass = G_NATIVE_VOLUME_MONITOR_CLASS (g_type_class_ref (native_type));
-  if (klass->get_volume_for_mountpoint)
-    volume = klass->get_volume_for_mountpoint (mountpoint);
+  if (klass->get_mount_for_mount_path)
+    mount = klass->get_mount_for_mount_path (mount_path);
   
   g_type_class_unref (klass);
 
-  return volume;
+  return mount;
 }
 
 #define __G_UNION_VOLUME_MONITOR_C__
index 6527dbf..fc9f4af 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #ifndef __G_UNION_VOLUME_MONITOR_H__
diff --git a/gio/gunixdrive.c b/gio/gunixdrive.c
deleted file mode 100644 (file)
index ab8eebf..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-/* GIO - GLib Input, Output and Streaming Library
- * 
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include <glib.h>
-#include "gunixdrive.h"
-#include "gunixvolume.h"
-#include "gthemedicon.h"
-#include "gvolumemonitor.h"
-#include "glibintl.h"
-
-#include "gioalias.h"
-
-struct _GUnixDrive {
-  GObject parent;
-
-  GUnixVolume *volume; /* owned by volume monitor */
-  char *name;
-  char *icon;
-  char *mountpoint;
-  GUnixMountType guessed_type;
-};
-
-static void g_unix_volume_drive_iface_init (GDriveIface *iface);
-
-#define g_unix_drive_get_type _g_unix_drive_get_type
-G_DEFINE_TYPE_WITH_CODE (GUnixDrive, g_unix_drive, G_TYPE_OBJECT,
-                        G_IMPLEMENT_INTERFACE (G_TYPE_DRIVE,
-                                               g_unix_volume_drive_iface_init))
-
-static void
-g_unix_drive_finalize (GObject *object)
-{
-  GUnixDrive *drive;
-  
-  drive = G_UNIX_DRIVE (object);
-
-  if (drive->volume)
-    _g_unix_volume_unset_drive (drive->volume, drive);
-  
-  g_free (drive->name);
-  g_free (drive->icon);
-  g_free (drive->mountpoint);
-
-  if (G_OBJECT_CLASS (g_unix_drive_parent_class)->finalize)
-    (*G_OBJECT_CLASS (g_unix_drive_parent_class)->finalize) (object);
-}
-
-static void
-g_unix_drive_class_init (GUnixDriveClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  gobject_class->finalize = g_unix_drive_finalize;
-}
-
-static void
-g_unix_drive_init (GUnixDrive *unix_drive)
-{
-}
-
-static char *
-type_to_icon (GUnixMountType type)
-{
-  const char *icon_name = NULL;
-  
-  switch (type)
-    {
-    case G_UNIX_MOUNT_TYPE_HD:
-      icon_name = "drive-harddisk";
-      break;
-    case G_UNIX_MOUNT_TYPE_FLOPPY:
-    case G_UNIX_MOUNT_TYPE_ZIP:
-    case G_UNIX_MOUNT_TYPE_JAZ:
-    case G_UNIX_MOUNT_TYPE_MEMSTICK:
-      icon_name = "drive-removable-media";
-      break;
-    case G_UNIX_MOUNT_TYPE_CDROM:
-      icon_name = "drive-optical";
-      break;
-    case G_UNIX_MOUNT_TYPE_NFS:
-      /* TODO: Would like a better icon here... */
-      icon_name = "drive-removable-media";
-      break;
-    case G_UNIX_MOUNT_TYPE_CAMERA:
-      icon_name = "camera-photo";
-      break;
-    case G_UNIX_MOUNT_TYPE_IPOD:
-      icon_name = "multimedia-player";
-      break;
-    case G_UNIX_MOUNT_TYPE_UNKNOWN:
-    default:
-      icon_name = "drive-removable-media";
-      break;
-    }
-  return g_strdup (icon_name);
-}
-
-/**
- * g_unix_drive_new:
- * @volume_monitor: a #GVolumeMonitor.
- * @mountpoint: a #GUnixMountPoint.
- * 
- * Returns: a #GUnixDrive for the given #GUnixMountPoint.
- **/
-GUnixDrive *
-_g_unix_drive_new (GVolumeMonitor  *volume_monitor,
-                   GUnixMountPoint *mountpoint)
-{
-  GUnixDrive *drive;
-  
-  if (!(g_unix_mount_point_is_user_mountable (mountpoint) ||
-       g_str_has_prefix (g_unix_mount_point_get_device_path (mountpoint), "/vol/")) ||
-      g_unix_mount_point_is_loopback (mountpoint))
-    return NULL;
-  
-  drive = g_object_new (G_TYPE_UNIX_DRIVE, NULL);
-
-  drive->guessed_type = g_unix_mount_point_guess_type (mountpoint);
-  
-  /* TODO: */
-  drive->mountpoint = g_strdup (g_unix_mount_point_get_mount_path (mountpoint));
-  drive->icon = type_to_icon (drive->guessed_type);
-  drive->name = g_strdup (_("Unknown drive"));
-  
-  return drive;
-}
-
-/**
- * g_unix_drive_disconnected:
- * @drive:
- * 
- **/
-void
-_g_unix_drive_disconnected (GUnixDrive *drive)
-{
-  if (drive->volume)
-    {
-      _g_unix_volume_unset_drive (drive->volume, drive);
-      drive->volume = NULL;
-    }
-}
-
-/**
- * g_unix_drive_set_volume:
- * @drive:
- * @volume:
- *  
- **/
-void
-_g_unix_drive_set_volume (GUnixDrive  *drive,
-                         GUnixVolume *volume)
-{
-  if (drive->volume == volume)
-    return;
-  
-  if (drive->volume)
-    _g_unix_volume_unset_drive (drive->volume, drive);
-  
-  drive->volume = volume;
-  
-  /* TODO: Emit changed in idle to avoid locking issues */
-  g_signal_emit_by_name (drive, "changed");
-}
-
-/**
- * g_unix_drive_unset_volume:
- * @drive:
- * @volume:
- *
- **/
-void
-_g_unix_drive_unset_volume (GUnixDrive  *drive,
-                           GUnixVolume *volume)
-{
-  if (drive->volume == volume)
-    {
-      drive->volume = NULL;
-      /* TODO: Emit changed in idle to avoid locking issues */
-      g_signal_emit_by_name (drive, "changed");
-    }
-}
-
-static GIcon *
-g_unix_drive_get_icon (GDrive *drive)
-{
-  GUnixDrive *unix_drive = G_UNIX_DRIVE (drive);
-
-  return g_themed_icon_new (unix_drive->icon);
-}
-
-static char *
-g_unix_drive_get_name (GDrive *drive)
-{
-  GUnixDrive *unix_drive = G_UNIX_DRIVE (drive);
-  
-  return g_strdup (unix_drive->name);
-}
-
-static gboolean
-g_unix_drive_is_automounted (GDrive *drive)
-{
-  /* TODO */
-  return FALSE;
-}
-
-static gboolean
-g_unix_drive_can_mount (GDrive *drive)
-{
-  /* TODO */
-  return TRUE;
-}
-
-static gboolean
-g_unix_drive_can_eject (GDrive *drive)
-{
-  /* TODO */
-  return FALSE;
-}
-
-static GList *
-g_unix_drive_get_volumes (GDrive *drive)
-{
-  GList *l;
-  GUnixDrive *unix_drive = G_UNIX_DRIVE (drive);
-
-  l = NULL;
-  if (unix_drive->volume)
-    l = g_list_prepend (l, g_object_ref (unix_drive->volume));
-
-  return l;
-}
-
-static gboolean
-g_unix_drive_has_volumes (GDrive *drive)
-{
-  GUnixDrive *unix_drive = G_UNIX_DRIVE (drive);
-
-  return unix_drive->volume != NULL;
-}
-
-
-gboolean
-_g_unix_drive_has_mountpoint (GUnixDrive *drive,
-                            const char  *mountpoint)
-{
-  return strcmp (drive->mountpoint, mountpoint) == 0;
-}
-
-static void
-g_unix_drive_mount (GDrive              *drive,
-                    GMountOperation     *mount_operation,
-                    GCancellable        *cancellable,
-                    GAsyncReadyCallback  callback,
-                    gpointer             user_data)
-{
-  /* TODO */
-}
-
-
-static gboolean
-g_unix_drive_mount_finish (GDrive        *drive,
-                           GAsyncResult  *result,
-                           GError       **error)
-{
-  return TRUE;
-}
-
-static void
-g_unix_drive_eject (GDrive              *drive,
-                    GCancellable        *cancellable,
-                    GAsyncReadyCallback  callback,
-                    gpointer             user_data)
-{
-  /* TODO */
-}
-
-static gboolean
-g_unix_drive_eject_finish (GDrive        *drive,
-                           GAsyncResult  *result,
-                           GError       **error)
-{
-  return TRUE;
-}
-
-static void
-g_unix_volume_drive_iface_init (GDriveIface *iface)
-{
-  iface->get_name = g_unix_drive_get_name;
-  iface->get_icon = g_unix_drive_get_icon;
-  iface->has_volumes = g_unix_drive_has_volumes;
-  iface->get_volumes = g_unix_drive_get_volumes;
-  iface->is_automounted = g_unix_drive_is_automounted;
-  iface->can_mount = g_unix_drive_can_mount;
-  iface->can_eject = g_unix_drive_can_eject;
-  iface->mount_fn = g_unix_drive_mount;
-  iface->mount_finish = g_unix_drive_mount_finish;
-  iface->eject = g_unix_drive_eject;
-  iface->eject_finish = g_unix_drive_eject_finish;
-}
diff --git a/gio/gunixdrive.h b/gio/gunixdrive.h
deleted file mode 100644 (file)
index 7881210..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* GIO - GLib Input, Output and Streaming Library
- * 
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef __G_UNIX_DRIVE_H__
-#define __G_UNIX_DRIVE_H__
-
-#include <glib-object.h>
-#include <gio/gdrive.h>
-#include <gio/gunixmounts.h>
-#include <gio/gunixvolumemonitor.h>
-
-G_BEGIN_DECLS
-
-#define G_TYPE_UNIX_DRIVE        (_g_unix_drive_get_type ())
-#define G_UNIX_DRIVE(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_UNIX_DRIVE, GUnixDrive))
-#define G_UNIX_DRIVE_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_UNIX_DRIVE, GUnixDriveClass))
-#define G_IS_UNIX_DRIVE(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_UNIX_DRIVE))
-#define G_IS_UNIX_DRIVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_UNIX_DRIVE))
-
-typedef struct _GUnixDriveClass GUnixDriveClass;
-
-struct _GUnixDriveClass {
-   GObjectClass parent_class;
-};
-
-GType _g_unix_drive_get_type (void) G_GNUC_CONST;
-
-GUnixDrive *_g_unix_drive_new            (GVolumeMonitor *volume_monitor,
-                                         GUnixMountPoint *mountpoint);
-gboolean    _g_unix_drive_has_mountpoint (GUnixDrive     *drive,
-                                         const char     *mountpoint);
-void        _g_unix_drive_set_volume     (GUnixDrive     *drive,
-                                         GUnixVolume    *volume);
-void        _g_unix_drive_unset_volume   (GUnixDrive     *drive,
-                                         GUnixVolume    *volume);
-void        _g_unix_drive_disconnected   (GUnixDrive     *drive);
-
-G_END_DECLS
-
-#endif /* __G_UNIX_DRIVE_H__ */
diff --git a/gio/gunixmount.c b/gio/gunixmount.c
new file mode 100644 (file)
index 0000000..6246357
--- /dev/null
@@ -0,0 +1,348 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include "gunixvolumemonitor.h"
+#include "gunixmount.h"
+#include "gunixvolume.h"
+#include "gmountprivate.h"
+#include "gvolumemonitor.h"
+#include "gthemedicon.h"
+#include "gsimpleasyncresult.h"
+#include "glibintl.h"
+
+#include "gioalias.h"
+
+struct _GUnixMount {
+  GObject parent;
+
+  GVolumeMonitor   *volume_monitor;
+
+  GUnixVolume      *volume; /* owned by volume monitor */
+
+  char *name;
+  GIcon *icon;
+  char *device_path;
+  char *mount_path;
+};
+
+static void g_unix_mount_mount_iface_init (GMountIface *iface);
+
+#define g_unix_mount_get_type _g_unix_mount_get_type
+G_DEFINE_TYPE_WITH_CODE (GUnixMount, g_unix_mount, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT,
+                                               g_unix_mount_mount_iface_init))
+
+
+static void
+g_unix_mount_finalize (GObject *object)
+{
+  GUnixMount *mount;
+  
+  mount = G_UNIX_MOUNT (object);
+
+  if (mount->volume_monitor != NULL)
+    g_object_unref (mount->volume_monitor);
+
+  if (mount->volume)
+    _g_unix_volume_unset_mount (mount->volume, mount);
+    
+  //TODO: g_warn_if_fail (volume->volume == NULL);
+  g_object_unref (mount->icon);
+  g_free (mount->name);
+  g_free (mount->device_path);
+  g_free (mount->mount_path);
+  
+  if (G_OBJECT_CLASS (g_unix_mount_parent_class)->finalize)
+    (*G_OBJECT_CLASS (g_unix_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_unix_mount_class_init (GUnixMountClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = g_unix_mount_finalize;
+}
+
+static void
+g_unix_mount_init (GUnixMount *unix_mount)
+{
+}
+
+GUnixMount *
+_g_unix_mount_new (GVolumeMonitor        *volume_monitor,
+                   GUnixMountEntry       *mount_entry,
+                   GUnixVolume  *volume)
+{
+  GUnixMount *mount;
+  
+  /* No volume for mount: Ignore internal things */
+  if (volume == NULL && g_unix_mount_is_system_internal (mount_entry))
+    return NULL;
+
+  mount = g_object_new (G_TYPE_UNIX_MOUNT, NULL);
+  mount->volume_monitor = volume_monitor != NULL ? g_object_ref (volume_monitor) : NULL;
+  mount->device_path = g_strdup (g_unix_mount_get_device_path (mount_entry));
+  mount->mount_path = g_strdup (g_unix_mount_get_mount_path (mount_entry));
+  mount->name = g_unix_mount_guess_name (mount_entry);
+  mount->icon = g_unix_mount_guess_icon (mount_entry);
+
+  /* need to do this last */
+  mount->volume = volume;
+  if (volume != NULL)
+    _g_unix_volume_set_mount (volume, mount);
+
+  return mount;
+}
+
+void
+_g_unix_mount_unmounted (GUnixMount *mount)
+{
+  if (mount->volume != NULL)
+    {
+      _g_unix_volume_unset_mount (mount->volume, mount);
+      mount->volume = NULL;
+      g_signal_emit_by_name (mount, "changed");
+      /* there's really no need to emit mount_changed on the volume monitor 
+       * as we're going to be deleted.. */
+    }
+}
+
+void
+_g_unix_mount_unset_volume (GUnixMount *mount,
+                            GUnixVolume  *volume)
+{
+  if (mount->volume == volume)
+    {
+      mount->volume = NULL;
+      /* TODO: Emit changed in idle to avoid locking issues */
+      g_signal_emit_by_name (mount, "changed");
+      if (mount->volume_monitor != NULL)
+        g_signal_emit_by_name (mount->volume_monitor, "mount_changed", mount);
+    }
+}
+
+static GFile *
+g_unix_mount_get_root (GMount *mount)
+{
+  GUnixMount *unix_mount = G_UNIX_MOUNT (mount);
+
+  return g_file_new_for_path (unix_mount->mount_path);
+}
+
+static GIcon *
+g_unix_mount_get_icon (GMount *mount)
+{
+  GUnixMount *unix_mount = G_UNIX_MOUNT (mount);
+
+  return g_object_ref (unix_mount->icon);
+}
+
+static char *
+g_unix_mount_get_name (GMount *mount)
+{
+  GUnixMount *unix_mount = G_UNIX_MOUNT (mount);
+  
+  return g_strdup (unix_mount->name);
+}
+
+gboolean
+_g_unix_mount_has_mount_path (GUnixMount *mount,
+                              const char  *mount_path)
+{
+  return strcmp (mount->mount_path, mount_path) == 0;
+}
+
+static GDrive *
+g_unix_mount_get_drive (GMount *mount)
+{
+  GUnixMount *unix_mount = G_UNIX_MOUNT (mount);
+
+  if (unix_mount->volume != NULL)
+    return g_volume_get_drive (G_VOLUME (unix_mount->volume));
+
+  return NULL;
+}
+
+static GVolume *
+g_unix_mount_get_volume (GMount *mount)
+{
+  GUnixMount *unix_mount = G_UNIX_MOUNT (mount);
+
+  if (unix_mount->volume)
+    return G_VOLUME (g_object_ref (unix_mount->volume));
+  
+  return NULL;
+}
+
+static gboolean
+g_unix_mount_can_unmount (GMount *mount)
+{
+  return TRUE;
+}
+
+
+typedef struct {
+  GUnixMount *unix_mount;
+  GAsyncReadyCallback callback;
+  gpointer user_data;
+  GCancellable *cancellable;
+  int error_fd;
+  GIOChannel *error_channel;
+  guint error_channel_source_id;
+  GString *error_string;
+} UnmountOp;
+
+static void 
+unmount_cb (GPid pid, gint status, gpointer user_data)
+{
+  UnmountOp *data = user_data;
+  GSimpleAsyncResult *simple;
+  
+  if (WEXITSTATUS (status) != 0)
+    {
+      GError *error;
+      error = g_error_new_literal (G_IO_ERROR, 
+                                   G_IO_ERROR_FAILED,
+                                   data->error_string->str);
+      simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_mount),
+                                                     data->callback,
+                                                     data->user_data,
+                                                     error);
+      g_error_free (error);
+    }
+  else
+    {
+      simple = g_simple_async_result_new (G_OBJECT (data->unix_mount),
+                                          data->callback,
+                                          data->user_data,
+                                          NULL);
+    }
+
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+
+  g_source_remove (data->error_channel_source_id);
+  g_io_channel_unref (data->error_channel);
+  g_string_free (data->error_string, TRUE);
+  close (data->error_fd);
+  g_spawn_close_pid (pid);
+  g_free (data);
+}
+
+static gboolean
+unmount_read_error (GIOChannel *channel,
+                    GIOCondition condition,
+                    gpointer user_data)
+{
+  char *str;
+  gsize str_len;
+  UnmountOp *data = user_data;
+
+  g_io_channel_read_to_end (channel, &str, &str_len, NULL);
+  g_string_append (data->error_string, str);
+  g_free (str);
+  return TRUE;
+}
+
+static void
+g_unix_mount_unmount (GMount             *mount,
+                      GCancellable        *cancellable,
+                      GAsyncReadyCallback  callback,
+                      gpointer             user_data)
+{
+  GUnixMount *unix_mount = G_UNIX_MOUNT (mount);
+  UnmountOp *data;
+  GPid child_pid;
+  GError *error;
+  char *argv[] = {"umount", NULL, NULL};
+
+  if (unix_mount->mount_path != NULL)
+    argv[1] = unix_mount->mount_path;
+  else
+    argv[1] = unix_mount->device_path;
+  
+  data = g_new0 (UnmountOp, 1);
+  data->unix_mount = unix_mount;
+  data->callback = callback;
+  data->user_data = user_data;
+  data->cancellable = cancellable;
+  
+  error = NULL;
+  if (!g_spawn_async_with_pipes (NULL,         /* working dir */
+                                 argv,
+                                 NULL,         /* envp */
+                                 G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
+                                 NULL,         /* child_setup */
+                                 NULL,         /* user_data for child_setup */
+                                 &child_pid,
+                                 NULL,           /* standard_input */
+                                 NULL,           /* standard_output */
+                                 &(data->error_fd),
+                                 &error)) {
+    GSimpleAsyncResult *simple;
+    simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_mount),
+                                                   data->callback,
+                                                   data->user_data,
+                                                   error);
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+    g_error_free (error);
+    g_free (data);
+    return;
+  }
+  data->error_string = g_string_new ("");
+  data->error_channel = g_io_channel_unix_new (data->error_fd);
+  data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, unmount_read_error, data);
+  g_child_watch_add (child_pid, unmount_cb, data);
+}
+
+static gboolean
+g_unix_mount_unmount_finish (GMount       *mount,
+                             GAsyncResult  *result,
+                             GError       **error)
+{
+  return TRUE;
+}
+
+static void
+g_unix_mount_mount_iface_init (GMountIface *iface)
+{
+  iface->get_root = g_unix_mount_get_root;
+  iface->get_name = g_unix_mount_get_name;
+  iface->get_icon = g_unix_mount_get_icon;
+  iface->get_drive = g_unix_mount_get_drive;
+  iface->get_volume = g_unix_mount_get_volume;
+  iface->can_unmount = g_unix_mount_can_unmount;
+  iface->unmount = g_unix_mount_unmount;
+  iface->unmount_finish = g_unix_mount_unmount_finish;
+}
diff --git a/gio/gunixmount.h b/gio/gunixmount.h
new file mode 100644 (file)
index 0000000..cafae79
--- /dev/null
@@ -0,0 +1,59 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_UNIX_MOUNT_H__
+#define __G_UNIX_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gmount.h>
+#include <gio/gunixmounts.h>
+#include <gio/gunixvolumemonitor.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_UNIX_MOUNT        (_g_unix_mount_get_type ())
+#define G_UNIX_MOUNT(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_UNIX_MOUNT, GUnixMount))
+#define G_UNIX_MOUNT_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_UNIX_MOUNT, GUnixMountClass))
+#define G_IS_UNIX_MOUNT(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_UNIX_MOUNT))
+#define G_IS_UNIX_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_UNIX_MOUNT))
+
+typedef struct _GUnixMountClass GUnixMountClass;
+
+struct _GUnixMountClass {
+   GObjectClass parent_class;
+};
+
+GType _g_unix_mount_get_type (void) G_GNUC_CONST;
+
+GUnixMount *_g_unix_mount_new                    (GVolumeMonitor       *volume_monitor,
+                                                  GUnixMountEntry      *mount_entry,
+                                                  GUnixVolume          *volume);
+gboolean     _g_unix_mount_has_mount_path        (GUnixMount           *mount,
+                                                  const char           *mount_path);
+void         _g_unix_mount_unset_volume          (GUnixMount            *mount,
+                                                  GUnixVolume           *volume);
+void         _g_unix_mount_unmounted             (GUnixMount           *mount);
+
+G_END_DECLS
+
+#endif /* __G_UNIX_MOUNT_H__ */
index 069154c..51db6dc 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
 /* GIO - GLib Input, Output and Streaming Library
  * 
  * Copyright (C) 2006-2007 Red Hat, Inc.
 #include "gunixmounts.h"
 #include "gfile.h"
 #include "gfilemonitor.h"
+#include "glibintl.h"
+#include "gthemedicon.h"
 
 #include "gioalias.h"
 
+static const char *_resolve_dev_root (void);
+
 /**
  * SECTION:gunixmounts
  * @short_description: Unix Mounts
  *
  **/
 
-struct _GUnixMount {
+/**
+ * GUnixMountType:
+ * @G_UNIX_MOUNT_TYPE_UNKNOWN: Unknown UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_FLOPPY: Floppy disk UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_CDROM: CDROM UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_NFS: Network File System (NFS) UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_ZIP: ZIP UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_JAZ: JAZZ UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_MEMSTICK: Memory Stick UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_CF: Compact Flash UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_SM: Smart Media UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_SDMMC: SD/MMC UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_IPOD: iPod UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_CAMERA: Digital camera UNIX mount type.
+ * @G_UNIX_MOUNT_TYPE_HD: Hard drive UNIX mount type.
+ * 
+ * Types of UNIX mounts.
+ **/
+typedef enum {
+  G_UNIX_MOUNT_TYPE_UNKNOWN,
+  G_UNIX_MOUNT_TYPE_FLOPPY,
+  G_UNIX_MOUNT_TYPE_CDROM,
+  G_UNIX_MOUNT_TYPE_NFS,
+  G_UNIX_MOUNT_TYPE_ZIP,
+  G_UNIX_MOUNT_TYPE_JAZ,
+  G_UNIX_MOUNT_TYPE_MEMSTICK,
+  G_UNIX_MOUNT_TYPE_CF,
+  G_UNIX_MOUNT_TYPE_SM,
+  G_UNIX_MOUNT_TYPE_SDMMC,
+  G_UNIX_MOUNT_TYPE_IPOD,
+  G_UNIX_MOUNT_TYPE_CAMERA,
+  G_UNIX_MOUNT_TYPE_HD
+} GUnixMountType;
+
+struct _GUnixMountEntry {
   char *mount_path;
   char *device_path;
   char *filesystem_type;
@@ -151,6 +191,63 @@ is_in (const char *value, const char *set[])
   return FALSE;
 }
 
+/**
+ * g_unix_is_mount_path_system_internal:
+ * @mount_path: a mount path, e.g. <literal>/media/disk</literal> or <literal>/usr</literal>
+ *
+ * Determines if @mount_path is considered an implementation of the
+ * OS. This is primarily used for hiding mountable and mounted volumes
+ * that only are used in the OS and has little to no relevance to the
+ * casual user.
+ *
+ * Returns; %TRUE if @mount_path is considered an implementation detail of the OS.
+ **/
+gboolean
+g_unix_is_mount_path_system_internal (const char *mount_path)
+{
+  const char *ignore_mountpoints[] = {
+    /* Includes all FHS 2.3 toplevel dirs and other specilized
+     * directories that we want to hide from the user.
+     */
+    "/",              /* we already have "Filesystem root" in Nautilus */ 
+    "/bin",
+    "/boot",
+    "/dev",
+    "/etc",
+    "/home",
+    "/lib",
+    "/lib64",
+    "/media",
+    "/mnt",
+    "/opt",
+    "/root",
+    "/sbin",
+    "/srv",
+    "/tmp",
+    "/usr",
+    "/var",
+    "/var/log/audit", /* https://bugzilla.redhat.com/show_bug.cgi?id=333041 */
+    "/var/tmp",       /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */
+    "/proc",
+    "/sbin",
+    "/net",
+    NULL
+  };
+
+  if (is_in (mount_path, ignore_mountpoints))
+    return TRUE;
+  
+  if (g_str_has_prefix (mount_path, "/dev") ||
+      g_str_has_prefix (mount_path, "/proc") ||
+      g_str_has_prefix (mount_path, "/sys"))
+    return TRUE;
+
+  if (strstr (mount_path, "/.gvfs") != NULL)
+    return TRUE;
+
+  return FALSE;
+}
+
 static gboolean
 guess_system_internal (const char *mountpoint,
                       const char *fs,
@@ -183,29 +280,6 @@ guess_system_internal (const char *mountpoint,
     "/dev/vn",
     NULL
   };
-  const char *ignore_mountpoints[] = {
-    /* Includes all FHS 2.3 toplevel dirs */
-    "/bin",
-    "/boot",
-    "/dev",
-    "/etc",
-    "/home",
-    "/lib",
-    "/lib64",
-    "/media",
-    "/mnt",
-    "/opt",
-    "/root",
-    "/sbin",
-    "/srv",
-    "/tmp",
-    "/usr",
-    "/var",
-    "/proc",
-    "/sbin",
-    "/net",
-    NULL
-  };
   
   if (is_in (fs, ignore_fs))
     return TRUE;
@@ -213,15 +287,7 @@ guess_system_internal (const char *mountpoint,
   if (is_in (device, ignore_devices))
     return TRUE;
 
-  if (is_in (mountpoint, ignore_mountpoints))
-    return TRUE;
-  
-  if (g_str_has_prefix (mountpoint, "/dev") ||
-      g_str_has_prefix (mountpoint, "/proc") ||
-      g_str_has_prefix (mountpoint, "/sys"))
-    return TRUE;
-
-  if (strstr (mountpoint, "/.gvfs") != NULL)
+  if (g_unix_is_mount_path_system_internal (mountpoint))
     return TRUE;
   
   return FALSE;
@@ -261,7 +327,7 @@ _g_get_unix_mounts ()
   struct mntent *mntent;
   FILE *file;
   char *read_file;
-  GUnixMount *mount_entry;
+  GUnixMountEntry *mount_entry;
   GHashTable *mounts_hash;
   GList *return_list;
   
@@ -291,11 +357,14 @@ _g_get_unix_mounts ()
       if (mntent->mnt_fsname != NULL &&
          mntent->mnt_fsname[0] == '/' &&
          g_hash_table_lookup (mounts_hash, mntent->mnt_fsname))
-       continue;
+        continue;
       
-      mount_entry = g_new0 (GUnixMount, 1);
+      mount_entry = g_new0 (GUnixMountEntry, 1);
       mount_entry->mount_path = g_strdup (mntent->mnt_dir);
-      mount_entry->device_path = g_strdup (mntent->mnt_fsname);
+      if (strcmp (mntent->mnt_fsname, "/dev/root") == 0)
+        mount_entry->device_path = g_strdup (_resolve_dev_root ());
+      else
+        mount_entry->device_path = g_strdup (mntent->mnt_fsname);
       mount_entry->filesystem_type = g_strdup (mntent->mnt_type);
       
 #if defined (HAVE_HASMNTOPT)
@@ -349,7 +418,7 @@ _g_get_unix_mounts (void)
   struct mnttab mntent;
   FILE *file;
   char *read_file;
-  GUnixMount *mount_entry;
+  GUnixMountEntry *mount_entry;
   GList *return_list;
   
   read_file = get_mtab_read_file ();
@@ -363,7 +432,7 @@ _g_get_unix_mounts (void)
   G_LOCK (getmntent);
   while (! getmntent (file, &mntent))
     {
-      mount_entry = g_new0 (GUnixMount, 1);
+      mount_entry = g_new0 (GUnixMountEntry, 1);
       
       mount_entry->mount_path = g_strdup (mntent.mnt_mountp);
       mount_entry->device_path = g_strdup (mntent.mnt_special);
@@ -432,7 +501,7 @@ _g_get_unix_mounts (void)
   return_list = NULL;
   while (vmount_number > 0)
     {
-      mount_entry = g_new0 (GUnixMount, 1);
+      mount_entry = g_new0 (GUnixMountEntry, 1);
       
       mount_entry->device_path = g_strdup (vmt2dataptr (vmount_info, VMT_OBJECT));
       mount_entry->mount_path = g_strdup (vmt2dataptr (vmount_info, VMT_STUB));
@@ -477,7 +546,7 @@ _g_get_unix_mounts (void)
 {
   struct statfs *mntent = NULL;
   int num_mounts, i;
-  GUnixMount *mount_entry;
+  GUnixMountEntry *mount_entry;
   GList *return_list;
   
   /* Pass MNT_NOWAIT to avoid blocking trying to update NFS mounts. */
@@ -488,7 +557,7 @@ _g_get_unix_mounts (void)
   
   for (i = 0; i < num_mounts; i++)
     {
-      mount_entry = g_new0 (GUnixMount, 1);
+      mount_entry = g_new0 (GUnixMountEntry, 1);
       
       mount_entry->mount_path = g_strdup (mntent[i].f_mntonname);
       mount_entry->device_path = g_strdup (mntent[i].f_mntfromname);
@@ -554,10 +623,13 @@ _g_get_unix_mount_points (void)
       if ((strcmp (mntent->mnt_dir, "ignore") == 0) ||
          (strcmp (mntent->mnt_dir, "swap") == 0))
        continue;
-      
+
       mount_entry = g_new0 (GUnixMountPoint, 1);
       mount_entry->mount_path = g_strdup (mntent->mnt_dir);
-      mount_entry->device_path = g_strdup (mntent->mnt_fsname);
+      if (strcmp (mntent->mnt_fsname, "/dev/root") == 0)
+        mount_entry->device_path = g_strdup (_resolve_dev_root ());
+      else
+        mount_entry->device_path = g_strdup (mntent->mnt_fsname);
       mount_entry->filesystem_type = g_strdup (mntent->mnt_type);
       
 #ifdef HAVE_HASMNTOPT
@@ -931,18 +1003,18 @@ g_get_unix_mounts (guint64 *time_read)
  * @mount_path: path for a possible unix mount.
  * @time_read: guint64 to contain a timestamp.
  * 
- * Gets a #GUnixMount for a given mount path. If @time_read
+ * Gets a #GUnixMountEntry for a given mount path. If @time_read
  * is set, it will be filled with a unix timestamp for checking
  * if the mounts have changed since with g_unix_mounts_changed_since().
  * 
  * Returns: a #GUnixMount. 
  **/
-GUnixMount *
+GUnixMountEntry *
 g_get_unix_mount_at (const char *mount_path,
                     guint64 *time_read)
 {
   GList *mounts, *l;
-  GUnixMount *mount_entry, *found;
+  GUnixMountEntry *mount_entry, *found;
   
   mounts = g_get_unix_mounts (time_read);
 
@@ -1156,7 +1228,7 @@ g_unix_mount_monitor_new (void)
  * Frees a unix mount.
  **/
 void
-g_unix_mount_free (GUnixMount *mount_entry)
+g_unix_mount_free (GUnixMountEntry *mount_entry)
 {
   g_return_if_fail (mount_entry != NULL);
 
@@ -1198,8 +1270,8 @@ strcmp_null (const char *str1,
 
 /**
  * g_unix_mount_compare:
- * @mount1: first #GUnixMount to compare.
- * @mount2: second #GUnixMount to compare.
+ * @mount1: first #GUnixMountEntry to compare.
+ * @mount2: second #GUnixMountEntry to compare.
  * 
  * Compares two unix mounts.
  * 
@@ -1207,8 +1279,8 @@ strcmp_null (const char *str1,
  * or less than @mount2, respectively. 
  **/
 gint
-g_unix_mount_compare (GUnixMount *mount1,
-                     GUnixMount *mount2)
+g_unix_mount_compare (GUnixMountEntry *mount1,
+                     GUnixMountEntry *mount2)
 {
   int res;
 
@@ -1235,14 +1307,14 @@ g_unix_mount_compare (GUnixMount *mount1,
 
 /**
  * g_unix_mount_get_mount_path:
- * @mount_entry: input #GUnixMount to get the mount path for.
+ * @mount_entry: input #GUnixMountEntry to get the mount path for.
  * 
  * Gets the mount path for a unix mount.
  * 
  * Returns: the mount path for @mount_entry.
  **/
 const char *
-g_unix_mount_get_mount_path (GUnixMount *mount_entry)
+g_unix_mount_get_mount_path (GUnixMountEntry *mount_entry)
 {
   g_return_val_if_fail (mount_entry != NULL, NULL);
 
@@ -1258,7 +1330,7 @@ g_unix_mount_get_mount_path (GUnixMount *mount_entry)
  * Returns: a string containing the device path.
  **/
 const char *
-g_unix_mount_get_device_path (GUnixMount *mount_entry)
+g_unix_mount_get_device_path (GUnixMountEntry *mount_entry)
 {
   g_return_val_if_fail (mount_entry != NULL, NULL);
 
@@ -1274,7 +1346,7 @@ g_unix_mount_get_device_path (GUnixMount *mount_entry)
  * Returns: a string containing the file system type.
  **/
 const char *
-g_unix_mount_get_fs_type (GUnixMount *mount_entry)
+g_unix_mount_get_fs_type (GUnixMountEntry *mount_entry)
 {
   g_return_val_if_fail (mount_entry != NULL, NULL);
 
@@ -1290,7 +1362,7 @@ g_unix_mount_get_fs_type (GUnixMount *mount_entry)
  * Returns: %TRUE if @mount_entry is read only.
  **/
 gboolean
-g_unix_mount_is_readonly (GUnixMount *mount_entry)
+g_unix_mount_is_readonly (GUnixMountEntry *mount_entry)
 {
   g_return_val_if_fail (mount_entry != NULL, FALSE);
 
@@ -1306,7 +1378,7 @@ g_unix_mount_is_readonly (GUnixMount *mount_entry)
  * Returns: %TRUE if the unix mount is for a system path.
  **/
 gboolean
-g_unix_mount_is_system_internal (GUnixMount *mount_entry)
+g_unix_mount_is_system_internal (GUnixMountEntry *mount_entry)
 {
   g_return_val_if_fail (mount_entry != NULL, FALSE);
 
@@ -1560,7 +1632,7 @@ guess_mount_type (const char *mount_path,
  * Returns: a #GUnixMountType. 
  **/
 GUnixMountType
-g_unix_mount_guess_type (GUnixMount *mount_entry)
+g_unix_mount_guess_type (GUnixMountEntry *mount_entry)
 {
   g_return_val_if_fail (mount_entry != NULL, G_UNIX_MOUNT_TYPE_UNKNOWN);
   g_return_val_if_fail (mount_entry->mount_path != NULL, G_UNIX_MOUNT_TYPE_UNKNOWN);
@@ -1594,5 +1666,273 @@ g_unix_mount_point_guess_type (GUnixMountPoint *mount_point)
                           mount_point->filesystem_type);
 }
 
+static const char *
+type_to_icon (GUnixMountType type, gboolean is_mount_point)
+{
+  const char *icon_name;
+  
+  switch (type)
+    {
+    case G_UNIX_MOUNT_TYPE_HD:
+      if (is_mount_point)
+        icon_name = "drive-removable-media";
+      else
+        icon_name = "drive-harddisk";
+      break;
+    case G_UNIX_MOUNT_TYPE_FLOPPY:
+    case G_UNIX_MOUNT_TYPE_ZIP:
+    case G_UNIX_MOUNT_TYPE_JAZ:
+      if (is_mount_point)
+        icon_name = "drive-removable-media";
+      else
+        icon_name = "media-floppy";
+      break;
+    case G_UNIX_MOUNT_TYPE_CDROM:
+      if (is_mount_point)
+        icon_name = "drive-optical";
+      else
+        icon_name = "media-optical";
+      break;
+    case G_UNIX_MOUNT_TYPE_NFS:
+      /* TODO: Would like a better icon here... */
+      if (is_mount_point)
+        icon_name = "drive-removable-media";
+      else
+        icon_name = "drive-harddisk";
+      break;
+    case G_UNIX_MOUNT_TYPE_MEMSTICK:
+      if (is_mount_point)
+        icon_name = "drive-removable-media";
+      else
+        icon_name = "media-flash";
+      break;
+    case G_UNIX_MOUNT_TYPE_CAMERA:
+      if (is_mount_point)
+        icon_name = "drive-removable-media";
+      else
+        icon_name = "camera-photo";
+      break;
+    case G_UNIX_MOUNT_TYPE_IPOD:
+      if (is_mount_point)
+        icon_name = "drive-removable-media";
+      else
+        icon_name = "multimedia-player";
+      break;
+    case G_UNIX_MOUNT_TYPE_UNKNOWN:
+    default:
+      if (is_mount_point)
+        icon_name = "drive-removable-media";
+      else
+        icon_name = "drive-harddisk";
+      break;
+    }
+
+  return icon_name;
+}
+
+char *
+g_unix_mount_guess_name (GUnixMountEntry *mount_entry)
+{
+  char *name;
+
+  if (strcmp (mount_entry->mount_path, "/") == 0)
+    name = g_strdup (_("Filesystem root"));
+  else
+    name = g_filename_display_basename (mount_entry->mount_path);
+
+  return name;
+}
+
+GIcon *
+g_unix_mount_guess_icon (GUnixMountEntry *mount_entry)
+{
+  return g_themed_icon_new (type_to_icon (g_unix_mount_guess_type (mount_entry), FALSE));
+}
+
+char *
+g_unix_mount_point_guess_name (GUnixMountPoint *mount_point)
+{
+  char *name;
+
+  if (strcmp (mount_point->mount_path, "/") == 0)
+    name = g_strdup (_("Filesystem root"));
+  else
+    name = g_filename_display_basename (mount_point->mount_path);
+
+  return name;
+}
+
+GIcon *
+g_unix_mount_point_guess_icon (GUnixMountPoint *mount_point)
+{
+  return g_themed_icon_new (type_to_icon (g_unix_mount_point_guess_type (mount_point), TRUE));
+}
+
+
+/* borrowed from gtk/gtkfilesystemunix.c in GTK+ on 02/23/2006 */
+static void
+_canonicalize_filename (gchar *filename)
+{
+  gchar *p, *q;
+  gboolean last_was_slash = FALSE;
+  
+  p = filename;
+  q = filename;
+  
+  while (*p)
+    {
+      if (*p == G_DIR_SEPARATOR)
+        {
+          if (!last_was_slash)
+            *q++ = G_DIR_SEPARATOR;
+          
+          last_was_slash = TRUE;
+        }
+      else
+        {
+          if (last_was_slash && *p == '.')
+            {
+              if (*(p + 1) == G_DIR_SEPARATOR ||
+                  *(p + 1) == '\0')
+                {
+                  if (*(p + 1) == '\0')
+                    break;
+                  
+                  p += 1;
+                }
+              else if (*(p + 1) == '.' &&
+                       (*(p + 2) == G_DIR_SEPARATOR ||
+                        *(p + 2) == '\0'))
+                {
+                  if (q > filename + 1)
+                    {
+                      q--;
+                      while (q > filename + 1 &&
+                             *(q - 1) != G_DIR_SEPARATOR)
+                        q--;
+                    }
+                  
+                  if (*(p + 2) == '\0')
+                    break;
+                  
+                  p += 2;
+                }
+              else
+                {
+                  *q++ = *p;
+                  last_was_slash = FALSE;
+                }
+            }
+          else
+            {
+              *q++ = *p;
+              last_was_slash = FALSE;
+            }
+        }
+      
+      p++;
+    }
+  
+  if (q > filename + 1 && *(q - 1) == G_DIR_SEPARATOR)
+    q--;
+  
+  *q = '\0';
+}
+
+static char *
+_resolve_symlink (const char *file)
+{
+  GError *error;
+  char *dir;
+  char *link;
+  char *f;
+  char *f1;
+  
+  f = g_strdup (file);
+  
+  while (g_file_test (f, G_FILE_TEST_IS_SYMLINK)) {
+    link = g_file_read_link (f, &error);
+    if (link == NULL) {
+      g_error_free (error);
+      g_free (f);
+      f = NULL;
+      goto out;
+    }
+    
+    dir = g_path_get_dirname (f);
+    f1 = g_strdup_printf ("%s/%s", dir, link);
+    g_free (dir);
+    g_free (link);
+    g_free (f);
+    f = f1;
+  }
+  
+ out:
+  if (f != NULL)
+    _canonicalize_filename (f);
+  return f;
+}
+
+static const char *
+_resolve_dev_root (void)
+{
+  static gboolean have_real_dev_root = FALSE;
+  static char real_dev_root[256];
+  struct stat statbuf;
+  
+  /* see if it's cached already */
+  if (have_real_dev_root)
+    goto found;
+  
+  /* otherwise we're going to find it right away.. */
+  have_real_dev_root = TRUE;
+  
+  if (stat ("/dev/root", &statbuf) == 0) {
+    if (! S_ISLNK (statbuf.st_mode)) {
+      dev_t root_dev = statbuf.st_dev;
+      FILE *f;
+      char buf[1024];
+      
+      /* see if device with similar major:minor as /dev/root is mention
+       * in /etc/mtab (it usually is) 
+       */
+      f = fopen ("/etc/mtab", "r");
+      if (f != NULL) {
+        struct mntent ent;
+        
+        while (getmntent_r (f, &ent, buf, sizeof (buf)) != NULL) {
+          
+          if (stat (ent.mnt_fsname, &statbuf) == 0 &&
+              statbuf.st_dev == root_dev) {
+            strncpy (real_dev_root, ent.mnt_fsname, sizeof (real_dev_root) - 1);
+            real_dev_root[sizeof (real_dev_root) - 1] = '\0';
+            fclose (f);
+            goto found;
+          }
+        }
+        fclose (f);
+      }                                        
+      
+      /* no, that didn't work.. next we could scan /dev ... but I digress.. */
+      
+    } else {
+      char *resolved;
+      resolved = _resolve_symlink ("/dev/root");
+      if (resolved != NULL) {
+        strncpy (real_dev_root, resolved, sizeof (real_dev_root) - 1);
+        real_dev_root[sizeof (real_dev_root) - 1] = '\0';
+        g_free (resolved);
+        goto found;
+      }
+    }
+  }
+  
+  /* bah sucks.. */
+  strcpy (real_dev_root, "/dev/root");
+  
+ found:
+  return real_dev_root;
+}
+
 #define __G_UNIX_MOUNTS_C__
 #include "gioaliasdef.c"
index 401612c..1ad6f10 100644 (file)
 
 #include <glib.h>
 #include <glib-object.h>
+#include <gio/gicon.h>
 
 G_BEGIN_DECLS
 
 /**
- * GUnixMount:
+ * GUnixMountEntry:
  * 
- * Defines a Unix mount.
+ * Defines a Unix mount entry (e.g. "/media/cdrom").
  **/
-typedef struct _GUnixMount GUnixMount;
+typedef struct _GUnixMountEntry GUnixMountEntry;
 
 /**
  * GUnixMountPoint:
@@ -43,40 +44,6 @@ typedef struct _GUnixMount GUnixMount;
 typedef struct _GUnixMountPoint GUnixMountPoint;
 
 /**
- * GUnixMountType:
- * @G_UNIX_MOUNT_TYPE_UNKNOWN: Unknown UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_FLOPPY: Floppy disk UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_CDROM: CDROM UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_NFS: Network File System (NFS) UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_ZIP: ZIP UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_JAZ: JAZZ UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_MEMSTICK: Memory Stick UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_CF: Compact Flash UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_SM: Smart Media UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_SDMMC: SD/MMC UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_IPOD: iPod UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_CAMERA: Digital camera UNIX mount type.
- * @G_UNIX_MOUNT_TYPE_HD: Hard drive UNIX mount type.
- * 
- * Types of UNIX mounts.
- **/
-typedef enum {
-  G_UNIX_MOUNT_TYPE_UNKNOWN,
-  G_UNIX_MOUNT_TYPE_FLOPPY,
-  G_UNIX_MOUNT_TYPE_CDROM,
-  G_UNIX_MOUNT_TYPE_NFS,
-  G_UNIX_MOUNT_TYPE_ZIP,
-  G_UNIX_MOUNT_TYPE_JAZ,
-  G_UNIX_MOUNT_TYPE_MEMSTICK,
-  G_UNIX_MOUNT_TYPE_CF,
-  G_UNIX_MOUNT_TYPE_SM,
-  G_UNIX_MOUNT_TYPE_SDMMC,
-  G_UNIX_MOUNT_TYPE_IPOD,
-  G_UNIX_MOUNT_TYPE_CAMERA,
-  G_UNIX_MOUNT_TYPE_HD
-} GUnixMountType;
-
-/**
  * GUnixMountMonitor:
  * 
  * Watches #GUnixMount<!-- -->s for changes.
@@ -90,16 +57,17 @@ typedef struct _GUnixMountMonitorClass GUnixMountMonitorClass;
 #define G_IS_UNIX_MOUNT_MONITOR(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_UNIX_MOUNT_MONITOR))
 #define G_IS_UNIX_MOUNT_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_UNIX_MOUNT_MONITOR))
 
-void           g_unix_mount_free                    (GUnixMount         *mount_entry);
+void           g_unix_mount_free                    (GUnixMountEntry    *mount_entry);
 void           g_unix_mount_point_free              (GUnixMountPoint    *mount_point);
-gint           g_unix_mount_compare                 (GUnixMount         *mount1,
-                                                    GUnixMount         *mount2);
-const char *   g_unix_mount_get_mount_path          (GUnixMount         *mount_entry);
-const char *   g_unix_mount_get_device_path         (GUnixMount         *mount_entry);
-const char *   g_unix_mount_get_fs_type             (GUnixMount         *mount_entry);
-gboolean       g_unix_mount_is_readonly             (GUnixMount         *mount_entry);
-gboolean       g_unix_mount_is_system_internal      (GUnixMount         *mount_entry);
-GUnixMountType g_unix_mount_guess_type              (GUnixMount         *mount_entry);
+gint           g_unix_mount_compare                 (GUnixMountEntry    *mount1,
+                                                    GUnixMountEntry    *mount2);
+const char *   g_unix_mount_get_mount_path          (GUnixMountEntry    *mount_entry);
+const char *   g_unix_mount_get_device_path         (GUnixMountEntry    *mount_entry);
+const char *   g_unix_mount_get_fs_type             (GUnixMountEntry    *mount_entry);
+gboolean       g_unix_mount_is_readonly             (GUnixMountEntry    *mount_entry);
+gboolean       g_unix_mount_is_system_internal      (GUnixMountEntry    *mount_entry);
+char *         g_unix_mount_guess_name              (GUnixMountEntry    *mount_entry);
+GIcon *        g_unix_mount_guess_icon              (GUnixMountEntry    *mount_entry);
 
 gint           g_unix_mount_point_compare           (GUnixMountPoint    *mount1,
                                                     GUnixMountPoint    *mount2);
@@ -109,11 +77,12 @@ const char *   g_unix_mount_point_get_fs_type       (GUnixMountPoint    *mount_p
 gboolean       g_unix_mount_point_is_readonly       (GUnixMountPoint    *mount_point);
 gboolean       g_unix_mount_point_is_user_mountable (GUnixMountPoint    *mount_point);
 gboolean       g_unix_mount_point_is_loopback       (GUnixMountPoint    *mount_point);
-GUnixMountType g_unix_mount_point_guess_type        (GUnixMountPoint    *mount_point);
+char *         g_unix_mount_point_guess_name        (GUnixMountPoint    *mount_point);
+GIcon *        g_unix_mount_point_guess_icon        (GUnixMountPoint    *mount_point);
 
 GList *        g_get_unix_mount_points              (guint64            *time_read);
 GList *        g_get_unix_mounts                    (guint64            *time_read);
-GUnixMount *   g_get_unix_mount_at                  (const char         *mount_path,
+GUnixMountEntry * g_get_unix_mount_at               (const char         *mount_path,
                                                     guint64            *time_read);
 gboolean       g_unix_mounts_changed_since          (guint64             time);
 gboolean       g_unix_mount_points_changed_since    (guint64             time);
@@ -121,6 +90,12 @@ gboolean       g_unix_mount_points_changed_since    (guint64             time);
 GType              g_unix_mount_monitor_get_type (void) G_GNUC_CONST;
 GUnixMountMonitor *g_unix_mount_monitor_new      (void);
 
+
+
+char *g_unix_get_canonical_device_path (const char *device_path);
+
+gboolean g_unix_is_mount_path_system_internal (const char *mount_path);
+
 G_END_DECLS
 
 #endif /* __G_UNIX_MOUNTS_H__ */
index 28e0598..1d7fafb 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
 /* GIO - GLib Input, Output and Streaming Library
  * 
  * Copyright (C) 2006-2007 Red Hat, Inc.
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #include <config.h>
 
 #include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
 #include <glib.h>
-#include "gunixvolumemonitor.h"
 #include "gunixvolume.h"
-#include "gunixdrive.h"
-#include "gvolumeprivate.h"
-#include "gvolumemonitor.h"
+#include "gunixmount.h"
 #include "gthemedicon.h"
+#include "gvolumemonitor.h"
+#include "gsimpleasyncresult.h"
 #include "glibintl.h"
 
 #include "gioalias.h"
 struct _GUnixVolume {
   GObject parent;
 
-  GUnixDrive *drive; /* owned by volume monitor */
+  GVolumeMonitor *volume_monitor;
+  GUnixMount     *mount; /* owned by volume monitor */
+  
+  char *device_path;
+  char *mount_path;
   char *name;
-  char *icon;
-  char *mountpoint;
+  GIcon *icon;
 };
 
 static void g_unix_volume_volume_iface_init (GVolumeIface *iface);
@@ -51,7 +58,6 @@ G_DEFINE_TYPE_WITH_CODE (GUnixVolume, g_unix_volume, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME,
                                                g_unix_volume_volume_iface_init))
 
-
 static void
 g_unix_volume_finalize (GObject *object)
 {
@@ -59,14 +65,17 @@ g_unix_volume_finalize (GObject *object)
   
   volume = G_UNIX_VOLUME (object);
 
-  if (volume->drive)
-    _g_unix_drive_unset_volume (volume->drive, volume);
-    
-  g_warn_if_fail (volume->drive == NULL);
-  g_free (volume->name);
-  g_free (volume->icon);
-  g_free (volume->mountpoint);
+  if (volume->volume_monitor != NULL)
+    g_object_unref (volume->volume_monitor);
+
+  if (volume->mount)
+    _g_unix_mount_unset_volume (volume->mount, volume);
   
+  g_object_unref (volume->icon);
+  g_free (volume->name);
+  g_free (volume->mount_path);
+  g_free (volume->device_path);
+
   if (G_OBJECT_CLASS (g_unix_volume_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_unix_volume_parent_class)->finalize) (object);
 }
@@ -84,210 +93,261 @@ g_unix_volume_init (GUnixVolume *unix_volume)
 {
 }
 
-static char *
-get_filesystem_volume_name (const char *fs_type)
-{
-  /* TODO: add translation table from gnome-vfs */
-  return g_strdup_printf (_("%s volume"), fs_type);
-}
-
-static char *
-type_to_icon (GUnixMountType type)
-{
-  const char *icon_name = NULL;
-  
-  switch (type)
-    {
-    case G_UNIX_MOUNT_TYPE_HD:
-      icon_name = "drive-harddisk";
-      break;
-    case G_UNIX_MOUNT_TYPE_FLOPPY:
-    case G_UNIX_MOUNT_TYPE_ZIP:
-    case G_UNIX_MOUNT_TYPE_JAZ:
-      icon_name = "media-floppy";
-      break;
-    case G_UNIX_MOUNT_TYPE_CDROM:
-      icon_name = "media-optical";
-      break;
-    case G_UNIX_MOUNT_TYPE_NFS:
-      /* TODO: Would like a better icon here... */
-      icon_name = "drive-harddisk";
-      break;
-    case G_UNIX_MOUNT_TYPE_MEMSTICK:
-      icon_name = "media-flash";
-      break;
-    case G_UNIX_MOUNT_TYPE_CAMERA:
-      icon_name = "camera-photo";
-      break;
-    case G_UNIX_MOUNT_TYPE_IPOD:
-      icon_name = "multimedia-player";
-      break;
-    case G_UNIX_MOUNT_TYPE_UNKNOWN:
-    default:
-      icon_name = "drive-harddisk";
-      break;
-    }
-  return g_strdup (icon_name);
-}
-
+/**
+ * g_unix_volume_new:
+ * @volume_monitor: a #GVolumeMonitor.
+ * @mountpoint: a #GUnixMountPoint.
+ * 
+ * Returns: a #GUnixVolume for the given #GUnixMountPoint.
+ **/
 GUnixVolume *
-_g_unix_volume_new (GUnixMount *mount,
-                   GUnixDrive *drive)
+_g_unix_volume_new (GVolumeMonitor  *volume_monitor,
+                    GUnixMountPoint *mountpoint)
 {
   GUnixVolume *volume;
-  GUnixMountType type;
-  const char *mount_path;
-  char *volume_name;
   
-  mount_path = g_unix_mount_get_mount_path (mount);
-  
-  /* No drive for volume. Ignore internal things */
-  if (drive == NULL && g_unix_mount_is_system_internal (mount))
+  if (!(g_unix_mount_point_is_user_mountable (mountpoint) ||
+       g_str_has_prefix (g_unix_mount_point_get_device_path (mountpoint), "/vol/")) ||
+      g_unix_mount_point_is_loopback (mountpoint))
     return NULL;
   
   volume = g_object_new (G_TYPE_UNIX_VOLUME, NULL);
-  volume->drive = drive;
-  if (drive)
-    _g_unix_drive_set_volume (drive, volume);
-  volume->mountpoint = g_strdup (mount_path);
-
-  type = g_unix_mount_guess_type (mount);
-  
-  volume->icon = type_to_icon (type);
-                                         
-  volume_name = NULL;
-  if (mount_path)
-    {
-      if (strcmp (mount_path, "/") == 0)
-       volume_name = g_strdup (_("Filesystem root"));
-      else
-       volume_name = g_filename_display_basename (mount_path);
-    }
-      
-  if (volume_name == NULL)
-    {
-      if (g_unix_mount_get_fs_type (mount) != NULL)
-       volume_name = g_strdup (get_filesystem_volume_name (g_unix_mount_get_fs_type (mount)));
-    }
-  
-  if (volume_name == NULL)
-    /* TODO: Use volume size as name? */
-    volume_name = g_strdup (_("Unknown volume"));
-  
-  volume->name = volume_name;
+  volume->volume_monitor = volume_monitor != NULL ? g_object_ref (volume_monitor) : NULL;
+  volume->mount_path = g_strdup (g_unix_mount_point_get_mount_path (mountpoint));
+  volume->device_path = g_strdup (g_unix_mount_point_get_device_path (mountpoint));
 
+  volume->name = g_unix_mount_point_guess_name (mountpoint);
+  volume->icon = g_unix_mount_point_guess_icon (mountpoint);
   return volume;
 }
 
+/**
+ * g_unix_volume_disconnected:
+ * @volume:
+ * 
+ **/
 void
-_g_unix_volume_unmounted (GUnixVolume *volume)
+_g_unix_volume_disconnected (GUnixVolume *volume)
 {
-  if (volume->drive)
+  if (volume->mount)
     {
-      _g_unix_drive_unset_volume (volume->drive, volume);
-      volume->drive = NULL;
-      g_signal_emit_by_name (volume, "changed");
+      _g_unix_mount_unset_volume (volume->mount, volume);
+      volume->mount = NULL;
     }
 }
 
+/**
+ * g_unix_volume_set_mount:
+ * @volume:
+ * @mount:
+ *  
+ **/
+void
+_g_unix_volume_set_mount (GUnixVolume  *volume,
+                          GUnixMount *mount)
+{
+  if (volume->mount == mount)
+    return;
+  
+  if (volume->mount)
+    _g_unix_mount_unset_volume (volume->mount, volume);
+  
+  volume->mount = mount;
+  
+  /* TODO: Emit changed in idle to avoid locking issues */
+  g_signal_emit_by_name (volume, "changed");
+  if (volume->volume_monitor != NULL)
+    g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+}
+
+/**
+ * g_unix_volume_unset_mount:
+ * @volume:
+ * @mount:
+ *
+ **/
 void
-_g_unix_volume_unset_drive (GUnixVolume *volume,
-                           GUnixDrive  *drive)
+_g_unix_volume_unset_mount (GUnixVolume  *volume,
+                            GUnixMount *mount)
 {
-  if (volume->drive == drive)
+  if (volume->mount == mount)
     {
-      volume->drive = NULL;
+      volume->mount = NULL;
       /* TODO: Emit changed in idle to avoid locking issues */
       g_signal_emit_by_name (volume, "changed");
+      if (volume->volume_monitor != NULL)
+        g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
     }
 }
 
-static GFile *
-g_unix_volume_get_root (GVolume *volume)
-{
-  GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
-
-  return g_file_new_for_path (unix_volume->mountpoint);
-}
-
 static GIcon *
 g_unix_volume_get_icon (GVolume *volume)
 {
   GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
-
-  return g_themed_icon_new (unix_volume->icon);
+  return g_object_ref (unix_volume->icon);
 }
 
 static char *
 g_unix_volume_get_name (GVolume *volume)
 {
   GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
-  
   return g_strdup (unix_volume->name);
 }
 
-gboolean
-_g_unix_volume_has_mountpoint (GUnixVolume *volume,
-                              const char  *mountpoint)
+static gboolean
+g_unix_volume_can_mount (GVolume *volume)
 {
-  return strcmp (volume->mountpoint, mountpoint) == 0;
+  return TRUE;
 }
 
 static GDrive *
 g_unix_volume_get_drive (GVolume *volume)
 {
-  GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
-
-  if (unix_volume->drive)
-    return G_DRIVE (g_object_ref (unix_volume->drive));
-  
+  /* TODO */
   return NULL;
 }
 
-static gboolean
-g_unix_volume_can_unmount (GVolume *volume)
+static GMount *
+g_unix_volume_get_mount (GVolume *volume)
 {
-  /* TODO */
-  return FALSE;
+  GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
+
+  if (unix_volume->mount != NULL)
+    return g_object_ref (unix_volume->mount);
+
+  return NULL;
 }
 
-static gboolean
-g_unix_volume_can_eject (GVolume *volume)
+
+gboolean
+_g_unix_volume_has_mount_path (GUnixVolume *volume,
+                                         const char  *mount_path)
 {
-  /* TODO */
-  return FALSE;
+  return strcmp (volume->mount_path, mount_path) == 0;
 }
 
-static void
-g_unix_volume_unmount (GVolume             *volume,
-                      GCancellable        *cancellable,
-                      GAsyncReadyCallback  callback,
-                      gpointer             user_data)
+
+typedef struct {
+  GUnixVolume *unix_volume;
+  GAsyncReadyCallback callback;
+  gpointer user_data;
+  GCancellable *cancellable;
+  int error_fd;
+  GIOChannel *error_channel;
+  guint error_channel_source_id;
+  GString *error_string;
+} MountOp;
+
+static void 
+mount_cb (GPid pid, gint status, gpointer user_data)
 {
-  /* TODO */
+  MountOp *data = user_data;
+  GSimpleAsyncResult *simple;
+  
+  if (WEXITSTATUS (status) != 0)
+    {
+      GError *error;
+      error = g_error_new_literal (G_IO_ERROR, 
+                                   G_IO_ERROR_FAILED,
+                                   data->error_string->str);
+      simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_volume),
+                                                     data->callback,
+                                                     data->user_data,
+                                                     error);
+      g_error_free (error);
+    }
+  else
+    {
+      simple = g_simple_async_result_new (G_OBJECT (data->unix_volume),
+                                          data->callback,
+                                          data->user_data,
+                                          NULL);
+    }
+
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+
+  g_source_remove (data->error_channel_source_id);
+  g_io_channel_unref (data->error_channel);
+  g_string_free (data->error_string, TRUE);
+  close (data->error_fd);
+  g_spawn_close_pid (pid);
+  g_free (data);
 }
 
 static gboolean
-g_unix_volume_unmount_finish (GVolume       *volume,
-                             GAsyncResult  *result,
-                             GError       **error)
+mount_read_error (GIOChannel *channel,
+                  GIOCondition condition,
+                  gpointer user_data)
 {
+  char *str;
+  gsize str_len;
+  MountOp *data = user_data;
+
+  g_io_channel_read_to_end (channel, &str, &str_len, NULL);
+  g_string_append (data->error_string, str);
+  g_free (str);
   return TRUE;
 }
 
 static void
-g_unix_volume_eject (GVolume         *volume,
-                    GCancellable    *cancellable,
-                    GAsyncReadyCallback callback,
-                    gpointer         user_data)
+g_unix_volume_mount (GVolume    *volume,
+                     GMountOperation     *mount_operation,
+                     GCancellable        *cancellable,
+                     GAsyncReadyCallback  callback,
+                     gpointer             user_data)
 {
-  /* TODO */
+  GUnixVolume *unix_volume = G_UNIX_VOLUME (volume);
+  MountOp *data;
+  GPid child_pid;
+  GError *error;
+  char *argv[] = {"mount", NULL, NULL};
+
+  if (unix_volume->mount_path != NULL)
+    argv[1] = unix_volume->mount_path;
+  else
+    argv[1] = unix_volume->device_path;
+  
+  data = g_new0 (MountOp, 1);
+  data->unix_volume = unix_volume;
+  data->callback = callback;
+  data->user_data = user_data;
+  data->cancellable = cancellable;
+  
+  error = NULL;
+  if (!g_spawn_async_with_pipes (NULL,         /* working dir */
+                                 argv,
+                                 NULL,         /* envp */
+                                 G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
+                                 NULL,         /* child_setup */
+                                 NULL,         /* user_data for child_setup */
+                                 &child_pid,
+                                 NULL,           /* standard_input */
+                                 NULL,           /* standard_output */
+                                 &(data->error_fd),
+                                 &error)) {
+    GSimpleAsyncResult *simple;
+    simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_volume),
+                                                   data->callback,
+                                                   data->user_data,
+                                                   error);
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+    g_error_free (error);
+    g_free (data);
+    return;
+  }
+  data->error_string = g_string_new ("");
+  data->error_channel = g_io_channel_unix_new (data->error_fd);
+  data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, mount_read_error, data);
+  g_child_watch_add (child_pid, mount_cb, data);
 }
 
+
 static gboolean
-g_unix_volume_eject_finish (GVolume *volume,
-                           GAsyncResult *result,
-                           GError **error)
+g_unix_volume_mount_finish (GVolume        *volume,
+                           GAsyncResult  *result,
+                           GError       **error)
 {
   return TRUE;
 }
@@ -295,14 +355,11 @@ g_unix_volume_eject_finish (GVolume *volume,
 static void
 g_unix_volume_volume_iface_init (GVolumeIface *iface)
 {
-  iface->get_root = g_unix_volume_get_root;
   iface->get_name = g_unix_volume_get_name;
   iface->get_icon = g_unix_volume_get_icon;
   iface->get_drive = g_unix_volume_get_drive;
-  iface->can_unmount = g_unix_volume_can_unmount;
-  iface->can_eject = g_unix_volume_can_eject;
-  iface->unmount = g_unix_volume_unmount;
-  iface->unmount_finish = g_unix_volume_unmount_finish;
-  iface->eject = g_unix_volume_eject;
-  iface->eject_finish = g_unix_volume_eject_finish;
+  iface->get_mount = g_unix_volume_get_mount;
+  iface->can_mount = g_unix_volume_can_mount;
+  iface->mount_fn = g_unix_volume_mount;
+  iface->mount_finish = g_unix_volume_mount_finish;
 }
index 5756798..8e6e225 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #ifndef __G_UNIX_VOLUME_H__
@@ -44,13 +45,15 @@ struct _GUnixVolumeClass {
 
 GType _g_unix_volume_get_type (void) G_GNUC_CONST;
 
-GUnixVolume *_g_unix_volume_new            (GUnixMount     *mount,
-                                           GUnixDrive     *drive);
-gboolean     _g_unix_volume_has_mountpoint (GUnixVolume    *volume,
-                                           const char     *mountpoint);
-void         _g_unix_volume_unset_drive    (GUnixVolume    *volume,
-                                           GUnixDrive     *drive);
-void         _g_unix_volume_unmounted      (GUnixVolume    *volume);
+GUnixVolume *_g_unix_volume_new           (GVolumeMonitor    *volume_monitor,
+                                           GUnixMountPoint   *mountpoint);
+gboolean    _g_unix_volume_has_mount_path (GUnixVolume       *volume,
+                                           const char        *mount_path);
+void        _g_unix_volume_set_mount      (GUnixVolume       *volume,
+                                           GUnixMount        *mount);
+void        _g_unix_volume_unset_mount    (GUnixVolume       *volume,
+                                           GUnixMount        *mount);
+void        _g_unix_volume_disconnected   (GUnixVolume       *volume);
 
 G_END_DECLS
 
index 43475f5..395a820 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
 /* GIO - GLib Input, Output and Streaming Library
  * 
  * Copyright (C) 2006-2007 Red Hat, Inc.
@@ -18,6 +20,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #include <config.h>
@@ -27,9 +30,9 @@
 #include <glib.h>
 #include "gunixvolumemonitor.h"
 #include "gunixmounts.h"
+#include "gunixmount.h"
 #include "gunixvolume.h"
-#include "gunixdrive.h"
-#include "gvolumeprivate.h"
+#include "gmountprivate.h"
 #include "glibintl.h"
 
 #include "gioalias.h"
@@ -42,16 +45,16 @@ struct _GUnixVolumeMonitor {
   GList *last_mountpoints;
   GList *last_mounts;
 
-  GList *drives;
   GList *volumes;
+  GList *mounts;
 };
 
-static void mountpoints_changed (GUnixMountMonitor  *mount_monitor,
-                                gpointer            user_data);
-static void mounts_changed      (GUnixMountMonitor  *mount_monitor,
-                                gpointer            user_data);
-static void update_drives       (GUnixVolumeMonitor *monitor);
-static void update_volumes      (GUnixVolumeMonitor *monitor);
+static void mountpoints_changed      (GUnixMountMonitor  *mount_monitor,
+                                      gpointer            user_data);
+static void mounts_changed           (GUnixMountMonitor  *mount_monitor,
+                                      gpointer            user_data);
+static void update_volumes           (GUnixVolumeMonitor *monitor);
+static void update_mounts            (GUnixVolumeMonitor *monitor);
 
 #define g_unix_volume_monitor_get_type _g_unix_volume_monitor_get_type
 G_DEFINE_TYPE (GUnixVolumeMonitor, g_unix_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR);
@@ -68,58 +71,66 @@ g_unix_volume_monitor_finalize (GObject *object)
                                        
   g_object_unref (monitor->mount_monitor);
 
+  g_list_foreach (monitor->last_mountpoints, (GFunc)g_unix_mount_point_free, NULL);
+  g_list_free (monitor->last_mountpoints);
   g_list_foreach (monitor->last_mounts, (GFunc)g_unix_mount_free, NULL);
   g_list_free (monitor->last_mounts);
 
   g_list_foreach (monitor->volumes, (GFunc)g_object_unref, NULL);
   g_list_free (monitor->volumes);
-  g_list_foreach (monitor->drives, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->drives);
+  g_list_foreach (monitor->mounts, (GFunc)g_object_unref, NULL);
+  g_list_free (monitor->mounts);
   
   if (G_OBJECT_CLASS (g_unix_volume_monitor_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_unix_volume_monitor_parent_class)->finalize) (object);
 }
 
 static GList *
-get_mounted_volumes (GVolumeMonitor *volume_monitor)
+get_mounts (GVolumeMonitor *volume_monitor)
 {
   GUnixVolumeMonitor *monitor;
   GList *l;
   
   monitor = G_UNIX_VOLUME_MONITOR (volume_monitor);
 
-  l = g_list_copy (monitor->volumes);
+  l = g_list_copy (monitor->mounts);
   g_list_foreach (l, (GFunc)g_object_ref, NULL);
 
   return l;
 }
 
 static GList *
-get_connected_drives (GVolumeMonitor *volume_monitor)
+get_volumes (GVolumeMonitor *volume_monitor)
 {
   GUnixVolumeMonitor *monitor;
   GList *l;
   
   monitor = G_UNIX_VOLUME_MONITOR (volume_monitor);
 
-  l = g_list_copy (monitor->drives);
+  l = g_list_copy (monitor->volumes);
   g_list_foreach (l, (GFunc)g_object_ref, NULL);
 
   return l;
 }
 
-static GVolume *
-get_volume_for_mountpoint (const char *mountpoint)
+static GList *
+get_connected_drives (GVolumeMonitor *volume_monitor)
 {
+  return NULL;
+}
+
+static GMount *
+get_mount_for_mount_path (const char *mount_path)
+{
+  GUnixMountEntry *mount_entry;
   GUnixMount *mount;
-  GUnixVolume *volume;
 
-  mount = g_get_unix_mount_at (mountpoint, NULL);
+  mount_entry = g_get_unix_mount_at (mount_path, NULL);
   
-  /* TODO: Set drive? */
-  volume = _g_unix_volume_new (mount, NULL);
+  /* TODO: Set mountable volume? */
+  mount = _g_unix_mount_new (NULL, mount_entry, NULL);
 
-  return G_VOLUME (volume);
+  return G_MOUNT (mount);
 }
 
 static void
@@ -131,11 +142,12 @@ g_unix_volume_monitor_class_init (GUnixVolumeMonitorClass *klass)
   
   gobject_class->finalize = g_unix_volume_monitor_finalize;
 
-  monitor_class->get_mounted_volumes = get_mounted_volumes;
+  monitor_class->get_mounts = get_mounts;
+  monitor_class->get_volumes = get_volumes;
   monitor_class->get_connected_drives = get_connected_drives;
 
   native_class->priority = 0;
-  native_class->get_volume_for_mountpoint = get_volume_for_mountpoint;
+  native_class->get_mount_for_mount_path = get_mount_for_mount_path;
 }
 
 static void
@@ -144,9 +156,9 @@ mountpoints_changed (GUnixMountMonitor *mount_monitor,
 {
   GUnixVolumeMonitor *unix_monitor = user_data;
 
-  /* Update both to make sure drives are created before volumes */
-  update_drives (unix_monitor);
+  /* Update both to make sure volumes are created before mounts */
   update_volumes (unix_monitor);
+  update_mounts (unix_monitor);
 }
 
 static void
@@ -155,9 +167,9 @@ mounts_changed (GUnixMountMonitor *mount_monitor,
 {
   GUnixVolumeMonitor *unix_monitor = user_data;
 
-  /* Update both to make sure drives are created before volumes */
-  update_drives (unix_monitor);
+  /* Update both to make sure volumes are created before mounts */
   update_volumes (unix_monitor);
+  update_mounts (unix_monitor);
 }
 
 static void
@@ -174,9 +186,8 @@ g_unix_volume_monitor_init (GUnixVolumeMonitor *unix_monitor)
                    "mountpoints_changed", G_CALLBACK (mountpoints_changed),
                    unix_monitor);
                    
-  update_drives (unix_monitor);
   update_volumes (unix_monitor);
-
+  update_mounts (unix_monitor);
 }
 
 /**
@@ -239,53 +250,53 @@ diff_sorted_lists (GList         *list1,
 }
 
 /**
- * g_unix_volume_lookup_drive_for_mountpoint
+ * _g_unix_volume_monitor_lookup_volume_for_mount_path
  * @monitor:
- * @mountpoint:
+ * @mount_path:
  * 
- * Returns:  #GUnixDrive for the given @mountpoint.
+ * Returns:  #GUnixVolume for the given @mount_path.
  **/
-GUnixDrive *
-_g_unix_volume_monitor_lookup_drive_for_mountpoint (GUnixVolumeMonitor *monitor,
-                                                   const char         *mountpoint)
+GUnixVolume *
+_g_unix_volume_monitor_lookup_volume_for_mount_path (GUnixVolumeMonitor *monitor,
+                                                     const char         *mount_path)
 {
   GList *l;
 
-  for (l = monitor->drives; l != NULL; l = l->next)
+  for (l = monitor->volumes; l != NULL; l = l->next)
     {
-      GUnixDrive *drive = l->data;
+      GUnixVolume *volume = l->data;
 
-      if (_g_unix_drive_has_mountpoint (drive, mountpoint))
-       return drive;
+      if (_g_unix_volume_has_mount_path (volume, mount_path))
+       return volume;
     }
   
   return NULL;
 }
 
-static GUnixVolume *
-find_volume_by_mountpoint (GUnixVolumeMonitor *monitor,
-                          const char *mountpoint)
+static GUnixMount *
+find_mount_by_mountpath (GUnixVolumeMonitor *monitor,
+                         const char *mount_path)
 {
   GList *l;
 
-  for (l = monitor->volumes; l != NULL; l = l->next)
+  for (l = monitor->mounts; l != NULL; l = l->next)
     {
-      GUnixVolume *volume = l->data;
+      GUnixMount *mount = l->data;
 
-      if (_g_unix_volume_has_mountpoint (volume, mountpoint))
-       return volume;
+      if (_g_unix_mount_has_mount_path (mount, mount_path))
+       return mount;
     }
   
   return NULL;
 }
 
 static void
-update_drives (GUnixVolumeMonitor *monitor)
+update_volumes (GUnixVolumeMonitor *monitor)
 {
   GList *new_mountpoints;
   GList *removed, *added;
   GList *l;
-  GUnixDrive *drive;
+  GUnixVolume *volume;
   
   new_mountpoints = g_get_unix_mount_points (NULL);
   
@@ -299,14 +310,14 @@ update_drives (GUnixVolumeMonitor *monitor)
     {
       GUnixMountPoint *mountpoint = l->data;
       
-      drive = _g_unix_volume_monitor_lookup_drive_for_mountpoint (monitor,
-                                                                 g_unix_mount_point_get_mount_path (mountpoint));
-      if (drive)
+      volume = _g_unix_volume_monitor_lookup_volume_for_mount_path (monitor,
+                                                                    g_unix_mount_point_get_mount_path (mountpoint));
+      if (volume)
        {
-         _g_unix_drive_disconnected (drive);
-         monitor->drives = g_list_remove (monitor->drives, drive);
-         g_signal_emit_by_name (monitor, "drive_disconnected", drive);
-         g_object_unref (drive);
+         _g_unix_volume_disconnected (volume);
+         monitor->volumes = g_list_remove (monitor->volumes, volume);
+         g_signal_emit_by_name (monitor, "volume_removed", volume);
+         g_object_unref (volume);
        }
     }
   
@@ -314,11 +325,11 @@ update_drives (GUnixVolumeMonitor *monitor)
     {
       GUnixMountPoint *mountpoint = l->data;
       
-      drive = _g_unix_drive_new (G_VOLUME_MONITOR (monitor), mountpoint);
-      if (drive)
+      volume = _g_unix_volume_new (G_VOLUME_MONITOR (monitor), mountpoint);
+      if (volume)
        {
-         monitor->drives = g_list_prepend (monitor->drives, drive);
-         g_signal_emit_by_name (monitor, "drive_connected", drive);
+         monitor->volumes = g_list_prepend (monitor->volumes, volume);
+         g_signal_emit_by_name (monitor, "volume_added", volume);
        }
     }
   
@@ -331,13 +342,13 @@ update_drives (GUnixVolumeMonitor *monitor)
 }
 
 static void
-update_volumes (GUnixVolumeMonitor *monitor)
+update_mounts (GUnixVolumeMonitor *monitor)
 {
   GList *new_mounts;
   GList *removed, *added;
   GList *l;
+  GUnixMount *mount;
   GUnixVolume *volume;
-  GUnixDrive *drive;
   const char *mount_path;
   
   new_mounts = g_get_unix_mounts (NULL);
@@ -350,31 +361,34 @@ update_volumes (GUnixVolumeMonitor *monitor)
   
   for (l = removed; l != NULL; l = l->next)
     {
-      GUnixMount *mount = l->data;
+      GUnixMountEntry *mount_entry = l->data;
       
-      volume = find_volume_by_mountpoint (monitor, g_unix_mount_get_mount_path (mount));
-      if (volume)
+      g_warning ("%s %s removed", 
+                 g_unix_mount_get_mount_path (mount_entry),
+                 g_unix_mount_get_device_path (mount_entry));
+
+      mount = find_mount_by_mountpath (monitor, g_unix_mount_get_mount_path (mount_entry));
+      if (mount)
        {
-         _g_unix_volume_unmounted (volume);
-         monitor->volumes = g_list_remove (monitor->volumes, volume);
-         g_signal_emit_by_name (monitor, "volume_unmounted", volume);
-         g_object_unref (volume);
+         _g_unix_mount_unmounted (mount);
+         monitor->mounts = g_list_remove (monitor->mounts, mount);
+         g_signal_emit_by_name (monitor, "mount_removed", mount);
+         g_object_unref (mount);
        }
     }
   
   for (l = added; l != NULL; l = l->next)
     {
-      GUnixMount *mount = l->data;
+      GUnixMountEntry *mount_entry = l->data;
 
-      mount_path = g_unix_mount_get_mount_path (mount);
+      mount_path = g_unix_mount_get_mount_path (mount_entry);
       
-      drive = _g_unix_volume_monitor_lookup_drive_for_mountpoint (monitor,
-                                                                mount_path);
-      volume = _g_unix_volume_new (mount, drive);
-      if (volume)
+      volume = _g_unix_volume_monitor_lookup_volume_for_mount_path (monitor, mount_path);
+      mount = _g_unix_mount_new (G_VOLUME_MONITOR (monitor), mount_entry, volume);
+      if (mount)
        {
-         monitor->volumes = g_list_prepend (monitor->volumes, volume);
-         g_signal_emit_by_name (monitor, "volume_mounted", volume);
+         monitor->mounts = g_list_prepend (monitor->mounts, mount);
+         g_signal_emit_by_name (monitor, "mount_added", mount);
        }
     }
   
index ecaffd5..1732c14 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #ifndef __G_UNIX_VOLUME_MONITOR_H__
@@ -38,8 +39,8 @@ typedef struct _GUnixVolumeMonitor GUnixVolumeMonitor;
 typedef struct _GUnixVolumeMonitorClass GUnixVolumeMonitorClass;
 
 /* Forward definitions */
+typedef struct _GUnixMount GUnixMount;
 typedef struct _GUnixVolume GUnixVolume;
-typedef struct _GUnixDrive GUnixDrive;
 
 struct _GUnixVolumeMonitorClass {
   GNativeVolumeMonitorClass parent_class;
@@ -48,9 +49,9 @@ struct _GUnixVolumeMonitorClass {
 
 GType _g_unix_volume_monitor_get_type (void) G_GNUC_CONST;
 
-GVolumeMonitor *_g_unix_volume_monitor_new                         (void);
-GUnixDrive *    _g_unix_volume_monitor_lookup_drive_for_mountpoint (GUnixVolumeMonitor *monitor,
-                                                                   const char         *mountpoint);
+GVolumeMonitor * _g_unix_volume_monitor_new                          (void);
+GUnixVolume *    _g_unix_volume_monitor_lookup_volume_for_mount_path (GUnixVolumeMonitor *monitor,
+                                                                      const char         *mount_path);
 
 G_END_DECLS
 
index 2b0bb12..25c07ff 100644 (file)
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #include <config.h>
+#include "gmount.h"
 #include "gvolume.h"
-#include "gvolumeprivate.h"
 #include "gsimpleasyncresult.h"
 #include "glibintl.h"
 
 #include "gioalias.h"
 
 /**
- * SECTION:gvolume
- * @short_description: mounted volume management
+ * SECTION:volume
+ * @short_description: volume management
  * 
- * Class for managing mounted volumes.
- * 
- * Unmounting volumes is an asynchronous operation. For more information about
- * asynchronous operations, see #GAsyncReady and #GSimpleAsyncReady. To unmount a volume, 
- * first call g_volume_unmount() with (at least) the volume and a #GAsyncReadyCallback.
- * The callback will be fired when the operation has resolved (either with success or failure), 
- * and a #GAsyncReady structure will be passed to the callback. 
- * That callback should then call g_volume_unmount_finish() with
- * the volume and the #GAsyncReady data to see if the operation was completed successfully.
- * If an @error is present when g_volume_unmount_finish() is called, then it will
- * be filled with any error information.
- * 
- * Ejecting volumes is also an asynchronous operation. 
- * To eject a volume, call g_volume_eject() with (at least) the volume to eject 
- * and a #GAsyncReadyCallback. The callback will be fired when the eject operation
- * has resolved (either with success or failure), and a #GAsyncReady structure will
- * be passed to the callback. That callback should then call g_volume_eject_finish()
- * with the volume and the #GAsyncReady data to determine if the operation was completed
- * successfully. If an @error is present when g_volume_eject_finish() is called, then
- * it will be filled with any error information. 
+ * The #GVolume interface represents user-visible objects that can be
+ * mounted. Note, when porting from GnomeVFS, #GVolume is the moral
+ * equivalent of #GnomeVFSDrive.
  *
+ * Mounting a #GVolume instance is an asynchronous operation. For more
+ * information about asynchronous operations, see #GAsyncReady and
+ * #GSimpleAsyncReady. To mount a #GVolume, first call
+ * g_volume_mount() with (at least) the #GVolume instane, a
+ * #GMountOperation object and a #GAsyncReadyCallback.  The callback
+ * will be fired when the operation has resolved (either with success
+ * or failure), and a #GAsyncReady structure will be passed to the
+ * callback.  That callback should then call g_volume_mount_finish()
+ * with the #GVolume instance and the #GAsyncReady data to see if the
+ * operation was completed successfully.  If an @error is present when
+ * g_volume_mount_finish() is called, then it will be filled with any
+ * error information.
  **/
 
 static void g_volume_base_init (gpointer g_class);
 static void g_volume_class_init (gpointer g_class,
-                                gpointer class_data);
+                                 gpointer class_data);
 
 GType
 g_volume_get_type (void)
@@ -91,7 +87,7 @@ g_volume_get_type (void)
 
 static void
 g_volume_class_init (gpointer g_class,
-                  gpointer class_data)
+                     gpointer class_data)
 {
 }
 
@@ -120,26 +116,6 @@ g_volume_base_init (gpointer g_class)
 }
 
 /**
- * g_volume_get_root:
- * @volume: a #GVolume.
- * 
- * Gets the root directory on @volume.
- * 
- * Returns: a #GFile.
- **/
-GFile *
-g_volume_get_root (GVolume *volume)
-{
-  GVolumeIface *iface;
-
-  g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
-
-  iface = G_VOLUME_GET_IFACE (volume);
-
-  return (* iface->get_root) (volume);
-}
-
-/**
  * g_volume_get_name:
  * @volume: a #GVolume.
  * 
@@ -186,7 +162,7 @@ g_volume_get_icon (GVolume *volume)
  * 
  * Gets the drive for the @volume.
  * 
- * Returns: a #GDrive.
+ * Returns: a #GDrive or %NULL if @volume is not associated with a drive.
  **/
 GDrive *
 g_volume_get_drive (GVolume *volume)
@@ -201,35 +177,36 @@ g_volume_get_drive (GVolume *volume)
 }
 
 /**
- * g_volume_can_unmount: 
+ * g_volume_get_mount:
  * @volume: a #GVolume.
  * 
- * Checks if @volume can be mounted.
+ * Gets the mount for the @volume.
  * 
- * Returns: %TRUE if the @volume can be unmounted.
+ * Returns: a #GMount or %NULL if @volume isn't mounted.
  **/
-gboolean
-g_volume_can_unmount (GVolume *volume)
+GMount *
+g_volume_get_mount (GVolume *volume)
 {
   GVolumeIface *iface;
 
-  g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
+  g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
 
   iface = G_VOLUME_GET_IFACE (volume);
 
-  return (* iface->can_unmount) (volume);
+  return (* iface->get_mount) (volume);
 }
 
+
 /**
- * g_volume_can_eject:
+ * g_volume_can_mount:
  * @volume: a #GVolume.
  * 
- * Checks if @volume can be ejected.
+ * Checks if a volume can be mounted.
  * 
- * Returns: %TRUE if the @volume can be ejected.
+ * Returns: %TRUE if the @volume can be mounted. %FALSE otherwise.
  **/
 gboolean
-g_volume_can_eject (GVolume *volume)
+g_volume_can_mount (GVolume *volume)
 {
   GVolumeIface *iface;
 
@@ -237,130 +214,62 @@ g_volume_can_eject (GVolume *volume)
 
   iface = G_VOLUME_GET_IFACE (volume);
 
-  return (* iface->can_eject) (volume);
-}
-
-/**
- * g_volume_unmount:
- * @volume: a #GVolume.
- * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @callback: a #GAsyncReadyCallback.
- * @user_data: user data passed to @callback.
- * 
- * Unmounts a volume. This is an asynchronous operation, and is 
- * finished by calling g_volume_unmount_finish() with the @volume 
- * and #GAsyncResults data returned in the @callback.
- **/
-void
-g_volume_unmount (GVolume             *volume,
-                 GCancellable        *cancellable,
-                 GAsyncReadyCallback  callback,
-                 gpointer             user_data)
-{
-  GVolumeIface *iface;
-
-  g_return_if_fail (G_IS_VOLUME (volume));
-  
-  iface = G_VOLUME_GET_IFACE (volume);
-
-  if (iface->unmount == NULL)
-    {
-      g_simple_async_report_error_in_idle (G_OBJECT (volume),
-                                          callback, user_data,
-                                          G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                                          _("volume doesn't implement unmount"));
-      
-      return;
-    }
-  
-  (* iface->unmount) (volume, cancellable, callback, user_data);
-}
+  if (iface->can_mount == NULL)
+    return FALSE;
 
-/**
- * g_volume_unmount_finish:
- * @volume: a #GVolume.
- * @result: a #GAsyncResult.
- * @error: a #GError location to store the error occuring, or %NULL to 
- * ignore.
- * 
- * Finishes unmounting a volume. If any errors occured during the operation, 
- * @error will be set to contain the errors and %FALSE will be returned.
- * 
- * Returns: %TRUE if the volume was successfully unmounted. %FALSE otherwise.
- **/
-gboolean
-g_volume_unmount_finish (GVolume       *volume,
-                        GAsyncResult  *result,
-                        GError       **error)
-{
-  GVolumeIface *iface;
-
-  g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
-  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
-
-  if (G_IS_SIMPLE_ASYNC_RESULT (result))
-    {
-      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-      if (g_simple_async_result_propagate_error (simple, error))
-       return FALSE;
-    }
-  
-  iface = G_VOLUME_GET_IFACE (volume);
-  return (* iface->unmount_finish) (volume, result, error);
+  return (* iface->can_mount) (volume);
 }
 
 /**
- * g_volume_eject:
+ * g_volume_mount:
  * @volume: a #GVolume.
- * @cancellable: optional #GCancellable object, %NULL to ignore. 
+ * @mount_operation: a #GMountOperation.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @callback: a #GAsyncReadyCallback.
- * @user_data: user data passed to @callback.
+ * @user_data: a #gpointer.
  * 
- * Ejects a volume. This is an asynchronous operation, and is 
- * finished by calling g_volume_eject_finish() from the @callback 
- * with the @volume and #GAsyncResults returned in the callback.
+ * Mounts a volume.
  **/
 void
-g_volume_eject (GVolume             *volume,
-               GCancellable        *cancellable,
-               GAsyncReadyCallback  callback,
-               gpointer             user_data)
+g_volume_mount (GVolume    *volume,
+                GMountOperation     *mount_operation,
+                GCancellable        *cancellable,
+                GAsyncReadyCallback  callback,
+                gpointer             user_data)
 {
   GVolumeIface *iface;
 
   g_return_if_fail (G_IS_VOLUME (volume));
+  g_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
 
   iface = G_VOLUME_GET_IFACE (volume);
 
-  if (iface->eject == NULL)
+  if (iface->mount_fn == NULL)
     {
-      g_simple_async_report_error_in_idle (G_OBJECT (volume),
-                                          callback, user_data,
+      g_simple_async_report_error_in_idle (G_OBJECT (volume), callback, user_data,
                                           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                                          _("volume doesn't implement eject"));
+                                          _("volume doesn't implement mount"));
       
       return;
     }
   
-  (* iface->eject) (volume, cancellable, callback, user_data);
+  (* iface->mount_fn) (volume, mount_operation, cancellable, callback, user_data);
 }
 
 /**
- * g_volume_eject_finish:
- * @volume: a #GVolume.
+ * g_volume_mount_finish:
+ * @volume: pointer to a #GVolume.
  * @result: a #GAsyncResult.
- * @error: a #GError location to store the error occuring, or %NULL to 
- * ignore.
+ * @error: a #GError.
  * 
- * Finishes ejecting the volume. If any errors occured during the operation, 
- * @error will be set to contain the errors and %FALSE will be returned.
+ * Finishes mounting a volume.
  * 
- * Returns: %TRUE if the volume was successfully ejected. %FALSE otherwise.
+ * Returns: %TRUE, %FALSE if operation failed.
  **/
 gboolean
-g_volume_eject_finish (GVolume       *volume,
-                      GAsyncResult  *result,
-                      GError       **error)
+g_volume_mount_finish (GVolume  *volume,
+                       GAsyncResult      *result,
+                       GError           **error)
 {
   GVolumeIface *iface;
 
@@ -375,7 +284,7 @@ g_volume_eject_finish (GVolume       *volume,
     }
   
   iface = G_VOLUME_GET_IFACE (volume);
-  return (* iface->eject_finish) (volume, result, error);
+  return (* iface->mount_finish) (volume, result, error);
 }
 
 #define __G_VOLUME_C__
index d45c901..c73241b 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #ifndef __G_VOLUME_H__
@@ -25,6 +26,7 @@
 
 #include <glib-object.h>
 #include <gio/gfile.h>
+#include <gio/gdrive.h>
 
 G_BEGIN_DECLS
 
@@ -33,32 +35,22 @@ G_BEGIN_DECLS
 #define G_IS_VOLUME(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_VOLUME))
 #define G_VOLUME_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_VOLUME, GVolumeIface))
 
-/* GVolume typedef is in gfile.h due to include order issues */
-/**
- * GDrive:
- * 
- * Opaque drive object.
- **/
-typedef struct _GDrive          GDrive; /* Dummy typedef */
-typedef struct _GVolumeIface    GVolumeIface;
-
 /**
  * GVolumeIface:
  * @g_iface: The parent interface.
  * @changed: Changed signal that is emitted when the volume's state has changed.
- * @get_root: Gets a #GFile to the root directory of the #GVolume.
  * @get_name: Gets a string containing the name of the #GVolume.
  * @get_icon: Gets a #GIcon for the #GVolume.
- * @get_drive: Gets a #GDrive the volume is located on.
- * @can_unmount: Checks if a #GVolume can be unmounted.
- * @can_eject: Checks if a #GVolume can be ejected.
- * @unmount: Starts unmounting a #GVolume.
- * @unmount_finish: Finishes an unmounting operation.
- * @eject: Starts ejecting a #GVolume.
- * @eject_finish: Finishes an eject operation.
+ * @get_drive: Gets a #GDrive the volume is located on. Returns %NULL if the #GVolume is not associated with a #GDrive.
+ * @get_mount: Gets a #GMount representing the mounted volume. Returns %NULL if the #GVolume is not mounted.
+ * @can_mount: Returns %TRUE if the #GVolume can be mounted.
+ * @mount: Mounts a given #GVolume.
+ * @mount_finish: Finishes a mount operation.
  * 
- * Interface for implementing operations for mounted volumes.
+ * Interface for implementing operations for mountable volumes.
  **/
+typedef struct _GVolumeIface    GVolumeIface;
+
 struct _GVolumeIface
 {
   GTypeInterface g_iface;
@@ -69,50 +61,47 @@ struct _GVolumeIface
   
   /* Virtual Table */
 
-  GFile *  (*get_root)       (GVolume         *volume);
-  char *   (*get_name)       (GVolume         *volume);
-  GIcon *  (*get_icon)       (GVolume         *volume);
-  GDrive * (*get_drive)      (GVolume         *volume);
-  gboolean (*can_unmount)    (GVolume         *volume);
-  gboolean (*can_eject)      (GVolume         *volume);
-  void     (*unmount)        (GVolume         *volume,
-                             GCancellable    *cancellable,
-                             GAsyncReadyCallback callback,
-                             gpointer         user_data);
-  gboolean (*unmount_finish) (GVolume         *volume,
-                             GAsyncResult    *result,
-                             GError         **error);
-  void     (*eject)          (GVolume         *volume,
-                             GCancellable    *cancellable,
-                             GAsyncReadyCallback callback,
-                             gpointer         user_data);
-  gboolean (*eject_finish)   (GVolume         *volume,
-                             GAsyncResult    *result,
-                             GError         **error);
+  char *    (*get_name)       (GVolume             *volume);
+  GIcon *   (*get_icon)       (GVolume             *volume);
+  GDrive *  (*get_drive)      (GVolume             *volume);
+  GMount *  (*get_mount)      (GVolume             *volume);
+  gboolean  (*can_mount)      (GVolume             *volume);
+  void      (*mount_fn)       (GVolume             *volume,
+                               GMountOperation     *mount_operation,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data);
+  gboolean  (*mount_finish)   (GVolume             *volume,
+                               GAsyncResult        *result,
+                               GError             **error);
+
+  /*< private >*/
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+  void (*_g_reserved6) (void);
+  void (*_g_reserved7) (void);
+  void (*_g_reserved8) (void);
 };
 
-GType g_volume_get_type (void) G_GNUC_CONST;
+GType     g_volume_get_type       (void) G_GNUC_CONST;
 
-GFile   *g_volume_get_root       (GVolume              *volume);
-char *   g_volume_get_name       (GVolume              *volume);
-GIcon *  g_volume_get_icon       (GVolume              *volume);
-GDrive * g_volume_get_drive      (GVolume              *volume);
-gboolean g_volume_can_unmount    (GVolume              *volume);
-gboolean g_volume_can_eject      (GVolume              *volume);
-void     g_volume_unmount        (GVolume              *volume,
-                                 GCancellable         *cancellable,
-                                 GAsyncReadyCallback   callback,
-                                 gpointer              user_data);
-gboolean g_volume_unmount_finish (GVolume              *volume,
-                                 GAsyncResult         *result,
-                                 GError              **error);
-void     g_volume_eject          (GVolume              *volume,
-                                 GCancellable         *cancellable,
-                                 GAsyncReadyCallback   callback,
-                                 gpointer              user_data);
-gboolean g_volume_eject_finish   (GVolume              *volume,
-                                 GAsyncResult         *result,
-                                 GError              **error);
+char *    g_volume_get_name       (GVolume              *volume);
+GIcon *   g_volume_get_icon       (GVolume              *volume);
+GDrive *  g_volume_get_drive      (GVolume              *volume);
+GMount *  g_volume_get_mount      (GVolume              *volume);
+gboolean  g_volume_can_mount      (GVolume              *volume);
+void      g_volume_mount          (GVolume              *volume,
+                                   GMountOperation      *mount_operation,
+                                   GCancellable         *cancellable,
+                                   GAsyncReadyCallback   callback,
+                                   gpointer              user_data);
+gboolean g_volume_mount_finish    (GVolume              *volume,
+                                   GAsyncResult         *result,
+                                   GError              **error);
 
 G_END_DECLS
 
index d4d59a5..36319aa 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #include <config.h>
 G_DEFINE_TYPE (GVolumeMonitor, g_volume_monitor, G_TYPE_OBJECT);
 
 enum {
-  VOLUME_MOUNTED,
-  VOLUME_PRE_UNMOUNT,
-  VOLUME_UNMOUNTED,
+  VOLUME_ADDED,
+  VOLUME_REMOVED,
+  VOLUME_CHANGED,
+  MOUNT_ADDED,
+  MOUNT_REMOVED,
+  MOUNT_PRE_UNMOUNT,
+  MOUNT_CHANGED,
   DRIVE_CONNECTED,
   DRIVE_DISCONNECTED,
+  DRIVE_CHANGED,
   LAST_SIGNAL
 };
 
@@ -67,47 +73,110 @@ g_volume_monitor_class_init (GVolumeMonitorClass *klass)
   gobject_class->finalize = g_volume_monitor_finalize;
 
   /**
-   * GVolumeMonitor::volume-mounted:   
+   * GVolumeMonitor::volume-added:
    * @volume_monitor: The volume monitor emitting the signal.
-   * @volume: the volume that was mounted.
-   *
-   * Emitted when a volume is mounted.
+   * @volume: a #GVolume that was added.
+   * 
+   * Emitted when a mountable volume is added to the system.
    **/
-  signals[VOLUME_MOUNTED] = g_signal_new (I_("volume_mounted"),
-                                         G_TYPE_VOLUME_MONITOR,
-                                         G_SIGNAL_RUN_LAST,
-                                         G_STRUCT_OFFSET (GVolumeMonitorClass, volume_mounted),
-                                         NULL, NULL,
-                                         g_cclosure_marshal_VOID__OBJECT,
-                                         G_TYPE_NONE, 1, G_TYPE_VOLUME);
+  signals[VOLUME_ADDED] = g_signal_new (I_("volume_added"),
+                                        G_TYPE_VOLUME_MONITOR,
+                                        G_SIGNAL_RUN_LAST,
+                                        G_STRUCT_OFFSET (GVolumeMonitorClass, volume_added),
+                                        NULL, NULL,
+                                        g_cclosure_marshal_VOID__OBJECT,
+                                        G_TYPE_NONE, 1, G_TYPE_VOLUME);
+  
   /**
-   * GVolumeMonitor::volume-pre-unmount:
+   * GVolumeMonitor::volume-removed:
    * @volume_monitor: The volume monitor emitting the signal.
-   * @volume: the volume that is being unmounted.
-   *
-   * Emitted when a volume is about to be unmounted.
-   **/ 
-  signals[VOLUME_PRE_UNMOUNT] = g_signal_new (I_("volume_pre_unmount"),
-                                             G_TYPE_VOLUME_MONITOR,
-                                             G_SIGNAL_RUN_LAST,
-                                             G_STRUCT_OFFSET (GVolumeMonitorClass, volume_pre_unmount),
-                                             NULL, NULL,
-                                             g_cclosure_marshal_VOID__OBJECT,
-                                             G_TYPE_NONE, 1, G_TYPE_VOLUME);
+   * @volume: a #GVolume that was removed.
+   * 
+   * Emitted when a mountable volume is removed from the system.
+   **/  
+  signals[VOLUME_REMOVED] = g_signal_new (I_("volume_removed"),
+                                          G_TYPE_VOLUME_MONITOR,
+                                          G_SIGNAL_RUN_LAST,
+                                          G_STRUCT_OFFSET (GVolumeMonitorClass, volume_removed),
+                                          NULL, NULL,
+                                          g_cclosure_marshal_VOID__OBJECT,
+                                          G_TYPE_NONE, 1, G_TYPE_VOLUME);
+  
   /**
-   * GVolumeMonitor::volume-unmounted:
+   * GVolumeMonitor::volume-changed:
    * @volume_monitor: The volume monitor emitting the signal.
-   * @volume: the volume that was unmounted.
+   * @volume: a #GVolume that changed.
    * 
-   * Emitted when a volume is unmounted.
+   * Emitted when mountable volume is changed.
    **/  
-  signals[VOLUME_UNMOUNTED] = g_signal_new (I_("volume_unmounted"),
-                                           G_TYPE_VOLUME_MONITOR,
-                                           G_SIGNAL_RUN_LAST,
-                                           G_STRUCT_OFFSET (GVolumeMonitorClass, volume_unmounted),
-                                           NULL, NULL,
-                                           g_cclosure_marshal_VOID__OBJECT,
-                                           G_TYPE_NONE, 1, G_TYPE_VOLUME);
+  signals[VOLUME_CHANGED] = g_signal_new (I_("volume_changed"),
+                                          G_TYPE_VOLUME_MONITOR,
+                                          G_SIGNAL_RUN_LAST,
+                                          G_STRUCT_OFFSET (GVolumeMonitorClass, volume_changed),
+                                          NULL, NULL,
+                                          g_cclosure_marshal_VOID__OBJECT,
+                                          G_TYPE_NONE, 1, G_TYPE_VOLUME);
+
+  /**
+   * GVolumeMonitor::mount-added:
+   * @volume_monitor: The volume monitor emitting the signal.
+   * @mount: a #GMount that was added.
+   * 
+   * Emitted when a mount is added.
+   **/
+  signals[MOUNT_ADDED] = g_signal_new (I_("mount_added"),
+                                       G_TYPE_VOLUME_MONITOR,
+                                       G_SIGNAL_RUN_LAST,
+                                       G_STRUCT_OFFSET (GVolumeMonitorClass, mount_added),
+                                       NULL, NULL,
+                                       g_cclosure_marshal_VOID__OBJECT,
+                                       G_TYPE_NONE, 1, G_TYPE_MOUNT);
+
+  /**
+   * GVolumeMonitor::mount-removed:
+   * @volume_monitor: The volume monitor emitting the signal.
+   * @mount: a #GMount that was removed.
+   * 
+   * Emitted when a mount is removed.
+   **/
+  signals[MOUNT_REMOVED] = g_signal_new (I_("mount_removed"),
+                                         G_TYPE_VOLUME_MONITOR,
+                                         G_SIGNAL_RUN_LAST,
+                                         G_STRUCT_OFFSET (GVolumeMonitorClass, mount_removed),
+                                         NULL, NULL,
+                                         g_cclosure_marshal_VOID__OBJECT,
+                                         G_TYPE_NONE, 1, G_TYPE_MOUNT);
+
+  /**
+   * GVolumeMonitor::mount-pre-unmount:
+   * @volume_monitor: The volume monitor emitting the signal.
+   * @mount: a #GMount that is being unmounted.
+   *
+   * Emitted when a mount is about to be removed.
+   **/ 
+  signals[MOUNT_PRE_UNMOUNT] = g_signal_new (I_("mount_pre_unmount"),
+                                             G_TYPE_VOLUME_MONITOR,
+                                             G_SIGNAL_RUN_LAST,
+                                             G_STRUCT_OFFSET (GVolumeMonitorClass, mount_pre_unmount),
+                                             NULL, NULL,
+                                             g_cclosure_marshal_VOID__OBJECT,
+                                             G_TYPE_NONE, 1, G_TYPE_MOUNT);
+
+  /**
+   * GVolumeMonitor::mount-changed:
+   * @volume_monitor: The volume monitor emitting the signal.
+   * @mount: a #GMount that changed.
+   *
+   * Emitted when a mount changes.
+   **/ 
+  signals[MOUNT_CHANGED] = g_signal_new (I_("mount_changed"),
+                                         G_TYPE_VOLUME_MONITOR,
+                                         G_SIGNAL_RUN_LAST,
+                                         G_STRUCT_OFFSET (GVolumeMonitorClass, mount_changed),
+                                         NULL, NULL,
+                                         g_cclosure_marshal_VOID__OBJECT,
+                                         G_TYPE_NONE, 1, G_TYPE_MOUNT);
+
   /**
    * GVolumeMonitor::drive-connected:
    * @volume_monitor: The volume monitor emitting the signal.
@@ -137,6 +206,22 @@ g_volume_monitor_class_init (GVolumeMonitorClass *klass)
                                              NULL, NULL,
                                              g_cclosure_marshal_VOID__OBJECT,
                                              G_TYPE_NONE, 1, G_TYPE_DRIVE);
+
+  /**
+   * GVolumeMonitor::drive-changed:
+   * @volume_monitor: The volume monitor emitting the signal.
+   * @drive: the drive that changed
+   *
+   * Emitted when a drive changes.
+   **/ 
+  signals[DRIVE_CHANGED] = g_signal_new (I_("drive_changed"),
+                                         G_TYPE_VOLUME_MONITOR,
+                                         G_SIGNAL_RUN_LAST,
+                                         G_STRUCT_OFFSET (GVolumeMonitorClass, drive_changed),
+                                         NULL, NULL,
+                                         g_cclosure_marshal_VOID__OBJECT,
+                                         G_TYPE_NONE, 1, G_TYPE_DRIVE);
+
 }
 
 static void
@@ -144,16 +229,17 @@ g_volume_monitor_init (GVolumeMonitor *monitor)
 {
 }
 
+
 /**
- * g_volume_monitor_get_mounted_volumes:
+ * g_volume_monitor_get_drives:
  * @volume_monitor: a #GVolumeMonitor.
  * 
- * Gets a list of volumes mounted on the computer.
+ * Gets a list of drives connected to the system.
  * 
- * Returns: a #GList of mounted #GVolumes.
+ * Returns: a #GList of connected #GDrives. 
  **/
 GList *
-g_volume_monitor_get_mounted_volumes (GVolumeMonitor *volume_monitor)
+g_volume_monitor_get_connected_drives (GVolumeMonitor *volume_monitor)
 {
   GVolumeMonitorClass *class;
 
@@ -161,19 +247,19 @@ g_volume_monitor_get_mounted_volumes (GVolumeMonitor *volume_monitor)
 
   class = G_VOLUME_MONITOR_GET_CLASS (volume_monitor);
 
-  return class->get_mounted_volumes (volume_monitor);
+  return class->get_connected_drives (volume_monitor);
 }
 
 /**
- * g_volume_monitor_get_connected_drives:
+ * g_volume_monitor_get_volumes:
  * @volume_monitor: a #GVolumeMonitor.
  * 
- * Gets a list of drives connected to the computer.
+ * Gets a list of the volumes on the system.
  * 
- * Returns: a #GList of connected #GDrives. 
+ * Returns: a #GList of #GVolume.
  **/
 GList *
-g_volume_monitor_get_connected_drives (GVolumeMonitor *volume_monitor)
+g_volume_monitor_get_volumes (GVolumeMonitor *volume_monitor)
 {
   GVolumeMonitorClass *class;
 
@@ -181,7 +267,27 @@ g_volume_monitor_get_connected_drives (GVolumeMonitor *volume_monitor)
 
   class = G_VOLUME_MONITOR_GET_CLASS (volume_monitor);
 
-  return class->get_connected_drives (volume_monitor);
+  return class->get_volumes (volume_monitor);
+}
+
+/**
+ * g_volume_monitor_get_mounts:
+ * @volume_monitor: a #GVolumeMonitor.
+ * 
+ * Gets a list of the mounts on the system.
+ * 
+ * Returns: a #GList of #GMount.
+ **/
+GList *
+g_volume_monitor_get_mounts (GVolumeMonitor *volume_monitor)
+{
+  GVolumeMonitorClass *class;
+
+  g_return_val_if_fail (G_IS_VOLUME_MONITOR (volume_monitor), NULL);
+
+  class = G_VOLUME_MONITOR_GET_CLASS (volume_monitor);
+
+  return class->get_mounts (volume_monitor);
 }
 
 #define __G_VOLUME_MONITOR_C__
index 63892e9..46decc5 100644 (file)
  * Boston, MA 02111-1307, USA.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
+ *         David Zeuthen <davidz@redhat.com>
  */
 
 #ifndef __G_VOLUME_MONITOR_H__
 #define __G_VOLUME_MONITOR_H__
 
 #include <glib-object.h>
+#include <gio/gmount.h>
 #include <gio/gvolume.h>
 #include <gio/gdrive.h>
 
@@ -57,21 +59,34 @@ struct _GVolumeMonitorClass {
 
   /*< public >*/
   /* signals */
-  void (* volume_mounted)      (GVolumeMonitor *volume_monitor,
-                                GVolume        *volume);
-  void (* volume_pre_unmount)  (GVolumeMonitor *volume_monitor,
-                                GVolume        *volume);
-  void (* volume_unmounted)    (GVolumeMonitor *volume_monitor,
-                                GVolume        *volume);
-  void (* drive_connected)     (GVolumeMonitor *volume_monitor,
+  void (* volume_added)     (GVolumeMonitor   *volume_monitor,
+                             GVolume          *volume);
+  void (* volume_removed)   (GVolumeMonitor   *volume_monitor,
+                             GVolume          *volume);
+  void (* volume_changed)   (GVolumeMonitor   *volume_monitor,
+                             GVolume          *volume);
+
+  void (* mount_added)       (GVolumeMonitor *volume_monitor,
+                              GMount         *mount);
+  void (* mount_removed)     (GVolumeMonitor *volume_monitor,
+                              GMount         *mount);
+  void (* mount_pre_unmount) (GVolumeMonitor *volume_monitor,
+                              GMount         *mount);
+  void (* mount_changed)     (GVolumeMonitor *volume_monitor,
+                              GMount         *mount);
+
+  void (* drive_connected)      (GVolumeMonitor *volume_monitor,
                                 GDrive         *drive);
-  void (* drive_disconnected)  (GVolumeMonitor *volume_monitor,
+  void (* drive_disconnected)   (GVolumeMonitor *volume_monitor,
+                                GDrive         *drive);
+  void (* drive_changed)        (GVolumeMonitor *volume_monitor,
                                 GDrive         *drive);
 
   /* Vtable */
 
-  GList * (*get_mounted_volumes)  (GVolumeMonitor *volume_monitor);
-  GList * (*get_connected_drives) (GVolumeMonitor *volume_monitor);
+  GList * (*get_connected_drives)   (GVolumeMonitor *volume_monitor);
+  GList * (*get_volumes)            (GVolumeMonitor *volume_monitor);
+  GList * (*get_mounts)             (GVolumeMonitor *volume_monitor);
 
   /*< private >*/
   /* Padding for future expansion */
@@ -87,9 +102,10 @@ struct _GVolumeMonitorClass {
 
 GType g_volume_monitor_get_type (void) G_GNUC_CONST;
 
-GVolumeMonitor *g_volume_monitor_get                  (void);
-GList *         g_volume_monitor_get_mounted_volumes  (GVolumeMonitor *volume_monitor);
+GVolumeMonitor *g_volume_monitor_get          (void);
 GList *         g_volume_monitor_get_connected_drives (GVolumeMonitor *volume_monitor);
+GList *         g_volume_monitor_get_volumes          (GVolumeMonitor *volume_monitor);
+GList *         g_volume_monitor_get_mounts           (GVolumeMonitor *volume_monitor);
 
 G_END_DECLS