Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
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.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : * David Zeuthen <davidz@redhat.com>
22 : : */
23 : :
24 : : #include "config.h"
25 : : #include "gmount.h"
26 : : #include "gvolume.h"
27 : : #include "gthemedicon.h"
28 : : #include "gasyncresult.h"
29 : : #include "gtask.h"
30 : : #include "gioerror.h"
31 : : #include "glibintl.h"
32 : :
33 : :
34 : : /**
35 : : * GVolume:
36 : : *
37 : : * The `GVolume` interface represents user-visible objects that can be
38 : : * mounted. For example, a file system partition on a USB flash drive, or an
39 : : * optical disc inserted into a disc drive.
40 : : *
41 : : * If a `GVolume` is currently mounted, the corresponding [iface@Gio.Mount] can
42 : : * be retrieved using [method@Gio.Volume.get_mount].
43 : : *
44 : : * Mounting a `GVolume` instance is an asynchronous operation. For more
45 : : * information about asynchronous operations, see [iface@Gio.AsyncResult] and
46 : : * [class@Gio.Task]. To mount a `GVolume`, first call [method@Gio.Volume.mount]
47 : : * with (at least) the `GVolume` instance, optionally a
48 : : * [class@Gio.MountOperation] object and a [type@Gio.AsyncReadyCallback].
49 : : *
50 : : * Typically, one will only want to pass `NULL` for the
51 : : * [class@Gio.MountOperation] if automounting all volumes when a desktop session
52 : : * starts since it’s not desirable to put up a lot of dialogs asking
53 : : * for credentials.
54 : : *
55 : : * The callback will be fired when the operation has resolved (either
56 : : * with success or failure), and a [iface@Gio.AsyncResult] instance will be
57 : : * passed to the callback. That callback should then call
58 : : * [method@Gio.Volume.mount_finish] with the `GVolume` instance and the
59 : : * [iface@Gio.AsyncResult] data to see if the operation was completed
60 : : * successfully. If a [type@GLib.Error] is present when
61 : : * [method@Gio.Volume.mount_finish] is called, then it will be filled with any
62 : : * error information.
63 : : *
64 : : * Note, when [porting from GnomeVFS](migrating-gnome-vfs.html),
65 : : * `GVolume` is the moral equivalent of `GnomeVFSDrive`.
66 : : *
67 : : * ## Volume Identifiers
68 : : *
69 : : * It is sometimes necessary to directly access the underlying
70 : : * operating system object behind a volume (e.g. for passing a volume
71 : : * to an application via the command line). For this purpose, GIO
72 : : * allows to obtain an ‘identifier’ for the volume. There can be
73 : : * different kinds of identifiers, such as Hal UDIs, filesystem labels,
74 : : * traditional Unix devices (e.g. `/dev/sda2`), UUIDs. GIO uses predefined
75 : : * strings as names for the different kinds of identifiers:
76 : : * `G_VOLUME_IDENTIFIER_KIND_UUID`, `G_VOLUME_IDENTIFIER_KIND_LABEL`, etc.
77 : : * Use [method@Gio.Volume.get_identifier] to obtain an identifier for a volume.
78 : : *
79 : : * Note that `G_VOLUME_IDENTIFIER_KIND_HAL_UDI` will only be available
80 : : * when the GVFS hal volume monitor is in use. Other volume monitors
81 : : * will generally be able to provide the `G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE`
82 : : * identifier, which can be used to obtain a hal device by means of
83 : : * `libhal_manager_find_device_string_match()`.
84 : : */
85 : :
86 : : typedef GVolumeIface GVolumeInterface;
87 : 13 : G_DEFINE_INTERFACE(GVolume, g_volume, G_TYPE_OBJECT)
88 : :
89 : : static void
90 : 1 : g_volume_default_init (GVolumeInterface *iface)
91 : : {
92 : : /**
93 : : * GVolume::changed:
94 : : *
95 : : * Emitted when the volume has been changed.
96 : : */
97 : 1 : g_signal_new (I_("changed"),
98 : : G_TYPE_VOLUME,
99 : : G_SIGNAL_RUN_LAST,
100 : : G_STRUCT_OFFSET (GVolumeIface, changed),
101 : : NULL, NULL,
102 : : NULL,
103 : : G_TYPE_NONE, 0);
104 : :
105 : : /**
106 : : * GVolume::removed:
107 : : *
108 : : * This signal is emitted when the #GVolume have been removed. If
109 : : * the recipient is holding references to the object they should
110 : : * release them so the object can be finalized.
111 : : */
112 : 1 : g_signal_new (I_("removed"),
113 : : G_TYPE_VOLUME,
114 : : G_SIGNAL_RUN_LAST,
115 : : G_STRUCT_OFFSET (GVolumeIface, removed),
116 : : NULL, NULL,
117 : : NULL,
118 : : G_TYPE_NONE, 0);
119 : 1 : }
120 : :
121 : : /**
122 : : * g_volume_get_name:
123 : : * @volume: a #GVolume
124 : : *
125 : : * Gets the name of @volume.
126 : : *
127 : : * Returns: the name for the given @volume. The returned string should
128 : : * be freed with g_free() when no longer needed.
129 : : */
130 : : char *
131 : 0 : g_volume_get_name (GVolume *volume)
132 : : {
133 : : GVolumeIface *iface;
134 : :
135 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
136 : :
137 : 0 : iface = G_VOLUME_GET_IFACE (volume);
138 : :
139 : 0 : return (* iface->get_name) (volume);
140 : : }
141 : :
142 : : /**
143 : : * g_volume_get_icon:
144 : : * @volume: a #GVolume
145 : : *
146 : : * Gets the icon for @volume.
147 : : *
148 : : * Returns: (transfer full): a #GIcon.
149 : : * The returned object should be unreffed with g_object_unref()
150 : : * when no longer needed.
151 : : */
152 : : GIcon *
153 : 0 : g_volume_get_icon (GVolume *volume)
154 : : {
155 : : GVolumeIface *iface;
156 : :
157 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
158 : :
159 : 0 : iface = G_VOLUME_GET_IFACE (volume);
160 : :
161 : 0 : return (* iface->get_icon) (volume);
162 : : }
163 : :
164 : : /**
165 : : * g_volume_get_symbolic_icon:
166 : : * @volume: a #GVolume
167 : : *
168 : : * Gets the symbolic icon for @volume.
169 : : *
170 : : * Returns: (transfer full): a #GIcon.
171 : : * The returned object should be unreffed with g_object_unref()
172 : : * when no longer needed.
173 : : *
174 : : * Since: 2.34
175 : : */
176 : : GIcon *
177 : 0 : g_volume_get_symbolic_icon (GVolume *volume)
178 : : {
179 : : GVolumeIface *iface;
180 : : GIcon *ret;
181 : :
182 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
183 : :
184 : 0 : iface = G_VOLUME_GET_IFACE (volume);
185 : :
186 : 0 : if (iface->get_symbolic_icon != NULL)
187 : 0 : ret = iface->get_symbolic_icon (volume);
188 : : else
189 : 0 : ret = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic");
190 : :
191 : 0 : return ret;
192 : :
193 : : }
194 : :
195 : : /**
196 : : * g_volume_get_uuid:
197 : : * @volume: a #GVolume
198 : : *
199 : : * Gets the UUID for the @volume. The reference is typically based on
200 : : * the file system UUID for the volume in question and should be
201 : : * considered an opaque string. Returns %NULL if there is no UUID
202 : : * available.
203 : : *
204 : : * Returns: (nullable) (transfer full): the UUID for @volume or %NULL if no UUID
205 : : * can be computed.
206 : : * The returned string should be freed with g_free()
207 : : * when no longer needed.
208 : : */
209 : : char *
210 : 0 : g_volume_get_uuid (GVolume *volume)
211 : : {
212 : : GVolumeIface *iface;
213 : :
214 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
215 : :
216 : 0 : iface = G_VOLUME_GET_IFACE (volume);
217 : :
218 : 0 : return (* iface->get_uuid) (volume);
219 : : }
220 : :
221 : : /**
222 : : * g_volume_get_drive:
223 : : * @volume: a #GVolume
224 : : *
225 : : * Gets the drive for the @volume.
226 : : *
227 : : * Returns: (transfer full) (nullable): a #GDrive or %NULL if @volume is not
228 : : * associated with a drive. The returned object should be unreffed
229 : : * with g_object_unref() when no longer needed.
230 : : */
231 : : GDrive *
232 : 0 : g_volume_get_drive (GVolume *volume)
233 : : {
234 : : GVolumeIface *iface;
235 : :
236 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
237 : :
238 : 0 : iface = G_VOLUME_GET_IFACE (volume);
239 : :
240 : 0 : return (* iface->get_drive) (volume);
241 : : }
242 : :
243 : : /**
244 : : * g_volume_get_mount:
245 : : * @volume: a #GVolume
246 : : *
247 : : * Gets the mount for the @volume.
248 : : *
249 : : * Returns: (transfer full) (nullable): a #GMount or %NULL if @volume isn't mounted.
250 : : * The returned object should be unreffed with g_object_unref()
251 : : * when no longer needed.
252 : : */
253 : : GMount *
254 : 0 : g_volume_get_mount (GVolume *volume)
255 : : {
256 : : GVolumeIface *iface;
257 : :
258 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
259 : :
260 : 0 : iface = G_VOLUME_GET_IFACE (volume);
261 : :
262 : 0 : return (* iface->get_mount) (volume);
263 : : }
264 : :
265 : :
266 : : /**
267 : : * g_volume_can_mount:
268 : : * @volume: a #GVolume
269 : : *
270 : : * Checks if a volume can be mounted.
271 : : *
272 : : * Returns: %TRUE if the @volume can be mounted. %FALSE otherwise
273 : : */
274 : : gboolean
275 : 0 : g_volume_can_mount (GVolume *volume)
276 : : {
277 : : GVolumeIface *iface;
278 : :
279 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
280 : :
281 : 0 : iface = G_VOLUME_GET_IFACE (volume);
282 : :
283 : 0 : if (iface->can_mount == NULL)
284 : 0 : return FALSE;
285 : :
286 : 0 : return (* iface->can_mount) (volume);
287 : : }
288 : :
289 : : /**
290 : : * g_volume_can_eject:
291 : : * @volume: a #GVolume
292 : : *
293 : : * Checks if a volume can be ejected.
294 : : *
295 : : * Returns: %TRUE if the @volume can be ejected. %FALSE otherwise
296 : : */
297 : : gboolean
298 : 0 : g_volume_can_eject (GVolume *volume)
299 : : {
300 : : GVolumeIface *iface;
301 : :
302 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
303 : :
304 : 0 : iface = G_VOLUME_GET_IFACE (volume);
305 : :
306 : 0 : if (iface->can_eject == NULL)
307 : 0 : return FALSE;
308 : :
309 : 0 : return (* iface->can_eject) (volume);
310 : : }
311 : :
312 : : /**
313 : : * g_volume_should_automount:
314 : : * @volume: a #GVolume
315 : : *
316 : : * Returns whether the volume should be automatically mounted.
317 : : *
318 : : * Returns: %TRUE if the volume should be automatically mounted
319 : : */
320 : : gboolean
321 : 0 : g_volume_should_automount (GVolume *volume)
322 : : {
323 : : GVolumeIface *iface;
324 : :
325 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
326 : :
327 : 0 : iface = G_VOLUME_GET_IFACE (volume);
328 : :
329 : 0 : if (iface->should_automount == NULL)
330 : 0 : return FALSE;
331 : :
332 : 0 : return (* iface->should_automount) (volume);
333 : : }
334 : :
335 : :
336 : : /**
337 : : * g_volume_mount: (virtual mount_fn)
338 : : * @volume: a #GVolume
339 : : * @flags: flags affecting the operation
340 : : * @mount_operation: (nullable): a #GMountOperation or %NULL to avoid user interaction
341 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
342 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL
343 : : * @user_data: user data that gets passed to @callback
344 : : *
345 : : * Mounts a volume. This is an asynchronous operation, and is
346 : : * finished by calling g_volume_mount_finish() with the @volume
347 : : * and #GAsyncResult returned in the @callback.
348 : : */
349 : : void
350 : 0 : g_volume_mount (GVolume *volume,
351 : : GMountMountFlags flags,
352 : : GMountOperation *mount_operation,
353 : : GCancellable *cancellable,
354 : : GAsyncReadyCallback callback,
355 : : gpointer user_data)
356 : : {
357 : : GVolumeIface *iface;
358 : :
359 : 0 : g_return_if_fail (G_IS_VOLUME (volume));
360 : :
361 : 0 : iface = G_VOLUME_GET_IFACE (volume);
362 : :
363 : 0 : if (iface->mount_fn == NULL)
364 : : {
365 : 0 : g_task_report_new_error (volume, callback, user_data,
366 : : g_volume_mount,
367 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
368 : 0 : _("volume doesn’t implement mount"));
369 : 0 : return;
370 : : }
371 : :
372 : 0 : (* iface->mount_fn) (volume, flags, mount_operation, cancellable, callback, user_data);
373 : : }
374 : :
375 : : /**
376 : : * g_volume_mount_finish:
377 : : * @volume: a #GVolume
378 : : * @result: a #GAsyncResult
379 : : * @error: a #GError location to store an error, or %NULL to ignore
380 : : *
381 : : * Finishes mounting a volume. If any errors occurred during the operation,
382 : : * @error will be set to contain the errors and %FALSE will be returned.
383 : : *
384 : : * If the mount operation succeeded, g_volume_get_mount() on @volume
385 : : * is guaranteed to return the mount right after calling this
386 : : * function; there's no need to listen for the 'mount-added' signal on
387 : : * #GVolumeMonitor.
388 : : *
389 : : * Returns: %TRUE, %FALSE if operation failed
390 : : */
391 : : gboolean
392 : 0 : g_volume_mount_finish (GVolume *volume,
393 : : GAsyncResult *result,
394 : : GError **error)
395 : : {
396 : : GVolumeIface *iface;
397 : :
398 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
399 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
400 : :
401 : 0 : if (g_async_result_legacy_propagate_error (result, error))
402 : 0 : return FALSE;
403 : 0 : else if (g_async_result_is_tagged (result, g_volume_mount))
404 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
405 : :
406 : 0 : iface = G_VOLUME_GET_IFACE (volume);
407 : 0 : return (* iface->mount_finish) (volume, result, error);
408 : : }
409 : :
410 : : /**
411 : : * g_volume_eject:
412 : : * @volume: a #GVolume
413 : : * @flags: flags affecting the unmount if required for eject
414 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
415 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL
416 : : * @user_data: user data that gets passed to @callback
417 : : *
418 : : * Ejects a volume. This is an asynchronous operation, and is
419 : : * finished by calling g_volume_eject_finish() with the @volume
420 : : * and #GAsyncResult returned in the @callback.
421 : : *
422 : : * Deprecated: 2.22: Use g_volume_eject_with_operation() instead.
423 : : */
424 : : void
425 : 0 : g_volume_eject (GVolume *volume,
426 : : GMountUnmountFlags flags,
427 : : GCancellable *cancellable,
428 : : GAsyncReadyCallback callback,
429 : : gpointer user_data)
430 : : {
431 : : GVolumeIface *iface;
432 : :
433 : 0 : g_return_if_fail (G_IS_VOLUME (volume));
434 : :
435 : 0 : iface = G_VOLUME_GET_IFACE (volume);
436 : :
437 : 0 : if (iface->eject == NULL)
438 : : {
439 : 0 : g_task_report_new_error (volume, callback, user_data,
440 : : g_volume_eject_with_operation,
441 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
442 : 0 : _("volume doesn’t implement eject"));
443 : 0 : return;
444 : : }
445 : :
446 : 0 : (* iface->eject) (volume, flags, cancellable, callback, user_data);
447 : : }
448 : :
449 : : /**
450 : : * g_volume_eject_finish:
451 : : * @volume: pointer to a #GVolume
452 : : * @result: a #GAsyncResult
453 : : * @error: a #GError location to store an error, or %NULL to ignore
454 : : *
455 : : * Finishes ejecting a volume. If any errors occurred during the operation,
456 : : * @error will be set to contain the errors and %FALSE will be returned.
457 : : *
458 : : * Returns: %TRUE, %FALSE if operation failed
459 : : *
460 : : * Deprecated: 2.22: Use g_volume_eject_with_operation_finish() instead.
461 : : **/
462 : : gboolean
463 : 0 : g_volume_eject_finish (GVolume *volume,
464 : : GAsyncResult *result,
465 : : GError **error)
466 : : {
467 : : GVolumeIface *iface;
468 : :
469 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
470 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
471 : :
472 : 0 : if (g_async_result_legacy_propagate_error (result, error))
473 : 0 : return FALSE;
474 : 0 : if (g_async_result_is_tagged (result, g_volume_eject_with_operation))
475 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
476 : :
477 : 0 : iface = G_VOLUME_GET_IFACE (volume);
478 : 0 : return (* iface->eject_finish) (volume, result, error);
479 : : }
480 : :
481 : : /**
482 : : * g_volume_eject_with_operation:
483 : : * @volume: a #GVolume
484 : : * @flags: flags affecting the unmount if required for eject
485 : : * @mount_operation: (nullable): a #GMountOperation or %NULL to
486 : : * avoid user interaction
487 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
488 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL
489 : : * @user_data: user data passed to @callback
490 : : *
491 : : * Ejects a volume. This is an asynchronous operation, and is
492 : : * finished by calling g_volume_eject_with_operation_finish() with the @volume
493 : : * and #GAsyncResult data returned in the @callback.
494 : : *
495 : : * Since: 2.22
496 : : **/
497 : : void
498 : 0 : g_volume_eject_with_operation (GVolume *volume,
499 : : GMountUnmountFlags flags,
500 : : GMountOperation *mount_operation,
501 : : GCancellable *cancellable,
502 : : GAsyncReadyCallback callback,
503 : : gpointer user_data)
504 : : {
505 : : GVolumeIface *iface;
506 : :
507 : 0 : g_return_if_fail (G_IS_VOLUME (volume));
508 : :
509 : 0 : iface = G_VOLUME_GET_IFACE (volume);
510 : :
511 : 0 : if (iface->eject == NULL && iface->eject_with_operation == NULL)
512 : : {
513 : 0 : g_task_report_new_error (volume, callback, user_data,
514 : : g_volume_eject_with_operation,
515 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
516 : : /* Translators: This is an error
517 : : * message for volume objects that
518 : : * don't implement any of eject or eject_with_operation. */
519 : 0 : _("volume doesn’t implement eject or eject_with_operation"));
520 : 0 : return;
521 : : }
522 : :
523 : 0 : if (iface->eject_with_operation != NULL)
524 : 0 : (* iface->eject_with_operation) (volume, flags, mount_operation, cancellable, callback, user_data);
525 : : else
526 : 0 : (* iface->eject) (volume, flags, cancellable, callback, user_data);
527 : : }
528 : :
529 : : /**
530 : : * g_volume_eject_with_operation_finish:
531 : : * @volume: a #GVolume
532 : : * @result: a #GAsyncResult
533 : : * @error: a #GError location to store the error occurring, or %NULL
534 : : *
535 : : * Finishes ejecting a volume. If any errors occurred during the operation,
536 : : * @error will be set to contain the errors and %FALSE will be returned.
537 : : *
538 : : * Returns: %TRUE if the volume was successfully ejected. %FALSE otherwise
539 : : *
540 : : * Since: 2.22
541 : : **/
542 : : gboolean
543 : 0 : g_volume_eject_with_operation_finish (GVolume *volume,
544 : : GAsyncResult *result,
545 : : GError **error)
546 : : {
547 : : GVolumeIface *iface;
548 : :
549 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
550 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
551 : :
552 : 0 : if (g_async_result_legacy_propagate_error (result, error))
553 : 0 : return FALSE;
554 : 0 : else if (g_async_result_is_tagged (result, g_volume_eject_with_operation))
555 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
556 : :
557 : 0 : iface = G_VOLUME_GET_IFACE (volume);
558 : 0 : if (iface->eject_with_operation_finish != NULL)
559 : 0 : return (* iface->eject_with_operation_finish) (volume, result, error);
560 : : else
561 : 0 : return (* iface->eject_finish) (volume, result, error);
562 : : }
563 : :
564 : : /**
565 : : * g_volume_get_identifier:
566 : : * @volume: a #GVolume
567 : : * @kind: the kind of identifier to return
568 : : *
569 : : * Gets the identifier of the given kind for @volume.
570 : : * See the [introduction](#volume-identifiers) for more
571 : : * information about volume identifiers.
572 : : *
573 : : * Returns: (nullable) (transfer full): a newly allocated string containing the
574 : : * requested identifier, or %NULL if the #GVolume
575 : : * doesn't have this kind of identifier
576 : : */
577 : : char *
578 : 0 : g_volume_get_identifier (GVolume *volume,
579 : : const char *kind)
580 : : {
581 : : GVolumeIface *iface;
582 : :
583 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
584 : 0 : g_return_val_if_fail (kind != NULL, NULL);
585 : :
586 : 0 : iface = G_VOLUME_GET_IFACE (volume);
587 : :
588 : 0 : if (iface->get_identifier == NULL)
589 : 0 : return NULL;
590 : :
591 : 0 : return (* iface->get_identifier) (volume, kind);
592 : : }
593 : :
594 : : /**
595 : : * g_volume_enumerate_identifiers:
596 : : * @volume: a #GVolume
597 : : *
598 : : * Gets the kinds of [identifiers](#volume-identifiers) that @volume has.
599 : : * Use g_volume_get_identifier() to obtain the identifiers themselves.
600 : : *
601 : : * Returns: (array zero-terminated=1) (transfer full): a %NULL-terminated array
602 : : * of strings containing kinds of identifiers. Use g_strfreev() to free.
603 : : */
604 : : char **
605 : 0 : g_volume_enumerate_identifiers (GVolume *volume)
606 : : {
607 : : GVolumeIface *iface;
608 : :
609 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
610 : 0 : iface = G_VOLUME_GET_IFACE (volume);
611 : :
612 : 0 : if (iface->enumerate_identifiers == NULL)
613 : 0 : return NULL;
614 : :
615 : 0 : return (* iface->enumerate_identifiers) (volume);
616 : : }
617 : :
618 : : /**
619 : : * g_volume_get_activation_root:
620 : : * @volume: a #GVolume
621 : : *
622 : : * Gets the activation root for a #GVolume if it is known ahead of
623 : : * mount time. Returns %NULL otherwise. If not %NULL and if @volume
624 : : * is mounted, then the result of g_mount_get_root() on the
625 : : * #GMount object obtained from g_volume_get_mount() will always
626 : : * either be equal or a prefix of what this function returns. In
627 : : * other words, in code
628 : : *
629 : : * |[<!-- language="C" -->
630 : : * GMount *mount;
631 : : * GFile *mount_root
632 : : * GFile *volume_activation_root;
633 : : *
634 : : * mount = g_volume_get_mount (volume); // mounted, so never NULL
635 : : * mount_root = g_mount_get_root (mount);
636 : : * volume_activation_root = g_volume_get_activation_root (volume); // assume not NULL
637 : : * ]|
638 : : * then the expression
639 : : * |[<!-- language="C" -->
640 : : * (g_file_has_prefix (volume_activation_root, mount_root) ||
641 : : * g_file_equal (volume_activation_root, mount_root))
642 : : * ]|
643 : : * will always be %TRUE.
644 : : *
645 : : * Activation roots are typically used in #GVolumeMonitor
646 : : * implementations to find the underlying mount to shadow, see
647 : : * g_mount_is_shadowed() for more details.
648 : : *
649 : : * Returns: (nullable) (transfer full): the activation root of @volume
650 : : * or %NULL. Use g_object_unref() to free.
651 : : *
652 : : * Since: 2.18
653 : : */
654 : : GFile *
655 : 0 : g_volume_get_activation_root (GVolume *volume)
656 : : {
657 : : GVolumeIface *iface;
658 : :
659 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
660 : 0 : iface = G_VOLUME_GET_IFACE (volume);
661 : :
662 : 0 : if (iface->get_activation_root == NULL)
663 : 0 : return NULL;
664 : :
665 : 0 : return (* iface->get_activation_root) (volume);
666 : : }
667 : :
668 : : /**
669 : : * g_volume_get_sort_key:
670 : : * @volume: a #GVolume
671 : : *
672 : : * Gets the sort key for @volume, if any.
673 : : *
674 : : * Returns: (nullable): Sorting key for @volume or %NULL if no such key is available
675 : : *
676 : : * Since: 2.32
677 : : */
678 : : const gchar *
679 : 0 : g_volume_get_sort_key (GVolume *volume)
680 : : {
681 : 0 : const gchar *ret = NULL;
682 : : GVolumeIface *iface;
683 : :
684 : 0 : g_return_val_if_fail (G_IS_VOLUME (volume), NULL);
685 : :
686 : 0 : iface = G_VOLUME_GET_IFACE (volume);
687 : 0 : if (iface->get_sort_key != NULL)
688 : 0 : ret = iface->get_sort_key (volume);
689 : :
690 : 0 : return ret;
691 : : }
|