Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : * David Zeuthen <davidz@redhat.com>
22 : : */
23 : :
24 : : #include "config.h"
25 : : #include "gdrive.h"
26 : : #include "gtask.h"
27 : : #include "gthemedicon.h"
28 : : #include "gasyncresult.h"
29 : : #include "gioerror.h"
30 : : #include "glibintl.h"
31 : :
32 : :
33 : : /**
34 : : * GDrive:
35 : : *
36 : : * `GDrive` represents a piece of hardware connected to the machine.
37 : : * It’s generally only created for removable hardware or hardware with
38 : : * removable media. For example, an optical disc drive, or a USB flash drive.
39 : : *
40 : : * `GDrive` is a container class for [iface@Gio.Volume] objects that stem from
41 : : * the same piece of media. As such, `GDrive` abstracts a drive with
42 : : * (or without) removable media and provides operations for querying
43 : : * whether media is available, determining whether media change is
44 : : * automatically detected and ejecting the media.
45 : : *
46 : : * If the `GDrive` reports that media isn’t automatically detected, one
47 : : * can poll for media; typically one should not do this periodically
48 : : * as a poll for media operation is potentially expensive and may
49 : : * spin up the drive creating noise.
50 : : *
51 : : * `GDrive` supports starting and stopping drives with authentication
52 : : * support for the former. This can be used to support a diverse set
53 : : * of use cases including connecting/disconnecting iSCSI devices,
54 : : * powering down external disk enclosures and starting/stopping
55 : : * multi-disk devices such as RAID devices. Note that the actual
56 : : * semantics and side-effects of starting/stopping a `GDrive` may vary
57 : : * according to implementation. To choose the correct verbs in e.g. a
58 : : * file manager, use [method@Gio.Drive.get_start_stop_type].
59 : : *
60 : : * For [porting from GnomeVFS](migrating-gnome-vfs.html) note that there is no
61 : : * equivalent of `GDrive` in that API.
62 : : **/
63 : :
64 : : typedef GDriveIface GDriveInterface;
65 : 21 : G_DEFINE_INTERFACE(GDrive, g_drive, G_TYPE_OBJECT)
66 : :
67 : : static void
68 : 1 : g_drive_default_init (GDriveInterface *iface)
69 : : {
70 : : /**
71 : : * GDrive::changed:
72 : : * @drive: a #GDrive.
73 : : *
74 : : * Emitted when the drive's state has changed.
75 : : **/
76 : 1 : g_signal_new (I_("changed"),
77 : : G_TYPE_DRIVE,
78 : : G_SIGNAL_RUN_LAST,
79 : : G_STRUCT_OFFSET (GDriveIface, changed),
80 : : NULL, NULL,
81 : : NULL,
82 : : G_TYPE_NONE, 0);
83 : :
84 : : /**
85 : : * GDrive::disconnected:
86 : : * @drive: a #GDrive.
87 : : *
88 : : * This signal is emitted when the #GDrive have been
89 : : * disconnected. If the recipient is holding references to the
90 : : * object they should release them so the object can be
91 : : * finalized.
92 : : **/
93 : 1 : g_signal_new (I_("disconnected"),
94 : : G_TYPE_DRIVE,
95 : : G_SIGNAL_RUN_LAST,
96 : : G_STRUCT_OFFSET (GDriveIface, disconnected),
97 : : NULL, NULL,
98 : : NULL,
99 : : G_TYPE_NONE, 0);
100 : :
101 : : /**
102 : : * GDrive::eject-button:
103 : : * @drive: a #GDrive.
104 : : *
105 : : * Emitted when the physical eject button (if any) of a drive has
106 : : * been pressed.
107 : : **/
108 : 1 : g_signal_new (I_("eject-button"),
109 : : G_TYPE_DRIVE,
110 : : G_SIGNAL_RUN_LAST,
111 : : G_STRUCT_OFFSET (GDriveIface, eject_button),
112 : : NULL, NULL,
113 : : NULL,
114 : : G_TYPE_NONE, 0);
115 : :
116 : : /**
117 : : * GDrive::stop-button:
118 : : * @drive: a #GDrive.
119 : : *
120 : : * Emitted when the physical stop button (if any) of a drive has
121 : : * been pressed.
122 : : *
123 : : * Since: 2.22
124 : : **/
125 : 1 : g_signal_new (I_("stop-button"),
126 : : G_TYPE_DRIVE,
127 : : G_SIGNAL_RUN_LAST,
128 : : G_STRUCT_OFFSET (GDriveIface, stop_button),
129 : : NULL, NULL,
130 : : NULL,
131 : : G_TYPE_NONE, 0);
132 : 1 : }
133 : :
134 : : /**
135 : : * g_drive_get_name:
136 : : * @drive: a #GDrive.
137 : : *
138 : : * Gets the name of @drive.
139 : : *
140 : : * Returns: a string containing @drive's name. The returned
141 : : * string should be freed when no longer needed.
142 : : **/
143 : : char *
144 : 0 : g_drive_get_name (GDrive *drive)
145 : : {
146 : : GDriveIface *iface;
147 : :
148 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
149 : :
150 : 0 : iface = G_DRIVE_GET_IFACE (drive);
151 : :
152 : 0 : return (* iface->get_name) (drive);
153 : : }
154 : :
155 : : /**
156 : : * g_drive_get_icon:
157 : : * @drive: a #GDrive.
158 : : *
159 : : * Gets the icon for @drive.
160 : : *
161 : : * Returns: (transfer full): #GIcon for the @drive.
162 : : * Free the returned object with g_object_unref().
163 : : **/
164 : : GIcon *
165 : 0 : g_drive_get_icon (GDrive *drive)
166 : : {
167 : : GDriveIface *iface;
168 : :
169 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
170 : :
171 : 0 : iface = G_DRIVE_GET_IFACE (drive);
172 : :
173 : 0 : return (* iface->get_icon) (drive);
174 : : }
175 : :
176 : : /**
177 : : * g_drive_get_symbolic_icon:
178 : : * @drive: a #GDrive.
179 : : *
180 : : * Gets the icon for @drive.
181 : : *
182 : : * Returns: (transfer full): symbolic #GIcon for the @drive.
183 : : * Free the returned object with g_object_unref().
184 : : *
185 : : * Since: 2.34
186 : : **/
187 : : GIcon *
188 : 0 : g_drive_get_symbolic_icon (GDrive *drive)
189 : : {
190 : : GDriveIface *iface;
191 : : GIcon *ret;
192 : :
193 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
194 : :
195 : 0 : iface = G_DRIVE_GET_IFACE (drive);
196 : :
197 : 0 : if (iface->get_symbolic_icon != NULL)
198 : 0 : ret = iface->get_symbolic_icon (drive);
199 : : else
200 : 0 : ret = g_themed_icon_new_with_default_fallbacks ("drive-removable-media-symbolic");
201 : :
202 : 0 : return ret;
203 : : }
204 : :
205 : : /**
206 : : * g_drive_has_volumes:
207 : : * @drive: a #GDrive.
208 : : *
209 : : * Check if @drive has any mountable volumes.
210 : : *
211 : : * Returns: %TRUE if the @drive contains volumes, %FALSE otherwise.
212 : : **/
213 : : gboolean
214 : 0 : g_drive_has_volumes (GDrive *drive)
215 : : {
216 : : GDriveIface *iface;
217 : :
218 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
219 : :
220 : 0 : iface = G_DRIVE_GET_IFACE (drive);
221 : :
222 : 0 : return (* iface->has_volumes) (drive);
223 : : }
224 : :
225 : : /**
226 : : * g_drive_get_volumes:
227 : : * @drive: a #GDrive.
228 : : *
229 : : * Get a list of mountable volumes for @drive.
230 : : *
231 : : * The returned list should be freed with g_list_free(), after
232 : : * its elements have been unreffed with g_object_unref().
233 : : *
234 : : * Returns: (element-type GVolume) (transfer full): #GList containing any #GVolume objects on the given @drive.
235 : : **/
236 : : GList *
237 : 0 : g_drive_get_volumes (GDrive *drive)
238 : : {
239 : : GDriveIface *iface;
240 : :
241 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
242 : :
243 : 0 : iface = G_DRIVE_GET_IFACE (drive);
244 : :
245 : 0 : return (* iface->get_volumes) (drive);
246 : : }
247 : :
248 : : /**
249 : : * g_drive_is_media_check_automatic:
250 : : * @drive: a #GDrive.
251 : : *
252 : : * Checks if @drive is capable of automatically detecting media changes.
253 : : *
254 : : * Returns: %TRUE if the @drive is capable of automatically detecting
255 : : * media changes, %FALSE otherwise.
256 : : **/
257 : : gboolean
258 : 0 : g_drive_is_media_check_automatic (GDrive *drive)
259 : : {
260 : : GDriveIface *iface;
261 : :
262 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
263 : :
264 : 0 : iface = G_DRIVE_GET_IFACE (drive);
265 : :
266 : 0 : return (* iface->is_media_check_automatic) (drive);
267 : : }
268 : :
269 : : /**
270 : : * g_drive_is_removable:
271 : : * @drive: a #GDrive.
272 : : *
273 : : * Checks if the #GDrive and/or its media is considered removable by the user.
274 : : * See g_drive_is_media_removable().
275 : : *
276 : : * Returns: %TRUE if @drive and/or its media is considered removable, %FALSE otherwise.
277 : : *
278 : : * Since: 2.50
279 : : **/
280 : : gboolean
281 : 0 : g_drive_is_removable (GDrive *drive)
282 : : {
283 : : GDriveIface *iface;
284 : :
285 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
286 : :
287 : 0 : iface = G_DRIVE_GET_IFACE (drive);
288 : 0 : if (iface->is_removable != NULL)
289 : 0 : return iface->is_removable (drive);
290 : :
291 : 0 : return FALSE;
292 : : }
293 : :
294 : : /**
295 : : * g_drive_is_media_removable:
296 : : * @drive: a #GDrive.
297 : : *
298 : : * Checks if the @drive supports removable media.
299 : : *
300 : : * Returns: %TRUE if @drive supports removable media, %FALSE otherwise.
301 : : **/
302 : : gboolean
303 : 0 : g_drive_is_media_removable (GDrive *drive)
304 : : {
305 : : GDriveIface *iface;
306 : :
307 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
308 : :
309 : 0 : iface = G_DRIVE_GET_IFACE (drive);
310 : :
311 : 0 : return (* iface->is_media_removable) (drive);
312 : : }
313 : :
314 : : /**
315 : : * g_drive_has_media:
316 : : * @drive: a #GDrive.
317 : : *
318 : : * Checks if the @drive has media. Note that the OS may not be polling
319 : : * the drive for media changes; see g_drive_is_media_check_automatic()
320 : : * for more details.
321 : : *
322 : : * Returns: %TRUE if @drive has media, %FALSE otherwise.
323 : : **/
324 : : gboolean
325 : 0 : g_drive_has_media (GDrive *drive)
326 : : {
327 : : GDriveIface *iface;
328 : :
329 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
330 : :
331 : 0 : iface = G_DRIVE_GET_IFACE (drive);
332 : :
333 : 0 : return (* iface->has_media) (drive);
334 : : }
335 : :
336 : : /**
337 : : * g_drive_can_eject:
338 : : * @drive: a #GDrive.
339 : : *
340 : : * Checks if a drive can be ejected.
341 : : *
342 : : * Returns: %TRUE if the @drive can be ejected, %FALSE otherwise.
343 : : **/
344 : : gboolean
345 : 0 : g_drive_can_eject (GDrive *drive)
346 : : {
347 : : GDriveIface *iface;
348 : :
349 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
350 : :
351 : 0 : iface = G_DRIVE_GET_IFACE (drive);
352 : :
353 : 0 : if (iface->can_eject == NULL)
354 : 0 : return FALSE;
355 : :
356 : 0 : return (* iface->can_eject) (drive);
357 : : }
358 : :
359 : : /**
360 : : * g_drive_can_poll_for_media:
361 : : * @drive: a #GDrive.
362 : : *
363 : : * Checks if a drive can be polled for media changes.
364 : : *
365 : : * Returns: %TRUE if the @drive can be polled for media changes,
366 : : * %FALSE otherwise.
367 : : **/
368 : : gboolean
369 : 0 : g_drive_can_poll_for_media (GDrive *drive)
370 : : {
371 : : GDriveIface *iface;
372 : :
373 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
374 : :
375 : 0 : iface = G_DRIVE_GET_IFACE (drive);
376 : :
377 : 0 : if (iface->poll_for_media == NULL)
378 : 0 : return FALSE;
379 : :
380 : 0 : return (* iface->can_poll_for_media) (drive);
381 : : }
382 : :
383 : : /**
384 : : * g_drive_eject:
385 : : * @drive: a #GDrive.
386 : : * @flags: flags affecting the unmount if required for eject
387 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
388 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
389 : : * @user_data: user data to pass to @callback
390 : : *
391 : : * Asynchronously ejects a drive.
392 : : *
393 : : * When the operation is finished, @callback will be called.
394 : : * You can then call g_drive_eject_finish() to obtain the
395 : : * result of the operation.
396 : : *
397 : : * Deprecated: 2.22: Use g_drive_eject_with_operation() instead.
398 : : **/
399 : : void
400 : 0 : g_drive_eject (GDrive *drive,
401 : : GMountUnmountFlags flags,
402 : : GCancellable *cancellable,
403 : : GAsyncReadyCallback callback,
404 : : gpointer user_data)
405 : : {
406 : : GDriveIface *iface;
407 : :
408 : 0 : g_return_if_fail (G_IS_DRIVE (drive));
409 : :
410 : 0 : iface = G_DRIVE_GET_IFACE (drive);
411 : :
412 : 0 : if (iface->eject == NULL)
413 : : {
414 : 0 : g_task_report_new_error (drive, callback, user_data,
415 : : g_drive_eject_with_operation,
416 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
417 : 0 : _("drive doesn’t implement eject"));
418 : 0 : return;
419 : : }
420 : :
421 : 0 : (* iface->eject) (drive, flags, cancellable, callback, user_data);
422 : : }
423 : :
424 : : /**
425 : : * g_drive_eject_finish:
426 : : * @drive: a #GDrive.
427 : : * @result: a #GAsyncResult.
428 : : * @error: a #GError, or %NULL
429 : : *
430 : : * Finishes ejecting a drive.
431 : : *
432 : : * Returns: %TRUE if the drive has been ejected successfully,
433 : : * %FALSE otherwise.
434 : : *
435 : : * Deprecated: 2.22: Use g_drive_eject_with_operation_finish() instead.
436 : : **/
437 : : gboolean
438 : 0 : g_drive_eject_finish (GDrive *drive,
439 : : GAsyncResult *result,
440 : : GError **error)
441 : : {
442 : : GDriveIface *iface;
443 : :
444 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
445 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
446 : :
447 : 0 : if (g_async_result_legacy_propagate_error (result, error))
448 : 0 : return FALSE;
449 : 0 : else if (g_async_result_is_tagged (result, g_drive_eject_with_operation))
450 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
451 : :
452 : 0 : iface = G_DRIVE_GET_IFACE (drive);
453 : :
454 : 0 : return (* iface->eject_finish) (drive, result, error);
455 : : }
456 : :
457 : : /**
458 : : * g_drive_eject_with_operation:
459 : : * @drive: a #GDrive.
460 : : * @flags: flags affecting the unmount if required for eject
461 : : * @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
462 : : * user interaction.
463 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
464 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
465 : : * @user_data: user data passed to @callback.
466 : : *
467 : : * Ejects a drive. This is an asynchronous operation, and is
468 : : * finished by calling g_drive_eject_with_operation_finish() with the @drive
469 : : * and #GAsyncResult data returned in the @callback.
470 : : *
471 : : * Since: 2.22
472 : : **/
473 : : void
474 : 0 : g_drive_eject_with_operation (GDrive *drive,
475 : : GMountUnmountFlags flags,
476 : : GMountOperation *mount_operation,
477 : : GCancellable *cancellable,
478 : : GAsyncReadyCallback callback,
479 : : gpointer user_data)
480 : : {
481 : : GDriveIface *iface;
482 : :
483 : 0 : g_return_if_fail (G_IS_DRIVE (drive));
484 : :
485 : 0 : iface = G_DRIVE_GET_IFACE (drive);
486 : :
487 : 0 : if (iface->eject == NULL && iface->eject_with_operation == NULL)
488 : : {
489 : 0 : g_task_report_new_error (drive, callback, user_data,
490 : : g_drive_eject_with_operation,
491 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
492 : : /* Translators: This is an error
493 : : * message for drive objects that
494 : : * don't implement any of eject or eject_with_operation. */
495 : 0 : _("drive doesn’t implement eject or eject_with_operation"));
496 : 0 : return;
497 : : }
498 : :
499 : 0 : if (iface->eject_with_operation != NULL)
500 : 0 : (* iface->eject_with_operation) (drive, flags, mount_operation, cancellable, callback, user_data);
501 : : else
502 : 0 : (* iface->eject) (drive, flags, cancellable, callback, user_data);
503 : : }
504 : :
505 : : /**
506 : : * g_drive_eject_with_operation_finish:
507 : : * @drive: a #GDrive.
508 : : * @result: a #GAsyncResult.
509 : : * @error: a #GError location to store the error occurring, or %NULL to
510 : : * ignore.
511 : : *
512 : : * Finishes ejecting a drive. If any errors occurred during the operation,
513 : : * @error will be set to contain the errors and %FALSE will be returned.
514 : : *
515 : : * Returns: %TRUE if the drive was successfully ejected. %FALSE otherwise.
516 : : *
517 : : * Since: 2.22
518 : : **/
519 : : gboolean
520 : 0 : g_drive_eject_with_operation_finish (GDrive *drive,
521 : : GAsyncResult *result,
522 : : GError **error)
523 : : {
524 : : GDriveIface *iface;
525 : :
526 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
527 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
528 : :
529 : 0 : if (g_async_result_legacy_propagate_error (result, error))
530 : 0 : return FALSE;
531 : 0 : else if (g_async_result_is_tagged (result, g_drive_eject_with_operation))
532 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
533 : :
534 : 0 : iface = G_DRIVE_GET_IFACE (drive);
535 : 0 : if (iface->eject_with_operation_finish != NULL)
536 : 0 : return (* iface->eject_with_operation_finish) (drive, result, error);
537 : : else
538 : 0 : return (* iface->eject_finish) (drive, result, error);
539 : : }
540 : :
541 : : /**
542 : : * g_drive_poll_for_media:
543 : : * @drive: a #GDrive.
544 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
545 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
546 : : * @user_data: user data to pass to @callback
547 : : *
548 : : * Asynchronously polls @drive to see if media has been inserted or removed.
549 : : *
550 : : * When the operation is finished, @callback will be called.
551 : : * You can then call g_drive_poll_for_media_finish() to obtain the
552 : : * result of the operation.
553 : : **/
554 : : void
555 : 0 : g_drive_poll_for_media (GDrive *drive,
556 : : GCancellable *cancellable,
557 : : GAsyncReadyCallback callback,
558 : : gpointer user_data)
559 : : {
560 : : GDriveIface *iface;
561 : :
562 : 0 : g_return_if_fail (G_IS_DRIVE (drive));
563 : :
564 : 0 : iface = G_DRIVE_GET_IFACE (drive);
565 : :
566 : 0 : if (iface->poll_for_media == NULL)
567 : : {
568 : 0 : g_task_report_new_error (drive, callback, user_data,
569 : : g_drive_poll_for_media,
570 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
571 : 0 : _("drive doesn’t implement polling for media"));
572 : 0 : return;
573 : : }
574 : :
575 : 0 : (* iface->poll_for_media) (drive, cancellable, callback, user_data);
576 : : }
577 : :
578 : : /**
579 : : * g_drive_poll_for_media_finish:
580 : : * @drive: a #GDrive.
581 : : * @result: a #GAsyncResult.
582 : : * @error: a #GError, or %NULL
583 : : *
584 : : * Finishes an operation started with g_drive_poll_for_media() on a drive.
585 : : *
586 : : * Returns: %TRUE if the drive has been poll_for_mediaed successfully,
587 : : * %FALSE otherwise.
588 : : **/
589 : : gboolean
590 : 0 : g_drive_poll_for_media_finish (GDrive *drive,
591 : : GAsyncResult *result,
592 : : GError **error)
593 : : {
594 : : GDriveIface *iface;
595 : :
596 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
597 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
598 : :
599 : 0 : if (g_async_result_legacy_propagate_error (result, error))
600 : 0 : return FALSE;
601 : 0 : else if (g_async_result_is_tagged (result, g_drive_poll_for_media))
602 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
603 : :
604 : 0 : iface = G_DRIVE_GET_IFACE (drive);
605 : :
606 : 0 : return (* iface->poll_for_media_finish) (drive, result, error);
607 : : }
608 : :
609 : : /**
610 : : * g_drive_get_identifier:
611 : : * @drive: a #GDrive
612 : : * @kind: the kind of identifier to return
613 : : *
614 : : * Gets the identifier of the given kind for @drive. The only
615 : : * identifier currently available is
616 : : * %G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE.
617 : : *
618 : : * Returns: (nullable) (transfer full): a newly allocated string containing the
619 : : * requested identifier, or %NULL if the #GDrive
620 : : * doesn't have this kind of identifier.
621 : : */
622 : : char *
623 : 0 : g_drive_get_identifier (GDrive *drive,
624 : : const char *kind)
625 : : {
626 : : GDriveIface *iface;
627 : :
628 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
629 : 0 : g_return_val_if_fail (kind != NULL, NULL);
630 : :
631 : 0 : iface = G_DRIVE_GET_IFACE (drive);
632 : :
633 : 0 : if (iface->get_identifier == NULL)
634 : 0 : return NULL;
635 : :
636 : 0 : return (* iface->get_identifier) (drive, kind);
637 : : }
638 : :
639 : : /**
640 : : * g_drive_enumerate_identifiers:
641 : : * @drive: a #GDrive
642 : : *
643 : : * Gets the kinds of identifiers that @drive has.
644 : : * Use g_drive_get_identifier() to obtain the identifiers
645 : : * themselves.
646 : : *
647 : : * Returns: (transfer full) (array zero-terminated=1): a %NULL-terminated
648 : : * array of strings containing kinds of identifiers. Use g_strfreev()
649 : : * to free.
650 : : */
651 : : char **
652 : 0 : g_drive_enumerate_identifiers (GDrive *drive)
653 : : {
654 : : GDriveIface *iface;
655 : :
656 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
657 : 0 : iface = G_DRIVE_GET_IFACE (drive);
658 : :
659 : 0 : if (iface->enumerate_identifiers == NULL)
660 : 0 : return NULL;
661 : :
662 : 0 : return (* iface->enumerate_identifiers) (drive);
663 : : }
664 : :
665 : : /**
666 : : * g_drive_get_start_stop_type:
667 : : * @drive: a #GDrive.
668 : : *
669 : : * Gets a hint about how a drive can be started/stopped.
670 : : *
671 : : * Returns: A value from the #GDriveStartStopType enumeration.
672 : : *
673 : : * Since: 2.22
674 : : */
675 : : GDriveStartStopType
676 : 0 : g_drive_get_start_stop_type (GDrive *drive)
677 : : {
678 : : GDriveIface *iface;
679 : :
680 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
681 : :
682 : 0 : iface = G_DRIVE_GET_IFACE (drive);
683 : :
684 : 0 : if (iface->get_start_stop_type == NULL)
685 : 0 : return G_DRIVE_START_STOP_TYPE_UNKNOWN;
686 : :
687 : 0 : return (* iface->get_start_stop_type) (drive);
688 : : }
689 : :
690 : :
691 : : /**
692 : : * g_drive_can_start:
693 : : * @drive: a #GDrive.
694 : : *
695 : : * Checks if a drive can be started.
696 : : *
697 : : * Returns: %TRUE if the @drive can be started, %FALSE otherwise.
698 : : *
699 : : * Since: 2.22
700 : : */
701 : : gboolean
702 : 0 : g_drive_can_start (GDrive *drive)
703 : : {
704 : : GDriveIface *iface;
705 : :
706 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
707 : :
708 : 0 : iface = G_DRIVE_GET_IFACE (drive);
709 : :
710 : 0 : if (iface->can_start == NULL)
711 : 0 : return FALSE;
712 : :
713 : 0 : return (* iface->can_start) (drive);
714 : : }
715 : :
716 : : /**
717 : : * g_drive_can_start_degraded:
718 : : * @drive: a #GDrive.
719 : : *
720 : : * Checks if a drive can be started degraded.
721 : : *
722 : : * Returns: %TRUE if the @drive can be started degraded, %FALSE otherwise.
723 : : *
724 : : * Since: 2.22
725 : : */
726 : : gboolean
727 : 0 : g_drive_can_start_degraded (GDrive *drive)
728 : : {
729 : : GDriveIface *iface;
730 : :
731 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
732 : :
733 : 0 : iface = G_DRIVE_GET_IFACE (drive);
734 : :
735 : 0 : if (iface->can_start_degraded == NULL)
736 : 0 : return FALSE;
737 : :
738 : 0 : return (* iface->can_start_degraded) (drive);
739 : : }
740 : :
741 : : /**
742 : : * g_drive_start:
743 : : * @drive: a #GDrive.
744 : : * @flags: flags affecting the start operation.
745 : : * @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
746 : : * user interaction.
747 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
748 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
749 : : * @user_data: user data to pass to @callback
750 : : *
751 : : * Asynchronously starts a drive.
752 : : *
753 : : * When the operation is finished, @callback will be called.
754 : : * You can then call g_drive_start_finish() to obtain the
755 : : * result of the operation.
756 : : *
757 : : * Since: 2.22
758 : : */
759 : : void
760 : 0 : g_drive_start (GDrive *drive,
761 : : GDriveStartFlags flags,
762 : : GMountOperation *mount_operation,
763 : : GCancellable *cancellable,
764 : : GAsyncReadyCallback callback,
765 : : gpointer user_data)
766 : : {
767 : : GDriveIface *iface;
768 : :
769 : 0 : g_return_if_fail (G_IS_DRIVE (drive));
770 : :
771 : 0 : iface = G_DRIVE_GET_IFACE (drive);
772 : :
773 : 0 : if (iface->start == NULL)
774 : : {
775 : 0 : g_task_report_new_error (drive, callback, user_data,
776 : : g_drive_start,
777 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
778 : 0 : _("drive doesn’t implement start"));
779 : 0 : return;
780 : : }
781 : :
782 : 0 : (* iface->start) (drive, flags, mount_operation, cancellable, callback, user_data);
783 : : }
784 : :
785 : : /**
786 : : * g_drive_start_finish:
787 : : * @drive: a #GDrive.
788 : : * @result: a #GAsyncResult.
789 : : * @error: a #GError, or %NULL
790 : : *
791 : : * Finishes starting a drive.
792 : : *
793 : : * Returns: %TRUE if the drive has been started successfully,
794 : : * %FALSE otherwise.
795 : : *
796 : : * Since: 2.22
797 : : */
798 : : gboolean
799 : 0 : g_drive_start_finish (GDrive *drive,
800 : : GAsyncResult *result,
801 : : GError **error)
802 : : {
803 : : GDriveIface *iface;
804 : :
805 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
806 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
807 : :
808 : 0 : if (g_async_result_legacy_propagate_error (result, error))
809 : 0 : return FALSE;
810 : 0 : else if (g_async_result_is_tagged (result, g_drive_start))
811 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
812 : :
813 : 0 : iface = G_DRIVE_GET_IFACE (drive);
814 : :
815 : 0 : return (* iface->start_finish) (drive, result, error);
816 : : }
817 : :
818 : : /**
819 : : * g_drive_can_stop:
820 : : * @drive: a #GDrive.
821 : : *
822 : : * Checks if a drive can be stopped.
823 : : *
824 : : * Returns: %TRUE if the @drive can be stopped, %FALSE otherwise.
825 : : *
826 : : * Since: 2.22
827 : : */
828 : : gboolean
829 : 0 : g_drive_can_stop (GDrive *drive)
830 : : {
831 : : GDriveIface *iface;
832 : :
833 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
834 : :
835 : 0 : iface = G_DRIVE_GET_IFACE (drive);
836 : :
837 : 0 : if (iface->can_stop == NULL)
838 : 0 : return FALSE;
839 : :
840 : 0 : return (* iface->can_stop) (drive);
841 : : }
842 : :
843 : : /**
844 : : * g_drive_stop:
845 : : * @drive: a #GDrive.
846 : : * @flags: flags affecting the unmount if required for stopping.
847 : : * @mount_operation: (nullable): a #GMountOperation or %NULL to avoid
848 : : * user interaction.
849 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
850 : : * @callback: (nullable): a #GAsyncReadyCallback, or %NULL.
851 : : * @user_data: user data to pass to @callback
852 : : *
853 : : * Asynchronously stops a drive.
854 : : *
855 : : * When the operation is finished, @callback will be called.
856 : : * You can then call g_drive_stop_finish() to obtain the
857 : : * result of the operation.
858 : : *
859 : : * Since: 2.22
860 : : */
861 : : void
862 : 0 : g_drive_stop (GDrive *drive,
863 : : GMountUnmountFlags flags,
864 : : GMountOperation *mount_operation,
865 : : GCancellable *cancellable,
866 : : GAsyncReadyCallback callback,
867 : : gpointer user_data)
868 : : {
869 : : GDriveIface *iface;
870 : :
871 : 0 : g_return_if_fail (G_IS_DRIVE (drive));
872 : :
873 : 0 : iface = G_DRIVE_GET_IFACE (drive);
874 : :
875 : 0 : if (iface->stop == NULL)
876 : : {
877 : 0 : g_task_report_new_error (drive, callback, user_data,
878 : : g_drive_start,
879 : : G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
880 : 0 : _("drive doesn’t implement stop"));
881 : 0 : return;
882 : : }
883 : :
884 : 0 : (* iface->stop) (drive, flags, mount_operation, cancellable, callback, user_data);
885 : : }
886 : :
887 : : /**
888 : : * g_drive_stop_finish:
889 : : * @drive: a #GDrive.
890 : : * @result: a #GAsyncResult.
891 : : * @error: a #GError, or %NULL
892 : : *
893 : : * Finishes stopping a drive.
894 : : *
895 : : * Returns: %TRUE if the drive has been stopped successfully,
896 : : * %FALSE otherwise.
897 : : *
898 : : * Since: 2.22
899 : : */
900 : : gboolean
901 : 0 : g_drive_stop_finish (GDrive *drive,
902 : : GAsyncResult *result,
903 : : GError **error)
904 : : {
905 : : GDriveIface *iface;
906 : :
907 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
908 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
909 : :
910 : 0 : if (g_async_result_legacy_propagate_error (result, error))
911 : 0 : return FALSE;
912 : 0 : else if (g_async_result_is_tagged (result, g_drive_start))
913 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
914 : :
915 : 0 : iface = G_DRIVE_GET_IFACE (drive);
916 : :
917 : 0 : return (* iface->stop_finish) (drive, result, error);
918 : : }
919 : :
920 : : /**
921 : : * g_drive_get_sort_key:
922 : : * @drive: A #GDrive.
923 : : *
924 : : * Gets the sort key for @drive, if any.
925 : : *
926 : : * Returns: (nullable): Sorting key for @drive or %NULL if no such key is available.
927 : : *
928 : : * Since: 2.32
929 : : */
930 : : const gchar *
931 : 0 : g_drive_get_sort_key (GDrive *drive)
932 : : {
933 : 0 : const gchar *ret = NULL;
934 : : GDriveIface *iface;
935 : :
936 : 0 : g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
937 : :
938 : 0 : iface = G_DRIVE_GET_IFACE (drive);
939 : 0 : if (iface->get_sort_key != NULL)
940 : 0 : ret = iface->get_sort_key (drive);
941 : :
942 : 0 : return ret;
943 : : }
|