hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gio / gvolume.c
index 75304e2..a14cbc6 100644 (file)
  * 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.
+ * 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 "config.h"
 #include "gmount.h"
 #include "gvolume.h"
-#include "gsimpleasyncresult.h"
+#include "gthemedicon.h"
+#include "gasyncresult.h"
+#include "gtask.h"
+#include "gioerror.h"
 #include "glibintl.h"
 
-#include "gioalias.h"
 
 /**
- * SECTION:volume
- * @short_description: volume management
+ * SECTION:gvolume
+ * @short_description: Volume management
+ * @include: gio/gio.h
  * 
  * 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);
-
-GType
-g_volume_get_type (void)
-{
-  static GType volume_type = 0;
-
-  if (! volume_type)
-    {
-      static const GTypeInfo volume_info =
-      {
-        sizeof (GVolumeIface), /* class_size */
-       g_volume_base_init,   /* base_init */
-       NULL,           /* base_finalize */
-       g_volume_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       0,
-       0,              /* n_preallocs */
-       NULL
-      };
-
-      volume_type =
-       g_type_register_static (G_TYPE_INTERFACE, I_("GVolume"),
-                               &volume_info, 0);
-
-      g_type_interface_add_prerequisite (volume_type, G_TYPE_OBJECT);
-    }
-
-  return volume_type;
-}
+ * information about asynchronous operations, see #GAsyncResult and
+ * #GTask. To mount a #GVolume, first call g_volume_mount() with (at
+ * least) the #GVolume instance, optionally a #GMountOperation object
+ * and a #GAsyncReadyCallback.
+ *
+ * Typically, one will only want to pass %NULL for the
+ * #GMountOperation if automounting all volumes when a desktop session
+ * starts since it's not desirable to put up a lot of dialogs asking
+ * for credentials.
+ *
+ * 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.
+ *
+ * ## Volume Identifiers # {#volume-identifier}
+ *
+ * It is sometimes necessary to directly access the underlying
+ * operating system object behind a volume (e.g. for passing a volume
+ * to an application via the commandline). For this purpose, GIO
+ * allows to obtain an 'identifier' for the volume. There can be
+ * different kinds of identifiers, such as Hal UDIs, filesystem labels,
+ * traditional Unix devices (e.g. `/dev/sda2`), UUIDs. GIO uses predefined
+ * strings as names for the different kinds of identifiers:
+ * #G_VOLUME_IDENTIFIER_KIND_HAL_UDI, #G_VOLUME_IDENTIFIER_KIND_LABEL, etc.
+ * Use g_volume_get_identifier() to obtain an identifier for a volume.
+ *
+ *
+ * Note that #G_VOLUME_IDENTIFIER_KIND_HAL_UDI will only be available
+ * when the gvfs hal volume monitor is in use. Other volume monitors
+ * will generally be able to provide the #G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE
+ * identifier, which can be used to obtain a hal device by means of
+ * libhal_manager_find_device_string_match().
+ */
 
-static void
-g_volume_class_init (gpointer g_class,
-                     gpointer class_data)
-{
-}
+typedef GVolumeIface GVolumeInterface;
+G_DEFINE_INTERFACE(GVolume, g_volume, G_TYPE_OBJECT)
 
 static void
