/src/glib/gio/gunionvolumemonitor.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ |
2 | | |
3 | | /* GIO - GLib Input, Output and Streaming Library |
4 | | * |
5 | | * Copyright (C) 2006-2007 Red Hat, Inc. |
6 | | * |
7 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
8 | | * |
9 | | * This library is free software; you can redistribute it and/or |
10 | | * modify it under the terms of the GNU Lesser General Public |
11 | | * License as published by the Free Software Foundation; either |
12 | | * version 2.1 of the License, or (at your option) any later version. |
13 | | * |
14 | | * This library is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | | * Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General |
20 | | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
21 | | * |
22 | | * Author: Alexander Larsson <alexl@redhat.com> |
23 | | * David Zeuthen <davidz@redhat.com> |
24 | | */ |
25 | | |
26 | | #include "config.h" |
27 | | |
28 | | #include <string.h> |
29 | | |
30 | | #include <glib.h> |
31 | | #include "gunionvolumemonitor.h" |
32 | | #include "gmountprivate.h" |
33 | | #include "giomodule-priv.h" |
34 | | #ifdef G_OS_UNIX |
35 | | #include "gunixvolumemonitor.h" |
36 | | #endif |
37 | | #include "gnativevolumemonitor.h" |
38 | | |
39 | | #include "glibintl.h" |
40 | | |
41 | | |
42 | | struct _GUnionVolumeMonitor { |
43 | | GVolumeMonitor parent; |
44 | | |
45 | | GList *monitors; |
46 | | }; |
47 | | |
48 | | static void g_union_volume_monitor_remove_monitor (GUnionVolumeMonitor *union_monitor, |
49 | | GVolumeMonitor *child_monitor); |
50 | | |
51 | | |
52 | | #define g_union_volume_monitor_get_type _g_union_volume_monitor_get_type |
53 | | G_DEFINE_TYPE (GUnionVolumeMonitor, g_union_volume_monitor, G_TYPE_VOLUME_MONITOR) |
54 | | |
55 | | static GRecMutex the_volume_monitor_mutex; |
56 | | |
57 | | static GUnionVolumeMonitor *the_volume_monitor = NULL; |
58 | | |
59 | | static void |
60 | | g_union_volume_monitor_finalize (GObject *object) |
61 | 0 | { |
62 | 0 | GUnionVolumeMonitor *monitor; |
63 | 0 | GVolumeMonitor *child_monitor; |
64 | |
|
65 | 0 | monitor = G_UNION_VOLUME_MONITOR (object); |
66 | |
|
67 | 0 | while (monitor->monitors != NULL) |
68 | 0 | { |
69 | 0 | child_monitor = monitor->monitors->data; |
70 | 0 | g_union_volume_monitor_remove_monitor (monitor, |
71 | 0 | child_monitor); |
72 | 0 | g_object_unref (child_monitor); |
73 | 0 | } |
74 | |
|
75 | 0 | G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->finalize (object); |
76 | 0 | } |
77 | | |
78 | | static void |
79 | | g_union_volume_monitor_dispose (GObject *object) |
80 | 0 | { |
81 | 0 | GUnionVolumeMonitor *monitor; |
82 | 0 | GVolumeMonitor *child_monitor; |
83 | 0 | GList *l; |
84 | |
|
85 | 0 | monitor = G_UNION_VOLUME_MONITOR (object); |
86 | |
|
87 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
88 | 0 | the_volume_monitor = NULL; |
89 | |
|
90 | 0 | for (l = monitor->monitors; l != NULL; l = l->next) |
91 | 0 | { |
92 | 0 | child_monitor = l->data; |
93 | 0 | g_object_run_dispose (G_OBJECT (child_monitor)); |
94 | 0 | } |
95 | | |
96 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
97 | |
|
98 | 0 | G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->dispose (object); |
99 | 0 | } |
100 | | |
101 | | static GList * |
102 | | get_mounts (GVolumeMonitor *volume_monitor) |
103 | 0 | { |
104 | 0 | GUnionVolumeMonitor *monitor; |
105 | 0 | GVolumeMonitor *child_monitor; |
106 | 0 | GList *res; |
107 | 0 | GList *l; |
108 | | |
109 | 0 | monitor = G_UNION_VOLUME_MONITOR (volume_monitor); |
110 | |
|
111 | 0 | res = NULL; |
112 | | |
113 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
114 | |
|
115 | 0 | for (l = monitor->monitors; l != NULL; l = l->next) |
116 | 0 | { |
117 | 0 | child_monitor = l->data; |
118 | |
|
119 | 0 | res = g_list_concat (res, g_volume_monitor_get_mounts (child_monitor)); |
120 | 0 | } |
121 | | |
122 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
123 | |
|
124 | 0 | return res; |
125 | 0 | } |
126 | | |
127 | | static GList * |
128 | | get_volumes (GVolumeMonitor *volume_monitor) |
129 | 0 | { |
130 | 0 | GUnionVolumeMonitor *monitor; |
131 | 0 | GVolumeMonitor *child_monitor; |
132 | 0 | GList *res; |
133 | 0 | GList *l; |
134 | | |
135 | 0 | monitor = G_UNION_VOLUME_MONITOR (volume_monitor); |
136 | |
|
137 | 0 | res = NULL; |
138 | | |
139 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
140 | |
|
141 | 0 | for (l = monitor->monitors; l != NULL; l = l->next) |
142 | 0 | { |
143 | 0 | child_monitor = l->data; |
144 | |
|
145 | 0 | res = g_list_concat (res, g_volume_monitor_get_volumes (child_monitor)); |
146 | 0 | } |
147 | | |
148 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
149 | |
|
150 | 0 | return res; |
151 | 0 | } |
152 | | |
153 | | static GList * |
154 | | get_connected_drives (GVolumeMonitor *volume_monitor) |
155 | 0 | { |
156 | 0 | GUnionVolumeMonitor *monitor; |
157 | 0 | GVolumeMonitor *child_monitor; |
158 | 0 | GList *res; |
159 | 0 | GList *l; |
160 | | |
161 | 0 | monitor = G_UNION_VOLUME_MONITOR (volume_monitor); |
162 | |
|
163 | 0 | res = NULL; |
164 | | |
165 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
166 | |
|
167 | 0 | for (l = monitor->monitors; l != NULL; l = l->next) |
168 | 0 | { |
169 | 0 | child_monitor = l->data; |
170 | |
|
171 | 0 | res = g_list_concat (res, g_volume_monitor_get_connected_drives (child_monitor)); |
172 | 0 | } |
173 | | |
174 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
175 | |
|
176 | 0 | return res; |
177 | 0 | } |
178 | | |
179 | | static GVolume * |
180 | | get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) |
181 | 0 | { |
182 | 0 | GUnionVolumeMonitor *monitor; |
183 | 0 | GVolumeMonitor *child_monitor; |
184 | 0 | GVolume *volume; |
185 | 0 | GList *l; |
186 | | |
187 | 0 | monitor = G_UNION_VOLUME_MONITOR (volume_monitor); |
188 | |
|
189 | 0 | volume = NULL; |
190 | | |
191 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
192 | |
|
193 | 0 | for (l = monitor->monitors; l != NULL; l = l->next) |
194 | 0 | { |
195 | 0 | child_monitor = l->data; |
196 | |
|
197 | 0 | volume = g_volume_monitor_get_volume_for_uuid (child_monitor, uuid); |
198 | 0 | if (volume != NULL) |
199 | 0 | break; |
200 | |
|
201 | 0 | } |
202 | | |
203 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
204 | |
|
205 | 0 | return volume; |
206 | 0 | } |
207 | | |
208 | | static GMount * |
209 | | get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) |
210 | 0 | { |
211 | 0 | GUnionVolumeMonitor *monitor; |
212 | 0 | GVolumeMonitor *child_monitor; |
213 | 0 | GMount *mount; |
214 | 0 | GList *l; |
215 | | |
216 | 0 | monitor = G_UNION_VOLUME_MONITOR (volume_monitor); |
217 | |
|
218 | 0 | mount = NULL; |
219 | | |
220 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
221 | |
|
222 | 0 | for (l = monitor->monitors; l != NULL; l = l->next) |
223 | 0 | { |
224 | 0 | child_monitor = l->data; |
225 | |
|
226 | 0 | mount = g_volume_monitor_get_mount_for_uuid (child_monitor, uuid); |
227 | 0 | if (mount != NULL) |
228 | 0 | break; |
229 | |
|
230 | 0 | } |
231 | | |
232 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
233 | |
|
234 | 0 | return mount; |
235 | 0 | } |
236 | | |
237 | | static void |
238 | | g_union_volume_monitor_class_init (GUnionVolumeMonitorClass *klass) |
239 | 0 | { |
240 | 0 | GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
241 | 0 | GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); |
242 | | |
243 | 0 | gobject_class->finalize = g_union_volume_monitor_finalize; |
244 | 0 | gobject_class->dispose = g_union_volume_monitor_dispose; |
245 | |
|
246 | 0 | monitor_class->get_connected_drives = get_connected_drives; |
247 | 0 | monitor_class->get_volumes = get_volumes; |
248 | 0 | monitor_class->get_mounts = get_mounts; |
249 | 0 | monitor_class->get_volume_for_uuid = get_volume_for_uuid; |
250 | 0 | monitor_class->get_mount_for_uuid = get_mount_for_uuid; |
251 | 0 | } |
252 | | |
253 | | static void |
254 | | child_volume_added (GVolumeMonitor *child_monitor, |
255 | | GVolume *child_volume, |
256 | | GUnionVolumeMonitor *union_monitor) |
257 | 0 | { |
258 | 0 | g_signal_emit_by_name (union_monitor, |
259 | 0 | "volume-added", |
260 | 0 | child_volume); |
261 | 0 | } |
262 | | |
263 | | static void |
264 | | child_volume_removed (GVolumeMonitor *child_monitor, |
265 | | GVolume *child_volume, |
266 | | GUnionVolumeMonitor *union_monitor) |
267 | 0 | { |
268 | 0 | g_signal_emit_by_name (union_monitor, |
269 | 0 | "volume-removed", |
270 | 0 | child_volume); |
271 | 0 | } |
272 | | |
273 | | static void |
274 | | child_volume_changed (GVolumeMonitor *child_monitor, |
275 | | GVolume *child_volume, |
276 | | GUnionVolumeMonitor *union_monitor) |
277 | 0 | { |
278 | 0 | g_signal_emit_by_name (union_monitor, |
279 | 0 | "volume-changed", |
280 | 0 | child_volume); |
281 | 0 | } |
282 | | |
283 | | static void |
284 | | child_mount_added (GVolumeMonitor *child_monitor, |
285 | | GMount *child_mount, |
286 | | GUnionVolumeMonitor *union_monitor) |
287 | 0 | { |
288 | 0 | g_signal_emit_by_name (union_monitor, |
289 | 0 | "mount-added", |
290 | 0 | child_mount); |
291 | 0 | } |
292 | | |
293 | | static void |
294 | | child_mount_removed (GVolumeMonitor *child_monitor, |
295 | | GMount *child_mount, |
296 | | GUnionVolumeMonitor *union_monitor) |
297 | 0 | { |
298 | 0 | g_signal_emit_by_name (union_monitor, |
299 | 0 | "mount-removed", |
300 | 0 | child_mount); |
301 | 0 | } |
302 | | |
303 | | static void |
304 | | child_mount_pre_unmount (GVolumeMonitor *child_monitor, |
305 | | GMount *child_mount, |
306 | | GUnionVolumeMonitor *union_monitor) |
307 | 0 | { |
308 | 0 | g_signal_emit_by_name (union_monitor, |
309 | 0 | "mount-pre-unmount", |
310 | 0 | child_mount); |
311 | 0 | } |
312 | | |
313 | | |
314 | | static void |
315 | | child_mount_changed (GVolumeMonitor *child_monitor, |
316 | | GMount *child_mount, |
317 | | GUnionVolumeMonitor *union_monitor) |
318 | 0 | { |
319 | 0 | g_signal_emit_by_name (union_monitor, |
320 | 0 | "mount-changed", |
321 | 0 | child_mount); |
322 | 0 | } |
323 | | |
324 | | static void |
325 | | child_drive_connected (GVolumeMonitor *child_monitor, |
326 | | GDrive *child_drive, |
327 | | GUnionVolumeMonitor *union_monitor) |
328 | 0 | { |
329 | 0 | g_signal_emit_by_name (union_monitor, |
330 | 0 | "drive-connected", |
331 | 0 | child_drive); |
332 | 0 | } |
333 | | |
334 | | static void |
335 | | child_drive_disconnected (GVolumeMonitor *child_monitor, |
336 | | GDrive *child_drive, |
337 | | GUnionVolumeMonitor *union_monitor) |
338 | 0 | { |
339 | 0 | g_signal_emit_by_name (union_monitor, |
340 | 0 | "drive-disconnected", |
341 | 0 | child_drive); |
342 | 0 | } |
343 | | |
344 | | static void |
345 | | child_drive_changed (GVolumeMonitor *child_monitor, |
346 | | GDrive *child_drive, |
347 | | GUnionVolumeMonitor *union_monitor) |
348 | 0 | { |
349 | 0 | g_signal_emit_by_name (union_monitor, |
350 | 0 | "drive-changed", |
351 | 0 | child_drive); |
352 | 0 | } |
353 | | |
354 | | static void |
355 | | child_drive_eject_button (GVolumeMonitor *child_monitor, |
356 | | GDrive *child_drive, |
357 | | GUnionVolumeMonitor *union_monitor) |
358 | 0 | { |
359 | 0 | g_signal_emit_by_name (union_monitor, |
360 | 0 | "drive-eject-button", |
361 | 0 | child_drive); |
362 | 0 | } |
363 | | |
364 | | static void |
365 | | child_drive_stop_button (GVolumeMonitor *child_monitor, |
366 | | GDrive *child_drive, |
367 | | GUnionVolumeMonitor *union_monitor) |
368 | 0 | { |
369 | 0 | g_signal_emit_by_name (union_monitor, |
370 | 0 | "drive-stop-button", |
371 | 0 | child_drive); |
372 | 0 | } |
373 | | |
374 | | static void |
375 | | g_union_volume_monitor_add_monitor (GUnionVolumeMonitor *union_monitor, |
376 | | GVolumeMonitor *volume_monitor) |
377 | 0 | { |
378 | 0 | if (g_list_find (union_monitor->monitors, volume_monitor)) |
379 | 0 | return; |
380 | | |
381 | 0 | union_monitor->monitors = |
382 | 0 | g_list_prepend (union_monitor->monitors, |
383 | 0 | g_object_ref (volume_monitor)); |
384 | |
|
385 | 0 | g_signal_connect (volume_monitor, "volume-added", (GCallback)child_volume_added, union_monitor); |
386 | 0 | g_signal_connect (volume_monitor, "volume-removed", (GCallback)child_volume_removed, union_monitor); |
387 | 0 | g_signal_connect (volume_monitor, "volume-changed", (GCallback)child_volume_changed, union_monitor); |
388 | 0 | g_signal_connect (volume_monitor, "mount-added", (GCallback)child_mount_added, union_monitor); |
389 | 0 | g_signal_connect (volume_monitor, "mount-removed", (GCallback)child_mount_removed, union_monitor); |
390 | 0 | g_signal_connect (volume_monitor, "mount-pre-unmount", (GCallback)child_mount_pre_unmount, union_monitor); |
391 | 0 | g_signal_connect (volume_monitor, "mount-changed", (GCallback)child_mount_changed, union_monitor); |
392 | 0 | g_signal_connect (volume_monitor, "drive-connected", (GCallback)child_drive_connected, union_monitor); |
393 | 0 | g_signal_connect (volume_monitor, "drive-disconnected", (GCallback)child_drive_disconnected, union_monitor); |
394 | 0 | g_signal_connect (volume_monitor, "drive-changed", (GCallback)child_drive_changed, union_monitor); |
395 | 0 | g_signal_connect (volume_monitor, "drive-eject-button", (GCallback)child_drive_eject_button, union_monitor); |
396 | 0 | g_signal_connect (volume_monitor, "drive-stop-button", (GCallback)child_drive_stop_button, union_monitor); |
397 | 0 | } |
398 | | |
399 | | static void |
400 | | g_union_volume_monitor_remove_monitor (GUnionVolumeMonitor *union_monitor, |
401 | | GVolumeMonitor *child_monitor) |
402 | 0 | { |
403 | 0 | GList *l; |
404 | |
|
405 | 0 | l = g_list_find (union_monitor->monitors, child_monitor); |
406 | 0 | if (l == NULL) |
407 | 0 | return; |
408 | | |
409 | 0 | union_monitor->monitors = g_list_delete_link (union_monitor->monitors, l); |
410 | |
|
411 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_volume_added, union_monitor); |
412 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_volume_removed, union_monitor); |
413 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_volume_changed, union_monitor); |
414 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_mount_added, union_monitor); |
415 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_mount_removed, union_monitor); |
416 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_mount_pre_unmount, union_monitor); |
417 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_mount_changed, union_monitor); |
418 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_drive_connected, union_monitor); |
419 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_drive_disconnected, union_monitor); |
420 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_drive_changed, union_monitor); |
421 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_drive_eject_button, union_monitor); |
422 | 0 | g_signal_handlers_disconnect_by_func (child_monitor, child_drive_stop_button, union_monitor); |
423 | 0 | } |
424 | | |
425 | | static GType |
426 | | get_default_native_class (gpointer data) |
427 | 0 | { |
428 | 0 | return _g_io_module_get_default_type (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME, |
429 | 0 | "GIO_USE_VOLUME_MONITOR", |
430 | 0 | G_STRUCT_OFFSET (GVolumeMonitorClass, is_supported)); |
431 | 0 | } |
432 | | |
433 | | /* We return the class, with a ref taken. |
434 | | * This way we avoid unloading the class/module |
435 | | * between selecting the type and creating the |
436 | | * instance on the first call. |
437 | | */ |
438 | | static GNativeVolumeMonitorClass * |
439 | | get_native_class (void) |
440 | 0 | { |
441 | 0 | static GOnce once_init = G_ONCE_INIT; |
442 | 0 | GTypeClass *type_class; |
443 | |
|
444 | 0 | type_class = NULL; |
445 | 0 | g_once (&once_init, (GThreadFunc)get_default_native_class, &type_class); |
446 | |
|
447 | 0 | if (type_class == NULL && once_init.retval != GUINT_TO_POINTER(G_TYPE_INVALID)) |
448 | 0 | type_class = g_type_class_ref ((GType)once_init.retval); |
449 | | |
450 | 0 | return (GNativeVolumeMonitorClass *)type_class; |
451 | 0 | } |
452 | | |
453 | | static void |
454 | | g_union_volume_monitor_init (GUnionVolumeMonitor *union_monitor) |
455 | 0 | { |
456 | 0 | } |
457 | | |
458 | | static void |
459 | | populate_union_monitor (GUnionVolumeMonitor *union_monitor) |
460 | 0 | { |
461 | 0 | GVolumeMonitor *monitor; |
462 | 0 | GNativeVolumeMonitorClass *native_class; |
463 | 0 | GVolumeMonitorClass *klass; |
464 | 0 | GIOExtensionPoint *ep; |
465 | 0 | GIOExtension *extension; |
466 | 0 | GList *l; |
467 | |
|
468 | 0 | native_class = get_native_class (); |
469 | |
|
470 | 0 | if (native_class != NULL) |
471 | 0 | { |
472 | 0 | monitor = g_object_new (G_TYPE_FROM_CLASS (native_class), NULL); |
473 | 0 | g_union_volume_monitor_add_monitor (union_monitor, monitor); |
474 | 0 | g_object_unref (monitor); |
475 | 0 | g_type_class_unref (native_class); |
476 | 0 | } |
477 | |
|
478 | 0 | ep = g_io_extension_point_lookup (G_VOLUME_MONITOR_EXTENSION_POINT_NAME); |
479 | 0 | for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next) |
480 | 0 | { |
481 | 0 | extension = l->data; |
482 | | |
483 | 0 | klass = G_VOLUME_MONITOR_CLASS (g_io_extension_ref_class (extension)); |
484 | 0 | if (klass->is_supported == NULL || klass->is_supported()) |
485 | 0 | { |
486 | 0 | monitor = g_object_new (g_io_extension_get_type (extension), NULL); |
487 | 0 | g_union_volume_monitor_add_monitor (union_monitor, monitor); |
488 | 0 | g_object_unref (monitor); |
489 | 0 | } |
490 | 0 | g_type_class_unref (klass); |
491 | 0 | } |
492 | 0 | } |
493 | | |
494 | | static GUnionVolumeMonitor * |
495 | | g_union_volume_monitor_new (void) |
496 | 0 | { |
497 | 0 | GUnionVolumeMonitor *monitor; |
498 | |
|
499 | 0 | monitor = g_object_new (G_TYPE_UNION_VOLUME_MONITOR, NULL); |
500 | | |
501 | 0 | return monitor; |
502 | 0 | } |
503 | | |
504 | | /** |
505 | | * g_volume_monitor_get: |
506 | | * |
507 | | * Gets the volume monitor used by gio. |
508 | | * |
509 | | * Returns: (transfer full): a reference to the #GVolumeMonitor used by gio. Call |
510 | | * g_object_unref() when done with it. |
511 | | **/ |
512 | | GVolumeMonitor * |
513 | | g_volume_monitor_get (void) |
514 | 0 | { |
515 | 0 | GVolumeMonitor *vm; |
516 | | |
517 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
518 | |
|
519 | 0 | if (the_volume_monitor) |
520 | 0 | vm = G_VOLUME_MONITOR (g_object_ref (the_volume_monitor)); |
521 | 0 | else |
522 | 0 | { |
523 | 0 | the_volume_monitor = g_union_volume_monitor_new (); |
524 | 0 | populate_union_monitor (the_volume_monitor); |
525 | 0 | vm = G_VOLUME_MONITOR (the_volume_monitor); |
526 | 0 | } |
527 | | |
528 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
529 | |
|
530 | 0 | return vm; |
531 | 0 | } |
532 | | |
533 | | GMount * |
534 | | _g_mount_get_for_mount_path (const gchar *mount_path, |
535 | | GCancellable *cancellable) |
536 | 0 | { |
537 | 0 | GNativeVolumeMonitorClass *klass; |
538 | 0 | GMount *mount; |
539 | | |
540 | 0 | klass = get_native_class (); |
541 | 0 | if (klass == NULL) |
542 | 0 | return NULL; |
543 | | |
544 | 0 | mount = NULL; |
545 | |
|
546 | 0 | if (klass->get_mount_for_mount_path) |
547 | 0 | mount = klass->get_mount_for_mount_path (mount_path, cancellable); |
548 | | |
549 | | /* TODO: How do we know this succeeded? Keep in mind that the native |
550 | | * volume monitor may fail (e.g. not being able to connect to |
551 | | * udisks). Is the get_mount_for_mount_path() method allowed to |
552 | | * return NULL? Seems like it is ... probably the method needs |
553 | | * to take a boolean and write if it succeeds or not.. Messy. |
554 | | * Very messy. |
555 | | */ |
556 | | |
557 | 0 | g_type_class_unref (klass); |
558 | |
|
559 | 0 | return mount; |
560 | 0 | } |
561 | | |
562 | | /** |
563 | | * g_volume_monitor_adopt_orphan_mount: |
564 | | * @mount: a #GMount object to find a parent for |
565 | | * |
566 | | * This function should be called by any #GVolumeMonitor |
567 | | * implementation when a new #GMount object is created that is not |
568 | | * associated with a #GVolume object. It must be called just before |
569 | | * emitting the @mount_added signal. |
570 | | * |
571 | | * If the return value is not %NULL, the caller must associate the |
572 | | * returned #GVolume object with the #GMount. This involves returning |
573 | | * it in its g_mount_get_volume() implementation. The caller must |
574 | | * also listen for the "removed" signal on the returned object |
575 | | * and give up its reference when handling that signal |
576 | | * |
577 | | * Similarly, if implementing g_volume_monitor_adopt_orphan_mount(), |
578 | | * the implementor must take a reference to @mount and return it in |
579 | | * its g_volume_get_mount() implemented. Also, the implementor must |
580 | | * listen for the "unmounted" signal on @mount and give up its |
581 | | * reference upon handling that signal. |
582 | | * |
583 | | * There are two main use cases for this function. |
584 | | * |
585 | | * One is when implementing a user space file system driver that reads |
586 | | * blocks of a block device that is already represented by the native |
587 | | * volume monitor (for example a CD Audio file system driver). Such |
588 | | * a driver will generate its own #GMount object that needs to be |
589 | | * associated with the #GVolume object that represents the volume. |
590 | | * |
591 | | * The other is for implementing a #GVolumeMonitor whose sole purpose |
592 | | * is to return #GVolume objects representing entries in the users |
593 | | * "favorite servers" list or similar. |
594 | | * |
595 | | * Returns: (transfer full): the #GVolume object that is the parent for @mount or %NULL |
596 | | * if no wants to adopt the #GMount. |
597 | | * |
598 | | * Deprecated: 2.20: Instead of using this function, #GVolumeMonitor |
599 | | * implementations should instead create shadow mounts with the URI of |
600 | | * the mount they intend to adopt. See the proxy volume monitor in |
601 | | * gvfs for an example of this. Also see g_mount_is_shadowed(), |
602 | | * g_mount_shadow() and g_mount_unshadow() functions. |
603 | | */ |
604 | | GVolume * |
605 | | g_volume_monitor_adopt_orphan_mount (GMount *mount) |
606 | 0 | { |
607 | 0 | GVolumeMonitor *child_monitor; |
608 | 0 | GVolumeMonitorClass *child_monitor_class; |
609 | 0 | GVolume *volume; |
610 | 0 | GList *l; |
611 | |
|
612 | 0 | g_return_val_if_fail (mount != NULL, NULL); |
613 | | |
614 | 0 | if (the_volume_monitor == NULL) |
615 | 0 | return NULL; |
616 | | |
617 | 0 | volume = NULL; |
618 | | |
619 | 0 | g_rec_mutex_lock (&the_volume_monitor_mutex); |
620 | |
|
621 | 0 | for (l = the_volume_monitor->monitors; l != NULL; l = l->next) |
622 | 0 | { |
623 | 0 | child_monitor = l->data; |
624 | 0 | child_monitor_class = G_VOLUME_MONITOR_GET_CLASS (child_monitor); |
625 | |
|
626 | 0 | if (child_monitor_class->adopt_orphan_mount != NULL) |
627 | 0 | { |
628 | 0 | volume = child_monitor_class->adopt_orphan_mount (mount, child_monitor); |
629 | 0 | if (volume != NULL) |
630 | 0 | break; |
631 | 0 | } |
632 | 0 | } |
633 | | |
634 | 0 | g_rec_mutex_unlock (&the_volume_monitor_mutex); |
635 | |
|
636 | 0 | return volume; |
637 | 0 | } |