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