glib/gio/gmount.c

1058 lines
32 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2008 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Author: Alexander Larsson <alexl@redhat.com>
* David Zeuthen <davidz@redhat.com>
*/
#include "config.h"
#include <string.h>
#include "gmount.h"
#include "gmountprivate.h"
#include "gthemedicon.h"
#include "gasyncresult.h"
#include "gtask.h"
#include "gioerror.h"
#include "glibintl.h"
/**
* SECTION:gmount
* @short_description: Mount management
* @include: gio/gio.h
* @see_also: GVolume, GUnixMountEntry, GUnixMountPoint
*
* The #GMount interface represents user-visible mounts. Note, when
* porting from GnomeVFS, #GMount is the moral equivalent of #GnomeVFSVolume.
*
* #GMount is a "mounted" filesystem that you can access. Mounted is in
* quotes because it's not the same as a unix mount, it might be a gvfs
* mount, but you can still access the files on it if you use GIO. Might or
* might not be related to a volume object.
*
* Unmounting a #GMount instance is an asynchronous operation. For
* more information about asynchronous operations, see #GAsyncResult
* and #GTask. To unmount a #GMount instance, first call
* g_mount_unmount_with_operation() 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_with_operation_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_with_operation_finish()
* is called, then it will be filled with any error information.
**/
typedef GMountIface GMountInterface;
G_DEFINE_INTERFACE (GMount, g_mount, G_TYPE_OBJECT)
static void
g_mount_default_init (GMountInterface *iface)
{
/**
* GMount::changed:
* @mount: the object on which the signal is emitted
*
* 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);
/**
* GMount::unmounted:
* @mount: the object on which the signal is emitted
*
* This signal is emitted when the #GMount have been
* unmounted. If the recipient is holding references to the
* object they should release them so the object can be
* finalized.
**/
g_signal_new (I_("unmounted"),
G_TYPE_MOUNT,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GMountIface, unmounted),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* GMount::pre-unmount:
* @mount: the object on which the signal is emitted
*
* This signal may be emitted when the #GMount is about to be
* unmounted.
*
* This signal depends on the backend and is only emitted if
* GIO was used to unmount.
*
* Since: 2.22
**/
g_signal_new (I_("pre-unmount"),
G_TYPE_MOUNT,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GMountIface, pre_unmount),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
/**
* g_mount_get_root:
* @mount: a #GMount.
*
* Gets the root directory on @mount.
*
* Returns: (transfer full): a #GFile.
* The returned object should be unreffed with
* g_object_unref() when no longer needed.
**/
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_default_location:
* @mount: a #GMount.
*
* Gets the default location of @mount. The default location of the given
* @mount is a path that reflects the main entry point for the user (e.g.
* the home directory, or the root of the volume).
*
* Returns: (transfer full): a #GFile.
* The returned object should be unreffed with
* g_object_unref() when no longer needed.
**/
GFile *
g_mount_get_default_location (GMount *mount)
{
GMountIface *iface;
GFile *file;
g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
iface = G_MOUNT_GET_IFACE (mount);
/* Fallback to get_root when default_location () is not available */
if (iface->get_default_location)
file = (* iface->get_default_location) (mount);
else
file = (* iface->get_root) (mount);
return file;
}
/**
* 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 with g_free()
* 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: (transfer full): a #GIcon.
* The returned object should be unreffed with
* g_object_unref() when no longer needed.
**/
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_symbolic_icon:
* @mount: a #GMount.
*
* Gets the symbolic icon for @mount.
*
* Returns: (transfer full): a #GIcon.
* The returned object should be unreffed with
* g_object_unref() when no longer needed.
*
* Since: 2.34
**/
GIcon *
g_mount_get_symbolic_icon (GMount *mount)
{
GMountIface *iface;
GIcon *ret;
g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
iface = G_MOUNT_GET_IFACE (mount);
if (iface->get_symbolic_icon != NULL)
ret = iface->get_symbolic_icon (mount);
else
ret = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic");
return ret;
}
/**
* g_mount_get_uuid:
* @mount: a #GMount.
*
* Gets the UUID for the @mount. The reference is typically based on
* the file system UUID for the mount in question and should be
* considered an opaque string. Returns %NULL if there is no UUID
* available.
*
* Returns: the UUID for @mount or %NULL if no UUID can be computed.
* The returned string should be freed with g_free()
* when no longer needed.
**/
char *
g_mount_get_uuid (GMount *mount)
{
GMountIface *iface;
g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
iface = G_MOUNT_GET_IFACE (mount);
return (* iface->get_uuid) (mount);
}
/**
* g_mount_get_volume:
* @mount: a #GMount.
*
* Gets the volume for the @mount.
*
* Returns: (transfer full): a #GVolume or %NULL if @mount is not associated with a volume.
* The returned object should be unreffed with
* g_object_unref() when no longer needed.
**/
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: (transfer full): a #GDrive or %NULL if @mount is not associated with a volume or a drive.
* The returned object should be unreffed with
* g_object_unref() when no longer needed.
**/
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 unmounted.
*
* 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_can_eject:
* @mount: a #GMount.
*
* Checks if @mount can be ejected.
*
* Returns: %TRUE if the @mount can be ejected.
**/
gboolean
g_mount_can_eject (GMount *mount)
{
GMountIface *iface;
g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
iface = G_MOUNT_GET_IFACE (mount);
return (* iface->can_eject) (mount);
}
/**
* g_mount_unmount:
* @mount: a #GMount.
* @flags: flags affecting the operation
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
* @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
* @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 #GAsyncResult data returned in the @callback.
*
* Deprecated: 2.22: Use g_mount_unmount_with_operation() instead.
**/
void
g_mount_unmount (GMount *mount,
GMountUnmountFlags flags,
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_task_report_new_error (mount, callback, user_data,
g_mount_unmount_with_operation,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
/* Translators: This is an error
* message for mount objects that
* don't implement unmount. */
_("mount doesnt implement “unmount”"));
return;
}
(* iface->unmount) (mount, flags, cancellable, callback, user_data);
}
/**
* g_mount_unmount_finish:
* @mount: a #GMount.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occurring, or %NULL to
* ignore.
*
* Finishes unmounting a mount. If any errors occurred 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.
*
* Deprecated: 2.22: Use g_mount_unmount_with_operation_finish() instead.
**/
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_async_result_legacy_propagate_error (result, error))
return FALSE;
else if (g_async_result_is_tagged (result, g_mount_unmount_with_operation))
return g_task_propagate_boolean (G_TASK (result), error);
iface = G_MOUNT_GET_IFACE (mount);
return (* iface->unmount_finish) (mount, result, error);
}
/**
* g_mount_eject:
* @mount: a #GMount.
* @flags: flags affecting the unmount if required for eject
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
* @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
* @user_data: user data passed to @callback.
*
* Ejects a mount. This is an asynchronous operation, and is
* finished by calling g_mount_eject_finish() with the @mount
* and #GAsyncResult data returned in the @callback.
*
* Deprecated: 2.22: Use g_mount_eject_with_operation() instead.
**/
void
g_mount_eject (GMount *mount,
GMountUnmountFlags flags,
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->eject == NULL)
{
g_task_report_new_error (mount, callback, user_data,
g_mount_eject_with_operation,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
/* Translators: This is an error
* message for mount objects that
* don't implement eject. */
_("mount doesnt implement “eject”"));
return;
}
(* iface->eject) (mount, flags, cancellable, callback, user_data);
}
/**
* g_mount_eject_finish:
* @mount: a #GMount.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occurring, or %NULL to
* ignore.
*
* Finishes ejecting a mount. If any errors occurred during the operation,
* @error will be set to contain the errors and %FALSE will be returned.
*
* Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
*
* Deprecated: 2.22: Use g_mount_eject_with_operation_finish() instead.
**/
gboolean
g_mount_eject_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_async_result_legacy_propagate_error (result, error))
return FALSE;
else if (g_async_result_is_tagged (result, g_mount_eject_with_operation))
return g_task_propagate_boolean (G_TASK (result), error);
iface = G_MOUNT_GET_IFACE (mount);
return (* iface->eject_finish) (mount, result, error);
}
/**
* g_mount_unmount_with_operation:
* @mount: a #GMount.
* @flags: flags affecting the operation
* @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
* user interaction.
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
* @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
* @user_data: user data passed to @callback.
*
* Unmounts a mount. This is an asynchronous operation, and is
* finished by calling g_mount_unmount_with_operation_finish() with the @mount
* and #GAsyncResult data returned in the @callback.
*
* Since: 2.22
**/
void
g_mount_unmount_with_operation (GMount *mount,
GMountUnmountFlags flags,
GMountOperation *mount_operation,
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 && iface->unmount_with_operation == NULL)
{
g_task_report_new_error (mount, callback, user_data,
g_mount_unmount_with_operation,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
/* Translators: This is an error
* message for mount objects that
* don't implement any of unmount or unmount_with_operation. */
_("mount doesnt implement “unmount” or “unmount_with_operation”"));
return;
}
if (iface->unmount_with_operation != NULL)
(* iface->unmount_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
else
(* iface->unmount) (mount, flags, cancellable, callback, user_data);
}
/**
* g_mount_unmount_with_operation_finish:
* @mount: a #GMount.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occurring, or %NULL to
* ignore.
*
* Finishes unmounting a mount. If any errors occurred 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.
*
* Since: 2.22
**/
gboolean
g_mount_unmount_with_operation_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_async_result_legacy_propagate_error (result, error))
return FALSE;
else if (g_async_result_is_tagged (result, g_mount_unmount_with_operation))
return g_task_propagate_boolean (G_TASK (result), error);
iface = G_MOUNT_GET_IFACE (mount);
if (iface->unmount_with_operation_finish != NULL)
return (* iface->unmount_with_operation_finish) (mount, result, error);
else
return (* iface->unmount_finish) (mount, result, error);
}
/**
* g_mount_eject_with_operation:
* @mount: a #GMount.
* @flags: flags affecting the unmount if required for eject
* @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
* user interaction.
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
* @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
* @user_data: user data passed to @callback.
*
* Ejects a mount. This is an asynchronous operation, and is
* finished by calling g_mount_eject_with_operation_finish() with the @mount
* and #GAsyncResult data returned in the @callback.
*
* Since: 2.22
**/
void
g_mount_eject_with_operation (GMount *mount,
GMountUnmountFlags flags,
GMountOperation *mount_operation,
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->eject == NULL && iface->eject_with_operation == NULL)
{
g_task_report_new_error (mount, callback, user_data,
g_mount_eject_with_operation,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
/* Translators: This is an error
* message for mount objects that
* don't implement any of eject or eject_with_operation. */
_("mount doesnt implement “eject” or “eject_with_operation”"));
return;
}
if (iface->eject_with_operation != NULL)
(* iface->eject_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
else
(* iface->eject) (mount, flags, cancellable, callback, user_data);
}
/**
* g_mount_eject_with_operation_finish:
* @mount: a #GMount.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occurring, or %NULL to
* ignore.
*
* Finishes ejecting a mount. If any errors occurred during the operation,
* @error will be set to contain the errors and %FALSE will be returned.
*
* Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
*
* Since: 2.22
**/
gboolean
g_mount_eject_with_operation_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_async_result_legacy_propagate_error (result, error))
return FALSE;
else if (g_async_result_is_tagged (result, g_mount_eject_with_operation))
return g_task_propagate_boolean (G_TASK (result), error);
iface = G_MOUNT_GET_IFACE (mount);
if (iface->eject_with_operation_finish != NULL)
return (* iface->eject_with_operation_finish) (mount, result, error);
else
return (* iface->eject_finish) (mount, result, error);
}
/**
* g_mount_remount:
* @mount: a #GMount.
* @flags: flags affecting the operation
* @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
* user interaction.
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
* @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
* @user_data: user data passed to @callback.
*
* Remounts a mount. This is an asynchronous operation, and is
* finished by calling g_mount_remount_finish() with the @mount
* and #GAsyncResults data returned in the @callback.
*
* Remounting is useful when some setting affecting the operation
* of the volume has been changed, as these may need a remount to
* take affect. While this is semantically equivalent with unmounting
* and then remounting not all backends might need to actually be
* unmounted.
**/
void
g_mount_remount (GMount *mount,
GMountMountFlags flags,
GMountOperation *mount_operation,
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->remount == NULL)
{
g_task_report_new_error (mount, callback, user_data,
g_mount_remount,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
/* Translators: This is an error
* message for mount objects that
* don't implement remount. */
_("mount doesnt implement “remount”"));
return;
}
(* iface->remount) (mount, flags, mount_operation, cancellable, callback, user_data);
}
/**
* g_mount_remount_finish:
* @mount: a #GMount.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occurring, or %NULL to
* ignore.
*
* Finishes remounting a mount. If any errors occurred during the operation,
* @error will be set to contain the errors and %FALSE will be returned.
*
* Returns: %TRUE if the mount was successfully remounted. %FALSE otherwise.
**/
gboolean
g_mount_remount_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_async_result_legacy_propagate_error (result, error))
return FALSE;
else if (g_async_result_is_tagged (result, g_mount_remount))
return g_task_propagate_boolean (G_TASK (result), error);
iface = G_MOUNT_GET_IFACE (mount);
return (* iface->remount_finish) (mount, result, error);
}
/**
* g_mount_guess_content_type:
* @mount: a #GMount
* @force_rescan: Whether to force a rescan of the content.
* Otherwise a cached result will be used if available
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
* @callback: a #GAsyncReadyCallback
* @user_data: user data passed to @callback
*
* Tries to guess the type of content stored on @mount. Returns one or
* more textual identifiers of well-known content types (typically
* prefixed with "x-content/"), e.g. x-content/image-dcf for camera
* memory cards. See the
* [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec)
* specification for more on x-content types.
*
* This is an asynchronous operation (see
* g_mount_guess_content_type_sync() for the synchronous version), and
* is finished by calling g_mount_guess_content_type_finish() with the
* @mount and #GAsyncResult data returned in the @callback.
*
* Since: 2.18
*/
void
g_mount_guess_content_type (GMount *mount,
gboolean force_rescan,
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->guess_content_type == NULL)
{
g_task_report_new_error (mount, callback, user_data,
g_mount_guess_content_type,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
/* Translators: This is an error
* message for mount objects that
* don't implement content type guessing. */
_("mount doesnt implement content type guessing"));
return;
}
(* iface->guess_content_type) (mount, force_rescan, cancellable, callback, user_data);
}
/**
* g_mount_guess_content_type_finish:
* @mount: a #GMount
* @result: a #GAsyncResult
* @error: a #GError location to store the error occurring, or %NULL to
* ignore
*
* Finishes guessing content types of @mount. If any errors occurred
* during the operation, @error will be set to contain the errors and
* %FALSE will be returned. In particular, you may get an
* %G_IO_ERROR_NOT_SUPPORTED if the mount does not support content
* guessing.
*
* Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error.
* Caller should free this array with g_strfreev() when done with it.
*
* Since: 2.18
**/
gchar **
g_mount_guess_content_type_finish (GMount *mount,
GAsyncResult *result,
GError **error)
{
GMountIface *iface;
g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
if (g_async_result_legacy_propagate_error (result, error))
return NULL;
else if (g_async_result_is_tagged (result, g_mount_guess_content_type))
return g_task_propagate_pointer (G_TASK (result), error);
iface = G_MOUNT_GET_IFACE (mount);
return (* iface->guess_content_type_finish) (mount, result, error);
}
/**
* g_mount_guess_content_type_sync:
* @mount: a #GMount
* @force_rescan: Whether to force a rescan of the content.
* Otherwise a cached result will be used if available
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
* @error: a #GError location to store the error occurring, or %NULL to
* ignore
*
* Tries to guess the type of content stored on @mount. Returns one or
* more textual identifiers of well-known content types (typically
* prefixed with "x-content/"), e.g. x-content/image-dcf for camera
* memory cards. See the
* [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec)
* specification for more on x-content types.
*
* This is an synchronous operation and as such may block doing IO;
* see g_mount_guess_content_type() for the asynchronous version.
*
* Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error.
* Caller should free this array with g_strfreev() when done with it.
*
* Since: 2.18
*/
char **
g_mount_guess_content_type_sync (GMount *mount,
gboolean force_rescan,
GCancellable *cancellable,
GError **error)
{
GMountIface *iface;
g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
iface = G_MOUNT_GET_IFACE (mount);
if (iface->guess_content_type_sync == NULL)
{
g_set_error_literal (error,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
/* Translators: This is an error
* message for mount objects that
* don't implement content type guessing. */
_("mount doesnt implement synchronous content type guessing"));
return NULL;
}
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);
}
/**
* g_mount_get_sort_key:
* @mount: A #GMount.
*
* Gets the sort key for @mount, if any.
*
* Returns: Sorting key for @mount or %NULL if no such key is available.
*
* Since: 2.32
*/
const gchar *
g_mount_get_sort_key (GMount *mount)
{
const gchar *ret = NULL;
GMountIface *iface;
g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
iface = G_MOUNT_GET_IFACE (mount);
if (iface->get_sort_key != NULL)
ret = iface->get_sort_key (mount);
return ret;
}