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

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
This commit is contained in:
David Zeuthen 2007-12-11 21:23:55 +00:00 committed by David Zeuthen
parent c2643afd24
commit 3ca9fd4dbb
29 changed files with 2408 additions and 1283 deletions

View 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

View 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 \

View File

@ -18,6 +18,7 @@
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
* David Zeuthen <davidz@redhat.com>
*/
#include <config.h>
@ -32,9 +33,19 @@
* @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,74 +281,26 @@ g_drive_can_eject (GDrive *drive)
}
/**
* g_drive_mount:
* g_drive_can_poll_for_media:
* @drive: a #GDrive.
* @mount_operation: a #GMountOperation.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @callback: a #GAsyncReadyCallback.
* @user_data: a #gpointer.
*
* Mounts a drive.
**/
void
g_drive_mount (GDrive *drive,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
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)
{
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"));
return;
}
(* iface->mount_fn) (drive, mount_operation, cancellable, callback, user_data);
}
/**
* g_drive_mount_finish:
* @drive: a #GDrive.
* @result: a #GAsyncResult.
* @error: a #GError.
* Checks if a drive can be polled for media changes.
*
* 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.
*
* Returns: %TRUE if the mount was finished successfully,
* %FALSE if operation failed.
* Returns: %TRUE if the @drive can be polled for media changes. %FALSE otherwise.
**/
gboolean
g_drive_mount_finish (GDrive *drive,
GAsyncResult *result,
GError **error)
g_drive_can_poll_for_media (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), 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_DRIVE_GET_IFACE (drive);
return (* iface->mount_finish) (drive, result, error);
if (iface->poll_for_media == NULL)
return FALSE;
return (* iface->can_poll_for_media) (drive);
}
/**
@ -363,9 +344,6 @@ g_drive_eject (GDrive *drive,
* @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.
*
* Returns: %TRUE if the drive has been ejected successfully,
* %FALSE otherwise.
@ -389,7 +367,74 @@ g_drive_eject_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_poll_for_media:
* @drive: a #GDrive.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @callback: a #GAsyncReadyCallback.
* @user_data: a #gpointer.
*
* Polls @drive to see if media has been inserted or removed.
*
**/
void
g_drive_poll_for_media (GDrive *drive,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDriveIface *iface;
g_return_if_fail (G_IS_DRIVE (drive));
iface = G_DRIVE_GET_IFACE (drive);
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 polling for media"));
return;
}
(* iface->poll_for_media) (drive, cancellable, callback, user_data);
}
/**
* g_drive_poll_for_media_finish
* @drive: a #GDrive.
* @result: a #GAsyncResult.
* @error: a #GError.
*
* Finishes poll_for_mediaing a drive.
*
* Returns: %TRUE if the drive has been poll_for_mediaed successfully,
* %FALSE otherwise.
**/
gboolean
g_drive_poll_for_media_finish (GDrive *drive,
GAsyncResult *result,
GError **error)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), 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_DRIVE_GET_IFACE (drive);
return (* iface->poll_for_media_finish) (drive, result, error);
}
#define __G_DRIVE_C__

View File

@ -18,12 +18,14 @@
* 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

View 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);
}
/**

View 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,

View 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

View 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;

View 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;

312
gio/gmount.c Normal file
View File

@ -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"

123
gio/gmount.h Normal file
View File

@ -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__ */

View 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

View 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;
};

View 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,38 +172,80 @@ 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,
child_volume_added (GVolumeMonitor *child_monitor,
GVolume *child_volume,
GUnionVolumeMonitor *union_monitor)
{
g_signal_emit_by_name (union_monitor,
"volume_added",
child_volume);
}
static void
child_volume_removed (GVolumeMonitor *child_monitor,
GVolume *child_volume,
GUnionVolumeMonitor *union_monitor)
{
g_signal_emit_by_name (union_monitor,
"volume_mounted",
"volume_removed",
child_volume);
}
static void
child_volume_pre_unmount (GVolumeMonitor *child_monitor,
GVolume *child_volume,
child_volume_changed (GVolumeMonitor *child_monitor,
GVolume *child_volume,
GUnionVolumeMonitor *union_monitor)
{
g_signal_emit_by_name (union_monitor,
"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,
"volume_pre_unmount",
child_volume);
"mount_pre_unmount",
child_mount);
}
static void
child_volume_unmounted (GVolumeMonitor *child_monitor,
GVolume *child_volume,
GUnionVolumeMonitor *union_monitor)
child_mount_changed (GVolumeMonitor *child_monitor,
GMount *child_mount,
GUnionVolumeMonitor *union_monitor)
{
g_signal_emit_by_name (union_monitor,
"volume_unmounted",
child_volume);
"mount_changed",
child_mount);
}
static void
@ -201,6 +268,16 @@ child_drive_disconnected (GVolumeMonitor *child_monitor,
child_drive);
}
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__

