From a95b7a3fab147ae79dccd8628576bae4cc82b438 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 1 Dec 2008 13:46:11 +0000 Subject: [PATCH] Add and document g_mount_is_shadowed plus calls to set/unset a mount as 2008-12-01 Alexander Larsson * gio.symbols: * gmount.[ch]: * gunionvolumemonitor.c: * gvolume.c: Add and document g_mount_is_shadowed plus calls to set/unset a mount as shadowed svn path=/trunk/; revision=7716 --- docs/reference/ChangeLog | 6 ++ docs/reference/gio/gio-sections.txt | 3 + gio/ChangeLog | 9 ++ gio/gio.symbols | 3 + gio/gmount.c | 134 ++++++++++++++++++++++++++++ gio/gmount.h | 8 +- gio/gunionvolumemonitor.c | 3 +- gio/gvolume.c | 34 +------ 8 files changed, 166 insertions(+), 34 deletions(-) diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 9c47c0269..041d58625 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,9 @@ +2008-12-01 Alexander Larsson + + Reviewed by NOBODY (OOPS!). + + * gio/gio-sections.txt: + 2008-11-30 Matthias Clasen * glib/running.sgml: Mention all and help special options in diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index c54272cf9..0e5dd4262 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -863,6 +863,9 @@ g_mount_eject_finish g_mount_guess_content_type g_mount_guess_content_type_finish g_mount_guess_content_type_sync +g_mount_is_shadowed +g_mount_shadow +g_mount_unshadow G_IS_MOUNT G_MOUNT diff --git a/gio/ChangeLog b/gio/ChangeLog index c1f38b84f..d4de9470d 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,3 +1,12 @@ +2008-12-01 Alexander Larsson + + * gio.symbols: + * gmount.[ch]: + * gunionvolumemonitor.c: + * gvolume.c: + Add and document g_mount_is_shadowed plus calls + to set/unset a mount as shadowed + 2008-11-28 Matthias Clasen * gio/tests/g-icon.c: Comment out two failing tests diff --git a/gio/gio.symbols b/gio/gio.symbols index 3be198820..625666681 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -727,6 +727,9 @@ g_mount_remount_finish g_mount_guess_content_type g_mount_guess_content_type_finish g_mount_guess_content_type_sync +g_mount_is_shadowed +g_mount_shadow +g_mount_unshadow #endif #endif diff --git a/gio/gmount.c b/gio/gmount.c index 3c8ae6182..dbdbeaf49 100644 --- a/gio/gmount.c +++ b/gio/gmount.c @@ -695,5 +695,139 @@ g_mount_guess_content_type_sync (GMount *mount, return (* iface->guess_content_type_sync) (mount, force_rescan, cancellable, error); } +G_LOCK_DEFINE_STATIC (priv_lock); + +/* only access this structure when holding priv_lock */ +typedef struct +{ + gint shadow_ref_count; +} GMountPrivate; + +static void +free_private (GMountPrivate *private) +{ + G_LOCK (priv_lock); + g_free (private); + G_UNLOCK (priv_lock); +} + +/* may only be called when holding priv_lock */ +static GMountPrivate * +get_private (GMount *mount) +{ + GMountPrivate *private; + + private = g_object_get_data (G_OBJECT (mount), "g-mount-private"); + if (G_LIKELY (private != NULL)) + goto out; + + private = g_new0 (GMountPrivate, 1); + g_object_set_data_full (G_OBJECT (mount), + "g-mount-private", + private, + (GDestroyNotify) free_private); + + out: + return private; +} + +/** + * g_mount_is_shadowed: + * @mount: A #GMount. + * + * Determines if @mount is shadowed. Applications or libraries should + * avoid displaying @mount in the user interface if it is shadowed. + * + * A mount is said to be shadowed if there exists one or more user + * visible objects (currently #GMount objects) with a root that is + * inside the root of @mount. + * + * One application of shadow mounts is when exposing a single file + * system that is used to address several logical volumes. In this + * situation, a #GVolumeMonitor implementation would create two + * #GVolume objects (for example, one for the camera functionality of + * the device and one for a SD card reader on the device) with + * activation URIs gphoto2://[usb:001,002]/store1/ + * and gphoto2://[usb:001,002]/store2/. When the + * underlying mount (with root + * gphoto2://[usb:001,002]/) is mounted, said + * #GVolumeMonitor implementation would create two #GMount objects + * (each with their root matching the corresponding volume activation + * root) that would shadow the original mount. + * + * The proxy monitor in GVfs 2.26 and later, automatically creates and + * manage shadow mounts (and shadows the underlying mount) if the + * activation root on a #GVolume is set. + * + * Returns: %TRUE if @mount is shadowed. + * + * Since: 2.20 + **/ +gboolean +g_mount_is_shadowed (GMount *mount) +{ + GMountPrivate *priv; + gboolean ret; + + g_return_val_if_fail (G_IS_MOUNT (mount), FALSE); + + G_LOCK (priv_lock); + priv = get_private (mount); + ret = (priv->shadow_ref_count > 0); + G_UNLOCK (priv_lock); + + return ret; +} + +/** + * g_mount_shadow: + * @mount: A #GMount. + * + * Increments the shadow count on @mount. Usually used by + * #GVolumeMonitor implementations when creating a shadow mount for + * @mount, see g_mount_is_shadowed() for more information. The caller + * will need to emit the #GMount::changed signal on @mount manually. + * + * Since: 2.20 + **/ +void +g_mount_shadow (GMount *mount) +{ + GMountPrivate *priv; + + g_return_if_fail (G_IS_MOUNT (mount)); + + G_LOCK (priv_lock); + priv = get_private (mount); + priv->shadow_ref_count += 1; + G_UNLOCK (priv_lock); +} + +/** + * g_mount_unshadow: + * @mount: A #GMount. + * + * Decrements the shadow count on @mount. Usually used by + * #GVolumeMonitor implementations when destroying a shadow mount for + * @mount, see g_mount_is_shadowed() for more information. The caller + * will need to emit the #GMount::changed signal on @mount manually. + * + * Since: 2.20 + **/ +void +g_mount_unshadow (GMount *mount) +{ + GMountPrivate *priv; + + g_return_if_fail (G_IS_MOUNT (mount)); + + G_LOCK (priv_lock); + priv = get_private (mount); + priv->shadow_ref_count -= 1; + if (priv->shadow_ref_count < 0) + g_warning ("Shadow ref count on GMount is negative"); + G_UNLOCK (priv_lock); +} + #define __G_MOUNT_C__ #include "gioaliasdef.c" diff --git a/gio/gmount.h b/gio/gmount.h index 66304bf7b..027960d5a 100644 --- a/gio/gmount.h +++ b/gio/gmount.h @@ -61,8 +61,8 @@ typedef struct _GMountIface GMountIface; * @guess_content_type: Starts guessing the type of the content of a #GMount. * See g_mount_guess_content_type() for more information on content * type guessing. This operation was added in 2.18. - * @guess_content_type_finish: Finishes a contenet type guessing operation. - * @guess_content_type_sync: Synchronous variant of @guess_content_type. + * @guess_content_type_finish: Finishes a contenet type guessing operation. Added in 2.18. + * @guess_content_type_sync: Synchronous variant of @guess_content_type. Added in 2.18 * * Interface for implementing operations for mounts. **/ @@ -180,6 +180,10 @@ gchar ** g_mount_guess_content_type_sync (GMount *mount, GCancellable *cancellable, GError **error); +gboolean g_mount_is_shadowed (GMount *mount); +void g_mount_shadow (GMount *mount); +void g_mount_unshadow (GMount *mount); + G_END_DECLS #endif /* __G_MOUNT_H__ */ diff --git a/gio/gunionvolumemonitor.c b/gio/gunionvolumemonitor.c index f12ecd905..1b5bafd6f 100644 --- a/gio/gunionvolumemonitor.c +++ b/gio/gunionvolumemonitor.c @@ -638,7 +638,8 @@ _g_mount_get_for_mount_path (const char *mount_path, * Deprecated: 2.20: Instead of using this function, #GVolumeMonitor * implementations should instead create shadow mounts with the URI of * the mount they intend to adopt. See the proxy volume monitor in - * gvfs for an example of this. + * gvfs for an example of this. Also see g_mount_is_shadowed(), + * g_mount_shadow() and g_mount_unshadow() functions. */ GVolume * g_volume_monitor_adopt_orphan_mount (GMount *mount) diff --git a/gio/gvolume.c b/gio/gvolume.c index 7607b4290..ef550d822 100644 --- a/gio/gvolume.c +++ b/gio/gvolume.c @@ -566,37 +566,9 @@ g_volume_enumerate_identifiers (GVolume *volume) * * will always be %TRUE. * - * There is a number of possible uses of this function. - * - * First, implementations of #GVolumeMonitor can use this method to - * determine if a #GMount should be adopted in the implementation of - * g_volume_monitor_adopt_orphan_mount() by testing if the result of - * this function equals (or has as prefix) the root of the given - * #GMount. In particular this is useful in the in-process proxy part - * of an out-of-process volume monitor implementation. - * - * Second, applications such as a file manager can use this to - * navigate to the correct root in response to the user navigating to - * a server. Now suppose there is a volume monitor for networked - * servers that creates #GVolume objects corresponding to the - * "favorite servers" (e.g. set up by the user via some "Connect to - * Server" dialog). Suppose also that one of the favorite servers is - * named "public_html @ fd.o" and the URI is - * sftp://people.freedesktop.org/home/david/public_html. - * - * Now, due to the way GIO works, when the corresponding #GVolume is - * mounted then a #GMount (typically adopted by the volume monitor) - * will appear with the mount root (e.g. the result of - * g_mount_get_root()) - * sftp://people.freedesktop.org. However, this - * function (g_volume_get_activation_root()) can return a #GFile for - * the URI - * sftp://people.freedesktop.org/home/david/public_html. - * - * All this means that a file manager can use the latter URI for - * navigating when the user clicks an icon representing the #GVolume - * (e.g. clicking an icon with the name "public_html @ fd.o" or - * similar). + * Activation roots are typically used in #GVolumeMonitor + * implementations to find the underlying mount to shadow, see + * g_mount_is_shadowed() for more details. * * Returns: the activation root of @volume or %NULL. Use * g_object_unref() to free.