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