View 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__

View File

@ -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;
}

View File

@ -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__ */

348
gio/gunixmount.c Normal file
View File

@ -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;
}

59
gio/gunixmount.h Normal file
View File

@ -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__ */

View 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.
@ -46,9 +48,13 @@
#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
@ -57,7 +63,41 @@
*
**/
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"

View File

@ -25,15 +25,16 @@
#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:
@ -42,40 +43,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:
*
@ -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__ */

View 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,19 +20,21 @@
* 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"
@ -38,10 +42,13 @@
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_unset_drive (GUnixVolume *volume,
GUnixDrive *drive)
_g_unix_volume_set_mount (GUnixVolume *volume,
GUnixMount *mount)
{
if (volume->drive == drive)
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_mount (GUnixVolume *volume,
GUnixMount *mount)
{
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;
}
gboolean
_g_unix_volume_has_mount_path (GUnixVolume *volume,
const char *mount_path)
{
return strcmp (volume->mount_path, mount_path) == 0;
}
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)
{
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_can_eject (GVolume *volume)
mount_read_error (GIOChannel *channel,
GIOCondition condition,
gpointer user_data)
{
/* TODO */
return FALSE;
}
char *str;
gsize str_len;
MountOp *data = user_data;
static void
g_unix_volume_unmount (GVolume *volume,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
/* TODO */
}
static gboolean
g_unix_volume_unmount_finish (GVolume *volume,
GAsyncResult *result,
GError **error)
{
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;
}

View 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

View 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,20 +71,36 @@ 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->mounts);
g_list_foreach (l, (GFunc)g_object_ref, NULL);
return l;
}
static GList *
get_volumes (GVolumeMonitor *volume_monitor)
{
GUnixVolumeMonitor *monitor;
GList *l;
@ -97,29 +116,21 @@ get_mounted_volumes (GVolumeMonitor *volume_monitor)
static GList *
get_connected_drives (GVolumeMonitor *volume_monitor)
{
GUnixVolumeMonitor *monitor;
GList *l;
monitor = G_UNIX_VOLUME_MONITOR (volume_monitor);
l = g_list_copy (monitor->drives);
g_list_foreach (l, (GFunc)g_object_ref, NULL);
return l;
return NULL;
}
static GVolume *
get_volume_for_mountpoint (const char *mountpoint)
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,32 +250,15 @@ 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)
{
GList *l;
for (l = monitor->drives; l != NULL; l = l->next)
{
GUnixDrive *drive = l->data;
if (_g_unix_drive_has_mountpoint (drive, mountpoint))
return drive;
}
return NULL;
}
static GUnixVolume *
find_volume_by_mountpoint (GUnixVolumeMonitor *monitor,
const char *mountpoint)
GUnixVolume *
_g_unix_volume_monitor_lookup_volume_for_mount_path (GUnixVolumeMonitor *monitor,
const char *mount_path)
{
GList *l;
@ -272,20 +266,37 @@ find_volume_by_mountpoint (GUnixVolumeMonitor *monitor,
{
GUnixVolume *volume = l->data;
if (_g_unix_volume_has_mountpoint (volume, mountpoint))
if (_g_unix_volume_has_mount_path (volume, mount_path))
return volume;
}
return NULL;
}
static GUnixMount *
find_mount_by_mountpath (GUnixVolumeMonitor *monitor,
const char *mount_path)
{
GList *l;
for (l = monitor->mounts; l != NULL; l = l->next)
{
GUnixMount *mount = l->data;
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);
}
}

View 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

View File

