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