Coverage Report

Created: 2025-06-13 06:55

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