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 | } |