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