@ -18,46 +18,42 @@
* 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)
{
}
@ -119,26 +115,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,15 +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.
**/
GMount *
g_volume_get_mount (GVolume *volume)
{
GVolumeIface *iface;
g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
iface = G_VOLUME_GET_IFACE (volume);
return (* iface->get_mount) (volume);
}
/**
* g_volume_can_mount:
* @volume: a #GVolume.
*
* Checks if a volume can be mounted.
*
* Returns: %TRUE if the @volume can be mounted. %FALSE otherwise.
**/
gboolean
g_volume_can_unmount (GVolume *volume)
g_volume_can_mount (GVolume *volume)
{
GVolumeIface *iface;
@ -217,81 +214,62 @@ g_volume_can_unmount (GVolume *volume)
iface = G_VOLUME_GET_IFACE (volume);
return (* iface->can_unmount) (volume);
if (iface->can_mount == NULL)
return FALSE;
return (* iface->can_mount) (volume);
}
/**
* g_volume_can_eject:
* @volume: a #GVolume.
*
* Checks if @volume can be ejected.
*
* Returns: %TRUE if the @volume can be ejected.
**/
gboolean
g_volume_can_eject (GVolume *volume)
{
GVolumeIface *iface;
g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
iface = G_VOLUME_GET_IFACE (volume);
return (* iface->can_eject) (volume);
}
/**
* g_volume_unmount:
* g_volume_mount:
* @volume: a #GVolume.
* @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.
*
* 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.
* Mounts a volume.
**/
void
g_volume_unmount (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->unmount == 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 unmount"));
_("volume doesn't implement mount"));
return;
}
(* iface->unmount) (volume, cancellable, callback, user_data);
(* iface->mount_fn) (volume, mount_operation, cancellable, callback, user_data);
}
/**
* g_volume_unmount_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 unmounting a 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 unmounted. %FALSE otherwise.
* Returns: %TRUE, %FALSE if operation failed.
**/
gboolean
g_volume_unmount_finish (GVolume *volume,
GAsyncResult *result,
GError **error)
g_volume_mount_finish (GVolume *volume,
GAsyncResult *result,
GError **error)
{
GVolumeIface *iface;
@ -306,76 +284,7 @@ g_volume_unmount_finish (GVolume *volume,
}
iface = G_VOLUME_GET_IFACE (volume);
return (* iface->unmount_finish) (volume, result, error);
}
/**
* g_volume_eject:
* @volume: a #GVolume.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @callback: a #GAsyncReadyCallback.
* @user_data: user data passed to @callback.
*
* 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.
**/
void
g_volume_eject (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->eject == 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 eject"));
return;
}
(* iface->eject) (volume, cancellable, callback, user_data);
}
/**
* g_volume_eject_finish:
* @volume: a #GVolume.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
*
* Finishes ejecting the 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 ejected. %FALSE otherwise.
**/
gboolean
g_volume_eject_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->eject_finish) (volume, result, error);
return (* iface->mount_finish) (volume, result, error);
}
#define __G_VOLUME_C__

View 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

View File

@ -18,6 +18,7 @@
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
* David Zeuthen <davidz@redhat.com>
*/
#include <config.h>
@ -37,11 +38,16 @@
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.
**/
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);
/**
* GVolumeMonitor::volume-pre-unmount:
* @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);
/**
* GVolumeMonitor::volume-unmounted:
* @volume_monitor: The volume monitor emitting the signal.
* @volume: the volume that was unmounted.
* @volume: a #GVolume that was added.
*
* Emitted when a volume is unmounted.
* Emitted when a mountable volume is added to the system.
**/
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-removed:
* @volume_monitor: The volume monitor emitting the signal.
* @volume: a #GVolume that was removed.
*
* Emitted when a mountable volume is removed from the system.
**/
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_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-changed:
* @volume_monitor: The volume monitor emitting the signal.
* @volume: a #GVolume that changed.
*
* Emitted when mountable volume is changed.
**/
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,31 +229,12 @@ g_volume_monitor_init (GVolumeMonitor *monitor)
{
}
/**
* g_volume_monitor_get_mounted_volumes:
* @volume_monitor: a #GVolumeMonitor.
*
* Gets a list of volumes mounted on the computer.
*
* Returns: a #GList of mounted #GVolumes.
**/
GList *
g_volume_monitor_get_mounted_volumes (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_mounted_volumes (volume_monitor);
}
/**
* g_volume_monitor_get_connected_drives:
* g_volume_monitor_get_drives:
* @volume_monitor: a #GVolumeMonitor.
*
* Gets a list of drives connected to the computer.
* Gets a list of drives connected to the system.
*
* Returns: a #GList of connected #GDrives.
**/
@ -184,5 +250,45 @@ g_volume_monitor_get_connected_drives (GVolumeMonitor *volume_monitor)
return class->get_connected_drives (volume_monitor);
}
/**
* g_volume_monitor_get_volumes:
* @volume_monitor: a #GVolumeMonitor.
*
* Gets a list of the volumes on the system.
*
* Returns: a #GList of #GVolume.
**/
GList *
g_volume_monitor_get_volumes (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_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__
#include "gioaliasdef.c"

View File

@ -18,12 +18,14 @@
* 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