Add symbolic icon support to drive, volume, and mount
[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 "gsimpleasyncresult.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 #GSimpleAsyncResult. 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_simple_async_report_error_in_idle (G_OBJECT (mount),
390                                            callback, user_data,
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
397       return;
398     }
399   
400   (* iface->unmount) (mount, flags, cancellable, callback, user_data);
401 }
402
403 /**
404  * g_mount_unmount_finish:
405  * @mount: a #GMount.
406  * @result: a #GAsyncResult.
407  * @error: a #GError location to store the error occurring, or %NULL to 
408  *     ignore.
409  * 
410  * Finishes unmounting a mount. If any errors occurred during the operation, 
411  * @error will be set to contain the errors and %FALSE will be returned.
412  * 
413  * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
414  *
415  * Deprecated: 2.22: Use g_mount_unmount_with_operation_finish() instead.
416  **/
417 gboolean
418 g_mount_unmount_finish (GMount        *mount,
419                         GAsyncResult  *result,
420                         GError       **error)
421 {
422   GMountIface *iface;
423
424   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
425   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
426
427   if (g_async_result_legacy_propagate_error (result, error))
428     return FALSE;
429   
430   iface = G_MOUNT_GET_IFACE (mount);
431   return (* iface->unmount_finish) (mount, result, error);
432 }
433
434
435 /**
436  * g_mount_eject:
437  * @mount: a #GMount.
438  * @flags: flags affecting the unmount if required for eject
439  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
440  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
441  * @user_data: user data passed to @callback.
442  * 
443  * Ejects a mount. This is an asynchronous operation, and is 
444  * finished by calling g_mount_eject_finish() with the @mount 
445  * and #GAsyncResult data returned in the @callback.
446  *
447  * Deprecated: 2.22: Use g_mount_eject_with_operation() instead.
448  **/
449 void
450 g_mount_eject (GMount              *mount,
451                GMountUnmountFlags   flags,
452                GCancellable        *cancellable,
453                GAsyncReadyCallback  callback,
454                gpointer             user_data)
455 {
456   GMountIface *iface;
457
458   g_return_if_fail (G_IS_MOUNT (mount));
459   
460   iface = G_MOUNT_GET_IFACE (mount);
461
462   if (iface->eject == NULL)
463     {
464       g_simple_async_report_error_in_idle (G_OBJECT (mount),
465                                            callback, user_data,
466                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
467                                            /* Translators: This is an error
468                                             * message for mount objects that
469                                             * don't implement eject. */
470                                            _("mount doesn't implement \"eject\""));
471       
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   
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_simple_async_report_error_in_idle (G_OBJECT (mount),
542                                            callback, user_data,
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
549       return;
550     }
551
552   if (iface->unmount_with_operation != NULL)
553     (* iface->unmount_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
554   else
555     (* iface->unmount) (mount, flags, cancellable, callback, user_data);
556 }
557
558 /**
559  * g_mount_unmount_with_operation_finish:
560  * @mount: a #GMount.
561  * @result: a #GAsyncResult.
562  * @error: a #GError location to store the error occurring, or %NULL to
563  *     ignore.
564  *
565  * Finishes unmounting a mount. If any errors occurred during the operation,
566  * @error will be set to contain the errors and %FALSE will be returned.
567  *
568  * Returns: %TRUE if the mount was successfully unmounted. %FALSE otherwise.
569  *
570  * Since: 2.22
571  **/
572 gboolean
573 g_mount_unmount_with_operation_finish (GMount        *mount,
574                                        GAsyncResult  *result,
575                                        GError       **error)
576 {
577   GMountIface *iface;
578
579   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
580   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
581
582   if (g_async_result_legacy_propagate_error (result, error))
583     return FALSE;
584
585   iface = G_MOUNT_GET_IFACE (mount);
586   if (iface->unmount_with_operation_finish != NULL)
587     return (* iface->unmount_with_operation_finish) (mount, result, error);
588   else
589     return (* iface->unmount_finish) (mount, result, error);
590 }
591
592
593 /**
594  * g_mount_eject_with_operation:
595  * @mount: a #GMount.
596  * @flags: flags affecting the unmount if required for eject
597  * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
598  *     user interaction.
599  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
600  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
601  * @user_data: user data passed to @callback.
602  *
603  * Ejects a mount. This is an asynchronous operation, and is
604  * finished by calling g_mount_eject_with_operation_finish() with the @mount
605  * and #GAsyncResult data returned in the @callback.
606  *
607  * Since: 2.22
608  **/
609 void
610 g_mount_eject_with_operation (GMount              *mount,
611                               GMountUnmountFlags   flags,
612                               GMountOperation     *mount_operation,
613                               GCancellable        *cancellable,
614                               GAsyncReadyCallback  callback,
615                               gpointer             user_data)
616 {
617   GMountIface *iface;
618
619   g_return_if_fail (G_IS_MOUNT (mount));
620
621   iface = G_MOUNT_GET_IFACE (mount);
622
623   if (iface->eject == NULL && iface->eject_with_operation == NULL)
624     {
625       g_simple_async_report_error_in_idle (G_OBJECT (mount),
626                                            callback, user_data,
627                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
628                                            /* Translators: This is an error
629                                             * message for mount objects that
630                                             * don't implement any of eject or eject_with_operation. */
631                                            _("mount doesn't implement \"eject\" or \"eject_with_operation\""));
632       return;
633     }
634
635   if (iface->eject_with_operation != NULL)
636     (* iface->eject_with_operation) (mount, flags, mount_operation, cancellable, callback, user_data);
637   else
638     (* iface->eject) (mount, flags, cancellable, callback, user_data);
639 }
640
641 /**
642  * g_mount_eject_with_operation_finish:
643  * @mount: a #GMount.
644  * @result: a #GAsyncResult.
645  * @error: a #GError location to store the error occurring, or %NULL to
646  *     ignore.
647  *
648  * Finishes ejecting a mount. If any errors occurred during the operation,
649  * @error will be set to contain the errors and %FALSE will be returned.
650  *
651  * Returns: %TRUE if the mount was successfully ejected. %FALSE otherwise.
652  *
653  * Since: 2.22
654  **/
655 gboolean
656 g_mount_eject_with_operation_finish (GMount        *mount,
657                                      GAsyncResult  *result,
658                                      GError       **error)
659 {
660   GMountIface *iface;
661
662   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
663   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
664
665   if (g_async_result_legacy_propagate_error (result, error))
666     return FALSE;
667
668   iface = G_MOUNT_GET_IFACE (mount);
669   if (iface->eject_with_operation_finish != NULL)
670     return (* iface->eject_with_operation_finish) (mount, result, error);
671   else
672     return (* iface->eject_finish) (mount, result, error);
673 }
674
675 /**
676  * g_mount_remount:
677  * @mount: a #GMount.
678  * @flags: flags affecting the operation
679  * @mount_operation: (allow-none): a #GMountOperation or %NULL to avoid
680  *     user interaction.
681  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
682  * @callback: (allow-none): a #GAsyncReadyCallback, or %NULL.
683  * @user_data: user data passed to @callback.
684  * 
685  * Remounts a mount. This is an asynchronous operation, and is 
686  * finished by calling g_mount_remount_finish() with the @mount 
687  * and #GAsyncResults data returned in the @callback.
688  *
689  * Remounting is useful when some setting affecting the operation
690  * of the volume has been changed, as these may need a remount to
691  * take affect. While this is semantically equivalent with unmounting
692  * and then remounting not all backends might need to actually be
693  * unmounted.
694  **/
695 void
696 g_mount_remount (GMount              *mount,
697                  GMountMountFlags     flags,
698                  GMountOperation     *mount_operation,
699                  GCancellable        *cancellable,
700                  GAsyncReadyCallback  callback,
701                  gpointer             user_data)
702 {
703   GMountIface *iface;
704
705   g_return_if_fail (G_IS_MOUNT (mount));
706   
707   iface = G_MOUNT_GET_IFACE (mount);
708
709   if (iface->remount == NULL)
710     { 
711       g_simple_async_report_error_in_idle (G_OBJECT (mount),
712                                            callback, user_data,
713                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
714                                            /* Translators: This is an error
715                                             * message for mount objects that
716                                             * don't implement remount. */
717                                            _("mount doesn't implement \"remount\""));
718       
719       return;
720     }
721   
722   (* iface->remount) (mount, flags, mount_operation, cancellable, callback, user_data);
723 }
724
725 /**
726  * g_mount_remount_finish:
727  * @mount: a #GMount.
728  * @result: a #GAsyncResult.
729  * @error: a #GError location to store the error occurring, or %NULL to 
730  *     ignore.
731  * 
732  * Finishes remounting a mount. If any errors occurred during the operation, 
733  * @error will be set to contain the errors and %FALSE will be returned.
734  * 
735  * Returns: %TRUE if the mount was successfully remounted. %FALSE otherwise.
736  **/
737 gboolean
738 g_mount_remount_finish (GMount        *mount,
739                         GAsyncResult  *result,
740                         GError       **error)
741 {
742   GMountIface *iface;
743
744   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
745   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
746
747   if (g_async_result_legacy_propagate_error (result, error))
748     return FALSE;
749   
750   iface = G_MOUNT_GET_IFACE (mount);
751   return (* iface->remount_finish) (mount, result, error);
752 }
753
754 /**
755  * g_mount_guess_content_type:
756  * @mount: a #GMount
757  * @force_rescan: Whether to force a rescan of the content. 
758  *     Otherwise a cached result will be used if available
759  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
760  * @callback: a #GAsyncReadyCallback
761  * @user_data: user data passed to @callback
762  * 
763  * Tries to guess the type of content stored on @mount. Returns one or
764  * more textual identifiers of well-known content types (typically
765  * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
766  * memory cards. See the <ulink url="http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec">shared-mime-info</ulink>
767  * specification for more on x-content types.
768  *
769  * This is an asynchronous operation (see
770  * g_mount_guess_content_type_sync() for the synchronous version), and
771  * is finished by calling g_mount_guess_content_type_finish() with the
772  * @mount and #GAsyncResult data returned in the @callback.
773  *
774  * Since: 2.18
775  */
776 void
777 g_mount_guess_content_type (GMount              *mount,
778                             gboolean             force_rescan,
779                             GCancellable        *cancellable,
780                             GAsyncReadyCallback  callback,
781                             gpointer             user_data)
782 {
783   GMountIface *iface;
784
785   g_return_if_fail (G_IS_MOUNT (mount));
786
787   iface = G_MOUNT_GET_IFACE (mount);
788
789   if (iface->guess_content_type == NULL)
790     {
791       g_simple_async_report_error_in_idle (G_OBJECT (mount),
792                                            callback, user_data,
793                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
794                                            /* Translators: This is an error
795                                             * message for mount objects that
796                                             * don't implement content type guessing. */
797                                            _("mount doesn't implement content type guessing"));
798
799       return;
800     }
801   
802   (* iface->guess_content_type) (mount, force_rescan, cancellable, callback, user_data);
803 }
804
805 /**
806  * g_mount_guess_content_type_finish:
807  * @mount: a #GMount
808  * @result: a #GAsyncResult
809  * @error: a #GError location to store the error occurring, or %NULL to 
810  *     ignore
811  * 
812  * Finishes guessing content types of @mount. If any errors occurred
813  * during the operation, @error will be set to contain the errors and
814  * %FALSE will be returned. In particular, you may get an 
815  * %G_IO_ERROR_NOT_SUPPORTED if the mount does not support content 
816  * guessing.
817  * 
818  * Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error. 
819  *     Caller should free this array with g_strfreev() when done with it.
820  *
821  * Since: 2.18
822  **/
823 gchar **
824 g_mount_guess_content_type_finish (GMount        *mount,
825                                    GAsyncResult  *result,
826                                    GError       **error)
827 {
828   GMountIface *iface;
829
830   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
831   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
832
833   if (g_async_result_legacy_propagate_error (result, error))
834     return NULL;
835   
836   iface = G_MOUNT_GET_IFACE (mount);
837   return (* iface->guess_content_type_finish) (mount, result, error);
838 }
839
840 /**
841  * g_mount_guess_content_type_sync:
842  * @mount: a #GMount
843  * @force_rescan: Whether to force a rescan of the content.
844  *     Otherwise a cached result will be used if available
845  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
846  * @error: a #GError location to store the error occurring, or %NULL to
847  *     ignore
848  *
849  * Tries to guess the type of content stored on @mount. Returns one or
850  * more textual identifiers of well-known content types (typically
851  * prefixed with "x-content/"), e.g. x-content/image-dcf for camera 
852  * memory cards. See the <ulink url="http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec">shared-mime-info</ulink>
853  * specification for more on x-content types.
854  *
855  * This is an synchronous operation and as such may block doing IO;
856  * see g_mount_guess_content_type() for the asynchronous version.
857  *
858  * Returns: (transfer full) (element-type utf8): a %NULL-terminated array of content types or %NULL on error.
859  *     Caller should free this array with g_strfreev() when done with it.
860  *
861  * Since: 2.18
862  */
863 char **
864 g_mount_guess_content_type_sync (GMount              *mount,
865                                  gboolean             force_rescan,
866                                  GCancellable        *cancellable,
867                                  GError             **error)
868 {
869   GMountIface *iface;
870
871   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
872
873   iface = G_MOUNT_GET_IFACE (mount);
874
875   if (iface->guess_content_type_sync == NULL)
876     {
877       g_set_error_literal (error,
878                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
879                            /* Translators: This is an error
880                             * message for mount objects that
881                             * don't implement content type guessing. */
882                            _("mount doesn't implement synchronous content type guessing"));
883
884       return NULL;
885     }
886
887   return (* iface->guess_content_type_sync) (mount, force_rescan, cancellable, error);
888 }
889
890 G_LOCK_DEFINE_STATIC (priv_lock);
891
892 /* only access this structure when holding priv_lock */
893 typedef struct
894 {
895   gint shadow_ref_count;
896 } GMountPrivate;
897
898 static void
899 free_private (GMountPrivate *private)
900 {
901   G_LOCK (priv_lock);
902   g_free (private);
903   G_UNLOCK (priv_lock);
904 }
905
906 /* may only be called when holding priv_lock */
907 static GMountPrivate *
908 get_private (GMount *mount)
909 {
910   GMountPrivate *private;
911
912   private = g_object_get_data (G_OBJECT (mount), "g-mount-private");
913   if (G_LIKELY (private != NULL))
914     goto out;
915
916   private = g_new0 (GMountPrivate, 1);
917   g_object_set_data_full (G_OBJECT (mount),
918                           "g-mount-private",
919                           private,
920                           (GDestroyNotify) free_private);
921
922  out:
923   return private;
924 }
925
926 /**
927  * g_mount_is_shadowed:
928  * @mount: A #GMount.
929  *
930  * Determines if @mount is shadowed. Applications or libraries should
931  * avoid displaying @mount in the user interface if it is shadowed.
932  *
933  * A mount is said to be shadowed if there exists one or more user
934  * visible objects (currently #GMount objects) with a root that is
935  * inside the root of @mount.
936  *
937  * One application of shadow mounts is when exposing a single file
938  * system that is used to address several logical volumes. In this
939  * situation, a #GVolumeMonitor implementation would create two
940  * #GVolume objects (for example, one for the camera functionality of
941  * the device and one for a SD card reader on the device) with
942  * activation URIs <literal>gphoto2://[usb:001,002]/store1/</literal>
943  * and <literal>gphoto2://[usb:001,002]/store2/</literal>. When the
944  * underlying mount (with root
945  * <literal>gphoto2://[usb:001,002]/</literal>) is mounted, said
946  * #GVolumeMonitor implementation would create two #GMount objects
947  * (each with their root matching the corresponding volume activation
948  * root) that would shadow the original mount.
949  *
950  * The proxy monitor in GVfs 2.26 and later, automatically creates and
951  * manage shadow mounts (and shadows the underlying mount) if the
952  * activation root on a #GVolume is set.
953  *
954  * Returns: %TRUE if @mount is shadowed.
955  *
956  * Since: 2.20
957  **/
958 gboolean
959 g_mount_is_shadowed (GMount *mount)
960 {
961   GMountPrivate *priv;
962   gboolean ret;
963
964   g_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
965
966   G_LOCK (priv_lock);
967   priv = get_private (mount);
968   ret = (priv->shadow_ref_count > 0);
969   G_UNLOCK (priv_lock);
970
971   return ret;
972 }
973
974 /**
975  * g_mount_shadow:
976  * @mount: A #GMount.
977  *
978  * Increments the shadow count on @mount. Usually used by
979  * #GVolumeMonitor implementations when creating a shadow mount for
980  * @mount, see g_mount_is_shadowed() for more information. The caller
981  * will need to emit the #GMount::changed signal on @mount manually.
982  *
983  * Since: 2.20
984  **/
985 void
986 g_mount_shadow (GMount *mount)
987 {
988   GMountPrivate *priv;
989
990   g_return_if_fail (G_IS_MOUNT (mount));
991
992   G_LOCK (priv_lock);
993   priv = get_private (mount);
994   priv->shadow_ref_count += 1;
995   G_UNLOCK (priv_lock);
996 }
997
998 /**
999  * g_mount_unshadow:
1000  * @mount: A #GMount.
1001  *
1002  * Decrements the shadow count on @mount. Usually used by
1003  * #GVolumeMonitor implementations when destroying a shadow mount for
1004  * @mount, see g_mount_is_shadowed() for more information. The caller
1005  * will need to emit the #GMount::changed signal on @mount manually.
1006  *
1007  * Since: 2.20
1008  **/
1009 void
1010 g_mount_unshadow (GMount *mount)
1011 {
1012   GMountPrivate *priv;
1013
1014   g_return_if_fail (G_IS_MOUNT (mount));
1015
1016   G_LOCK (priv_lock);
1017   priv = get_private (mount);
1018   priv->shadow_ref_count -= 1;
1019   if (priv->shadow_ref_count < 0)
1020     g_warning ("Shadow ref count on GMount is negative");
1021   G_UNLOCK (priv_lock);
1022 }
1023
1024 /**
1025  * g_mount_get_sort_key:
1026  * @mount: A #GMount.
1027  *
1028  * Gets the sort key for @mount, if any.
1029  *
1030  * Returns: Sorting key for @mount or %NULL if no such key is available.
1031  *
1032  * Since: 2.32
1033  */
1034 const gchar *
1035 g_mount_get_sort_key (GMount  *mount)
1036 {
1037   const gchar *ret = NULL;
1038   GMountIface *iface;
1039
1040   g_return_val_if_fail (G_IS_MOUNT (mount), NULL);
1041
1042   iface = G_MOUNT_GET_IFACE (mount);
1043   if (iface->get_sort_key != NULL)
1044     ret = iface->get_sort_key (mount);
1045
1046   return ret;
1047 }