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