-g_volume_base_init (gpointer g_class)
+g_volume_default_init (GVolumeInterface *iface)
 {
-  static gboolean initialized = FALSE;
-
-  if (! initialized)
-    {
-     /**
-      * GVolume::changed:
-      * 
-      * Emitted when the volume has been changed.
-      **/
-      g_signal_new (I_("changed"),
-                    G_TYPE_VOLUME,
-                    G_SIGNAL_RUN_LAST,
-                    G_STRUCT_OFFSET (GVolumeIface, changed),
-                    NULL, NULL,
-                    g_cclosure_marshal_VOID__VOID,
-                    G_TYPE_NONE, 0);
-
-      initialized = TRUE;
-    }
+  /**
+   * GVolume::changed:
+   * 
+   * Emitted when the volume has been changed.
+   */
+  g_signal_new (I_("changed"),
+               G_TYPE_VOLUME,
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (GVolumeIface, changed),
+               NULL, NULL,
+               g_cclosure_marshal_VOID__VOID,
+               G_TYPE_NONE, 0);
+
+  /**
+   * GVolume::removed:
+   * 
+   * This signal is emitted when the #GVolume have been removed. If
+   * the recipient is holding references to the object they should
+   * release them so the object can be finalized.
+   */
+  g_signal_new (I_("removed"),
+               G_TYPE_VOLUME,
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (GVolumeIface, removed),
+               NULL, NULL,
+               g_cclosure_marshal_VOID__VOID,
+               G_TYPE_NONE, 0);
 }
 
 /**
  * g_volume_get_name:
- * @volume: a #GVolume.
+ * @volume: a #GVolume
  * 
  * Gets the name of @volume.
  * 
  * Returns: the name for the given @volume. The returned string should 
- * be freed when no longer needed.
- **/
+ *     be freed with g_free() when no longer needed.
+ */
 char *
 g_volume_get_name (GVolume *volume)
 {
@@ -138,12 +135,14 @@ g_volume_get_name (GVolume *volume)
 
 /**
  * g_volume_get_icon:
- * @volume: a #GVolume.
+ * @volume: a #GVolume
  * 
  * Gets the icon for @volume.
  * 
- * Returns: a #GIcon.
- **/
+ * Returns: (transfer full): a #GIcon.
+ *     The returned object should be unreffed with g_object_unref()
+ *     when no longer needed.
+ */
 GIcon *
 g_volume_get_icon (GVolume *volume)
 {
@@ -157,8 +156,39 @@ g_volume_get_icon (GVolume *volume)
 }
 
 /**
+ * g_volume_get_symbolic_icon:
+ * @volume: a #GVolume
+ * 
+ * Gets the symbolic icon for @volume.
+ * 
+ * Returns: (transfer full): a #GIcon.
+ *     The returned object should be unreffed with g_object_unref()
+ *     when no longer needed.
+ *
+ * Since: 2.34
+ */
+GIcon *
+g_volume_get_symbolic_icon (GVolume *volume)
+{
+  GVolumeIface *iface;
+  GIcon *ret;
+
+  g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
+
+  iface = G_VOLUME_GET_IFACE (volume);
+
+  if (iface->get_symbolic_icon != NULL)
+    ret = iface->get_symbolic_icon (volume);
+  else
+    ret = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic");
+
+  return ret;
+
+}
+
+/**
  * g_volume_get_uuid:
- * @volume: a #GVolume.
+ * @volume: a #GVolume
  * 
  * Gets the UUID for the @volume. The reference is typically based on
  * the file system UUID for the volume in question and should be
@@ -166,7 +196,9 @@ g_volume_get_icon (GVolume *volume)
  * available.
  * 
  * Returns: the UUID for @volume or %NULL if no UUID can be computed.
- **/
+ *     The returned string should be freed with g_free() 
+ *     when no longer needed.
+ */
 char *
 g_volume_get_uuid (GVolume *volume)
 {
@@ -181,12 +213,14 @@ g_volume_get_uuid (GVolume *volume)
   
 /**
  * g_volume_get_drive:
- * @volume: a #GVolume.
+ * @volume: a #GVolume
  * 
  * Gets the drive for the @volume.
  * 
- * Returns: a #GDrive or %NULL if @volume is not associated with a drive.
- **/
+ * Returns: (transfer full): a #GDrive or %NULL if @volume is not
+ *     associated with a drive. The returned object should be unreffed
+ *     with g_object_unref() when no longer needed.
+ */
 GDrive *
 g_volume_get_drive (GVolume *volume)
 {
@@ -201,12 +235,14 @@ g_volume_get_drive (GVolume *volume)
 
 /**
  * g_volume_get_mount:
- * @volume: a #GVolume.
+ * @volume: a #GVolume
  * 
  * Gets the mount for the @volume.
  * 
- * Returns: a #GMount or %NULL if @volume isn't mounted.
- **/
+ * Returns: (transfer full): a #GMount or %NULL if @volume isn't mounted.
+ *     The returned object should be unreffed with g_object_unref()
+ *     when no longer needed.
+ */
 GMount *
 g_volume_get_mount (GVolume *volume)
 {
@@ -222,12 +258,12 @@ g_volume_get_mount (GVolume *volume)
 
 /**
  * g_volume_can_mount:
- * @volume: a #GVolume.
+ * @volume: a #GVolume
  * 
  * Checks if a volume can be mounted.
  * 
- * Returns: %TRUE if the @volume can be mounted. %FALSE otherwise.
- **/
+ * Returns: %TRUE if the @volume can be mounted. %FALSE otherwise
+ */
 gboolean
 g_volume_can_mount (GVolume *volume)
 {
@@ -245,12 +281,12 @@ g_volume_can_mount (GVolume *volume)
 
 /**
  * g_volume_can_eject:
- * @volume: a #GVolume.
+ * @volume: a #GVolume
  * 
  * Checks if a volume can be ejected.
  * 
- * Returns: %TRUE if the @volume can be ejected. %FALSE otherwise.
- **/
+ * Returns: %TRUE if the @volume can be ejected. %FALSE otherwise
+ */
 gboolean
 g_volume_can_eject (GVolume *volume)
 {
@@ -267,17 +303,47 @@ g_volume_can_eject (GVolume *volume)
 }
 
 /**
+ * g_volume_should_automount:
+ * @volume: a #GVolume
+ *
+ * Returns whether the volume should be automatically mounted.
+ * 
+ * Returns: %TRUE if the volume should be automatically mounted
+ */
+gboolean
+g_volume_should_automount (GVolume *volume)
+{
+  GVolumeIface *iface;
+
+  g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
+
+  iface = G_VOLUME_GET_IFACE (volume);
+
+  if (iface->should_automount == NULL)
+    return FALSE;
+
+  return (* iface->should_automount) (volume);
+}
+
+
+/**
  * g_volume_mount:
- * @volume: a #GVolume.
- * @mount_operation: a #GMountOperation.
- * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @callback: a #GAsyncReadyCallback.
- * @user_data: a #gpointer.
+ * @volume: a #GVolume
+ * @flags: flags affecting the operation
+ * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid user interaction
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
+ * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL
+ * @user_data: user data that gets passed to @callback
  * 
- * Mounts a volume.
- **/
+ * Mounts a volume. This is an asynchronous operation, and is
+ * finished by calling g_volume_mount_finish() with the @volume
+ * and #GAsyncResult returned in the @callback.
+ *
+ * Virtual: mount_fn
+ */
 void
-g_volume_mount (GVolume    *volume,
+g_volume_mount (GVolume             *volume,
+               GMountMountFlags     flags,
                 GMountOperation     *mount_operation,
                 GCancellable        *cancellable,
                 GAsyncReadyCallback  callback,
@@ -286,48 +352,51 @@ g_volume_mount (GVolume    *volume,
   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->mount_fn == 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 mount"));
-      
+      g_task_report_new_error (volume, callback, user_data,
+                               g_volume_mount,
+                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                               _("volume doesn't implement mount"));
       return;
     }
   
-  (* iface->mount_fn) (volume, mount_operation, cancellable, callback, user_data);
+  (* iface->mount_fn) (volume, flags, mount_operation, cancellable, callback, user_data);
 }
 
 /**
  * g_volume_mount_finish:
- * @volume: pointer to a #GVolume.
- * @result: a #GAsyncResult.
- * @error: a #GError.
+ * @volume: a #GVolume
+ * @result: a #GAsyncResult
+ * @error: a #GError location to store an error, or %NULL to ignore
  * 
- * Finishes mounting a volume.
+ * Finishes mounting a volume. If any errors occurred during the operation,
+ * @error will be set to contain the errors and %FALSE will be returned.
+ *
+ * If the mount operation succeeded, g_volume_get_mount() on @volume
+ * is guaranteed to return the mount right after calling this
+ * function; there's no need to listen for the 'mount-added' signal on
+ * #GVolumeMonitor.
  * 
- * Returns: %TRUE, %FALSE if operation failed.
- **/
+ * Returns: %TRUE, %FALSE if operation failed
+ */
 gboolean
-g_volume_mount_finish (GVolume  *volume,
-                       GAsyncResult      *result,
-                       GError           **error)
+g_volume_mount_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;
-    }
+  if (g_async_result_legacy_propagate_error (result, error))
+    return FALSE;
+  else if (g_async_result_is_tagged (result, g_volume_mount))
+    return g_task_propagate_boolean (G_TASK (result), error);
   
   iface = G_VOLUME_GET_IFACE (volume);
   return (* iface->mount_finish) (volume, result, error);
@@ -335,15 +404,21 @@ g_volume_mount_finish (GVolume  *volume,
 
 /**
  * g_volume_eject:
- * @volume: a #GVolume.
- * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @callback: a #GAsyncReadyCallback.
- * @user_data: a #gpointer.
+ * @volume: a #GVolume
+ * @flags: flags affecting the unmount if required for eject
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
+ * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL
+ * @user_data: user data that gets passed to @callback
  * 
- * Ejects a volume.
- **/
+ * Ejects a volume. This is an asynchronous operation, and is
+ * finished by calling g_volume_eject_finish() with the @volume
+ * and #GAsyncResult returned in the @callback.
+ *
+ * Deprecated: 2.22: Use g_volume_eject_with_operation() instead.
+ */
 void
-g_volume_eject (GVolume    *volume,
+g_volume_eject (GVolume             *volume,
+               GMountUnmountFlags   flags,
                 GCancellable        *cancellable,
                 GAsyncReadyCallback  callback,
                 gpointer             user_data)
@@ -356,46 +431,256 @@ g_volume_eject (GVolume    *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"));
-      
+      g_task_report_new_error (volume, callback, user_data,
+                               g_volume_eject_with_operation,
+                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                               _("volume doesn't implement eject"));
       return;
     }
   
-  (* iface->eject) (volume, cancellable, callback, user_data);
+  (* iface->eject) (volume, flags, cancellable, callback, user_data);
 }
 
 /**
  * g_volume_eject_finish:
- * @volume: pointer to a #GVolume.
- * @result: a #GAsyncResult.
- * @error: a #GError.
+ * @volume: pointer to a #GVolume
+ * @result: a #GAsyncResult
+ * @error: a #GError location to store an error, or %NULL to ignore
  * 
- * Finishes ejecting a volume.
+ * Finishes ejecting a volume. If any errors occurred during the operation,
+ * @error will be set to contain the errors and %FALSE will be returned.
  * 
- * Returns: %TRUE, %FALSE if operation failed.
+ * Returns: %TRUE, %FALSE if operation failed
+ *
+ * Deprecated: 2.22: Use g_volume_eject_with_operation_finish() instead.
  **/
 gboolean
-g_volume_eject_finish (GVolume  *volume,
-                       GAsyncResult      *result,
-                       GError           **error)
+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))
+  if (g_async_result_legacy_propagate_error (result, error))
+    return FALSE;
+  if (g_async_result_is_tagged (result, g_volume_eject_with_operation))
+    return g_task_propagate_boolean (G_TASK (result), error);
+  
+  iface = G_VOLUME_GET_IFACE (volume);
+  return (* iface->eject_finish) (volume, result, error);
+}
+
+/**
+ * g_volume_eject_with_operation:
+ * @volume: a #GVolume
+ * @flags: flags affecting the unmount if required for eject
+ * @mount_operation: (allow-none): a #GMountOperation or %NULL to
+ *     avoid user interaction
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
+ * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL
+ * @user_data: user data passed to @callback
+ *
+ * Ejects a volume. This is an asynchronous operation, and is
+ * finished by calling g_volume_eject_with_operation_finish() with the @volume
+ * and #GAsyncResult data returned in the @callback.
+ *
+ * Since: 2.22
+ **/
+void
+g_volume_eject_with_operation (GVolume              *volume,
+                               GMountUnmountFlags   flags,
+                               GMountOperation     *mount_operation,
+                               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 && iface->eject_with_operation == NULL)
     {
-      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-      if (g_simple_async_result_propagate_error (simple, error))
-       return FALSE;
+      g_task_report_new_error (volume, callback, user_data,
+                               g_volume_eject_with_operation,
+                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                               /* Translators: This is an error
+                                * message for volume objects that
+                                * don't implement any of eject or eject_with_operation. */
+                               _("volume doesn't implement eject or eject_with_operation"));
+      return;
     }
+
+  if (iface->eject_with_operation != NULL)
+    (* iface->eject_with_operation) (volume, flags, mount_operation, cancellable, callback, user_data);
+  else
+    (* iface->eject) (volume, flags, cancellable, callback, user_data);
+}
+
+/**
+ * g_volume_eject_with_operation_finish:
+ * @volume: a #GVolume
+ * @result: a #GAsyncResult
+ * @error: a #GError location to store the error occurring, or %NULL
+ *
+ * Finishes ejecting a volume. If any errors occurred 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
+ *
+ * Since: 2.22
+ **/
+gboolean
+g_volume_eject_with_operation_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_async_result_legacy_propagate_error (result, error))
+    return FALSE;
+  else if (g_async_result_is_tagged (result, g_volume_eject_with_operation))
+    return g_task_propagate_boolean (G_TASK (result), error);
+
+  iface = G_VOLUME_GET_IFACE (volume);
+  if (iface->eject_with_operation_finish != NULL)
+    return (* iface->eject_with_operation_finish) (volume, result, error);
+  else
+    return (* iface->eject_finish) (volume, result, error);
+}
+
+/**
+ * g_volume_get_identifier:
+ * @volume: a #GVolume
+ * @kind: the kind of identifier to return
+ *
+ * Gets the identifier of the given kind for @volume. 
+ * See the [introduction][volume-identifier] for more
+ * information about volume identifiers.
+ *
+ * Returns: a newly allocated string containing the
+ *     requested identfier, or %NULL if the #GVolume
+ *     doesn't have this kind of identifier
+ */
+char *
+g_volume_get_identifier (GVolume    *volume,
+                        const char *kind)
+{
+  GVolumeIface *iface;
+
+  g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
+  g_return_val_if_fail (kind != NULL, NULL);
+
+  iface = G_VOLUME_GET_IFACE (volume);
+
+  if (iface->get_identifier == NULL)
+    return NULL;
   
+  return (* iface->get_identifier) (volume, kind);
+}
+
+/**
+ * g_volume_enumerate_identifiers:
+ * @volume: a #GVolume
+ * 
+ * Gets the kinds of [identifiers][volume-identifier] that @volume has.
+ * Use g_volume_get_identifier() to obtain the identifiers themselves.
+ *
+ * Returns: (array zero-terminated=1) (transfer full): a %NULL-terminated array
+ *   of strings containing kinds of identifiers. Use g_strfreev() to free.
+ */
+char **
+g_volume_enumerate_identifiers (GVolume *volume)
+{
+  GVolumeIface *iface;
+
+  g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
   iface = G_VOLUME_GET_IFACE (volume);
-  return (* iface->eject_finish) (volume, result, error);
+
+  if (iface->enumerate_identifiers == NULL)
+    return NULL;
+  
+  return (* iface->enumerate_identifiers) (volume);
+}
+
+/**
+ * g_volume_get_activation_root:
+ * @volume: a #GVolume
+ *
+ * Gets the activation root for a #GVolume if it is known ahead of
+ * mount time. Returns %NULL otherwise. If not %NULL and if @volume
+ * is mounted, then the result of g_mount_get_root() on the
+ * #GMount object obtained from g_volume_get_mount() will always
+ * either be equal or a prefix of what this function returns. In
+ * other words, in code
+ *
+ * |[<!-- language="C" -->
+ *   GMount *mount;
+ *   GFile *mount_root
+ *   GFile *volume_activation_root;
+ *
+ *   mount = g_volume_get_mount (volume); // mounted, so never NULL
+ *   mount_root = g_mount_get_root (mount);
+ *   volume_activation_root = g_volume_get_activation_root (volume); // assume not NULL
+ * ]|
+ * then the expression
+ * |[<!-- language="C" -->
+ *   (g_file_has_prefix (volume_activation_root, mount_root) ||
+      g_file_equal (volume_activation_root, mount_root))
+ * ]|
+ * will always be %TRUE.
+ *
+ * Activation roots are typically used in #GVolumeMonitor
+ * implementations to find the underlying mount to shadow, see
+ * g_mount_is_shadowed() for more details.
+ *
+ * Returns: (nullable) (transfer full): the activation root of @volume
+ *     or %NULL. Use g_object_unref() to free.
+ *
+ * Since: 2.18
+ */
+GFile *
+g_volume_get_activation_root (GVolume *volume)
+{
+  GVolumeIface *iface;
+
+  g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
+  iface = G_VOLUME_GET_IFACE (volume);
+
+  if (iface->get_activation_root == NULL)
+    return NULL;
+
+  return (* iface->get_activation_root) (volume);
 }
 
-#define __G_VOLUME_C__
-#include "gioaliasdef.c"
+/**
+ * g_volume_get_sort_key:
+ * @volume: a #GVolume
+ *
+ * Gets the sort key for @volume, if any.
+ *
+ * Returns: Sorting key for @volume or %NULL if no such key is available
+ *
+ * Since: 2.32
+ */
+const gchar *
+g_volume_get_sort_key (GVolume *volume)
+{
+  const gchar *ret = NULL;
+  GVolumeIface *iface;
+
+  g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
+
+  iface = G_VOLUME_GET_IFACE (volume);
+  if (iface->get_sort_key != NULL)
+    ret = iface->get_sort_key (volume);
+
+  return ret;
+}