(root)/
glib-2.79.0/
gio/
gmount.c
       1  /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
       2  
       3  /* GIO - GLib Input, Output and Streaming Library
       4   * 
       5   * Copyright (C) 2006-2008 Red Hat, Inc.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   *
       9   * This library is free software; you can redistribute it and/or
      10   * modify it under the terms of the GNU Lesser General Public
      11   * License as published by the Free Software Foundation; either
      12   * version 2.1 of the License, or (at your option) any later version.
      13   *
      14   * This library is distributed in the hope that it will be useful,
      15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17   * Lesser General Public License for more details.
      18   *
      19   * You should have received a copy of the GNU Lesser General
      20   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      21   *
      22   * Author: Alexander Larsson <alexl@redhat.com>
      23   *         David Zeuthen <davidz@redhat.com>
      24   */
      25  
      26  #include "config.h"
      27  
      28  #include <string.h>
      29  
      30  #include "gmount.h"
      31  #include "gmountprivate.h"
      32  #include "gthemedicon.h"
      33  #include "gasyncresult.h"
      34  #include "gtask.h"
      35  #include "gioerror.h"
      36  #include "glibintl.h"
      37  
      38  
      39  /**
      40   * GMount:
      41   *
      42   * The `GMount` interface represents user-visible mounts. Note, when
      43   * [porting from GnomeVFS](migrating-gnome-vfs.html), `GMount` is the moral
      44   * equivalent of `GnomeVFSVolume`.
      45   *
      46   * `GMount` is a ‘mounted’ filesystem that you can access. Mounted is in
      47   * quotes because it’s not the same as a UNIX mount, it might be a GVFS
      48   * mount, but you can still access the files on it if you use GIO. Might or
      49   * might not be related to a volume object.
      50   * 
      51   * Unmounting a `GMount` instance is an asynchronous operation. For
      52   * more information about asynchronous operations, see [iface@Gio.AsyncResult]
      53   * and [class@Gio.Task]. To unmount a `GMount` instance, first call
      54   * [method@Gio.Mount.unmount_with_operation] with (at least) the `GMount`
      55   * instance and a [type@Gio.AsyncReadyCallback].  The callback will be fired
      56   * when the operation has resolved (either with success or failure), and a
      57   * [iface@Gio.AsyncResult] structure will be passed to the callback.  That
      58   * callback should then call [method@Gio.Mount.unmount_with_operation_finish]
      59   * with the `GMount` and the [iface@Gio.AsyncResult] data to see if the
      60   * operation was completed successfully.  If an `error` is present when
      61   * [method@Gio.Mount.unmount_with_operation_finish] is called, then it will be
      62   * filled with any error information.
      63   **/
      64  
      65  typedef GMountIface GMountInterface;
      66  G_DEFINE_INTERFACE (GMount, g_mount, G_TYPE_OBJECT)
      67  
      68  static void
      69  g_mount_default_init (GMountInterface *iface)
      70  {
      71    /**
      72     * GMount::changed:
      73     * @mount: the object on which the signal is emitted
      74     *
      75     * Emitted when the mount has been changed.
      76     **/
      77    g_signal_new (I_("changed"),
      78                  G_TYPE_MOUNT,
      79                  G_SIGNAL_RUN_LAST,
      80                  G_STRUCT_OFFSET (GMountIface, changed),
      81                  NULL, NULL,
      82                  NULL,
      83                  G_TYPE_NONE, 0);
      84  
      85    /**
      86     * GMount::unmounted:
      87     * @mount: the object on which the signal is emitted
      88     *
      89     * This signal is emitted when the #GMount have been
      90     * unmounted. If the recipient is holding references to the
      91     * object they should release them so the object can be
      92     * finalized.
      93     **/
      94    g_signal_new (I_("unmounted"),
      95                  G_TYPE_MOUNT,
      96                  G_SIGNAL_RUN_LAST,
      97                  G_STRUCT_OFFSET (GMountIface, unmounted),
      98                  NULL, NULL,
      99                  NULL,
     100                  G_TYPE_NONE, 0);
     101    /**
     102     * GMount::pre-unmount:
     103     * @mount: the object on which the signal is emitted
     104     *
     105     * This signal may be emitted when the #GMount is about to be
     106     * unmounted.
     107     *
     108     * This signal depends on the backend and is only emitted if
     109     * GIO was used to unmount.
     110     *
     111     * Since: 2.22
     112     **/
     113    g_signal_new (I_("pre-unmount"),
     114                  G_TYPE_MOUNT,
     115                  G_SIGNAL_RUN_LAST,
     116                  G_STRUCT_OFFSET (GMountIface, pre_unmount),
     117                  NULL, NULL,
     118                  NULL,
     119                  G_TYPE_NONE, 0);
     120  }
     121  
     122  /**
     123   * g_mount_get_root:
     124   * @mount: a #GMount.
     125   * 
     126   * Gets the root directory on @mount.
     127   * 
     128   * Returns: (transfer full): a #GFile. 
     129   *      The returned object should be unreffed with 
     130   *      g_object_unref() when no longer needed.
     131   **/
     132  GFile *
     133  g_mount_get_root (GMount *mount)
     134  {
     135    GMountIface *iface;
     136  
     137    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     138  
     139    iface = G_MOUNT_GET_IFACE (mount);
     140  
     141    return (* iface->get_root) (mount);
     142  }
     143  
     144  /**
     145   * g_mount_get_default_location:
     146   * @mount: a #GMount.
     147   *
     148   * Gets the default location of @mount. The default location of the given
     149   * @mount is a path that reflects the main entry point for the user (e.g.
     150   * the home directory, or the root of the volume).
     151   *
     152   * Returns: (transfer full): a #GFile.
     153   *      The returned object should be unreffed with
     154   *      g_object_unref() when no longer needed.
     155   **/
     156  GFile *
     157  g_mount_get_default_location (GMount *mount)
     158  {
     159    GMountIface *iface;
     160    GFile       *file;
     161  
     162    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     163  
     164    iface = G_MOUNT_GET_IFACE (mount);
     165    
     166    /* Fallback to get_root when default_location () is not available */
     167    if (iface->get_default_location)
     168      file = (* iface->get_default_location) (mount);
     169    else
     170      file = (* iface->get_root) (mount);
     171  
     172    return file;
     173  }
     174  
     175  /**
     176   * g_mount_get_name:
     177   * @mount: a #GMount.
     178   * 
     179   * Gets the name of @mount.
     180   * 
     181   * Returns: the name for the given @mount. 
     182   *     The returned string should be freed with g_free()
     183   *     when no longer needed.
     184   **/
     185  char *
     186  g_mount_get_name (GMount *mount)
     187  {
     188    GMountIface *iface;
     189  
     190    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     191  
     192    iface = G_MOUNT_GET_IFACE (mount);
     193  
     194    return (* iface->get_name) (mount);
     195  }
     196  
     197  /**
     198   * g_mount_get_icon:
     199   * @mount: a #GMount.
     200   * 
     201   * Gets the icon for @mount.
     202   * 
     203   * Returns: (transfer full): a #GIcon.
     204   *      The returned object should be unreffed with 
     205   *      g_object_unref() when no longer needed.
     206   **/
     207  GIcon *
     208  g_mount_get_icon (GMount *mount)
     209  {
     210    GMountIface *iface;
     211  
     212    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     213  
     214    iface = G_MOUNT_GET_IFACE (mount);
     215  
     216    return (* iface->get_icon) (mount);
     217  }
     218  
     219  
     220  /**
     221   * g_mount_get_symbolic_icon:
     222   * @mount: a #GMount.
     223   * 
     224   * Gets the symbolic icon for @mount.
     225   * 
     226   * Returns: (transfer full): a #GIcon.
     227   *      The returned object should be unreffed with 
     228   *      g_object_unref() when no longer needed.
     229   *
     230   * Since: 2.34
     231   **/
     232  GIcon *
     233  g_mount_get_symbolic_icon (GMount *mount)
     234  {
     235    GMountIface *iface;
     236    GIcon *ret;
     237  
     238    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     239  
     240    iface = G_MOUNT_GET_IFACE (mount);
     241  
     242    if (iface->get_symbolic_icon != NULL)
     243      ret = iface->get_symbolic_icon (mount);
     244    else
     245      ret = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic");
     246  
     247    return ret;
     248  }
     249  
     250  /**
     251   * g_mount_get_uuid:
     252   * @mount: a #GMount.
     253   * 
     254   * Gets the UUID for the @mount. The reference is typically based on
     255   * the file system UUID for the mount in question and should be
     256   * considered an opaque string. Returns %NULL if there is no UUID
     257   * available.
     258   * 
     259   * Returns: (nullable) (transfer full): the UUID for @mount or %NULL if no UUID
     260   *     can be computed.
     261   *     The returned string should be freed with g_free()
     262   *     when no longer needed.
     263   **/
     264  char *
     265  g_mount_get_uuid (GMount *mount)
     266  {
     267    GMountIface *iface;
     268  
     269    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     270  
     271    iface = G_MOUNT_GET_IFACE (mount);
     272  
     273    return (* iface->get_uuid) (mount);
     274  }
     275  
     276  /**
     277   * g_mount_get_volume:
     278   * @mount: a #GMount.
     279   * 
     280   * Gets the volume for the @mount.
     281   *
     282   * Returns: (transfer full) (nullable): a #GVolume or %NULL if @mount is not
     283   *      associated with a volume.
     284   *      The returned object should be unreffed with 
     285   *      g_object_unref() when no longer needed.
     286   **/
     287  GVolume *
     288  g_mount_get_volume (GMount *mount)
     289  {
     290    GMountIface *iface;
     291  
     292    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     293  
     294    iface = G_MOUNT_GET_IFACE (mount);
     295  
     296    return (* iface->get_volume) (mount);
     297  }
     298  
     299  /**
     300   * g_mount_get_drive:
     301   * @mount: a #GMount.
     302   * 
     303   * Gets the drive for the @mount.
     304   *
     305   * This is a convenience method for getting the #GVolume and then
     306   * using that object to get the #GDrive.
     307   * 
     308   * Returns: (transfer full) (nullable): a #GDrive or %NULL if @mount is not
     309   *      associated with a volume or a drive.
     310   *      The returned object should be unreffed with 
     311   *      g_object_unref() when no longer needed.
     312   **/
     313  GDrive *
     314  g_mount_get_drive (GMount *mount)
     315  {
     316    GMountIface *iface;
     317  
     318    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     319  
     320    iface = G_MOUNT_GET_IFACE (mount);
     321  
     322    return (* iface->get_drive) (mount);
     323  }
     324  
     325  /**
     326   * g_mount_can_unmount: 
     327   * @mount: a #GMount.
     328   * 
     329   * Checks if @mount can be unmounted.
     330   * 
     331   * Returns: %TRUE if the @mount can be unmounted.
     332   **/
     333  gboolean
     334  g_mount_can_unmount (GMount *mount)
     335  {
     336    GMountIface *iface;
     337  
     338    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     339  
     340    iface = G_MOUNT_GET_IFACE (mount);
     341  
     342    return (* iface->can_unmount) (mount);
     343  }
     344  
     345  /**
     346   * g_mount_can_eject: 
     347   * @mount: a #GMount.
     348   * 
     349   * Checks if @mount can be ejected.
     350   * 
     351   * Returns: %TRUE if the @mount can be ejected.
     352   **/
     353  gboolean
     354  g_mount_can_eject (GMount *mount)
     355  {
     356    GMountIface *iface;
     357  
     358    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     359  
     360    iface = G_MOUNT_GET_IFACE (mount);
     361  
     362    return (* iface->can_eject) (mount);
     363  }
     364  
     365  /**
     366   * g_mount_unmount:
     367   * @mount: a #GMount.
     368   * @flags: flags affecting the operation
     369   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     370   * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
     371   * @user_data: user data passed to @callback.
     372   * 
     373   * Unmounts a mount. This is an asynchronous operation, and is 
     374   * finished by calling g_mount_unmount_finish() with the @mount 
     375   * and #GAsyncResult data returned in the @callback.
     376   *
     377   * Deprecated: 2.22: Use g_mount_unmount_with_operation() instead.
     378   **/
     379  void
     380  g_mount_unmount (GMount              *mount,
     381                   GMountUnmountFlags   flags,
     382                   GCancellable        *cancellable,
     383                   GAsyncReadyCallback  callback,
     384                   gpointer             user_data)
     385  {
     386    GMountIface *iface;
     387  
     388    g_return_if_fail (G_IS_MOUNT (mount));
     389    
     390    iface = G_MOUNT_GET_IFACE (mount);
     391  
     392    if (iface->unmount == NULL)
     393      {
     394        g_task_report_new_error (mount, callback, user_data,
     395                                 g_mount_unmount_with_operation,
     396                                 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     397                                 /* Translators: This is an error
     398                                  * message for mount objects that
     399                                  * don't implement unmount. */
     400                                 _("mount doesn’t implement “unmount”"));
     401        return;
     402      }
     403    
     404    (* iface->unmount) (mount, flags, cancellable, callback, user_data);
     405  }
     406  
     407  /**
     408   * g_mount_unmount_finish:
     409   * @mount: a #GMount.
     410   * @result: a #GAsyncResult.
     411   * @error: a #GError location to store the error occurring, or %NULL to 
     412   *     ignore.
     413   * 
     414   * Finishes unmounting a mount. If any errors occurred during the operation, 
     415   * @error will be set to contain the errors and %FALSE will be returned.
     416   * 
     417   * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
     418   *
     419   * Deprecated: 2.22: Use g_mount_unmount_with_operation_finish() instead.
     420   **/
     421  gboolean
     422  g_mount_unmount_finish (GMount        *mount,
     423                          GAsyncResult  *result,
     424                          GError       **error)
     425  {
     426    GMountIface *iface;
     427  
     428    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     429    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
     430  
     431    if (g_async_result_legacy_propagate_error (result, error))
     432      return FALSE;
     433    else if (g_async_result_is_tagged (result, g_mount_unmount_with_operation))
     434      return g_task_propagate_boolean (G_TASK (result), error);
     435    
     436    iface = G_MOUNT_GET_IFACE (mount);
     437    return (* iface->unmount_finish) (mount, result, error);
     438  }
     439  
     440  
     441  /**
     442   * g_mount_eject:
     443   * @mount: a #GMount.
     444   * @flags: flags affecting the unmount if required for eject
     445   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     446   * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
     447   * @user_data: user data passed to @callback.
     448   * 
     449   * Ejects a mount. This is an asynchronous operation, and is 
     450   * finished by calling g_mount_eject_finish() with the @mount 
     451   * and #GAsyncResult data returned in the @callback.
     452   *
     453   * Deprecated: 2.22: Use g_mount_eject_with_operation() instead.
     454   **/
     455  void
     456  g_mount_eject (GMount              *mount,
     457                 GMountUnmountFlags   flags,
     458                 GCancellable        *cancellable,
     459                 GAsyncReadyCallback  callback,
     460                 gpointer             user_data)
     461  {
     462    GMountIface *iface;
     463  
     464    g_return_if_fail (G_IS_MOUNT (mount));
     465    
     466    iface = G_MOUNT_GET_IFACE (mount);
     467  
     468    if (iface->eject == NULL)
     469      {
     470        g_task_report_new_error (mount, callback, user_data,
     471                                 g_mount_eject_with_operation,
     472                                 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     473                                 /* Translators: This is an error
     474                                  * message for mount objects that
     475                                  * don't implement eject. */
     476                                 _("mount doesn’t implement “eject”"));
     477        return;
     478      }
     479    
     480    (* iface->eject) (mount, flags, cancellable, callback, user_data);
     481  }
     482  
     483  /**
     484   * g_mount_eject_finish:
     485   * @mount: a #GMount.
     486   * @result: a #GAsyncResult.
     487   * @error: a #GError location to store the error occurring, or %NULL to 
     488   *     ignore.
     489   * 
     490   * Finishes ejecting a mount. If any errors occurred during the operation, 
     491   * @error will be set to contain the errors and %FALSE will be returned.
     492   * 
     493   * Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
     494   *
     495   * Deprecated: 2.22: Use g_mount_eject_with_operation_finish() instead.
     496   **/
     497  gboolean
     498  g_mount_eject_finish (GMount        *mount,
     499                        GAsyncResult  *result,
     500                        GError       **error)
     501  {
     502    GMountIface *iface;
     503  
     504    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     505    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
     506  
     507    if (g_async_result_legacy_propagate_error (result, error))
     508      return FALSE;
     509    else if (g_async_result_is_tagged (result, g_mount_eject_with_operation))
     510      return g_task_propagate_boolean (G_TASK (result), error);
     511    
     512    iface = G_MOUNT_GET_IFACE (mount);
     513    return (* iface->eject_finish) (mount, result, error);
     514  }
     515  
     516  /**
     517   * g_mount_unmount_with_operation:
     518   * @mount: a #GMount.
     519   * @flags: flags affecting the operation
     520   * @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
     521   *     user interaction.
     522   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     523   * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
     524   * @user_data: user data passed to @callback.
     525   *
     526   * Unmounts a mount. This is an asynchronous operation, and is
     527   * finished by calling g_mount_unmount_with_operation_finish() with the @mount 
     528   * and #GAsyncResult data returned in the @callback.
     529   *
     530   * Since: 2.22
     531   **/
     532  void
     533  g_mount_unmount_with_operation (GMount              *mount,
     534                                  GMountUnmountFlags   flags,
     535                                  GMountOperation     *mount_operation,
     536                                  GCancellable        *cancellable,
     537                                  GAsyncReadyCallback  callback,
     538                                  gpointer             user_data)
     539  {
     540    GMountIface *iface;
     541  
     542    g_return_if_fail (G_IS_MOUNT (mount));
     543  
     544    iface = G_MOUNT_GET_IFACE (mount);
     545  
     546    if (iface->unmount == NULL && iface->unmount_with_operation == NULL)
     547      {
     548        g_task_report_new_error (mount, callback, user_data,
     549                                 g_mount_unmount_with_operation,
     550                                 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     551                                 /* Translators: This is an error
     552                                  * message for mount objects that
     553                                  * don't implement any of unmount or unmount_with_operation. */
     554                                 _("mount doesn’t implement “unmount” or “unmount_with_operation”"));
     555        return;
     556      }
     557  
     558    if (iface->unmount_with_operation != NULL)
     559      (* iface->unmount_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
     560    else
     561      (* iface->unmount) (mount, flags, cancellable, callback, user_data);
     562  }
     563  
     564  /**
     565   * g_mount_unmount_with_operation_finish:
     566   * @mount: a #GMount.
     567   * @result: a #GAsyncResult.
     568   * @error: a #GError location to store the error occurring, or %NULL to
     569   *     ignore.
     570   *
     571   * Finishes unmounting a mount. If any errors occurred during the operation,
     572   * @error will be set to contain the errors and %FALSE will be returned.
     573   *
     574   * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
     575   *
     576   * Since: 2.22
     577   **/
     578  gboolean
     579  g_mount_unmount_with_operation_finish (GMount        *mount,
     580                                         GAsyncResult  *result,
     581                                         GError       **error)
     582  {
     583    GMountIface *iface;
     584  
     585    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     586    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
     587  
     588    if (g_async_result_legacy_propagate_error (result, error))
     589      return FALSE;
     590    else if (g_async_result_is_tagged (result, g_mount_unmount_with_operation))
     591      return g_task_propagate_boolean (G_TASK (result), error);
     592  
     593    iface = G_MOUNT_GET_IFACE (mount);
     594    if (iface->unmount_with_operation_finish != NULL)
     595      return (* iface->unmount_with_operation_finish) (mount, result, error);
     596    else
     597      return (* iface->unmount_finish) (mount, result, error);
     598  }
     599  
     600  
     601  /**
     602   * g_mount_eject_with_operation:
     603   * @mount: a #GMount.
     604   * @flags: flags affecting the unmount if required for eject
     605   * @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
     606   *     user interaction.
     607   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     608   * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
     609   * @user_data: user data passed to @callback.
     610   *
     611   * Ejects a mount. This is an asynchronous operation, and is
     612   * finished by calling g_mount_eject_with_operation_finish() with the @mount
     613   * and #GAsyncResult data returned in the @callback.
     614   *
     615   * Since: 2.22
     616   **/
     617  void
     618  g_mount_eject_with_operation (GMount              *mount,
     619                                GMountUnmountFlags   flags,
     620                                GMountOperation     *mount_operation,
     621                                GCancellable        *cancellable,
     622                                GAsyncReadyCallback  callback,
     623                                gpointer             user_data)
     624  {
     625    GMountIface *iface;
     626  
     627    g_return_if_fail (G_IS_MOUNT (mount));
     628  
     629    iface = G_MOUNT_GET_IFACE (mount);
     630  
     631    if (iface->eject == NULL && iface->eject_with_operation == NULL)
     632      {
     633        g_task_report_new_error (mount, callback, user_data,
     634                                 g_mount_eject_with_operation,
     635                                 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     636                                 /* Translators: This is an error
     637                                  * message for mount objects that
     638                                  * don't implement any of eject or eject_with_operation. */
     639                                 _("mount doesn’t implement “eject” or “eject_with_operation”"));
     640        return;
     641      }
     642  
     643    if (iface->eject_with_operation != NULL)
     644      (* iface->eject_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
     645    else
     646      (* iface->eject) (mount, flags, cancellable, callback, user_data);
     647  }
     648  
     649  /**
     650   * g_mount_eject_with_operation_finish:
     651   * @mount: a #GMount.
     652   * @result: a #GAsyncResult.
     653   * @error: a #GError location to store the error occurring, or %NULL to
     654   *     ignore.
     655   *
     656   * Finishes ejecting a mount. If any errors occurred during the operation,
     657   * @error will be set to contain the errors and %FALSE will be returned.
     658   *
     659   * Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
     660   *
     661   * Since: 2.22
     662   **/
     663  gboolean
     664  g_mount_eject_with_operation_finish (GMount        *mount,
     665                                       GAsyncResult  *result,
     666                                       GError       **error)
     667  {
     668    GMountIface *iface;
     669  
     670    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     671    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
     672  
     673    if (g_async_result_legacy_propagate_error (result, error))
     674      return FALSE;
     675    else if (g_async_result_is_tagged (result, g_mount_eject_with_operation))
     676      return g_task_propagate_boolean (G_TASK (result), error);
     677  
     678    iface = G_MOUNT_GET_IFACE (mount);
     679    if (iface->eject_with_operation_finish != NULL)
     680      return (* iface->eject_with_operation_finish) (mount, result, error);
     681    else
     682      return (* iface->eject_finish) (mount, result, error);
     683  }
     684  
     685  /**
     686   * g_mount_remount:
     687   * @mount: a #GMount.
     688   * @flags: flags affecting the operation
     689   * @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
     690   *     user interaction.
     691   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     692   * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
     693   * @user_data: user data passed to @callback.
     694   * 
     695   * Remounts a mount. This is an asynchronous operation, and is 
     696   * finished by calling g_mount_remount_finish() with the @mount 
     697   * and #GAsyncResults data returned in the @callback.
     698   *
     699   * Remounting is useful when some setting affecting the operation
     700   * of the volume has been changed, as these may need a remount to
     701   * take affect. While this is semantically equivalent with unmounting
     702   * and then remounting not all backends might need to actually be
     703   * unmounted.
     704   **/
     705  void
     706  g_mount_remount (GMount              *mount,
     707                   GMountMountFlags     flags,
     708                   GMountOperation     *mount_operation,
     709                   GCancellable        *cancellable,
     710                   GAsyncReadyCallback  callback,
     711                   gpointer             user_data)
     712  {
     713    GMountIface *iface;
     714  
     715    g_return_if_fail (G_IS_MOUNT (mount));
     716    
     717    iface = G_MOUNT_GET_IFACE (mount);
     718  
     719    if (iface->remount == NULL)
     720      { 
     721        g_task_report_new_error (mount, callback, user_data,
     722                                 g_mount_remount,
     723                                 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     724                                 /* Translators: This is an error
     725                                  * message for mount objects that
     726                                  * don't implement remount. */
     727                                 _("mount doesn’t implement “remount”"));
     728        return;
     729      }
     730    
     731    (* iface->remount) (mount, flags, mount_operation, cancellable, callback, user_data);
     732  }
     733  
     734  /**
     735   * g_mount_remount_finish:
     736   * @mount: a #GMount.
     737   * @result: a #GAsyncResult.
     738   * @error: a #GError location to store the error occurring, or %NULL to 
     739   *     ignore.
     740   * 
     741   * Finishes remounting a mount. If any errors occurred during the operation, 
     742   * @error will be set to contain the errors and %FALSE will be returned.
     743   * 
     744   * Returns: %TRUE if the mount was successfully remounted. %FALSE otherwise.
     745   **/
     746  gboolean
     747  g_mount_remount_finish (GMount        *mount,
     748                          GAsyncResult  *result,
     749                          GError       **error)
     750  {
     751    GMountIface *iface;
     752  
     753    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     754    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
     755  
     756    if (g_async_result_legacy_propagate_error (result, error))
     757      return FALSE;
     758    else if (g_async_result_is_tagged (result, g_mount_remount))
     759      return g_task_propagate_boolean (G_TASK (result), error);
     760    
     761    iface = G_MOUNT_GET_IFACE (mount);
     762    return (* iface->remount_finish) (mount, result, error);
     763  }
     764  
     765  /**
     766   * g_mount_guess_content_type:
     767   * @mount: a #GMount
     768   * @force_rescan: Whether to force a rescan of the content. 
     769   *     Otherwise a cached result will be used if available
     770   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
     771   * @callback: a #GAsyncReadyCallback
     772   * @user_data: user data passed to @callback
     773   * 
     774   * Tries to guess the type of content stored on @mount. Returns one or
     775   * more textual identifiers of well-known content types (typically
     776   * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
     777   * memory cards. See the 
     778   * [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec)
     779   * specification for more on x-content types.
     780   *
     781   * This is an asynchronous operation (see
     782   * g_mount_guess_content_type_sync() for the synchronous version), and
     783   * is finished by calling g_mount_guess_content_type_finish() with the
     784   * @mount and #GAsyncResult data returned in the @callback.
     785   *
     786   * Since: 2.18
     787   */
     788  void
     789  g_mount_guess_content_type (GMount              *mount,
     790                              gboolean             force_rescan,
     791                              GCancellable        *cancellable,
     792                              GAsyncReadyCallback  callback,
     793                              gpointer             user_data)
     794  {
     795    GMountIface *iface;
     796  
     797    g_return_if_fail (G_IS_MOUNT (mount));
     798  
     799    iface = G_MOUNT_GET_IFACE (mount);
     800  
     801    if (iface->guess_content_type == NULL)
     802      {
     803        g_task_report_new_error (mount, callback, user_data,
     804                                 g_mount_guess_content_type,
     805                                 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     806                                 /* Translators: This is an error
     807                                  * message for mount objects that
     808                                  * don't implement content type guessing. */
     809                                 _("mount doesn’t implement content type guessing"));
     810        return;
     811      }
     812    
     813    (* iface->guess_content_type) (mount, force_rescan, cancellable, callback, user_data);
     814  }
     815  
     816  /**
     817   * g_mount_guess_content_type_finish:
     818   * @mount: a #GMount
     819   * @result: a #GAsyncResult
     820   * @error: a #GError location to store the error occurring, or %NULL to 
     821   *     ignore
     822   * 
     823   * Finishes guessing content types of @mount. If any errors occurred
     824   * during the operation, @error will be set to contain the errors and
     825   * %FALSE will be returned. In particular, you may get an 
     826   * %G_IO_ERROR_NOT_SUPPORTED if the mount does not support content 
     827   * guessing.
     828   * 
     829   * Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error. 
     830   *     Caller should free this array with g_strfreev() when done with it.
     831   *
     832   * Since: 2.18
     833   **/
     834  gchar **
     835  g_mount_guess_content_type_finish (GMount        *mount,
     836                                     GAsyncResult  *result,
     837                                     GError       **error)
     838  {
     839    GMountIface *iface;
     840  
     841    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     842    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
     843  
     844    if (g_async_result_legacy_propagate_error (result, error))
     845      return NULL;
     846    else if (g_async_result_is_tagged (result, g_mount_guess_content_type))
     847      return g_task_propagate_pointer (G_TASK (result), error);
     848    
     849    iface = G_MOUNT_GET_IFACE (mount);
     850    return (* iface->guess_content_type_finish) (mount, result, error);
     851  }
     852  
     853  /**
     854   * g_mount_guess_content_type_sync:
     855   * @mount: a #GMount
     856   * @force_rescan: Whether to force a rescan of the content.
     857   *     Otherwise a cached result will be used if available
     858   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
     859   * @error: a #GError location to store the error occurring, or %NULL to
     860   *     ignore
     861   *
     862   * Tries to guess the type of content stored on @mount. Returns one or
     863   * more textual identifiers of well-known content types (typically
     864   * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
     865   * memory cards. See the 
     866   * [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec)
     867   * specification for more on x-content types.
     868   *
     869   * This is a synchronous operation and as such may block doing IO;
     870   * see g_mount_guess_content_type() for the asynchronous version.
     871   *
     872   * Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error.
     873   *     Caller should free this array with g_strfreev() when done with it.
     874   *
     875   * Since: 2.18
     876   */
     877  char **
     878  g_mount_guess_content_type_sync (GMount              *mount,
     879                                   gboolean             force_rescan,
     880                                   GCancellable        *cancellable,
     881                                   GError             **error)
     882  {
     883    GMountIface *iface;
     884  
     885    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
     886  
     887    iface = G_MOUNT_GET_IFACE (mount);
     888  
     889    if (iface->guess_content_type_sync == NULL)
     890      {
     891        g_set_error_literal (error,
     892                             G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     893                             /* Translators: This is an error
     894                              * message for mount objects that
     895                              * don't implement content type guessing. */
     896                             _("mount doesn’t implement synchronous content type guessing"));
     897  
     898        return NULL;
     899      }
     900  
     901    return (* iface->guess_content_type_sync) (mount, force_rescan, cancellable, error);
     902  }
     903  
     904  G_LOCK_DEFINE_STATIC (priv_lock);
     905  
     906  /* only access this structure when holding priv_lock */
     907  typedef struct
     908  {
     909    gint shadow_ref_count;
     910  } GMountPrivate;
     911  
     912  static void
     913  free_private (GMountPrivate *private)
     914  {
     915    G_LOCK (priv_lock);
     916    g_free (private);
     917    G_UNLOCK (priv_lock);
     918  }
     919  
     920  /* may only be called when holding priv_lock */
     921  static GMountPrivate *
     922  get_private (GMount *mount)
     923  {
     924    GMountPrivate *private;
     925  
     926    private = g_object_get_data (G_OBJECT (mount), "g-mount-private");
     927    if (G_LIKELY (private != NULL))
     928      goto out;
     929  
     930    private = g_new0 (GMountPrivate, 1);
     931    g_object_set_data_full (G_OBJECT (mount),
     932                            "g-mount-private",
     933                            private,
     934                            (GDestroyNotify) free_private);
     935  
     936   out:
     937    return private;
     938  }
     939  
     940  /**
     941   * g_mount_is_shadowed:
     942   * @mount: A #GMount.
     943   *
     944   * Determines if @mount is shadowed. Applications or libraries should
     945   * avoid displaying @mount in the user interface if it is shadowed.
     946   *
     947   * A mount is said to be shadowed if there exists one or more user
     948   * visible objects (currently #GMount objects) with a root that is
     949   * inside the root of @mount.
     950   *
     951   * One application of shadow mounts is when exposing a single file
     952   * system that is used to address several logical volumes. In this
     953   * situation, a #GVolumeMonitor implementation would create two
     954   * #GVolume objects (for example, one for the camera functionality of
     955   * the device and one for a SD card reader on the device) with
     956   * activation URIs `gphoto2://[usb:001,002]/store1/`
     957   * and `gphoto2://[usb:001,002]/store2/`. When the
     958   * underlying mount (with root
     959   * `gphoto2://[usb:001,002]/`) is mounted, said
     960   * #GVolumeMonitor implementation would create two #GMount objects
     961   * (each with their root matching the corresponding volume activation
     962   * root) that would shadow the original mount.
     963   *
     964   * The proxy monitor in GVfs 2.26 and later, automatically creates and
     965   * manage shadow mounts (and shadows the underlying mount) if the
     966   * activation root on a #GVolume is set.
     967   *
     968   * Returns: %TRUE if @mount is shadowed.
     969   *
     970   * Since: 2.20
     971   **/
     972  gboolean
     973  g_mount_is_shadowed (GMount *mount)
     974  {
     975    GMountPrivate *priv;
     976    gboolean ret;
     977  
     978    g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
     979  
     980    G_LOCK (priv_lock);
     981    priv = get_private (mount);
     982    ret = (priv->shadow_ref_count > 0);
     983    G_UNLOCK (priv_lock);
     984  
     985    return ret;
     986  }
     987  
     988  /**
     989   * g_mount_shadow:
     990   * @mount: A #GMount.
     991   *
     992   * Increments the shadow count on @mount. Usually used by
     993   * #GVolumeMonitor implementations when creating a shadow mount for
     994   * @mount, see g_mount_is_shadowed() for more information. The caller
     995   * will need to emit the #GMount::changed signal on @mount manually.
     996   *
     997   * Since: 2.20
     998   **/
     999  void
    1000  g_mount_shadow (GMount *mount)
    1001  {
    1002    GMountPrivate *priv;
    1003  
    1004    g_return_if_fail (G_IS_MOUNT (mount));
    1005  
    1006    G_LOCK (priv_lock);
    1007    priv = get_private (mount);
    1008    priv->shadow_ref_count += 1;
    1009    G_UNLOCK (priv_lock);
    1010  }
    1011  
    1012  /**
    1013   * g_mount_unshadow:
    1014   * @mount: A #GMount.
    1015   *
    1016   * Decrements the shadow count on @mount. Usually used by
    1017   * #GVolumeMonitor implementations when destroying a shadow mount for
    1018   * @mount, see g_mount_is_shadowed() for more information. The caller
    1019   * will need to emit the #GMount::changed signal on @mount manually.
    1020   *
    1021   * Since: 2.20
    1022   **/
    1023  void
    1024  g_mount_unshadow (GMount *mount)
    1025  {
    1026    GMountPrivate *priv;
    1027  
    1028    g_return_if_fail (G_IS_MOUNT (mount));
    1029  
    1030    G_LOCK (priv_lock);
    1031    priv = get_private (mount);
    1032    priv->shadow_ref_count -= 1;
    1033    if (priv->shadow_ref_count < 0)
    1034      g_warning ("Shadow ref count on GMount is negative");
    1035    G_UNLOCK (priv_lock);
    1036  }
    1037  
    1038  /**
    1039   * g_mount_get_sort_key:
    1040   * @mount: A #GMount.
    1041   *
    1042   * Gets the sort key for @mount, if any.
    1043   *
    1044   * Returns: (nullable): Sorting key for @mount or %NULL if no such key is available.
    1045   *
    1046   * Since: 2.32
    1047   */
    1048  const gchar *
    1049  g_mount_get_sort_key (GMount  *mount)
    1050  {
    1051    const gchar *ret = NULL;
    1052    GMountIface *iface;
    1053  
    1054    g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
    1055  
    1056    iface = G_MOUNT_GET_IFACE (mount);
    1057    if (iface->get_sort_key != NULL)
    1058      ret = iface->get_sort_key (mount);
    1059  
    1060    return ret;
    1061  }