GVariant: support serialising to GVariantVectors
[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, see <http://www.gnu.org/licenses/>.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  *         David Zeuthen <davidz@redhat.com>
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27
28 #include "gmount.h"
29 #include "gmountprivate.h"
30 #include "gthemedicon.h"
31 #include "gasyncresult.h"
32 #include "gtask.h"
33 #include "gioerror.h"
34 #include "glibintl.h"
35
36
37 /**
38  * SECTION:gmount
39  * @short_description: Mount management
40  * @include: gio/gio.h
41  * @see_also: GVolume, GUnixMountEntry, GUnixMountPoint
42  *
43  * The #GMount interface represents user-visible mounts. Note, when 
44  * porting from GnomeVFS, #GMount is the moral 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 #GAsyncResult
53  * and #GTask. To unmount a #GMount instance, first call
54  * g_mount_unmount_with_operation() with (at least) the #GMount instance and a
55  * #GAsyncReadyCallback.  The callback will be fired when the
56  * operation has resolved (either with success or failure), and a
57  * #GAsyncReady structure will be passed to the callback.  That
58  * callback should then call g_mount_unmount_with_operation_finish() with the #GMount
59  * and the #GAsyncReady data to see if the operation was completed
60  * successfully.  If an @error is present when g_mount_unmount_with_operation_finish() 
61  * is called, then it will be filled with any error information.
62  **/
63
64 typedef GMountIface GMountInterface;
65 G_DEFINE_INTERFACE (GMount, g_mount, G_TYPE_OBJECT)
66
67 static void
68 g_mount_default_init (GMountInterface *iface)
69 {
70   /**
71    * GMount::changed:
72    * @mount: the object on which the signal is emitted
73    *
74    * Emitted when the mount has been changed.
75    **/
76   g_signal_new (I_("changed"),
77                 G_TYPE_MOUNT,
78                 G_SIGNAL_RUN_LAST,
79                 G_STRUCT_OFFSET (GMountIface, changed),
80                 NULL, NULL,
81                 g_cclosure_marshal_VOID__VOID,
82                 G_TYPE_NONE, 0);
83
84   /**
85    * GMount::unmounted:
86    * @mount: the object on which the signal is emitted
87    *
88    * This signal is emitted when the #GMount have been
89    * unmounted. If the recipient is holding references to the
90    * object they should release them so the object can be
91    * finalized.
92    **/
93   g_signal_new (I_("unmounted"),
94                 G_TYPE_MOUNT,
95                 G_SIGNAL_RUN_LAST,
96                 G_STRUCT_OFFSET (GMountIface, unmounted),
97                 NULL, NULL,
98                 g_cclosure_marshal_VOID__VOID,
99                 G_TYPE_NONE, 0);
100   /**
101    * GMount::pre-unmount:
102    * @mount: the object on which the signal is emitted
103    *
104    * This signal is emitted when the #GMount is about to be
105    * unmounted.
106    *
107    * Since: 2.22
108    **/
109   g_signal_new (I_("pre-unmount"),
110                 G_TYPE_MOUNT,
111                 G_SIGNAL_RUN_LAST,
112                 G_STRUCT_OFFSET (GMountIface, pre_unmount),
113                 NULL, NULL,
114                 g_cclosure_marshal_VOID__VOID,
115                 G_TYPE_NONE, 0);
116 }
117
118 /**
119  * g_mount_get_root:
120  * @mount: a #GMount.
121  * 
122  * Gets the root directory on @mount.
123  * 
124  * Returns: (transfer full): a #GFile. 
125  *      The returned object should be unreffed with 
126  *      g_object_unref() when no longer needed.
127  **/
128 GFile *
129 g_mount_get_root (GMount *mount)
130 {
131   GMountIface *iface;
132
133   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
134
135   iface = G_MOUNT_GET_IFACE (mount);
136
137   return (* iface->get_root) (mount);
138 }
139
140 /**
141  * g_mount_get_default_location:
142  * @mount: a #GMount.
143  *
144  * Gets the default location of @mount. The default location of the given
145  * @mount is a path that reflects the main entry point for the user (e.g.
146  * the home directory, or the root of the volume).
147  *
148  * Returns: (transfer full): a #GFile.
149  *      The returned object should be unreffed with
150  *      g_object_unref() when no longer needed.
151  **/
152 GFile *
153 g_mount_get_default_location (GMount *mount)
154 {
155   GMountIface *iface;
156   GFile       *file;
157
158   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
159
160   iface = G_MOUNT_GET_IFACE (mount);
161   
162   /* Fallback to get_root when default_location () is not available */
163   if (iface->get_default_location)
164     file = (* iface->get_default_location) (mount);
165   else
166     file = (* iface->get_root) (mount);
167
168   return file;
169 }
170
171 /**
172  * g_mount_get_name:
173  * @mount: a #GMount.
174  * 
175  * Gets the name of @mount.
176  * 
177  * Returns: the name for the given @mount. 
178  *     The returned string should be freed with g_free()
179  *     when no longer needed.
180  **/
181 char *
182 g_mount_get_name (GMount *mount)
183 {
184   GMountIface *iface;
185
186   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
187
188   iface = G_MOUNT_GET_IFACE (mount);
189
190   return (* iface->get_name) (mount);
191 }
192
193 /**
194  * g_mount_get_icon:
195  * @mount: a #GMount.
196  * 
197  * Gets the icon for @mount.
198  * 
199  * Returns: (transfer full): a #GIcon.
200  *      The returned object should be unreffed with 
201  *      g_object_unref() when no longer needed.
202  **/
203 GIcon *
204 g_mount_get_icon (GMount *mount)
205 {
206   GMountIface *iface;
207
208   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
209
210   iface = G_MOUNT_GET_IFACE (mount);
211
212   return (* iface->get_icon) (mount);
213 }
214
215
216 /**
217  * g_mount_get_symbolic_icon:
218  * @mount: a #GMount.
219  * 
220  * Gets the symbolic icon for @mount.
221  * 
222  * Returns: (transfer full): a #GIcon.
223  *      The returned object should be unreffed with 
224  *      g_object_unref() when no longer needed.
225  *
226  * Since: 2.34
227  **/
228 GIcon *
229 g_mount_get_symbolic_icon (GMount *mount)
230 {
231   GMountIface *iface;
232   GIcon *ret;
233
234   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
235
236   iface = G_MOUNT_GET_IFACE (mount);
237
238   if (iface->get_symbolic_icon != NULL)
239     ret = iface->get_symbolic_icon (mount);
240   else
241     ret = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic");
242
243   return ret;
244 }
245
246 /**
247  * g_mount_get_uuid:
248  * @mount: a #GMount.
249  * 
250  * Gets the UUID for the @mount. The reference is typically based on
251  * the file system UUID for the mount in question and should be
252  * considered an opaque string. Returns %NULL if there is no UUID
253  * available.
254  * 
255  * Returns: the UUID for @mount or %NULL if no UUID can be computed.
256  *     The returned string should be freed with g_free()
257  *     when no longer needed.
258  **/
259 char *
260 g_mount_get_uuid (GMount *mount)
261 {
262   GMountIface *iface;
263
264   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
265
266   iface = G_MOUNT_GET_IFACE (mount);
267
268   return (* iface->get_uuid) (mount);
269 }
270
271 /**
272  * g_mount_get_volume:
273  * @mount: a #GMount.
274  * 
275  * Gets the volume for the @mount.
276  * 
277  * Returns: (transfer full): a #GVolume or %NULL if @mount is not associated with a volume.
278  *      The returned object should be unreffed with 
279  *      g_object_unref() when no longer needed.
280  **/
281 GVolume *
282 g_mount_get_volume (GMount *mount)
283 {
284   GMountIface *iface;
285
286   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
287
288   iface = G_MOUNT_GET_IFACE (mount);
289
290   return (* iface->get_volume) (mount);
291 }
292
293 /**
294  * g_mount_get_drive:
295  * @mount: a #GMount.
296  * 
297  * Gets the drive for the @mount.
298  *
299  * This is a convenience method for getting the #GVolume and then
300  * using that object to get the #GDrive.
301  * 
302  * Returns: (transfer full): a #GDrive or %NULL if @mount is not associated with a volume or a drive.
303  *      The returned object should be unreffed with 
304  *      g_object_unref() when no longer needed.
305  **/
306 GDrive *
307 g_mount_get_drive (GMount *mount)
308 {
309   GMountIface *iface;
310
311   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
312
313   iface = G_MOUNT_GET_IFACE (mount);
314
315   return (* iface->get_drive) (mount);
316 }
317
318 /**
319  * g_mount_can_unmount: 
320  * @mount: a #GMount.
321  * 
322  * Checks if @mount can be mounted.
323  * 
324  * Returns: %TRUE if the @mount can be unmounted.
325  **/
326 gboolean
327 g_mount_can_unmount (GMount *mount)
328 {
329   GMountIface *iface;
330
331   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
332
333   iface = G_MOUNT_GET_IFACE (mount);
334
335   return (* iface->can_unmount) (mount);
336 }
337
338 /**
339  * g_mount_can_eject: 
340  * @mount: a #GMount.
341  * 
342  * Checks if @mount can be eject.
343  * 
344  * Returns: %TRUE if the @mount can be ejected.
345  **/
346 gboolean
347 g_mount_can_eject (GMount *mount)
348 {
349   GMountIface *iface;
350
351   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
352
353   iface = G_MOUNT_GET_IFACE (mount);
354
355   return (* iface->can_eject) (mount);
356 }
357
358 /**
359  * g_mount_unmount:
360  * @mount: a #GMount.
361  * @flags: flags affecting the operation
362  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
363  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
364  * @user_data: user data passed to @callback.
365  * 
366  * Unmounts a mount. This is an asynchronous operation, and is 
367  * finished by calling g_mount_unmount_finish() with the @mount 
368  * and #GAsyncResult data returned in the @callback.
369  *
370  * Deprecated: 2.22: Use g_mount_unmount_with_operation() instead.
371  **/
372 void
373 g_mount_unmount (GMount              *mount,
374                  GMountUnmountFlags   flags,
375                  GCancellable        *cancellable,
376                  GAsyncReadyCallback  callback,
377                  gpointer             user_data)
378 {
379   GMountIface *iface;
380
381   g_return_if_fail (G_IS_MOUNT (mount));
382   
383   iface = G_MOUNT_GET_IFACE (mount);
384
385   if (iface->unmount == NULL)
386     {
387       g_task_report_new_error (mount, callback, user_data,
388                                g_mount_unmount_with_operation,
389                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
390                                /* Translators: This is an error
391                                 * message for mount objects that
392                                 * don't implement unmount. */
393                                _("mount doesn't implement \"unmount\""));
394       return;
395     }
396   
397   (* iface->unmount) (mount, flags, cancellable, callback, user_data);
398 }
399
400 /**
401  * g_mount_unmount_finish:
402  * @mount: a #GMount.
403  * @result: a #GAsyncResult.
404  * @error: a #GError location to store the error occurring, or %NULL to 
405  *     ignore.
406  * 
407  * Finishes unmounting a mount. If any errors occurred during the operation, 
408  * @error will be set to contain the errors and %FALSE will be returned.
409  * 
410  * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
411  *
412  * Deprecated: 2.22: Use g_mount_unmount_with_operation_finish() instead.
413  **/
414 gboolean
415 g_mount_unmount_finish (GMount        *mount,
416                         GAsyncResult  *result,
417                         GError       **error)
418 {
419   GMountIface *iface;
420
421   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
422   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
423
424   if (g_async_result_legacy_propagate_error (result, error))
425     return FALSE;
426   else if (g_async_result_is_tagged (result, g_mount_unmount_with_operation))
427     return g_task_propagate_boolean (G_TASK (result), error);
428   
429   iface = G_MOUNT_GET_IFACE (mount);
430   return (* iface->unmount_finish) (mount, result, error);
431 }
432
433
434 /**
435  * g_mount_eject:
436  * @mount: a #GMount.
437  * @flags: flags affecting the unmount if required for eject
438  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
439  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
440  * @user_data: user data passed to @callback.
441  * 
442  * Ejects a mount. This is an asynchronous operation, and is 
443  * finished by calling g_mount_eject_finish() with the @mount 
444  * and #GAsyncResult data returned in the @callback.
445  *
446  * Deprecated: 2.22: Use g_mount_eject_with_operation() instead.
447  **/
448 void
449 g_mount_eject (GMount              *mount,
450                GMountUnmountFlags   flags,
451                GCancellable        *cancellable,
452                GAsyncReadyCallback  callback,
453                gpointer             user_data)
454 {
455   GMountIface *iface;
456
457   g_return_if_fail (G_IS_MOUNT (mount));
458   
459   iface = G_MOUNT_GET_IFACE (mount);
460
461   if (iface->eject == NULL)
462     {
463       g_task_report_new_error (mount, callback, user_data,
464                                g_mount_eject_with_operation,
465                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
466                                /* Translators: This is an error
467                                 * message for mount objects that
468                                 * don't implement eject. */
469                                _("mount doesn't implement \"eject\""));
470       return;
471     }
472   
473   (* iface->eject) (mount, flags, cancellable, callback, user_data);
474 }
475
476 /**
477  * g_mount_eject_finish:
478  * @mount: a #GMount.
479  * @result: a #GAsyncResult.
480  * @error: a #GError location to store the error occurring, or %NULL to 
481  *     ignore.
482  * 
483  * Finishes ejecting a mount. If any errors occurred during the operation, 
484  * @error will be set to contain the errors and %FALSE will be returned.
485  * 
486  * Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
487  *
488  * Deprecated: 2.22: Use g_mount_eject_with_operation_finish() instead.
489  **/
490 gboolean
491 g_mount_eject_finish (GMount        *mount,
492                       GAsyncResult  *result,
493                       GError       **error)
494 {
495   GMountIface *iface;
496
497   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
498   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
499
500   if (g_async_result_legacy_propagate_error (result, error))
501     return FALSE;
502   else if (g_async_result_is_tagged (result, g_mount_eject_with_operation))
503     return g_task_propagate_boolean (G_TASK (result), error);
504   
505   iface = G_MOUNT_GET_IFACE (mount);
506   return (* iface->eject_finish) (mount, result, error);
507 }
508
509 /**
510  * g_mount_unmount_with_operation:
511  * @mount: a #GMount.
512  * @flags: flags affecting the operation
513  * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
514  *     user interaction.
515  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
516  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
517  * @user_data: user data passed to @callback.
518  *
519  * Unmounts a mount. This is an asynchronous operation, and is
520  * finished by calling g_mount_unmount_with_operation_finish() with the @mount 
521  * and #GAsyncResult data returned in the @callback.
522  *
523  * Since: 2.22
524  **/
525 void
526 g_mount_unmount_with_operation (GMount              *mount,
527                                 GMountUnmountFlags   flags,
528                                 GMountOperation     *mount_operation,
529                                 GCancellable        *cancellable,
530                                 GAsyncReadyCallback  callback,
531                                 gpointer             user_data)
532 {
533   GMountIface *iface;
534
535   g_return_if_fail (G_IS_MOUNT (mount));
536
537   iface = G_MOUNT_GET_IFACE (mount);
538
539   if (iface->unmount == NULL && iface->unmount_with_operation == NULL)
540     {
541       g_task_report_new_error (mount, callback, user_data,
542                                g_mount_unmount_with_operation,
543                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
544                                /* Translators: This is an error
545                                 * message for mount objects that
546                                 * don't implement any of unmount or unmount_with_operation. */
547                                _("mount doesn't implement \"unmount\" or \"unmount_with_operation\""));
548       return;
549     }
550
551   if (iface->unmount_with_operation != NULL)
552     (* iface->unmount_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
553   else
554     (* iface->unmount) (mount, flags, cancellable, callback, user_data);
555 }
556
557 /**
558  * g_mount_unmount_with_operation_finish:
559  * @mount: a #GMount.
560  * @result: a #GAsyncResult.
561  * @error: a #GError location to store the error occurring, or %NULL to
562  *     ignore.
563  *
564  * Finishes unmounting a mount. If any errors occurred during the operation,
565  * @error will be set to contain the errors and %FALSE will be returned.
566  *
567  * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
568  *
569  * Since: 2.22
570  **/
571 gboolean
572 g_mount_unmount_with_operation_finish (GMount        *mount,
573                                        GAsyncResult  *result,
574                                        GError       **error)
575 {
576   GMountIface *iface;
577
578   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
579   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
580
581   if (g_async_result_legacy_propagate_error (result, error))
582     return FALSE;
583   else if (g_async_result_is_tagged (result, g_mount_unmount_with_operation))
584     return g_task_propagate_boolean (G_TASK (result), error);
585
586   iface = G_MOUNT_GET_IFACE (mount);
587   if (iface->unmount_with_operation_finish != NULL)
588     return (* iface->unmount_with_operation_finish) (mount, result, error);
589   else
590     return (* iface->unmount_finish) (mount, result, error);
591 }
592
593
594 /**
595  * g_mount_eject_with_operation:
596  * @mount: a #GMount.
597  * @flags: flags affecting the unmount if required for eject
598  * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
599  *     user interaction.
600  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
601  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
602  * @user_data: user data passed to @callback.
603  *
604  * Ejects a mount. This is an asynchronous operation, and is
605  * finished by calling g_mount_eject_with_operation_finish() with the @mount
606  * and #GAsyncResult data returned in the @callback.
607  *
608  * Since: 2.22
609  **/
610 void
611 g_mount_eject_with_operation (GMount              *mount,
612                               GMountUnmountFlags   flags,
613                               GMountOperation     *mount_operation,
614                               GCancellable        *cancellable,
615                               GAsyncReadyCallback  callback,
616                               gpointer             user_data)
617 {
618   GMountIface *iface;
619
620   g_return_if_fail (G_IS_MOUNT (mount));
621
622   iface = G_MOUNT_GET_IFACE (mount);
623
624   if (iface->eject == NULL && iface->eject_with_operation == NULL)
625     {
626       g_task_report_new_error (mount, callback, user_data,
627                                g_mount_eject_with_operation,
628                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
629                                /* Translators: This is an error
630                                 * message for mount objects that
631                                 * don't implement any of eject or eject_with_operation. */
632                                _("mount doesn't implement \"eject\" or \"eject_with_operation\""));
633       return;
634     }
635
636   if (iface->eject_with_operation != NULL)
637     (* iface->eject_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
638   else
639     (* iface->eject) (mount, flags, cancellable, callback, user_data);
640 }
641
642 /**
643  * g_mount_eject_with_operation_finish:
644  * @mount: a #GMount.
645  * @result: a #GAsyncResult.
646  * @error: a #GError location to store the error occurring, or %NULL to
647  *     ignore.
648  *
649  * Finishes ejecting a mount. If any errors occurred during the operation,
650  * @error will be set to contain the errors and %FALSE will be returned.
651  *
652  * Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
653  *
654  * Since: 2.22
655  **/
656 gboolean
657 g_mount_eject_with_operation_finish (GMount        *mount,
658                                      GAsyncResult  *result,
659                                      GError       **error)
660 {
661   GMountIface *iface;
662
663   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
664   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
665
666   if (g_async_result_legacy_propagate_error (result, error))
667     return FALSE;
668   else if (g_async_result_is_tagged (result, g_mount_eject_with_operation))
669     return g_task_propagate_boolean (G_TASK (result), error);
670
671   iface = G_MOUNT_GET_IFACE (mount);
672   if (iface->eject_with_operation_finish != NULL)
673     return (* iface->eject_with_operation_finish) (mount, result, error);
674   else
675     return (* iface->eject_finish) (mount, result, error);
676 }
677
678 /**
679  * g_mount_remount:
680  * @mount: a #GMount.
681  * @flags: flags affecting the operation
682  * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
683  *     user interaction.
684  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
685  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
686  * @user_data: user data passed to @callback.
687  * 
688  * Remounts a mount. This is an asynchronous operation, and is 
689  * finished by calling g_mount_remount_finish() with the @mount 
690  * and #GAsyncResults data returned in the @callback.
691  *
692  * Remounting is useful when some setting affecting the operation
693  * of the volume has been changed, as these may need a remount to
694  * take affect. While this is semantically equivalent with unmounting
695  * and then remounting not all backends might need to actually be
696  * unmounted.
697  **/
698 void
699 g_mount_remount (GMount              *mount,
700                  GMountMountFlags     flags,
701                  GMountOperation     *mount_operation,
702                  GCancellable        *cancellable,
703                  GAsyncReadyCallback  callback,
704                  gpointer             user_data)
705 {
706   GMountIface *iface;
707
708   g_return_if_fail (G_IS_MOUNT (mount));
709   
710   iface = G_MOUNT_GET_IFACE (mount);
711
712   if (iface->remount == NULL)
713     { 
714       g_task_report_new_error (mount, callback, user_data,
715                                g_mount_remount,
716                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
717                                /* Translators: This is an error
718                                 * message for mount objects that
719                                 * don't implement remount. */
720                                _("mount doesn't implement \"remount\""));
721       return;
722     }
723   
724   (* iface->remount) (mount, flags, mount_operation, cancellable, callback, user_data);
725 }
726
727 /**
728  * g_mount_remount_finish:
729  * @mount: a #GMount.
730  * @result: a #GAsyncResult.
731  * @error: a #GError location to store the error occurring, or %NULL to 
732  *     ignore.
733  * 
734  * Finishes remounting a mount. If any errors occurred during the operation, 
735  * @error will be set to contain the errors and %FALSE will be returned.
736  * 
737  * Returns: %TRUE if the mount was successfully remounted. %FALSE otherwise.
738  **/
739 gboolean
740 g_mount_remount_finish (GMount        *mount,
741                         GAsyncResult  *result,
742                         GError       **error)
743 {
744   GMountIface *iface;
745
746   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
747   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
748
749   if (g_async_result_legacy_propagate_error (result, error))
750     return FALSE;
751   else if (g_async_result_is_tagged (result, g_mount_remount))
752     return g_task_propagate_boolean (G_TASK (result), error);
753   
754   iface = G_MOUNT_GET_IFACE (mount);
755   return (* iface->remount_finish) (mount, result, error);
756 }
757
758 /**
759  * g_mount_guess_content_type:
760  * @mount: a #GMount
761  * @force_rescan: Whether to force a rescan of the content. 
762  *     Otherwise a cached result will be used if available
763  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
764  * @callback: a #GAsyncReadyCallback
765  * @user_data: user data passed to @callback
766  * 
767  * Tries to guess the type of content stored on @mount. Returns one or
768  * more textual identifiers of well-known content types (typically
769  * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
770  * memory cards. See the 
771  * [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec)
772  * specification for more on x-content types.
773  *
774  * This is an asynchronous operation (see
775  * g_mount_guess_content_type_sync() for the synchronous version), and
776  * is finished by calling g_mount_guess_content_type_finish() with the
777  * @mount and #GAsyncResult data returned in the @callback.
778  *
779  * Since: 2.18
780  */
781 void
782 g_mount_guess_content_type (GMount              *mount,
783                             gboolean             force_rescan,
784                             GCancellable        *cancellable,
785                             GAsyncReadyCallback  callback,
786                             gpointer             user_data)
787 {
788   GMountIface *iface;
789
790   g_return_if_fail (G_IS_MOUNT (mount));
791
792   iface = G_MOUNT_GET_IFACE (mount);
793
794   if (iface->guess_content_type == NULL)
795     {
796       g_task_report_new_error (mount, callback, user_data,
797                                g_mount_guess_content_type,
798                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
799                                /* Translators: This is an error
800                                 * message for mount objects that
801                                 * don't implement content type guessing. */
802                                _("mount doesn't implement content type guessing"));
803       return;
804     }
805   
806   (* iface->guess_content_type) (mount, force_rescan, cancellable, callback, user_data);
807 }
808
809 /**
810  * g_mount_guess_content_type_finish:
811  * @mount: a #GMount
812  * @result: a #GAsyncResult
813  * @error: a #GError location to store the error occurring, or %NULL to 
814  *     ignore
815  * 
816  * Finishes guessing content types of @mount. If any errors occurred
817  * during the operation, @error will be set to contain the errors and
818  * %FALSE will be returned. In particular, you may get an 
819  * %G_IO_ERROR_NOT_SUPPORTED if the mount does not support content 
820  * guessing.
821  * 
822  * Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error. 
823  *     Caller should free this array with g_strfreev() when done with it.
824  *
825  * Since: 2.18
826  **/
827 gchar **
828 g_mount_guess_content_type_finish (GMount        *mount,
829                                    GAsyncResult  *result,
830                                    GError       **error)
831 {
832   GMountIface *iface;
833
834   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
835   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
836
837   if (g_async_result_legacy_propagate_error (result, error))
838     return NULL;
839   else if (g_async_result_is_tagged (result, g_mount_guess_content_type))
840     return g_task_propagate_pointer (G_TASK (result), error);
841   
842   iface = G_MOUNT_GET_IFACE (mount);
843   return (* iface->guess_content_type_finish) (mount, result, error);
844 }
845
846 /**
847  * g_mount_guess_content_type_sync:
848  * @mount: a #GMount
849  * @force_rescan: Whether to force a rescan of the content.
850  *     Otherwise a cached result will be used if available
851  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
852  * @error: a #GError location to store the error occurring, or %NULL to
853  *     ignore
854  *
855  * Tries to guess the type of content stored on @mount. Returns one or
856  * more textual identifiers of well-known content types (typically
857  * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
858  * memory cards. See the 
859  * [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec)
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 `gphoto2://[usb:001,002]/store1/`
950  * and `gphoto2://[usb:001,002]/store2/`. When the
951  * underlying mount (with root
952  * `gphoto2://[usb:001,002]/`) 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 }