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 | | * This library is free software; you can redistribute it and/or |
6 | | * modify it under the terms of the GNU Lesser General Public |
7 | | * License as published by the Free Software Foundation; either |
8 | | * version 2.1 of the License, or (at your option) any later version. |
9 | | * |
10 | | * This library is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | | * Lesser General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU Lesser General |
16 | | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
17 | | * |
18 | | * Author: Alexander Larsson <alexl@redhat.com> |
19 | | * David Zeuthen <davidz@redhat.com> |
20 | | */ |
21 | | |
22 | | #include "config.h" |
23 | | #include "gmount.h" |
24 | | #include "gvolume.h" |
25 | | #include "gthemedicon.h" |
26 | | #include "gasyncresult.h" |
27 | | #include "gtask.h" |
28 | | #include "gioerror.h" |
29 | | #include "glibintl.h" |
30 | | |
31 | | |
32 | | /** |
33 | | * SECTION:gvolume |
34 | | * @short_description: Volume management |
35 | | * @include: gio/gio.h |
36 | | * |
37 | | * The #GVolume interface represents user-visible objects that can be |
38 | | * mounted. Note, when porting from GnomeVFS, #GVolume is the moral |
39 | | * equivalent of #GnomeVFSDrive. |
40 | | * |
41 | | * Mounting a #GVolume instance is an asynchronous operation. For more |
42 | | * information about asynchronous operations, see #GAsyncResult and |
43 | | * #GTask. To mount a #GVolume, first call g_volume_mount() with (at |
44 | | * least) the #GVolume instance, optionally a #GMountOperation object |
45 | | * and a #GAsyncReadyCallback. |
46 | | * |
47 | | * Typically, one will only want to pass %NULL for the |
48 | | * #GMountOperation 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 #GAsyncResult instance will be |
54 | | * passed to the callback. That callback should then call |
55 | | * g_volume_mount_finish() with the #GVolume instance and the |
56 | | * #GAsyncResult data to see if the operation was completed |
57 | | * successfully. If an @error is present when g_volume_mount_finish() |
58 | | * is called, then it will be filled with any error information. |
59 | | * |
60 | | * ## Volume Identifiers # {#volume-identifier} |
61 | | * |
62 | | * It is sometimes necessary to directly access the underlying |
63 | | * operating system object behind a volume (e.g. for passing a volume |
64 | | * to an application via the commandline). For this purpose, GIO |
65 | | * allows to obtain an 'identifier' for the volume. There can be |
66 | | * different kinds of identifiers, such as Hal UDIs, filesystem labels, |
67 | | * traditional Unix devices (e.g. `/dev/sda2`), UUIDs. GIO uses predefined |
68 | | * strings as names for the different kinds of identifiers: |
69 | | * #G_VOLUME_IDENTIFIER_KIND_UUID, #G_VOLUME_IDENTIFIER_KIND_LABEL, etc. |
70 | | * Use g_volume_get_identifier() to obtain an identifier for a volume. |
71 | | * |
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 | | G_DEFINE_INTERFACE(GVolume, g_volume, G_TYPE_OBJECT) |
82 | | |
83 | | static void |
84 | | g_volume_default_init (GVolumeInterface *iface) |
85 | 0 | { |
86 | | /** |
87 | | * GVolume::changed: |
88 | | * |
89 | | * Emitted when the volume has been changed. |
90 | | */ |
91 | 0 | g_signal_new (I_("changed"), |
92 | 0 | G_TYPE_VOLUME, |
93 | 0 | G_SIGNAL_RUN_LAST, |
94 | 0 | G_STRUCT_OFFSET (GVolumeIface, changed), |
95 | 0 | NULL, NULL, |
96 | 0 | NULL, |
97 | 0 | 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 | 0 | g_signal_new (I_("removed"), |
107 | 0 | G_TYPE_VOLUME, |
108 | 0 | G_SIGNAL_RUN_LAST, |
109 | 0 | G_STRUCT_OFFSET (GVolumeIface, removed), |
110 | 0 | NULL, NULL, |
111 | 0 | NULL, |
112 | 0 | G_TYPE_NONE, 0); |
113 | 0 | } |
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 | | g_volume_get_name (GVolume *volume) |
126 | 0 | { |
127 | 0 | 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 | 0 | } |
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 | | g_volume_get_icon (GVolume *volume) |
148 | 0 | { |
149 | 0 | 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 | 0 | } |
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 | | g_volume_get_symbolic_icon (GVolume *volume) |
172 | 0 | { |
173 | 0 | GVolumeIface *iface; |
174 | 0 | 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 | 0 | else |
183 | 0 | ret = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic"); |
184 | |
|
185 | 0 | return ret; |
186 | |
|
187 | 0 | } |
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 | | g_volume_get_uuid (GVolume *volume) |
205 | 0 | { |
206 | 0 | 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 | 0 | } |
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 | | g_volume_get_drive (GVolume *volume) |
227 | 0 | { |
228 | 0 | 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 | 0 | } |
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 | | g_volume_get_mount (GVolume *volume) |
249 | 0 | { |
250 | 0 | 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 | 0 | } |
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 | | g_volume_can_mount (GVolume *volume) |
270 | 0 | { |
271 | 0 | 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 | 0 | } |
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 | | g_volume_can_eject (GVolume *volume) |
293 | 0 | { |
294 | 0 | 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 | 0 | } |
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 | | g_volume_should_automount (GVolume *volume) |
316 | 0 | { |
317 | 0 | 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 | 0 | } |
328 | | |
329 | | |
330 | | /** |
331 | | * g_volume_mount: |
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 | | * Virtual: mount_fn |
344 | | */ |
345 | | void |
346 | | g_volume_mount (GVolume *volume, |
347 | | GMountMountFlags flags, |
348 | | GMountOperation *mount_operation, |
349 | | GCancellable *cancellable, |
350 | | GAsyncReadyCallback callback, |
351 | | gpointer user_data) |
352 | 0 | { |
353 | 0 | GVolumeIface *iface; |
354 | |
|
355 | 0 | g_return_if_fail (G_IS_VOLUME (volume)); |
356 | | |
357 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
358 | |
|
359 | 0 | if (iface->mount_fn == NULL) |
360 | 0 | { |
361 | 0 | g_task_report_new_error (volume, callback, user_data, |
362 | 0 | g_volume_mount, |
363 | 0 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
364 | 0 | _("volume doesn’t implement mount")); |
365 | 0 | return; |
366 | 0 | } |
367 | | |
368 | 0 | (* iface->mount_fn) (volume, flags, mount_operation, cancellable, callback, user_data); |
369 | 0 | } |
370 | | |
371 | | /** |
372 | | * g_volume_mount_finish: |
373 | | * @volume: a #GVolume |
374 | | * @result: a #GAsyncResult |
375 | | * @error: a #GError location to store an error, or %NULL to ignore |
376 | | * |
377 | | * Finishes mounting a volume. If any errors occurred during the operation, |
378 | | * @error will be set to contain the errors and %FALSE will be returned. |
379 | | * |
380 | | * If the mount operation succeeded, g_volume_get_mount() on @volume |
381 | | * is guaranteed to return the mount right after calling this |
382 | | * function; there's no need to listen for the 'mount-added' signal on |
383 | | * #GVolumeMonitor. |
384 | | * |
385 | | * Returns: %TRUE, %FALSE if operation failed |
386 | | */ |
387 | | gboolean |
388 | | g_volume_mount_finish (GVolume *volume, |
389 | | GAsyncResult *result, |
390 | | GError **error) |
391 | 0 | { |
392 | 0 | GVolumeIface *iface; |
393 | |
|
394 | 0 | g_return_val_if_fail (G_IS_VOLUME (volume), FALSE); |
395 | 0 | g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE); |
396 | | |
397 | 0 | if (g_async_result_legacy_propagate_error (result, error)) |
398 | 0 | return FALSE; |
399 | 0 | else if (g_async_result_is_tagged (result, g_volume_mount)) |
400 | 0 | return g_task_propagate_boolean (G_TASK (result), error); |
401 | | |
402 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
403 | 0 | return (* iface->mount_finish) (volume, result, error); |
404 | 0 | } |
405 | | |
406 | | /** |
407 | | * g_volume_eject: |
408 | | * @volume: a #GVolume |
409 | | * @flags: flags affecting the unmount if required for eject |
410 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore |
411 | | * @callback: (nullable): a #GAsyncReadyCallback, or %NULL |
412 | | * @user_data: user data that gets passed to @callback |
413 | | * |
414 | | * Ejects a volume. This is an asynchronous operation, and is |
415 | | * finished by calling g_volume_eject_finish() with the @volume |
416 | | * and #GAsyncResult returned in the @callback. |
417 | | * |
418 | | * Deprecated: 2.22: Use g_volume_eject_with_operation() instead. |
419 | | */ |
420 | | void |
421 | | g_volume_eject (GVolume *volume, |
422 | | GMountUnmountFlags flags, |
423 | | GCancellable *cancellable, |
424 | | GAsyncReadyCallback callback, |
425 | | gpointer user_data) |
426 | 0 | { |
427 | 0 | GVolumeIface *iface; |
428 | |
|
429 | 0 | g_return_if_fail (G_IS_VOLUME (volume)); |
430 | | |
431 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
432 | |
|
433 | 0 | if (iface->eject == NULL) |
434 | 0 | { |
435 | 0 | g_task_report_new_error (volume, callback, user_data, |
436 | 0 | g_volume_eject_with_operation, |
437 | 0 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
438 | 0 | _("volume doesn’t implement eject")); |
439 | 0 | return; |
440 | 0 | } |
441 | | |
442 | 0 | (* iface->eject) (volume, flags, cancellable, callback, user_data); |
443 | 0 | } |
444 | | |
445 | | /** |
446 | | * g_volume_eject_finish: |
447 | | * @volume: pointer to a #GVolume |
448 | | * @result: a #GAsyncResult |
449 | | * @error: a #GError location to store an error, or %NULL to ignore |
450 | | * |
451 | | * Finishes ejecting a volume. If any errors occurred during the operation, |
452 | | * @error will be set to contain the errors and %FALSE will be returned. |
453 | | * |
454 | | * Returns: %TRUE, %FALSE if operation failed |
455 | | * |
456 | | * Deprecated: 2.22: Use g_volume_eject_with_operation_finish() instead. |
457 | | **/ |
458 | | gboolean |
459 | | g_volume_eject_finish (GVolume *volume, |
460 | | GAsyncResult *result, |
461 | | GError **error) |
462 | 0 | { |
463 | 0 | GVolumeIface *iface; |
464 | |
|
465 | 0 | g_return_val_if_fail (G_IS_VOLUME (volume), FALSE); |
466 | 0 | g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE); |
467 | | |
468 | 0 | if (g_async_result_legacy_propagate_error (result, error)) |
469 | 0 | return FALSE; |
470 | 0 | if (g_async_result_is_tagged (result, g_volume_eject_with_operation)) |
471 | 0 | return g_task_propagate_boolean (G_TASK (result), error); |
472 | | |
473 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
474 | 0 | return (* iface->eject_finish) (volume, result, error); |
475 | 0 | } |
476 | | |
477 | | /** |
478 | | * g_volume_eject_with_operation: |
479 | | * @volume: a #GVolume |
480 | | * @flags: flags affecting the unmount if required for eject |
481 | | * @mount_operation: (nullable): a #GMountOperation or %NULL to |
482 | | * avoid user interaction |
483 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore |
484 | | * @callback: (nullable): a #GAsyncReadyCallback, or %NULL |
485 | | * @user_data: user data passed to @callback |
486 | | * |
487 | | * Ejects a volume. This is an asynchronous operation, and is |
488 | | * finished by calling g_volume_eject_with_operation_finish() with the @volume |
489 | | * and #GAsyncResult data returned in the @callback. |
490 | | * |
491 | | * Since: 2.22 |
492 | | **/ |
493 | | void |
494 | | g_volume_eject_with_operation (GVolume *volume, |
495 | | GMountUnmountFlags flags, |
496 | | GMountOperation *mount_operation, |
497 | | GCancellable *cancellable, |
498 | | GAsyncReadyCallback callback, |
499 | | gpointer user_data) |
500 | 0 | { |
501 | 0 | GVolumeIface *iface; |
502 | |
|
503 | 0 | g_return_if_fail (G_IS_VOLUME (volume)); |
504 | | |
505 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
506 | |
|
507 | 0 | if (iface->eject == NULL && iface->eject_with_operation == NULL) |
508 | 0 | { |
509 | 0 | g_task_report_new_error (volume, callback, user_data, |
510 | 0 | g_volume_eject_with_operation, |
511 | 0 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
512 | | /* Translators: This is an error |
513 | | * message for volume objects that |
514 | | * don't implement any of eject or eject_with_operation. */ |
515 | 0 | _("volume doesn’t implement eject or eject_with_operation")); |
516 | 0 | return; |
517 | 0 | } |
518 | | |
519 | 0 | if (iface->eject_with_operation != NULL) |
520 | 0 | (* iface->eject_with_operation) (volume, flags, mount_operation, cancellable, callback, user_data); |
521 | 0 | else |
522 | 0 | (* iface->eject) (volume, flags, cancellable, callback, user_data); |
523 | 0 | } |
524 | | |
525 | | /** |
526 | | * g_volume_eject_with_operation_finish: |
527 | | * @volume: a #GVolume |
528 | | * @result: a #GAsyncResult |
529 | | * @error: a #GError location to store the error occurring, or %NULL |
530 | | * |
531 | | * Finishes ejecting a volume. If any errors occurred during the operation, |
532 | | * @error will be set to contain the errors and %FALSE will be returned. |
533 | | * |
534 | | * Returns: %TRUE if the volume was successfully ejected. %FALSE otherwise |
535 | | * |
536 | | * Since: 2.22 |
537 | | **/ |
538 | | gboolean |
539 | | g_volume_eject_with_operation_finish (GVolume *volume, |
540 | | GAsyncResult *result, |
541 | | GError **error) |
542 | 0 | { |
543 | 0 | GVolumeIface *iface; |
544 | |
|
545 | 0 | g_return_val_if_fail (G_IS_VOLUME (volume), FALSE); |
546 | 0 | g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE); |
547 | | |
548 | 0 | if (g_async_result_legacy_propagate_error (result, error)) |
549 | 0 | return FALSE; |
550 | 0 | else if (g_async_result_is_tagged (result, g_volume_eject_with_operation)) |
551 | 0 | return g_task_propagate_boolean (G_TASK (result), error); |
552 | | |
553 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
554 | 0 | if (iface->eject_with_operation_finish != NULL) |
555 | 0 | return (* iface->eject_with_operation_finish) (volume, result, error); |
556 | 0 | else |
557 | 0 | return (* iface->eject_finish) (volume, result, error); |
558 | 0 | } |
559 | | |
560 | | /** |
561 | | * g_volume_get_identifier: |
562 | | * @volume: a #GVolume |
563 | | * @kind: the kind of identifier to return |
564 | | * |
565 | | * Gets the identifier of the given kind for @volume. |
566 | | * See the [introduction][volume-identifier] for more |
567 | | * information about volume identifiers. |
568 | | * |
569 | | * Returns: (nullable) (transfer full): a newly allocated string containing the |
570 | | * requested identifier, or %NULL if the #GVolume |
571 | | * doesn't have this kind of identifier |
572 | | */ |
573 | | char * |
574 | | g_volume_get_identifier (GVolume *volume, |
575 | | const char *kind) |
576 | 0 | { |
577 | 0 | GVolumeIface *iface; |
578 | |
|
579 | 0 | g_return_val_if_fail (G_IS_VOLUME (volume), NULL); |
580 | 0 | g_return_val_if_fail (kind != NULL, NULL); |
581 | | |
582 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
583 | |
|
584 | 0 | if (iface->get_identifier == NULL) |
585 | 0 | return NULL; |
586 | | |
587 | 0 | return (* iface->get_identifier) (volume, kind); |
588 | 0 | } |
589 | | |
590 | | /** |
591 | | * g_volume_enumerate_identifiers: |
592 | | * @volume: a #GVolume |
593 | | * |
594 | | * Gets the kinds of [identifiers][volume-identifier] that @volume has. |
595 | | * Use g_volume_get_identifier() to obtain the identifiers themselves. |
596 | | * |
597 | | * Returns: (array zero-terminated=1) (transfer full): a %NULL-terminated array |
598 | | * of strings containing kinds of identifiers. Use g_strfreev() to free. |
599 | | */ |
600 | | char ** |
601 | | g_volume_enumerate_identifiers (GVolume *volume) |
602 | 0 | { |
603 | 0 | GVolumeIface *iface; |
604 | |
|
605 | 0 | g_return_val_if_fail (G_IS_VOLUME (volume), NULL); |
606 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
607 | |
|
608 | 0 | if (iface->enumerate_identifiers == NULL) |
609 | 0 | return NULL; |
610 | | |
611 | 0 | return (* iface->enumerate_identifiers) (volume); |
612 | 0 | } |
613 | | |
614 | | /** |
615 | | * g_volume_get_activation_root: |
616 | | * @volume: a #GVolume |
617 | | * |
618 | | * Gets the activation root for a #GVolume if it is known ahead of |
619 | | * mount time. Returns %NULL otherwise. If not %NULL and if @volume |
620 | | * is mounted, then the result of g_mount_get_root() on the |
621 | | * #GMount object obtained from g_volume_get_mount() will always |
622 | | * either be equal or a prefix of what this function returns. In |
623 | | * other words, in code |
624 | | * |
625 | | * |[<!-- language="C" --> |
626 | | * GMount *mount; |
627 | | * GFile *mount_root |
628 | | * GFile *volume_activation_root; |
629 | | * |
630 | | * mount = g_volume_get_mount (volume); // mounted, so never NULL |
631 | | * mount_root = g_mount_get_root (mount); |
632 | | * volume_activation_root = g_volume_get_activation_root (volume); // assume not NULL |
633 | | * ]| |
634 | | * then the expression |
635 | | * |[<!-- language="C" --> |
636 | | * (g_file_has_prefix (volume_activation_root, mount_root) || |
637 | | * g_file_equal (volume_activation_root, mount_root)) |
638 | | * ]| |
639 | | * will always be %TRUE. |
640 | | * |
641 | | * Activation roots are typically used in #GVolumeMonitor |
642 | | * implementations to find the underlying mount to shadow, see |
643 | | * g_mount_is_shadowed() for more details. |
644 | | * |
645 | | * Returns: (nullable) (transfer full): the activation root of @volume |
646 | | * or %NULL. Use g_object_unref() to free. |
647 | | * |
648 | | * Since: 2.18 |
649 | | */ |
650 | | GFile * |
651 | | g_volume_get_activation_root (GVolume *volume) |
652 | 0 | { |
653 | 0 | GVolumeIface *iface; |
654 | |
|
655 | 0 | g_return_val_if_fail (G_IS_VOLUME (volume), NULL); |
656 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
657 | |
|
658 | 0 | if (iface->get_activation_root == NULL) |
659 | 0 | return NULL; |
660 | | |
661 | 0 | return (* iface->get_activation_root) (volume); |
662 | 0 | } |
663 | | |
664 | | /** |
665 | | * g_volume_get_sort_key: |
666 | | * @volume: a #GVolume |
667 | | * |
668 | | * Gets the sort key for @volume, if any. |
669 | | * |
670 | | * Returns: (nullable): Sorting key for @volume or %NULL if no such key is available |
671 | | * |
672 | | * Since: 2.32 |
673 | | */ |
674 | | const gchar * |
675 | | g_volume_get_sort_key (GVolume *volume) |
676 | 0 | { |
677 | 0 | const gchar *ret = NULL; |
678 | 0 | GVolumeIface *iface; |
679 | |
|
680 | 0 | g_return_val_if_fail (G_IS_VOLUME (volume), NULL); |
681 | | |
682 | 0 | iface = G_VOLUME_GET_IFACE (volume); |
683 | 0 | if (iface->get_sort_key != NULL) |
684 | 0 | ret = iface->get_sort_key (volume); |
685 | |
|
686 | 0 | return ret; |
687 | 0 | } |