/src/pango/subprojects/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 | | * 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 | | G_DEFINE_INTERFACE(GVolume, g_volume, G_TYPE_OBJECT) |
88 | | |
89 | | static void |
90 | | g_volume_default_init (GVolumeInterface *iface) |
91 | 0 | { |
92 | | /** |
93 | | * GVolume::changed: |
94 | | * |
95 | | * Emitted when the volume has been changed. |
96 | | */ |
97 | 0 | g_signal_new (I_("changed"), |
98 | 0 | G_TYPE_VOLUME, |
99 | 0 | G_SIGNAL_RUN_LAST, |
100 | 0 | G_STRUCT_OFFSET (GVolumeIface, changed), |
101 | 0 | NULL, NULL, |
102 | 0 | NULL, |
103 | 0 | 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 | 0 | g_signal_new (I_("removed"), |
113 | 0 | G_TYPE_VOLUME, |
114 | 0 | G_SIGNAL_RUN_LAST, |
115 | 0 | G_STRUCT_OFFSET (GVolumeIface, removed), |
116 | 0 | NULL, NULL, |
117 | 0 | NULL, |
118 | 0 | G_TYPE_NONE, 0); |
119 | 0 | } |
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 | | g_volume_get_name (GVolume *volume) |
132 | 0 | { |
133 | 0 | 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 | 0 | } |
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 | | g_volume_get_icon (GVolume *volume) |
154 | 0 | { |
155 | 0 | 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 | 0 | } |
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 | | g_volume_get_symbolic_icon (GVolume *volume) |
178 | 0 | { |
179 | 0 | GVolumeIface *iface; |
180 | 0 | 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 | 0 | else |
189 | 0 | ret = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic"); |
190 | |
|
191 | 0 | return ret; |
192 | |
|
193 | 0 | } |
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 | | g_volume_get_uuid (GVolume *volume) |
211 | 0 | { |
212 | 0 | 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 | 0 | } |
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 | | g_volume_get_drive (GVolume *volume) |
233 | 0 | { |
234 | 0 | 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 | 0 | } |
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 | | g_volume_get_mount (GVolume *volume) |
255 | 0 | { |
256 | 0 | 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 | 0 | } |
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 | | g_volume_can_mount (GVolume *volume) |
276 | 0 | { |
277 | 0 | 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 | 0 | } |
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 | | g_volume_can_eject (GVolume *volume) |
299 | 0 | { |
300 | 0 | 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 | 0 | } |
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 | | g_volume_should_automount (GVolume *volume) |
322 | 0 | { |
323 | 0 | 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 | 0 | } |
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 | | g_volume_mount (GVolume *volume, |
351 | | GMountMountFlags flags, |
352 | | GMountOperation *mount_operation, |
353 | | GCancellable *cancellable, |
354 | | GAsyncReadyCallback callback, |
355 | | gpointer user_data) |
356 | 0 | { |
357 | 0 | 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 | 0 | { |
365 | 0 | g_task_report_new_error (volume, callback, user_data, |
366 | 0 | g_volume_mount, |
367 | 0 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
368 | 0 | _("volume doesn’t implement mount")); |
369 | 0 | return; |
370 | 0 | } |
371 | | |
372 | 0 | (* iface->mount_fn) (volume, flags, mount_operation, cancellable, callback, user_data); |
373 | 0 | } |
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 | | g_volume_mount_finish (GVolume *volume, |
393 | | GAsyncResult *result, |
394 | | GError **error) |
395 | 0 | { |
396 | 0 | 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 | 0 | } |
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 | | g_volume_eject (GVolume *volume, |
426 | | GMountUnmountFlags flags, |
427 | | GCancellable *cancellable, |
428 | | GAsyncReadyCallback callback, |
429 | | gpointer user_data) |
430 | 0 | { |
431 | 0 | 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 | 0 | { |
439 | 0 | g_task_report_new_error (volume, callback, user_data, |
440 | 0 | g_volume_eject_with_operation, |
441 | 0 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
442 | 0 | _("volume doesn’t implement eject")); |
443 | 0 | return; |
444 | 0 | } |
445 | | |
446 | 0 | (* iface->eject) (volume, flags, cancellable, callback, user_data); |
447 | 0 | } |
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 | | g_volume_eject_finish (GVolume *volume, |
464 | | GAsyncResult *result, |
465 | | GError **error) |
466 | 0 | { |
467 | 0 | 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 | 0 | } |
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 | | 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 | 0 | { |
505 | 0 | 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 | 0 | { |
513 | 0 | g_task_report_new_error (volume, callback, user_data, |
514 | 0 | g_volume_eject_with_operation, |
515 | 0 | 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 | 0 | } |
522 | | |
523 | 0 | if (iface->eject_with_operation != NULL) |
524 | 0 | (* iface->eject_with_operation) (volume, flags, mount_operation, cancellable, callback, user_data); |
525 | 0 | else |
526 | 0 | (* iface->eject) (volume, flags, cancellable, callback, user_data); |
527 | 0 | } |
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 | | g_volume_eject_with_operation_finish (GVolume *volume, |
544 | | GAsyncResult *result, |
545 | | GError **error) |
546 | 0 | { |
547 | 0 | 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 | 0 | else |
561 | 0 | return (* iface->eject_finish) (volume, result, error); |
562 | 0 | } |
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 | | g_volume_get_identifier (GVolume *volume, |
579 | | const char *kind) |
580 | 0 | { |
581 | 0 | 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 | 0 | } |
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 | | g_volume_enumerate_identifiers (GVolume *volume) |
606 | 0 | { |
607 | 0 | 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 | 0 | } |
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 | | g_volume_get_activation_root (GVolume *volume) |
656 | 0 | { |
657 | 0 | 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 | 0 | } |
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 | | g_volume_get_sort_key (GVolume *volume) |
680 | 0 | { |
681 | 0 | const gchar *ret = NULL; |
682 | 0 | 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 | 0 | } |