Merge lp:~ubuntu-branches/ubuntu/oneiric/gvfs/oneiric-201109270612 into lp:ubuntu/oneiric/gvfs
- Oneiric (11.10)
- oneiric-201109270612
- Merge into oneiric
Status: | Rejected |
---|---|
Rejected by: | James Westby |
Proposed branch: | lp:~ubuntu-branches/ubuntu/oneiric/gvfs/oneiric-201109270612 |
Merge into: | lp:ubuntu/oneiric/gvfs |
Diff against target: |
7259 lines (+7182/-0) (has conflicts) 12 files modified
.pc/.quilt_patches (+1/-0) .pc/.quilt_series (+1/-0) .pc/.version (+1/-0) .pc/03_xdg-mount.patch/monitor/hal/ghaldrive.c (+959/-0) .pc/03_xdg-mount.patch/monitor/hal/ghalmount.c (+1192/-0) .pc/03_xdg-mount.patch/monitor/hal/ghalvolume.c (+1007/-0) .pc/04_hurd_path_max.patch/monitor/gdu/ggduvolumemonitor.c (+1799/-0) .pc/04_hurd_path_max.patch/monitor/hal/ghalvolumemonitor.c (+1360/-0) .pc/05_shared_libdaemon.patch/common/Makefile.am (+48/-0) .pc/05_shared_libdaemon.patch/daemon/Makefile.am (+529/-0) .pc/06_no_crash_on_unmount.patch/daemon/gvfsjobunmount.c (+281/-0) .pc/applied-patches (+4/-0) Conflict adding file .pc. Moved existing file to .pc.moved. |
To merge this branch: | bzr merge lp:~ubuntu-branches/ubuntu/oneiric/gvfs/oneiric-201109270612 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+77098@code.launchpad.net |
Commit message
Description of the change
The package importer has detected a possible inconsistency between the package history in the archive and the history in bzr. As the archive is authoritative the importer has made lp:ubuntu/oneiric/gvfs reflect what is in the archive and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/oneiric/gvfs/oneiric-201109270612. This merge proposal was created so that an Ubuntu developer can review the situations and perform a merge/upload if necessary. There are three typical cases where this can happen.
1. Where someone pushes a change to bzr and someone else uploads the package without that change. This is the reason that this check is done by the importer. If this appears to be the case then a merge/upload should be done if the changes that were in bzr are still desirable.
2. The importer incorrectly detected the above situation when someone made a change in bzr and then uploaded it.
3. The importer incorrectly detected the above situation when someone just uploaded a package and didn't touch bzr.
If this case doesn't appear to be the first situation then set the status of the merge proposal to "Rejected" and help avoid the problem in future by filing a bug at https:/
(this is an automatically generated message)
Unmerged revisions
- 173. By Martin Pitt
-
reapply patches
- 172. By Martin Pitt
-
releasing version 1.10.0-0ubuntu1
- 171. By Martin Pitt
-
new upstream release 1.10.0
- 170. By Martin Pitt
-
unapply patches
- 169. By Martin Pitt
-
clarify changelog
- 168. By Sebastien Bacher
-
Enable AFP backend
Preview Diff
1 | === added directory '.pc' |
2 | === renamed directory '.pc' => '.pc.moved' |
3 | === added file '.pc/.quilt_patches' |
4 | --- .pc/.quilt_patches 1970-01-01 00:00:00 +0000 |
5 | +++ .pc/.quilt_patches 2011-09-27 06:17:30 +0000 |
6 | @@ -0,0 +1,1 @@ |
7 | +debian/patches |
8 | |
9 | === added file '.pc/.quilt_series' |
10 | --- .pc/.quilt_series 1970-01-01 00:00:00 +0000 |
11 | +++ .pc/.quilt_series 2011-09-27 06:17:30 +0000 |
12 | @@ -0,0 +1,1 @@ |
13 | +series |
14 | |
15 | === added file '.pc/.version' |
16 | --- .pc/.version 1970-01-01 00:00:00 +0000 |
17 | +++ .pc/.version 2011-09-27 06:17:30 +0000 |
18 | @@ -0,0 +1,1 @@ |
19 | +2 |
20 | |
21 | === added directory '.pc/03_xdg-mount.patch' |
22 | === added file '.pc/03_xdg-mount.patch/.timestamp' |
23 | === added directory '.pc/03_xdg-mount.patch/monitor' |
24 | === added directory '.pc/03_xdg-mount.patch/monitor/hal' |
25 | === added file '.pc/03_xdg-mount.patch/monitor/hal/ghaldrive.c' |
26 | --- .pc/03_xdg-mount.patch/monitor/hal/ghaldrive.c 1970-01-01 00:00:00 +0000 |
27 | +++ .pc/03_xdg-mount.patch/monitor/hal/ghaldrive.c 2011-09-27 06:17:30 +0000 |
28 | @@ -0,0 +1,959 @@ |
29 | +/* GIO - GLib Input, Output and Streaming Library |
30 | + * |
31 | + * Copyright (C) 2006-2007 Red Hat, Inc. |
32 | + * |
33 | + * This library is free software; you can redistribute it and/or |
34 | + * modify it under the terms of the GNU Lesser General Public |
35 | + * License as published by the Free Software Foundation; either |
36 | + * version 2 of the License, or (at your option) any later version. |
37 | + * |
38 | + * This library is distributed in the hope that it will be useful, |
39 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
40 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
41 | + * Lesser General Public License for more details. |
42 | + * |
43 | + * You should have received a copy of the GNU Lesser General |
44 | + * Public License along with this library; if not, write to the |
45 | + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
46 | + * Boston, MA 02111-1307, USA. |
47 | + * |
48 | + * Author: David Zeuthen <davidz@redhat.com> |
49 | + */ |
50 | + |
51 | +#include <config.h> |
52 | + |
53 | +#include <string.h> |
54 | +#include <sys/wait.h> |
55 | +#include <unistd.h> |
56 | + |
57 | +#include <glib.h> |
58 | +#include <glib/gi18n-lib.h> |
59 | + |
60 | +#include "ghalvolumemonitor.h" |
61 | +#include "ghaldrive.h" |
62 | +#include "ghalvolume.h" |
63 | + |
64 | +struct _GHalDrive { |
65 | + GObject parent; |
66 | + |
67 | + GVolumeMonitor *volume_monitor; /* owned by volume monitor */ |
68 | + GList *volumes; /* entries in list are owned by volume_monitor */ |
69 | + |
70 | + char *name; |
71 | + char *icon; |
72 | + char *device_path; |
73 | + |
74 | + gboolean can_eject; |
75 | + gboolean can_poll_for_media; |
76 | + gboolean is_media_check_automatic; |
77 | + gboolean has_media; |
78 | + gboolean uses_removable_media; |
79 | + |
80 | + HalDevice *device; |
81 | + HalPool *pool; |
82 | +}; |
83 | + |
84 | +static void g_hal_drive_drive_iface_init (GDriveIface *iface); |
85 | + |
86 | +G_DEFINE_TYPE_EXTENDED (GHalDrive, g_hal_drive, G_TYPE_OBJECT, 0, |
87 | + G_IMPLEMENT_INTERFACE (G_TYPE_DRIVE, |
88 | + g_hal_drive_drive_iface_init)) |
89 | + |
90 | +static void |
91 | +g_hal_drive_finalize (GObject *object) |
92 | +{ |
93 | + GList *l; |
94 | + GHalDrive *drive; |
95 | + |
96 | + drive = G_HAL_DRIVE (object); |
97 | + |
98 | + for (l = drive->volumes; l != NULL; l = l->next) |
99 | + { |
100 | + GHalVolume *volume = l->data; |
101 | + g_hal_volume_unset_drive (volume, drive); |
102 | + } |
103 | + |
104 | + g_free (drive->device_path); |
105 | + if (drive->device != NULL) |
106 | + g_object_unref (drive->device); |
107 | + if (drive->pool != NULL) |
108 | + g_object_unref (drive->pool); |
109 | + |
110 | + g_free (drive->name); |
111 | + g_free (drive->icon); |
112 | + |
113 | + if (drive->volume_monitor != NULL) |
114 | + g_object_remove_weak_pointer (G_OBJECT (drive->volume_monitor), (gpointer) &(drive->volume_monitor)); |
115 | + |
116 | + if (G_OBJECT_CLASS (g_hal_drive_parent_class)->finalize) |
117 | + (*G_OBJECT_CLASS (g_hal_drive_parent_class)->finalize) (object); |
118 | +} |
119 | + |
120 | +static void |
121 | +g_hal_drive_class_init (GHalDriveClass *klass) |
122 | +{ |
123 | + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
124 | + |
125 | + gobject_class->finalize = g_hal_drive_finalize; |
126 | +} |
127 | + |
128 | +static void |
129 | +g_hal_drive_init (GHalDrive *hal_drive) |
130 | +{ |
131 | +} |
132 | + |
133 | +static char * |
134 | +_drive_get_description (HalDevice *d) |
135 | +{ |
136 | + char *s = NULL; |
137 | + const char *drive_type; |
138 | + const char *drive_bus; |
139 | + const char *name_from_hal; |
140 | + |
141 | + drive_type = hal_device_get_property_string (d, "storage.drive_type"); |
142 | + drive_bus = hal_device_get_property_string (d, "storage.bus"); |
143 | + name_from_hal = hal_device_get_property_string (d, "info.desktop.name"); |
144 | + |
145 | + |
146 | + if (strlen (name_from_hal) > 0) |
147 | + { |
148 | + s = g_strdup (name_from_hal); |
149 | + } |
150 | + else if (strcmp (drive_type, "cdrom") == 0) |
151 | + { |
152 | + const char *first; |
153 | + const char *second; |
154 | + |
155 | + first = _("CD-ROM"); |
156 | + if (hal_device_get_property_bool (d, "storage.cdrom.cdr")) |
157 | + first = _("CD-R"); |
158 | + if (hal_device_get_property_bool (d, "storage.cdrom.cdrw")) |
159 | + first = _("CD-RW"); |
160 | + |
161 | + second = NULL; |
162 | + if (hal_device_get_property_bool (d, "storage.cdrom.dvd")) |
163 | + second = _("DVD-ROM"); |
164 | + if (hal_device_get_property_bool (d, "storage.cdrom.dvdplusr")) |
165 | + second = _("DVD+R"); |
166 | + if (hal_device_get_property_bool (d, "storage.cdrom.dvdplusrw")) |
167 | + second = _("DVD+RW"); |
168 | + if (hal_device_get_property_bool (d, "storage.cdrom.dvdr")) |
169 | + second = _("DVD-R"); |
170 | + if (hal_device_get_property_bool (d, "storage.cdrom.dvdrw")) |
171 | + second = _("DVD-RW"); |
172 | + if (hal_device_get_property_bool (d, "storage.cdrom.dvdram")) |
173 | + second = _("DVD-RAM"); |
174 | + if ((hal_device_get_property_bool (d, "storage.cdrom.dvdr")) && |
175 | + (hal_device_get_property_bool (d, "storage.cdrom.dvdplusr"))) |
176 | + second = _("DVD\xc2\xb1R"); |
177 | + if (hal_device_get_property_bool (d, "storage.cdrom.dvdrw") && |
178 | + hal_device_get_property_bool (d, "storage.cdrom.dvdplusrw")) |
179 | + second = _("DVD\xc2\xb1RW"); |
180 | + if (hal_device_get_property_bool (d, "storage.cdrom.hddvd")) |
181 | + second = _("HDDVD"); |
182 | + if (hal_device_get_property_bool (d, "storage.cdrom.hddvdr")) |
183 | + second = _("HDDVD-r"); |
184 | + if (hal_device_get_property_bool (d, "storage.cdrom.hddvdrw")) |
185 | + second = _("HDDVD-RW"); |
186 | + if (hal_device_get_property_bool (d, "storage.cdrom.bd")) |
187 | + second = _("Blu-ray"); |
188 | + if (hal_device_get_property_bool (d, "storage.cdrom.bdr")) |
189 | + second = _("Blu-ray-R"); |
190 | + if (hal_device_get_property_bool (d, "storage.cdrom.bdre")) |
191 | + second = _("Blu-ray-RE"); |
192 | + |
193 | + if (second != NULL) |
194 | + { |
195 | + /* translators: This wis something like "CD-ROM/DVD Drive" or |
196 | + "CD-RW/Blue-ray Drive" depending on the properties of the drive */ |
197 | + s = g_strdup_printf (_("%s/%s Drive"), first, second); |
198 | + } |
199 | + else |
200 | + { |
201 | + /* translators: This wis something like "CD-ROM Drive" or "CD-RW Drive |
202 | + depending on the properties of the drive */ |
203 | + s = g_strdup_printf (_("%s Drive"), first); |
204 | + } |
205 | + } |
206 | + else if (strcmp (drive_type, "floppy") == 0) |
207 | + s = g_strdup (_("Floppy Drive")); |
208 | + else if (strcmp (drive_type, "disk") == 0) |
209 | + { |
210 | + if (drive_bus != NULL) |
211 | + { |
212 | + if (strcmp (drive_bus, "linux_raid") == 0) |
213 | + s = g_strdup (_("Software RAID Drive")); |
214 | + if (strcmp (drive_bus, "usb") == 0) |
215 | + s = g_strdup (_("USB Drive")); |
216 | + if (strcmp (drive_bus, "ide") == 0) |
217 | + s = g_strdup (_("ATA Drive")); |
218 | + if (strcmp (drive_bus, "scsi") == 0) |
219 | + s = g_strdup (_("SCSI Drive")); |
220 | + if (strcmp (drive_bus, "ieee1394") == 0) |
221 | + s = g_strdup (_("FireWire Drive")); |
222 | + } |
223 | + } |
224 | + else if (strcmp (drive_type, "tape") == 0) |
225 | + s = g_strdup (_("Tape Drive")); |
226 | + else if (strcmp (drive_type, "compact_flash") == 0) |
227 | + s = g_strdup (_("CompactFlash Drive")); |
228 | + else if (strcmp (drive_type, "memory_stick") == 0) |
229 | + s = g_strdup (_("MemoryStick Drive")); |
230 | + else if (strcmp (drive_type, "smart_media") == 0) |
231 | + s = g_strdup (_("SmartMedia Drive")); |
232 | + else if (strcmp (drive_type, "sd_mmc") == 0) |
233 | + s = g_strdup (_("SD/MMC Drive")); |
234 | + else if (strcmp (drive_type, "zip") == 0) |
235 | + s = g_strdup (_("Zip Drive")); |
236 | + else if (strcmp (drive_type, "jaz") == 0) |
237 | + s = g_strdup (_("Jaz Drive")); |
238 | + else if (strcmp (drive_type, "flashkey") == 0) |
239 | + s = g_strdup (_("Thumb Drive")); |
240 | + |
241 | + if (s == NULL) |
242 | + s = g_strdup (_("Mass Storage Drive")); |
243 | + |
244 | + return s; |
245 | +} |
246 | + |
247 | +char * |
248 | +_drive_get_icon (HalDevice *d) |
249 | +{ |
250 | + char *s = NULL; |
251 | + const char *drive_type; |
252 | + const char *drive_bus; |
253 | + const char *icon_from_hal; |
254 | + gboolean is_audio_player; |
255 | + |
256 | + drive_type = hal_device_get_property_string (d, "storage.drive_type"); |
257 | + drive_bus = hal_device_get_property_string (d, "storage.bus"); |
258 | + is_audio_player = hal_device_has_capability (d, "portable_audio_player"); |
259 | + icon_from_hal = hal_device_get_property_string (d, "storage.icon.drive"); |
260 | + |
261 | + if (strlen (icon_from_hal) > 0) |
262 | + s = g_strdup (icon_from_hal); |
263 | + else if (is_audio_player) |
264 | + s = g_strdup ("multimedia-player"); |
265 | + else if (strcmp (drive_type, "disk") == 0) |
266 | + { |
267 | + if (strcmp (drive_bus, "ide") == 0) |
268 | + s = g_strdup ("drive-removable-media-ata"); |
269 | + else if (strcmp (drive_bus, "scsi") == 0) |
270 | + s = g_strdup ("drive-removable-media-scsi"); |
271 | + else if (strcmp (drive_bus, "ieee1394") == 0) |
272 | + s = g_strdup ("drive-removable-media-ieee1394"); |
273 | + else if (strcmp (drive_bus, "usb") == 0) |
274 | + s = g_strdup ("drive-removable-media-usb"); |
275 | + else |
276 | + s = g_strdup ("drive-removable-media"); |
277 | + } |
278 | + else if (strcmp (drive_type, "cdrom") == 0) |
279 | + { |
280 | + /* TODO: maybe there's a better heuristic than this */ |
281 | + if (hal_device_get_property_int (d, "storage.cdrom.write_speed") > 0) |
282 | + s = g_strdup ("drive-optical-recorder"); |
283 | + else |
284 | + s = g_strdup ("drive-optical"); |
285 | + } |
286 | + else if (strcmp (drive_type, "floppy") == 0) |
287 | + s = g_strdup ("drive-removable-media-floppy"); |
288 | + else if (strcmp (drive_type, "tape") == 0) |
289 | + s = g_strdup ("drive-removable-media-tape"); |
290 | + else if (strcmp (drive_type, "compact_flash") == 0) |
291 | + s = g_strdup ("drive-removable-media-flash-cf"); |
292 | + else if (strcmp (drive_type, "memory_stick") == 0) |
293 | + s = g_strdup ("drive-removable-media-flash-ms"); |
294 | + else if (strcmp (drive_type, "smart_media") == 0) |
295 | + s = g_strdup ("drive-removable-media-flash-sm"); |
296 | + else if (strcmp (drive_type, "sd_mmc") == 0) |
297 | + s = g_strdup ("drive-removable-media-flash-sd"); |
298 | + |
299 | + if (s == NULL) |
300 | + s = g_strdup ("drive-removable-media"); |
301 | + |
302 | + return s; |
303 | +} |
304 | + |
305 | +static void |
306 | +_do_update_from_hal (GHalDrive *d) |
307 | +{ |
308 | + d->name = _drive_get_description (d->device); |
309 | + d->icon = _drive_get_icon (d->device); |
310 | + |
311 | + d->uses_removable_media = hal_device_get_property_bool (d->device, "storage.removable"); |
312 | + if (d->uses_removable_media) |
313 | + { |
314 | + d->has_media = hal_device_get_property_bool (d->device, "storage.removable.media_available"); |
315 | + d->is_media_check_automatic = hal_device_get_property_bool (d->device, "storage.media_check_enabled"); |
316 | + d->can_poll_for_media = hal_device_has_interface (d->device, "org.freedesktop.Hal.Device.Storage.Removable"); |
317 | + d->can_eject = hal_device_get_property_bool (d->device, "storage.requires_eject"); |
318 | + } |
319 | + else |
320 | + { |
321 | + d->has_media = TRUE; |
322 | + d->is_media_check_automatic = FALSE; |
323 | + d->can_poll_for_media = FALSE; |
324 | + d->can_eject = FALSE; |
325 | + } |
326 | +} |
327 | + |
328 | +static void |
329 | +emit_drive_changed (GHalDrive *drive) |
330 | +{ |
331 | + g_signal_emit_by_name (drive, "changed"); |
332 | + if (drive->volume_monitor != NULL) |
333 | + g_signal_emit_by_name (drive->volume_monitor, "drive_changed", drive); |
334 | +} |
335 | + |
336 | +static void |
337 | +_update_from_hal (GHalDrive *d, gboolean emit_changed) |
338 | +{ |
339 | + char *old_name; |
340 | + char *old_icon; |
341 | + gboolean old_uses_removable_media; |
342 | + gboolean old_has_media; |
343 | + gboolean old_is_media_check_automatic; |
344 | + gboolean old_can_poll_for_media; |
345 | + gboolean old_can_eject; |
346 | + |
347 | + old_name = g_strdup (d->name); |
348 | + old_icon = g_strdup (d->icon); |
349 | + old_uses_removable_media = d->uses_removable_media; |
350 | + old_has_media = d->has_media; |
351 | + old_is_media_check_automatic = d->is_media_check_automatic; |
352 | + old_can_poll_for_media = d->can_poll_for_media; |
353 | + old_can_eject = d->can_eject; |
354 | + |
355 | + g_free (d->name); |
356 | + g_free (d->icon); |
357 | + _do_update_from_hal (d); |
358 | + |
359 | + if (emit_changed && |
360 | + (old_uses_removable_media != d->uses_removable_media || |
361 | + old_has_media != d->has_media || |
362 | + old_is_media_check_automatic != d->is_media_check_automatic || |
363 | + old_can_poll_for_media != d->can_poll_for_media || |
364 | + old_can_eject != d->can_eject || |
365 | + old_name == NULL || |
366 | + old_icon == NULL || |
367 | + strcmp (old_name, d->name) != 0 || |
368 | + strcmp (old_icon, d->icon) != 0)) |
369 | + emit_drive_changed (d); |
370 | + |
371 | + g_free (old_name); |
372 | + g_free (old_icon); |
373 | +} |
374 | + |
375 | +static void |
376 | +hal_condition (HalDevice *device, const char *name, const char *detail, gpointer user_data) |
377 | +{ |
378 | + GHalDrive *hal_drive = G_HAL_DRIVE (user_data); |
379 | + |
380 | + if (strcmp (name, "EjectPressed") == 0) |
381 | + { |
382 | + g_signal_emit_by_name (hal_drive, "eject-button"); |
383 | + if (hal_drive->volume_monitor != NULL) |
384 | + g_signal_emit_by_name (hal_drive->volume_monitor, "drive-eject-button", hal_drive); |
385 | + } |
386 | + |
387 | +} |
388 | + |
389 | +static void |
390 | +hal_changed (HalDevice *device, const char *key, gpointer user_data) |
391 | +{ |
392 | + GHalDrive *hal_drive = G_HAL_DRIVE (user_data); |
393 | + |
394 | + /*g_warning ("volhal modifying %s (property %s changed)", hal_drive->device_path, key);*/ |
395 | + _update_from_hal (hal_drive, TRUE); |
396 | +} |
397 | + |
398 | +GHalDrive * |
399 | +g_hal_drive_new (GVolumeMonitor *volume_monitor, |
400 | + HalDevice *device, |
401 | + HalPool *pool) |
402 | +{ |
403 | + GHalDrive *drive; |
404 | + |
405 | + drive = g_object_new (G_TYPE_HAL_DRIVE, NULL); |
406 | + drive->volume_monitor = volume_monitor; |
407 | + g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(drive->volume_monitor)); |
408 | + drive->device_path = g_strdup (hal_device_get_property_string (device, "block.device")); |
409 | + drive->device = g_object_ref (device); |
410 | + drive->pool = g_object_ref (pool); |
411 | + |
412 | + drive->name = g_strdup_printf ("Drive for %s", drive->device_path); |
413 | + drive->icon = g_strdup_printf ("drive-removable-media"); |
414 | + |
415 | + g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, drive, 0); |
416 | + g_signal_connect_object (device, "hal_condition", (GCallback) hal_condition, drive, 0); |
417 | + |
418 | + _update_from_hal (drive, FALSE); |
419 | + |
420 | + return drive; |
421 | +} |
422 | + |
423 | +void |
424 | +g_hal_drive_disconnected (GHalDrive *drive) |
425 | +{ |
426 | + GList *l, *volumes; |
427 | + |
428 | + volumes = drive->volumes; |
429 | + drive->volumes = NULL; |
430 | + |
431 | + for (l = volumes; l != NULL; l = l->next) |
432 | + { |
433 | + GHalVolume *volume = l->data; |
434 | + g_hal_volume_unset_drive (volume, drive); |
435 | + } |
436 | + |
437 | + g_list_free (volumes); |
438 | +} |
439 | + |
440 | +void |
441 | +g_hal_drive_set_volume (GHalDrive *drive, |
442 | + GHalVolume *volume) |
443 | +{ |
444 | + |
445 | + if (g_list_find (drive->volumes, volume) == NULL) |
446 | + { |
447 | + drive->volumes = g_list_prepend (drive->volumes, volume); |
448 | + emit_drive_changed (drive); |
449 | + } |
450 | +} |
451 | + |
452 | +void |
453 | +g_hal_drive_unset_volume (GHalDrive *drive, |
454 | + GHalVolume *volume) |
455 | +{ |
456 | + GList *l; |
457 | + |
458 | + l = g_list_find (drive->volumes, volume); |
459 | + if (l != NULL) |
460 | + { |
461 | + drive->volumes = g_list_delete_link (drive->volumes, l); |
462 | + |
463 | + emit_drive_changed (drive); |
464 | + } |
465 | +} |
466 | + |
467 | +gboolean |
468 | +g_hal_drive_has_udi (GHalDrive *drive, const char *udi) |
469 | +{ |
470 | + gboolean res; |
471 | + |
472 | + res = strcmp (udi, hal_device_get_udi (drive->device)) == 0; |
473 | + |
474 | + return res; |
475 | +} |
476 | + |
477 | +static GIcon * |
478 | +g_hal_drive_get_icon (GDrive *drive) |
479 | +{ |
480 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
481 | + GIcon *icon; |
482 | + |
483 | + icon = g_themed_icon_new_with_default_fallbacks (hal_drive->icon); |
484 | + |
485 | + return icon; |
486 | +} |
487 | + |
488 | +static char * |
489 | +g_hal_drive_get_name (GDrive *drive) |
490 | +{ |
491 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
492 | + char *name; |
493 | + |
494 | + name = g_strdup (hal_drive->name); |
495 | + |
496 | + return name; |
497 | +} |
498 | + |
499 | +static GList * |
500 | +g_hal_drive_get_volumes (GDrive *drive) |
501 | +{ |
502 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
503 | + GList *l; |
504 | + |
505 | + l = g_list_copy (hal_drive->volumes); |
506 | + g_list_foreach (l, (GFunc) g_object_ref, NULL); |
507 | + |
508 | + return l; |
509 | +} |
510 | + |
511 | +static gboolean |
512 | +g_hal_drive_has_volumes (GDrive *drive) |
513 | +{ |
514 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
515 | + |
516 | + return hal_drive->volumes != NULL; |
517 | +} |
518 | + |
519 | +static gboolean |
520 | +g_hal_drive_is_media_removable (GDrive *drive) |
521 | +{ |
522 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
523 | + |
524 | + return hal_drive->uses_removable_media; |
525 | +} |
526 | + |
527 | +static gboolean |
528 | +g_hal_drive_has_media (GDrive *drive) |
529 | +{ |
530 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
531 | + |
532 | + return hal_drive->has_media; |
533 | +} |
534 | + |
535 | +static gboolean |
536 | +g_hal_drive_is_media_check_automatic (GDrive *drive) |
537 | +{ |
538 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
539 | + |
540 | + return hal_drive->is_media_check_automatic; |
541 | +} |
542 | + |
543 | +static gboolean |
544 | +g_hal_drive_can_eject (GDrive *drive) |
545 | +{ |
546 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
547 | + |
548 | + return hal_drive->can_eject; |
549 | +} |
550 | + |
551 | +static gboolean |
552 | +g_hal_drive_can_poll_for_media (GDrive *drive) |
553 | +{ |
554 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
555 | + |
556 | + return hal_drive->can_poll_for_media; |
557 | +} |
558 | + |
559 | +typedef struct { |
560 | + GObject *object; |
561 | + GAsyncReadyCallback callback; |
562 | + gpointer user_data; |
563 | + GCancellable *cancellable; |
564 | +} SpawnOp; |
565 | + |
566 | +static void |
567 | +spawn_cb (GPid pid, gint status, gpointer user_data) |
568 | +{ |
569 | + SpawnOp *data = user_data; |
570 | + GSimpleAsyncResult *simple; |
571 | + |
572 | + |
573 | + if (WEXITSTATUS (status) != 0) |
574 | + { |
575 | + GError *error; |
576 | + error = g_error_new_literal (G_IO_ERROR, |
577 | + G_IO_ERROR_FAILED_HANDLED, |
578 | + "You are not supposed to show G_IO_ERROR_FAILED_HANDLED in the UI"); |
579 | + simple = g_simple_async_result_new_from_error (data->object, |
580 | + data->callback, |
581 | + data->user_data, |
582 | + error); |
583 | + g_error_free (error); |
584 | + } |
585 | + else |
586 | + { |
587 | + simple = g_simple_async_result_new (data->object, |
588 | + data->callback, |
589 | + data->user_data, |
590 | + NULL); |
591 | + } |
592 | + g_simple_async_result_complete (simple); |
593 | + g_object_unref (simple); |
594 | + g_object_unref (data->object); |
595 | + g_free (data); |
596 | +} |
597 | + |
598 | +static void |
599 | +g_hal_drive_eject_do (GDrive *drive, |
600 | + GCancellable *cancellable, |
601 | + GAsyncReadyCallback callback, |
602 | + gpointer user_data) |
603 | +{ |
604 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
605 | + SpawnOp *data; |
606 | + GPid child_pid; |
607 | + GError *error; |
608 | + char *argv[] = {"gnome-mount", "-e", "-b", "-d", NULL, NULL}; |
609 | + |
610 | + argv[4] = g_strdup (hal_drive->device_path); |
611 | + |
612 | + data = g_new0 (SpawnOp, 1); |
613 | + data->object = g_object_ref (drive); |
614 | + data->callback = callback; |
615 | + data->user_data = user_data; |
616 | + data->cancellable = cancellable; |
617 | + |
618 | + error = NULL; |
619 | + if (!g_spawn_async (NULL, /* working dir */ |
620 | + argv, |
621 | + NULL, /* envp */ |
622 | + G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH, |
623 | + NULL, /* child_setup */ |
624 | + NULL, /* user_data for child_setup */ |
625 | + &child_pid, |
626 | + &error)) |
627 | + { |
628 | + GSimpleAsyncResult *simple; |
629 | + |
630 | + simple = g_simple_async_result_new_from_error (data->object, |
631 | + data->callback, |
632 | + data->user_data, |
633 | + error); |
634 | + g_simple_async_result_complete (simple); |
635 | + g_object_unref (simple); |
636 | + g_object_unref (drive); |
637 | + g_error_free (error); |
638 | + g_free (data); |
639 | + } |
640 | + else |
641 | + g_child_watch_add (child_pid, spawn_cb, data); |
642 | + |
643 | + g_free (argv[4]); |
644 | +} |
645 | + |
646 | + |
647 | +typedef struct { |
648 | + GDrive *drive; |
649 | + GAsyncReadyCallback callback; |
650 | + gpointer user_data; |
651 | + GMountOperation *mount_operation; |
652 | + GCancellable *cancellable; |
653 | + GMountUnmountFlags flags; |
654 | + |
655 | + GList *pending_mounts; |
656 | +} UnmountMountsOp; |
657 | + |
658 | +static void |
659 | +free_unmount_mounts_op (UnmountMountsOp *data) |
660 | +{ |
661 | + GList *l; |
662 | + |
663 | + for (l = data->pending_mounts; l != NULL; l = l->next) |
664 | + { |
665 | + GMount *mount = l->data; |
666 | + g_object_unref (mount); |
667 | + } |
668 | + g_list_free (data->pending_mounts); |
669 | +} |
670 | + |
671 | +static void _eject_unmount_mounts (UnmountMountsOp *data); |
672 | + |
673 | +static void |
674 | +_eject_unmount_mounts_cb (GObject *source_object, |
675 | + GAsyncResult *res, |
676 | + gpointer user_data) |
677 | +{ |
678 | + UnmountMountsOp *data = user_data; |
679 | + GMount *mount = G_MOUNT (source_object); |
680 | + GSimpleAsyncResult *simple; |
681 | + GError *error = NULL; |
682 | + |
683 | + if (!g_mount_unmount_with_operation_finish (mount, res, &error)) |
684 | + { |
685 | + /* make the error dialog more targeted to the drive.. unless the user has already seen a dialog */ |
686 | + if (error->code != G_IO_ERROR_FAILED_HANDLED) |
687 | + { |
688 | + g_error_free (error); |
689 | + error = g_error_new (G_IO_ERROR, G_IO_ERROR_BUSY, |
690 | + _("Failed to eject media; one or more volumes on the media are busy.")); |
691 | + } |
692 | + |
693 | + /* unmount failed; need to fail the whole eject operation */ |
694 | + simple = g_simple_async_result_new_from_error (G_OBJECT (data->drive), |
695 | + data->callback, |
696 | + data->user_data, |
697 | + error); |
698 | + g_error_free (error); |
699 | + g_simple_async_result_complete (simple); |
700 | + g_object_unref (simple); |
701 | + |
702 | + free_unmount_mounts_op (data); |
703 | + } |
704 | + else |
705 | + { |
706 | + |
707 | + /*g_warning ("successfully unmounted %p", mount);*/ |
708 | + |
709 | + /* move on to the next mount.. */ |
710 | + _eject_unmount_mounts (data); |
711 | + } |
712 | + |
713 | + g_object_unref (mount); |
714 | +} |
715 | + |
716 | +static void |
717 | +_eject_unmount_mounts (UnmountMountsOp *data) |
718 | +{ |
719 | + GMount *mount; |
720 | + |
721 | + if (data->pending_mounts == NULL) |
722 | + { |
723 | + |
724 | + /*g_warning ("all pending mounts done; ejecting drive");*/ |
725 | + |
726 | + g_hal_drive_eject_do (data->drive, |
727 | + data->cancellable, |
728 | + data->callback, |
729 | + data->user_data); |
730 | + |
731 | + g_object_unref (data->drive); |
732 | + g_free (data); |
733 | + } |
734 | + else |
735 | + { |
736 | + mount = data->pending_mounts->data; |
737 | + data->pending_mounts = g_list_remove (data->pending_mounts, mount); |
738 | + |
739 | + /*g_warning ("unmounting %p", mount);*/ |
740 | + |
741 | + g_mount_unmount_with_operation (mount, |
742 | + data->flags, |
743 | + data->mount_operation, |
744 | + data->cancellable, |
745 | + _eject_unmount_mounts_cb, |
746 | + data); |
747 | + } |
748 | +} |
749 | + |
750 | +static void |
751 | +g_hal_drive_eject_with_operation (GDrive *drive, |
752 | + GMountUnmountFlags flags, |
753 | + GMountOperation *mount_operation, |
754 | + GCancellable *cancellable, |
755 | + GAsyncReadyCallback callback, |
756 | + gpointer user_data) |
757 | +{ |
758 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
759 | + UnmountMountsOp *data; |
760 | + GList *l; |
761 | + |
762 | + /* first we need to go through all the volumes and unmount their assoicated mounts (if any) */ |
763 | + |
764 | + data = g_new0 (UnmountMountsOp, 1); |
765 | + data->drive = g_object_ref (drive); |
766 | + data->mount_operation = mount_operation; |
767 | + data->cancellable = cancellable; |
768 | + data->callback = callback; |
769 | + data->user_data = user_data; |
770 | + data->flags = flags; |
771 | + |
772 | + for (l = hal_drive->volumes; l != NULL; l = l->next) |
773 | + { |
774 | + GHalVolume *volume = l->data; |
775 | + GMount *mount; /* the mount may be foreign; cannot assume GHalMount */ |
776 | + |
777 | + mount = g_volume_get_mount (G_VOLUME (volume)); |
778 | + if (mount != NULL && g_mount_can_unmount (mount)) |
779 | + data->pending_mounts = g_list_prepend (data->pending_mounts, g_object_ref (mount)); |
780 | + } |
781 | + |
782 | + _eject_unmount_mounts (data); |
783 | +} |
784 | + |
785 | +static gboolean |
786 | +g_hal_drive_eject_with_operation_finish (GDrive *drive, |
787 | + GAsyncResult *result, |
788 | + GError **error) |
789 | +{ |
790 | + return TRUE; |
791 | +} |
792 | + |
793 | +static void |
794 | +g_hal_drive_eject (GDrive *drive, |
795 | + GMountUnmountFlags flags, |
796 | + GCancellable *cancellable, |
797 | + GAsyncReadyCallback callback, |
798 | + gpointer user_data) |
799 | +{ |
800 | + g_hal_drive_eject (drive, flags, cancellable, callback, user_data); |
801 | +} |
802 | + |
803 | +static gboolean |
804 | +g_hal_drive_eject_finish (GDrive *drive, |
805 | + GAsyncResult *result, |
806 | + GError **error) |
807 | +{ |
808 | + return g_hal_drive_eject_with_operation_finish (drive, result, error); |
809 | +} |
810 | + |
811 | +typedef struct { |
812 | + GObject *object; |
813 | + GAsyncReadyCallback callback; |
814 | + gpointer user_data; |
815 | + GCancellable *cancellable; |
816 | +} PollOp; |
817 | + |
818 | +static void |
819 | +poll_for_media_cb (DBusPendingCall *pending_call, void *user_data) |
820 | +{ |
821 | + PollOp *data = (PollOp *) user_data; |
822 | + GSimpleAsyncResult *simple; |
823 | + DBusMessage *reply; |
824 | + |
825 | + reply = dbus_pending_call_steal_reply (pending_call); |
826 | + |
827 | + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) |
828 | + { |
829 | + GError *error; |
830 | + DBusError dbus_error; |
831 | + |
832 | + dbus_error_init (&dbus_error); |
833 | + dbus_set_error_from_message (&dbus_error, reply); |
834 | + error = g_error_new (G_IO_ERROR, |
835 | + G_IO_ERROR_FAILED, |
836 | + "Cannot invoke CheckForMedia on HAL: %s: %s", dbus_error.name, dbus_error.message); |
837 | + simple = g_simple_async_result_new_from_error (data->object, |
838 | + data->callback, |
839 | + data->user_data, |
840 | + error); |
841 | + g_simple_async_result_complete (simple); |
842 | + g_object_unref (simple); |
843 | + g_error_free (error); |
844 | + dbus_error_free (&dbus_error); |
845 | + goto out; |
846 | + } |
847 | + |
848 | + /* TODO: parse reply and extract result? |
849 | + * (the result is whether the media availability state changed) |
850 | + */ |
851 | + |
852 | + simple = g_simple_async_result_new (data->object, |
853 | + data->callback, |
854 | + data->user_data, |
855 | + NULL); |
856 | + g_simple_async_result_complete (simple); |
857 | + g_object_unref (simple); |
858 | + |
859 | + out: |
860 | + g_object_unref (data->object); |
861 | + dbus_message_unref (reply); |
862 | + dbus_pending_call_unref (pending_call); |
863 | +} |
864 | + |
865 | + |
866 | +static void |
867 | +g_hal_drive_poll_for_media (GDrive *drive, |
868 | + GCancellable *cancellable, |
869 | + GAsyncReadyCallback callback, |
870 | + gpointer user_data) |
871 | +{ |
872 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
873 | + DBusConnection *con; |
874 | + DBusMessage *msg; |
875 | + DBusPendingCall *pending_call; |
876 | + PollOp *data; |
877 | + |
878 | + data = g_new0 (PollOp, 1); |
879 | + data->object = g_object_ref (drive); |
880 | + data->callback = callback; |
881 | + data->user_data = user_data; |
882 | + data->cancellable = cancellable; |
883 | + |
884 | + /*g_warning ("Rescanning udi %s", hal_device_get_udi (hal_drive->device));*/ |
885 | + |
886 | + con = hal_pool_get_dbus_connection (hal_drive->pool); |
887 | + msg = dbus_message_new_method_call ("org.freedesktop.Hal", |
888 | + hal_device_get_udi (hal_drive->device), |
889 | + "org.freedesktop.Hal.Device.Storage.Removable", |
890 | + "CheckForMedia"); |
891 | + |
892 | + if (!dbus_connection_send_with_reply (con, msg, &pending_call, -1)) |
893 | + { |
894 | + GError *error; |
895 | + GSimpleAsyncResult *simple; |
896 | + error = g_error_new_literal (G_IO_ERROR, |
897 | + G_IO_ERROR_FAILED, |
898 | + "Cannot invoke CheckForMedia on HAL"); |
899 | + simple = g_simple_async_result_new_from_error (data->object, |
900 | + data->callback, |
901 | + data->user_data, |
902 | + error); |
903 | + g_simple_async_result_complete (simple); |
904 | + g_object_unref (simple); |
905 | + g_error_free (error); |
906 | + g_object_unref (data->object); |
907 | + g_free (data); |
908 | + } |
909 | + else |
910 | + dbus_pending_call_set_notify (pending_call, |
911 | + poll_for_media_cb, |
912 | + data, |
913 | + (DBusFreeFunction) g_free); |
914 | + |
915 | + dbus_message_unref (msg); |
916 | +} |
917 | + |
918 | +static gboolean |
919 | +g_hal_drive_poll_for_media_finish (GDrive *drive, |
920 | + GAsyncResult *result, |
921 | + GError **error) |
922 | +{ |
923 | + /*g_warning ("poll finish");*/ |
924 | + return TRUE; |
925 | +} |
926 | + |
927 | +static char * |
928 | +g_hal_drive_get_identifier (GDrive *drive, |
929 | + const char *kind) |
930 | +{ |
931 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
932 | + char *res; |
933 | + |
934 | + res = NULL; |
935 | + |
936 | + if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0) |
937 | + res = g_strdup (hal_device_get_udi (hal_drive->device)); |
938 | + |
939 | + if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0) |
940 | + res = g_strdup (hal_drive->device_path); |
941 | + |
942 | + return res; |
943 | +} |
944 | + |
945 | +static char ** |
946 | +g_hal_drive_enumerate_identifiers (GDrive *drive) |
947 | +{ |
948 | + GHalDrive *hal_drive = G_HAL_DRIVE (drive); |
949 | + GPtrArray *res; |
950 | + |
951 | + res = g_ptr_array_new (); |
952 | + |
953 | + g_ptr_array_add (res, |
954 | + g_strdup (G_VOLUME_IDENTIFIER_KIND_HAL_UDI)); |
955 | + |
956 | + if (hal_drive->device_path && *hal_drive->device_path != 0) |
957 | + g_ptr_array_add (res, |
958 | + g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE)); |
959 | + |
960 | + |
961 | + /* Null-terminate */ |
962 | + g_ptr_array_add (res, NULL); |
963 | + |
964 | + return (char **)g_ptr_array_free (res, FALSE); |
965 | +} |
966 | + |
967 | +static void |
968 | +g_hal_drive_drive_iface_init (GDriveIface *iface) |
969 | +{ |
970 | + iface->get_name = g_hal_drive_get_name; |
971 | + iface->get_icon = g_hal_drive_get_icon; |
972 | + iface->has_volumes = g_hal_drive_has_volumes; |
973 | + iface->get_volumes = g_hal_drive_get_volumes; |
974 | + iface->is_media_removable = g_hal_drive_is_media_removable; |
975 | + iface->has_media = g_hal_drive_has_media; |
976 | + iface->is_media_check_automatic = g_hal_drive_is_media_check_automatic; |
977 | + iface->can_eject = g_hal_drive_can_eject; |
978 | + iface->can_poll_for_media = g_hal_drive_can_poll_for_media; |
979 | + iface->eject = g_hal_drive_eject; |
980 | + iface->eject_finish = g_hal_drive_eject_finish; |
981 | + iface->eject_with_operation = g_hal_drive_eject_with_operation; |
982 | + iface->eject_with_operation_finish = g_hal_drive_eject_with_operation_finish; |
983 | + iface->poll_for_media = g_hal_drive_poll_for_media; |
984 | + iface->poll_for_media_finish = g_hal_drive_poll_for_media_finish; |
985 | + iface->get_identifier = g_hal_drive_get_identifier; |
986 | + iface->enumerate_identifiers = g_hal_drive_enumerate_identifiers; |
987 | +} |
988 | |
989 | === added file '.pc/03_xdg-mount.patch/monitor/hal/ghalmount.c' |
990 | --- .pc/03_xdg-mount.patch/monitor/hal/ghalmount.c 1970-01-01 00:00:00 +0000 |
991 | +++ .pc/03_xdg-mount.patch/monitor/hal/ghalmount.c 2011-09-27 06:17:30 +0000 |
992 | @@ -0,0 +1,1192 @@ |
993 | +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ |
994 | +/* GIO - GLib Input, Output and Streaming Library |
995 | + * |
996 | + * Copyright (C) 2006-2007 Red Hat, Inc. |
997 | + * |
998 | + * This library is free software; you can redistribute it and/or |
999 | + * modify it under the terms of the GNU Lesser General Public |
1000 | + * License as published by the Free Software Foundation; either |
1001 | + * version 2 of the License, or (at your option) any later version. |
1002 | + * |
1003 | + * This library is distributed in the hope that it will be useful, |
1004 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1005 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1006 | + * Lesser General Public License for more details. |
1007 | + * |
1008 | + * You should have received a copy of the GNU Lesser General |
1009 | + * Public License along with this library; if not, write to the |
1010 | + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
1011 | + * Boston, MA 02111-1307, USA. |
1012 | + * |
1013 | + * Author: David Zeuthen <davidz@redhat.com> |
1014 | + */ |
1015 | + |
1016 | +#include <config.h> |
1017 | + |
1018 | +#include <string.h> |
1019 | +#include <sys/wait.h> |
1020 | +#include <unistd.h> |
1021 | + |
1022 | +#include <glib.h> |
1023 | +#include <glib/gi18n-lib.h> |
1024 | +#include <gio/gio.h> |
1025 | + |
1026 | +#include <gvfsmountinfo.h> |
1027 | + |
1028 | +#include "ghalvolumemonitor.h" |
1029 | +#include "ghalmount.h" |
1030 | +#include "ghalvolume.h" |
1031 | + |
1032 | +#include "hal-utils.h" |
1033 | + |
1034 | +struct _GHalMount { |
1035 | + GObject parent; |
1036 | + |
1037 | + GVolumeMonitor *volume_monitor; /* owned by volume monitor */ |
1038 | + GHalVolume *volume; /* owned by volume monitor */ |
1039 | + |
1040 | + char *name; |
1041 | + GIcon *icon; |
1042 | + char *device_path; |
1043 | + char *mount_path; |
1044 | + |
1045 | + char *uuid; |
1046 | + |
1047 | + char *override_name; |
1048 | + GIcon *override_icon; |
1049 | + GFile *override_root; |
1050 | + gboolean cannot_unmount; |
1051 | + |
1052 | + HalDevice *device; |
1053 | + HalDevice *drive_device; |
1054 | + |
1055 | + GIcon *autorun_icon; |
1056 | + gboolean searched_for_autorun; |
1057 | + |
1058 | + gchar *xdg_volume_info_name; |
1059 | + GIcon *xdg_volume_info_icon; |
1060 | + gboolean searched_for_xdg_volume_info; |
1061 | +}; |
1062 | + |
1063 | +static GFile *get_root (GHalMount *hal_mount); |
1064 | + |
1065 | +static void update_from_hal (GHalMount *m, gboolean emit_changed); |
1066 | + |
1067 | +static void g_hal_mount_mount_iface_init (GMountIface *iface); |
1068 | + |
1069 | +G_DEFINE_TYPE_EXTENDED (GHalMount, g_hal_mount, G_TYPE_OBJECT, 0, |
1070 | + G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT, |
1071 | + g_hal_mount_mount_iface_init)) |
1072 | + |
1073 | +static void |
1074 | +g_hal_mount_finalize (GObject *object) |
1075 | +{ |
1076 | + GHalMount *mount; |
1077 | + |
1078 | + mount = G_HAL_MOUNT (object); |
1079 | + |
1080 | + if (mount->volume != NULL) |
1081 | + g_hal_volume_unset_mount (mount->volume, mount); |
1082 | + |
1083 | + g_free (mount->device_path); |
1084 | + g_free (mount->mount_path); |
1085 | + g_free (mount->uuid); |
1086 | + |
1087 | + if (mount->device != NULL) |
1088 | + g_object_unref (mount->device); |
1089 | + if (mount->drive_device != NULL) |
1090 | + g_object_unref (mount->drive_device); |
1091 | + |
1092 | + g_free (mount->name); |
1093 | + if (mount->icon != NULL) |
1094 | + g_object_unref (mount->icon); |
1095 | + |
1096 | + g_free (mount->override_name); |
1097 | + if (mount->override_icon != NULL) |
1098 | + g_object_unref (mount->override_icon); |
1099 | + |
1100 | + if (mount->override_root != NULL) |
1101 | + g_object_unref (mount->override_root); |
1102 | + |
1103 | + if (mount->autorun_icon != NULL) |
1104 | + g_object_unref (mount->autorun_icon); |
1105 | + |
1106 | + g_free (mount->xdg_volume_info_name); |
1107 | + if (mount->xdg_volume_info_icon != NULL) |
1108 | + g_object_unref (mount->xdg_volume_info_icon); |
1109 | + |
1110 | + if (mount->volume_monitor != NULL) |
1111 | + g_object_remove_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor)); |
1112 | + |
1113 | + if (G_OBJECT_CLASS (g_hal_mount_parent_class)->finalize) |
1114 | + (*G_OBJECT_CLASS (g_hal_mount_parent_class)->finalize) (object); |
1115 | +} |
1116 | + |
1117 | +static void |
1118 | +g_hal_mount_class_init (GHalMountClass *klass) |
1119 | +{ |
1120 | + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
1121 | + |
1122 | + gobject_class->finalize = g_hal_mount_finalize; |
1123 | +} |
1124 | + |
1125 | +static void |
1126 | +g_hal_mount_init (GHalMount *hal_mount) |
1127 | +{ |
1128 | +} |
1129 | + |
1130 | +static void |
1131 | +emit_mount_changed (GHalMount *mount) |
1132 | +{ |
1133 | + g_signal_emit_by_name (mount, "changed"); |
1134 | + if (mount->volume_monitor != NULL) |
1135 | + g_signal_emit_by_name (mount->volume_monitor, "mount_changed", mount); |
1136 | +} |
1137 | + |
1138 | +#define KILOBYTE_FACTOR 1000.0 |
1139 | +#define MEGABYTE_FACTOR (1000.0 * 1000.0) |
1140 | +#define GIGABYTE_FACTOR (1000.0 * 1000.0 * 1000.0) |
1141 | + |
1142 | +static char * |
1143 | +format_size_for_display (guint64 size) |
1144 | +{ |
1145 | + char *str; |
1146 | + gdouble displayed_size; |
1147 | + |
1148 | + if (size < MEGABYTE_FACTOR) |
1149 | + { |
1150 | + displayed_size = (double) size / KILOBYTE_FACTOR; |
1151 | + str = g_strdup_printf (_("%.1f kB"), displayed_size); |
1152 | + } |
1153 | + else if (size < GIGABYTE_FACTOR) |
1154 | + { |
1155 | + displayed_size = (double) size / MEGABYTE_FACTOR; |
1156 | + str = g_strdup_printf (_("%.1f MB"), displayed_size); |
1157 | + } |
1158 | + else |
1159 | + { |
1160 | + displayed_size = (double) size / GIGABYTE_FACTOR; |
1161 | + str = g_strdup_printf (_("%.1f GB"), displayed_size); |
1162 | + } |
1163 | + |
1164 | + return str; |
1165 | +} |
1166 | + |
1167 | +static void |
1168 | +got_autorun_info_cb (GObject *source_object, |
1169 | + GAsyncResult *res, |
1170 | + gpointer user_data) |
1171 | +{ |
1172 | + GHalMount *mount = G_HAL_MOUNT (user_data); |
1173 | + |
1174 | + mount->autorun_icon = g_vfs_mount_info_query_autorun_info_finish (G_FILE (source_object), |
1175 | + res, |
1176 | + NULL); |
1177 | + |
1178 | + update_from_hal (mount, TRUE); |
1179 | + |
1180 | + g_object_unref (mount); |
1181 | +} |
1182 | + |
1183 | +static void |
1184 | +got_xdg_volume_info_cb (GObject *source_object, |
1185 | + GAsyncResult *res, |
1186 | + gpointer user_data) |
1187 | +{ |
1188 | + GHalMount *mount = G_HAL_MOUNT (user_data); |
1189 | + |
1190 | + mount->xdg_volume_info_icon = g_vfs_mount_info_query_xdg_volume_info_finish (G_FILE (source_object), |
1191 | + res, |
1192 | + &(mount->xdg_volume_info_name), |
1193 | + NULL); |
1194 | + update_from_hal (mount, TRUE); |
1195 | + |
1196 | + g_object_unref (mount); |
1197 | +} |
1198 | + |
1199 | +static void |
1200 | +do_update_from_hal (GHalMount *m) |
1201 | +{ |
1202 | + HalDevice *volume; |
1203 | + HalDevice *drive; |
1204 | + char *name; |
1205 | + const char *icon_name; |
1206 | + const char *icon_name_fallback; |
1207 | + const char *drive_type; |
1208 | + const char *drive_bus; |
1209 | + gboolean drive_uses_removable_media; |
1210 | + const char *volume_fs_label; |
1211 | + guint64 volume_size; |
1212 | + gboolean volume_is_disc; |
1213 | + gboolean volume_disc_has_audio; |
1214 | + gboolean volume_disc_has_data; |
1215 | + const char *volume_disc_type; |
1216 | + gboolean volume_disc_is_blank; |
1217 | + gboolean is_audio_player; |
1218 | + const char *icon_from_hal; |
1219 | + const char *volume_icon_from_hal; |
1220 | + const char *name_from_hal; |
1221 | + const char *volume_name_from_hal; |
1222 | + gboolean is_crypto; |
1223 | + gboolean is_crypto_cleartext; |
1224 | + |
1225 | + volume = m->device; |
1226 | + drive = m->drive_device; |
1227 | + |
1228 | + drive_type = hal_device_get_property_string (drive, "storage.drive_type"); |
1229 | + drive_bus = hal_device_get_property_string (drive, "storage.bus"); |
1230 | + drive_uses_removable_media = hal_device_get_property_bool (drive, "storage.removable"); |
1231 | + volume_fs_label = hal_device_get_property_string (volume, "volume.label"); |
1232 | + volume_size = hal_device_get_property_uint64 (volume, "volume.size"); |
1233 | + volume_is_disc = hal_device_get_property_bool (volume, "volume.is_disc"); |
1234 | + volume_disc_has_audio = hal_device_get_property_bool (volume, "volume.disc.has_audio"); |
1235 | + volume_disc_has_data = hal_device_get_property_bool (volume, "volume.disc.has_data"); |
1236 | + volume_disc_is_blank = hal_device_get_property_bool (volume, "volume.disc.is_blank"); |
1237 | + volume_disc_type = hal_device_get_property_string (volume, "volume.disc.type"); |
1238 | + is_audio_player = hal_device_has_capability (drive, "portable_audio_player"); |
1239 | + icon_from_hal = hal_device_get_property_string (drive, "storage.icon.drive"); |
1240 | + volume_icon_from_hal = hal_device_get_property_string (volume, "storage.icon.volume"); |
1241 | + name_from_hal = hal_device_get_property_string (drive, "info.desktop.name"); |
1242 | + volume_name_from_hal = hal_device_get_property_string (volume, "info.desktop.name"); |
1243 | + |
1244 | + is_crypto = FALSE; |
1245 | + is_crypto_cleartext = FALSE; |
1246 | + if (strcmp (hal_device_get_property_string (volume, "volume.fsusage"), "crypto") == 0) |
1247 | + is_crypto = TRUE; |
1248 | + |
1249 | + if (strlen (hal_device_get_property_string (volume, "volume.crypto_luks.clear.backing_volume")) > 0) |
1250 | + is_crypto_cleartext = TRUE; |
1251 | + |
1252 | + /*g_warning ("drive_type='%s'", drive_type); */ |
1253 | + /*g_warning ("drive_bus='%s'", drive_bus); */ |
1254 | + /*g_warning ("drive_uses_removable_media=%d", drive_uses_removable_media); */ |
1255 | + |
1256 | + icon_name_fallback = NULL; |
1257 | + |
1258 | + if (strlen (volume_icon_from_hal) > 0) |
1259 | + icon_name = volume_icon_from_hal; |
1260 | + else if (strlen (icon_from_hal) > 0) |
1261 | + icon_name = icon_from_hal; |
1262 | + else if (is_audio_player) |
1263 | + icon_name = "multimedia-player"; |
1264 | + else if (strcmp (drive_type, "disk") == 0) |
1265 | + { |
1266 | + if (strcmp (drive_bus, "ide") == 0) |
1267 | + icon_name = "drive-harddisk-ata"; |
1268 | + else if (strcmp (drive_bus, "scsi") == 0) |
1269 | + icon_name = "drive-harddisk-scsi"; |
1270 | + else if (strcmp (drive_bus, "ieee1394") == 0) |
1271 | + icon_name = "drive-harddisk-ieee1394"; |
1272 | + else if (strcmp (drive_bus, "usb") == 0) |
1273 | + icon_name = "drive-harddisk-usb"; |
1274 | + else |
1275 | + icon_name = "drive-harddisk"; |
1276 | + } |
1277 | + else if (strcmp (drive_type, "cdrom") == 0) |
1278 | + icon_name = get_disc_icon (volume_disc_type); |
1279 | + else if (strcmp (drive_type, "floppy") == 0) |
1280 | + icon_name = "media-floppy"; |
1281 | + else if (strcmp (drive_type, "tape") == 0) |
1282 | + icon_name = "media-tape"; |
1283 | + else if (strcmp (drive_type, "compact_flash") == 0) |
1284 | + icon_name = "media-flash-cf"; |
1285 | + else if (strcmp (drive_type, "memory_stick") == 0) |
1286 | + icon_name = "media-flash-ms"; |
1287 | + else if (strcmp (drive_type, "smart_media") == 0) |
1288 | + icon_name = "media-flash-sm"; |
1289 | + else if (strcmp (drive_type, "sd_mmc") == 0) |
1290 | + icon_name = "media-flash-sd"; |
1291 | + else |
1292 | + icon_name = "drive-harddisk"; |
1293 | + |
1294 | + /* Create default fallbacks for the icon_name by default |
1295 | + * with get_themed_icon_with_fallbacks () */ |
1296 | + icon_name_fallback = icon_name; |
1297 | + |
1298 | + /* Note: we are not chaning the default fallbacks |
1299 | + * so we get all the fallbacks if the media-encrytped |
1300 | + * icon is not there */ |
1301 | + if (is_crypto || is_crypto_cleartext) |
1302 | + icon_name = "media-encrypted"; |
1303 | + |
1304 | + if (strlen (volume_name_from_hal) > 0) |
1305 | + name = g_strdup (volume_name_from_hal); |
1306 | + else if (strlen (name_from_hal) > 0) |
1307 | + name = g_strdup (name_from_hal); |
1308 | + else if (volume_fs_label != NULL && strlen (volume_fs_label) > 0) |
1309 | + name = g_strdup (volume_fs_label); |
1310 | + else if (volume_is_disc) |
1311 | + { |
1312 | + if (volume_disc_has_audio) |
1313 | + { |
1314 | + if (volume_disc_has_data) |
1315 | + name = g_strdup (_("Mixed Audio/Data Disc")); |
1316 | + else |
1317 | + name = g_strdup (_("Audio Disc")); |
1318 | + } |
1319 | + else |
1320 | + name = g_strdup (get_disc_name (volume_disc_type, volume_disc_is_blank)); |
1321 | + } |
1322 | + else |
1323 | + { |
1324 | + char *size; |
1325 | + |
1326 | + size = format_size_for_display (volume_size); |
1327 | + /* Translators: %s is the size of the mount (e.g. 512 MB) */ |
1328 | + name = g_strdup_printf (_("%s Medium"), size); |
1329 | + g_free (size); |
1330 | + } |
1331 | + |
1332 | + /* order of preference : xdg, override, probed */ |
1333 | + if (m->xdg_volume_info_name != NULL) |
1334 | + { |
1335 | + m->name = g_strdup (m->xdg_volume_info_name); |
1336 | + g_free (name); |
1337 | + } |
1338 | + else if (m->override_name != NULL) |
1339 | + { |
1340 | + m->name = g_strdup (m->override_name); |
1341 | + g_free (name); |
1342 | + } |
1343 | + else |
1344 | + m->name = name; |
1345 | + |
1346 | + /* order of preference: xdg, autorun, override, probed */ |
1347 | + if (m->xdg_volume_info_icon != NULL) |
1348 | + m->icon = g_object_ref (m->xdg_volume_info_icon); |
1349 | + else if (m->autorun_icon != NULL) |
1350 | + m->icon = g_object_ref (m->autorun_icon); |
1351 | + else if (m->override_icon != NULL) |
1352 | + m->icon = g_object_ref (m->override_icon); |
1353 | + else |
1354 | + m->icon = get_themed_icon_with_fallbacks (icon_name, |
1355 | + icon_name_fallback); |
1356 | + |
1357 | + /* search for .xdg-volume-info */ |
1358 | + if (!m->searched_for_xdg_volume_info) |
1359 | + { |
1360 | + GFile *root; |
1361 | + root = get_root (m); |
1362 | + m->searched_for_xdg_volume_info = TRUE; |
1363 | + g_vfs_mount_info_query_xdg_volume_info (root, |
1364 | + NULL, |
1365 | + got_xdg_volume_info_cb, |
1366 | + g_object_ref (m)); |
1367 | + g_object_unref (root); |
1368 | + } |
1369 | + |
1370 | + /* search for autorun.inf */ |
1371 | + if (!m->searched_for_autorun) |
1372 | + { |
1373 | + GFile *root; |
1374 | + root = get_root (m); |
1375 | + m->searched_for_autorun = TRUE; |
1376 | + g_vfs_mount_info_query_autorun_info (root, |
1377 | + NULL, |
1378 | + got_autorun_info_cb, |
1379 | + g_object_ref (m)); |
1380 | + g_object_unref (root); |
1381 | + } |
1382 | +} |
1383 | + |
1384 | + |
1385 | +static void |
1386 | +update_from_hal (GHalMount *m, gboolean emit_changed) |
1387 | +{ |
1388 | + char *old_name; |
1389 | + GIcon *old_icon; |
1390 | + |
1391 | + old_name = g_strdup (m->name); |
1392 | + old_icon = m->icon != NULL ? g_object_ref (m->icon) : NULL; |
1393 | + |
1394 | + g_free (m->name); |
1395 | + if (m->icon != NULL) |
1396 | + g_object_unref (m->icon); |
1397 | + do_update_from_hal (m); |
1398 | + |
1399 | + if (emit_changed) |
1400 | + { |
1401 | + if (old_name == NULL || |
1402 | + old_icon == NULL || |
1403 | + strcmp (old_name, m->name) != 0 || |
1404 | + (! g_icon_equal (old_icon, m->icon))) |
1405 | + emit_mount_changed (m); |
1406 | + } |
1407 | + g_free (old_name); |
1408 | + if (old_icon != NULL) |
1409 | + g_object_unref (old_icon); |
1410 | +} |
1411 | + |
1412 | +static void |
1413 | +hal_changed (HalDevice *device, const char *key, gpointer user_data) |
1414 | +{ |
1415 | + GHalMount *hal_mount = G_HAL_MOUNT (user_data); |
1416 | + |
1417 | + /*g_warning ("mounthal modifying %s (property %s changed)", hal_mount->device_path, key); */ |
1418 | + update_from_hal (hal_mount, TRUE); |
1419 | +} |
1420 | + |
1421 | +static void |
1422 | +compute_uuid (GHalMount *mount) |
1423 | +{ |
1424 | + const char *fs_uuid; |
1425 | + const char *fs_label; |
1426 | + |
1427 | + /* use the FS uuid before falling back to the FS label */ |
1428 | + |
1429 | + fs_uuid = hal_device_get_property_string (mount->device, "volume.uuid"); |
1430 | + fs_label = hal_device_get_property_string (mount->device, "volume.label"); |
1431 | + |
1432 | + if (strlen (fs_uuid) == 0) |
1433 | + { |
1434 | + if (strlen (fs_label) == 0) |
1435 | + mount->uuid = NULL; |
1436 | + else |
1437 | + mount->uuid = g_strdup (fs_label); |
1438 | + } |
1439 | + else |
1440 | + mount->uuid = g_strdup (fs_uuid); |
1441 | +} |
1442 | + |
1443 | + |
1444 | +GHalMount * |
1445 | +g_hal_mount_new_for_hal_device (GVolumeMonitor *volume_monitor, |
1446 | + HalDevice *device, |
1447 | + GFile *override_root, |
1448 | + const char *override_name, |
1449 | + GIcon *override_icon, |
1450 | + gboolean cannot_unmount, |
1451 | + HalPool *pool, |
1452 | + GHalVolume *volume) |
1453 | +{ |
1454 | + HalDevice *drive_device; |
1455 | + const char *storage_udi; |
1456 | + GHalMount *mount; |
1457 | + |
1458 | + storage_udi = hal_device_get_property_string (device, "block.storage_device"); |
1459 | + if (storage_udi == NULL) |
1460 | + goto fail; |
1461 | + |
1462 | + /* g_warning ("storage_udi = %s", storage_udi); */ |
1463 | + |
1464 | + drive_device = hal_pool_get_device_by_udi (pool, storage_udi); |
1465 | + if (drive_device == NULL) |
1466 | + goto fail; |
1467 | + |
1468 | + /* g_warning ("drive_device = %p", drive_device); */ |
1469 | + |
1470 | + mount = g_object_new (G_TYPE_HAL_MOUNT, NULL); |
1471 | + mount->volume_monitor = volume_monitor; |
1472 | + g_object_add_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor)); |
1473 | + mount->device_path = g_strdup (hal_device_get_property_string (device, "block.device")); |
1474 | + mount->mount_path = g_strdup ("/"); |
1475 | + mount->device = g_object_ref (device); |
1476 | + mount->drive_device = g_object_ref (drive_device); |
1477 | + mount->override_root = override_root != NULL ? g_object_ref (override_root) : NULL; |
1478 | + mount->override_icon = override_icon != NULL ? g_object_ref (override_icon) : NULL; |
1479 | + mount->override_name = g_strdup (override_name); |
1480 | + mount->cannot_unmount = cannot_unmount; |
1481 | + |
1482 | + g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, mount, 0); |
1483 | + g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, mount, 0); |
1484 | + |
1485 | + compute_uuid (mount); |
1486 | + update_from_hal (mount, FALSE); |
1487 | + |
1488 | + /* need to do this last */ |
1489 | + mount->volume = volume; |
1490 | + if (volume != NULL) |
1491 | + g_hal_volume_set_mount (volume, mount); |
1492 | + |
1493 | + return mount; |
1494 | + |
1495 | + fail: |
1496 | + return NULL; |
1497 | +} |
1498 | + |
1499 | +void |
1500 | +g_hal_mount_override_name (GHalMount *mount, const char *name) |
1501 | +{ |
1502 | + g_free (mount->override_name); |
1503 | + |
1504 | + if (name != NULL) |
1505 | + mount->override_name = g_strdup (name); |
1506 | + else |
1507 | + mount->override_name = NULL; |
1508 | + |
1509 | + update_from_hal (mount, TRUE); |
1510 | +} |
1511 | + |
1512 | +void |
1513 | +g_hal_mount_override_icon (GHalMount *mount, GIcon *icon) |
1514 | +{ |
1515 | + if (mount->override_icon != NULL) |
1516 | + g_object_unref (mount->override_icon); |
1517 | + |
1518 | + if (icon != NULL) |
1519 | + mount->override_icon = g_object_ref (icon); |
1520 | + else |
1521 | + mount->override_icon = NULL; |
1522 | + |
1523 | + update_from_hal (mount, TRUE); |
1524 | +} |
1525 | + |
1526 | +GHalMount * |
1527 | +g_hal_mount_new (GVolumeMonitor *volume_monitor, |
1528 | + GUnixMountEntry *mount_entry, |
1529 | + HalPool *pool, |
1530 | + GHalVolume *volume) |
1531 | +{ |
1532 | + HalDevice *device; |
1533 | + HalDevice *drive_device; |
1534 | + const char *storage_udi; |
1535 | + GHalMount *mount; |
1536 | + |
1537 | + /* If no volume for mount - Ignore internal things */ |
1538 | + if (volume == NULL && !g_unix_mount_guess_should_display (mount_entry)) |
1539 | + return NULL; |
1540 | + |
1541 | + mount = g_object_new (G_TYPE_HAL_MOUNT, NULL); |
1542 | + mount->volume_monitor = volume_monitor; |
1543 | + g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(mount->volume_monitor)); |
1544 | + mount->device_path = g_strdup (g_unix_mount_get_device_path (mount_entry)); |
1545 | + mount->mount_path = g_strdup (g_unix_mount_get_mount_path (mount_entry)); |
1546 | + mount->device = NULL; |
1547 | + mount->drive_device = NULL; |
1548 | + mount->uuid = NULL; |
1549 | + |
1550 | + if (pool != NULL) |
1551 | + { |
1552 | + device = hal_pool_get_device_by_capability_and_string (pool, |
1553 | + "volume", |
1554 | + "block.device", |
1555 | + mount->device_path); |
1556 | + /* g_warning ("device = %p for %s", device, mount->device_path); */ |
1557 | + if (device != NULL) |
1558 | + { |
1559 | + /* g_warning ("udi = %s", hal_device_get_udi (device)); */ |
1560 | + |
1561 | + storage_udi = hal_device_get_property_string (device, "block.storage_device"); |
1562 | + if (storage_udi == NULL) |
1563 | + goto not_hal; |
1564 | + |
1565 | + /* g_warning ("storage_udi = %s", storage_udi); */ |
1566 | + |
1567 | + drive_device = hal_pool_get_device_by_udi (pool, storage_udi); |
1568 | + if (drive_device == NULL) |
1569 | + goto not_hal; |
1570 | + |
1571 | + /* g_warning ("drive_device = %p", drive_device); */ |
1572 | + |
1573 | + mount->device = g_object_ref (device); |
1574 | + mount->drive_device = g_object_ref (drive_device); |
1575 | + |
1576 | + g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, mount, 0); |
1577 | + g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, mount, 0); |
1578 | + |
1579 | + compute_uuid (mount); |
1580 | + update_from_hal (mount, FALSE); |
1581 | + |
1582 | + goto was_hal; |
1583 | + } |
1584 | + } |
1585 | + |
1586 | + not_hal: |
1587 | + |
1588 | + if (volume != NULL) |
1589 | + { |
1590 | + g_object_unref (mount); |
1591 | + return NULL; |
1592 | + } |
1593 | + |
1594 | + mount->name = g_unix_mount_guess_name (mount_entry); |
1595 | + mount->icon = g_unix_mount_guess_icon (mount_entry); |
1596 | + |
1597 | + was_hal: |
1598 | + |
1599 | + /* need to do this last */ |
1600 | + mount->volume = volume; |
1601 | + if (volume != NULL) |
1602 | + g_hal_volume_set_mount (volume, mount); |
1603 | + |
1604 | + return mount; |
1605 | +} |
1606 | + |
1607 | +void |
1608 | +g_hal_mount_unmounted (GHalMount *mount) |
1609 | +{ |
1610 | + if (mount->volume != NULL) |
1611 | + { |
1612 | + g_hal_volume_unset_mount (mount->volume, mount); |
1613 | + mount->volume = NULL; |
1614 | + emit_mount_changed (mount); |
1615 | + } |
1616 | +} |
1617 | + |
1618 | +void |
1619 | +g_hal_mount_unset_volume (GHalMount *mount, |
1620 | + GHalVolume *volume) |
1621 | +{ |
1622 | + if (mount->volume == volume) |
1623 | + { |
1624 | + mount->volume = NULL; |
1625 | + emit_mount_changed (mount); |
1626 | + } |
1627 | +} |
1628 | + |
1629 | +static GFile * |
1630 | +get_root (GHalMount *hal_mount) |
1631 | +{ |
1632 | + if (hal_mount->override_root != NULL) |
1633 | + return g_object_ref (hal_mount->override_root); |
1634 | + else |
1635 | + return g_file_new_for_path (hal_mount->mount_path); |
1636 | +} |
1637 | + |
1638 | +static GFile * |
1639 | +g_hal_mount_get_root (GMount *mount) |
1640 | +{ |
1641 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1642 | + |
1643 | + return get_root (hal_mount); |
1644 | +} |
1645 | + |
1646 | +static GIcon * |
1647 | +g_hal_mount_get_icon (GMount *mount) |
1648 | +{ |
1649 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1650 | + |
1651 | + return g_object_ref (hal_mount->icon); |
1652 | +} |
1653 | + |
1654 | +static char * |
1655 | +g_hal_mount_get_uuid (GMount *mount) |
1656 | +{ |
1657 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1658 | + |
1659 | + return g_strdup (hal_mount->uuid); |
1660 | +} |
1661 | + |
1662 | +static char * |
1663 | +g_hal_mount_get_name (GMount *mount) |
1664 | +{ |
1665 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1666 | + |
1667 | + return g_strdup (hal_mount->name); |
1668 | +} |
1669 | + |
1670 | +gboolean |
1671 | +g_hal_mount_has_uuid (GHalMount *mount, |
1672 | + const char *uuid) |
1673 | +{ |
1674 | + gboolean res; |
1675 | + |
1676 | + res = FALSE; |
1677 | + if (mount->uuid != NULL) |
1678 | + res = strcmp (mount->uuid, uuid) == 0; |
1679 | + |
1680 | + return res; |
1681 | +} |
1682 | + |
1683 | +gboolean |
1684 | +g_hal_mount_has_mount_path (GHalMount *mount, |
1685 | + const char *mount_path) |
1686 | +{ |
1687 | + return strcmp (mount->mount_path, mount_path) == 0; |
1688 | +} |
1689 | + |
1690 | +gboolean |
1691 | +g_hal_mount_has_udi (GHalMount *mount, |
1692 | + const char *udi) |
1693 | +{ |
1694 | + gboolean res; |
1695 | + |
1696 | + res = FALSE; |
1697 | + if (mount->device != NULL) |
1698 | + res = strcmp (hal_device_get_udi (mount->device), udi) == 0; |
1699 | + |
1700 | + return res; |
1701 | +} |
1702 | + |
1703 | +static GDrive * |
1704 | +g_hal_mount_get_drive (GMount *mount) |
1705 | +{ |
1706 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1707 | + GDrive *drive; |
1708 | + |
1709 | + drive = NULL; |
1710 | + if (hal_mount->volume != NULL) |
1711 | + drive = g_volume_get_drive (G_VOLUME (hal_mount->volume)); |
1712 | + |
1713 | + return drive; |
1714 | +} |
1715 | + |
1716 | +static GVolume * |
1717 | +g_hal_mount_get_volume (GMount *mount) |
1718 | +{ |
1719 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1720 | + GVolume *volume; |
1721 | + |
1722 | + volume = NULL; |
1723 | + if (hal_mount->volume) |
1724 | + volume = G_VOLUME (g_object_ref (hal_mount->volume)); |
1725 | + |
1726 | + return volume; |
1727 | +} |
1728 | + |
1729 | +static gboolean |
1730 | +g_hal_mount_can_unmount (GMount *mount) |
1731 | +{ |
1732 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1733 | + gboolean res; |
1734 | + |
1735 | + res = TRUE; |
1736 | + if (hal_mount->cannot_unmount) |
1737 | + res = FALSE; |
1738 | + |
1739 | + return res; |
1740 | +} |
1741 | + |
1742 | +static gboolean |
1743 | +g_hal_mount_can_eject (GMount *mount) |
1744 | +{ |
1745 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1746 | + GDrive *drive; |
1747 | + gboolean can_eject; |
1748 | + |
1749 | + can_eject = FALSE; |
1750 | + if (hal_mount->volume != NULL) |
1751 | + { |
1752 | + drive = g_volume_get_drive (G_VOLUME (hal_mount->volume)); |
1753 | + if (drive != NULL) |
1754 | + can_eject = g_drive_can_eject (drive); |
1755 | + } |
1756 | + |
1757 | + return can_eject; |
1758 | +} |
1759 | + |
1760 | +typedef struct { |
1761 | + GObject *object; |
1762 | + GAsyncReadyCallback callback; |
1763 | + gpointer user_data; |
1764 | + GCancellable *cancellable; |
1765 | + int error_fd; |
1766 | + GIOChannel *error_channel; |
1767 | + guint error_channel_source_id; |
1768 | + GString *error_string; |
1769 | + gboolean using_legacy; |
1770 | + gchar **argv; |
1771 | +} UnmountOp; |
1772 | + |
1773 | +static void |
1774 | +unmount_cb (GPid pid, gint status, gpointer user_data) |
1775 | +{ |
1776 | + UnmountOp *data = user_data; |
1777 | + GSimpleAsyncResult *simple; |
1778 | + |
1779 | + if (WEXITSTATUS (status) != 0) |
1780 | + { |
1781 | + if (data->using_legacy) |
1782 | + { |
1783 | + GError *error; |
1784 | + error = g_error_new_literal (G_IO_ERROR, |
1785 | + G_IO_ERROR_FAILED, |
1786 | + data->error_string->str); |
1787 | + simple = g_simple_async_result_new_from_error (data->object, |
1788 | + data->callback, |
1789 | + data->user_data, |
1790 | + error); |
1791 | + g_error_free (error); |
1792 | + } |
1793 | + else |
1794 | + { |
1795 | + GError *error; |
1796 | + error = g_error_new_literal (G_IO_ERROR, |
1797 | + G_IO_ERROR_FAILED_HANDLED, |
1798 | + "You are not supposed to show G_IO_ERROR_FAILED_HANDLED in the UI"); |
1799 | + simple = g_simple_async_result_new_from_error (data->object, |
1800 | + data->callback, |
1801 | + data->user_data, |
1802 | + error); |
1803 | + g_error_free (error); |
1804 | + } |
1805 | + } |
1806 | + else |
1807 | + { |
1808 | + simple = g_simple_async_result_new (data->object, |
1809 | + data->callback, |
1810 | + data->user_data, |
1811 | + NULL); |
1812 | + } |
1813 | + |
1814 | + g_simple_async_result_complete (simple); |
1815 | + g_object_unref (simple); |
1816 | + |
1817 | + g_source_remove (data->error_channel_source_id); |
1818 | + g_io_channel_unref (data->error_channel); |
1819 | + g_string_free (data->error_string, TRUE); |
1820 | + g_strfreev (data->argv); |
1821 | + close (data->error_fd); |
1822 | + g_spawn_close_pid (pid); |
1823 | + |
1824 | + g_object_unref (data->object); |
1825 | + g_free (data); |
1826 | +} |
1827 | + |
1828 | +static gboolean |
1829 | +unmount_read_error (GIOChannel *channel, |
1830 | + GIOCondition condition, |
1831 | + gpointer user_data) |
1832 | +{ |
1833 | + char *str; |
1834 | + gsize str_len; |
1835 | + UnmountOp *data = user_data; |
1836 | + |
1837 | + g_io_channel_read_to_end (channel, &str, &str_len, NULL); |
1838 | + g_string_append (data->error_string, str); |
1839 | + g_free (str); |
1840 | + return TRUE; |
1841 | +} |
1842 | + |
1843 | +static gboolean |
1844 | +unmount_do_cb (gpointer user_data) |
1845 | +{ |
1846 | + UnmountOp *data = (UnmountOp *) user_data; |
1847 | + GPid child_pid; |
1848 | + GError *error; |
1849 | + |
1850 | + error = NULL; |
1851 | + if (!g_spawn_async_with_pipes (NULL, /* working dir */ |
1852 | + data->argv, |
1853 | + NULL, /* envp */ |
1854 | + G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH, |
1855 | + NULL, /* child_setup */ |
1856 | + NULL, /* user_data for child_setup */ |
1857 | + &child_pid, |
1858 | + NULL, /* standard_input */ |
1859 | + NULL, /* standard_output */ |
1860 | + &(data->error_fd), |
1861 | + &error)) |
1862 | + { |
1863 | + GSimpleAsyncResult *simple; |
1864 | + simple = g_simple_async_result_new_from_error (data->object, |
1865 | + data->callback, |
1866 | + data->user_data, |
1867 | + error); |
1868 | + g_simple_async_result_complete (simple); |
1869 | + g_object_unref (simple); |
1870 | + g_error_free (error); |
1871 | + g_strfreev (data->argv); |
1872 | + g_free (data); |
1873 | + |
1874 | + return FALSE; |
1875 | + } |
1876 | + data->error_string = g_string_new (""); |
1877 | + data->error_channel = g_io_channel_unix_new (data->error_fd); |
1878 | + data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, unmount_read_error, data); |
1879 | + g_child_watch_add (child_pid, unmount_cb, data); |
1880 | + |
1881 | + return FALSE; |
1882 | +} |
1883 | + |
1884 | +static void |
1885 | +unmount_do (GMount *mount, |
1886 | + GCancellable *cancellable, |
1887 | + GAsyncReadyCallback callback, |
1888 | + gpointer user_data, |
1889 | + char **argv, |
1890 | + gboolean using_legacy) |
1891 | +{ |
1892 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1893 | + UnmountOp *data; |
1894 | + |
1895 | + data = g_new0 (UnmountOp, 1); |
1896 | + data->object = g_object_ref (mount); |
1897 | + data->callback = callback; |
1898 | + data->user_data = user_data; |
1899 | + data->cancellable = cancellable; |
1900 | + data->using_legacy = using_legacy; |
1901 | + data->argv = g_strdupv (argv); |
1902 | + |
1903 | + if (hal_mount->volume_monitor != NULL) |
1904 | + g_signal_emit_by_name (hal_mount->volume_monitor, "mount-pre-unmount", mount); |
1905 | + |
1906 | + g_timeout_add (500, unmount_do_cb, data); |
1907 | +} |
1908 | + |
1909 | +static void |
1910 | +g_hal_mount_unmount_with_operation (GMount *mount, |
1911 | + GMountUnmountFlags flags, |
1912 | + GMountOperation *mount_operation, |
1913 | + GCancellable *cancellable, |
1914 | + GAsyncReadyCallback callback, |
1915 | + gpointer user_data) |
1916 | +{ |
1917 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1918 | + char *argv[] = {"gnome-mount", "-u", "-b", "-d", NULL, NULL}; |
1919 | + gboolean using_legacy = FALSE; |
1920 | + char *d, *m; |
1921 | + |
1922 | + d = g_strdup (hal_mount->device_path); |
1923 | + m = g_strdup (hal_mount->mount_path); |
1924 | + |
1925 | + if (hal_mount->device != NULL) |
1926 | + argv[4] = d; |
1927 | + else |
1928 | + { |
1929 | + using_legacy = TRUE; |
1930 | + argv[0] = "umount"; |
1931 | + argv[1] = m; |
1932 | + argv[2] = NULL; |
1933 | + } |
1934 | + |
1935 | + unmount_do (mount, cancellable, callback, user_data, argv, using_legacy); |
1936 | + g_free (d); |
1937 | + g_free (m); |
1938 | +} |
1939 | + |
1940 | +static gboolean |
1941 | +g_hal_mount_unmount_with_operation_finish (GMount *mount, |
1942 | + GAsyncResult *result, |
1943 | + GError **error) |
1944 | +{ |
1945 | + return TRUE; |
1946 | +} |
1947 | + |
1948 | +static void |
1949 | +g_hal_mount_unmount (GMount *mount, |
1950 | + GMountUnmountFlags flags, |
1951 | + GCancellable *cancellable, |
1952 | + GAsyncReadyCallback callback, |
1953 | + gpointer user_data) |
1954 | +{ |
1955 | + return g_hal_mount_unmount_with_operation (mount, flags, NULL, cancellable, callback, user_data); |
1956 | +} |
1957 | + |
1958 | +static gboolean |
1959 | +g_hal_mount_unmount_finish (GMount *mount, |
1960 | + GAsyncResult *result, |
1961 | + GError **error) |
1962 | +{ |
1963 | + return g_hal_mount_unmount_with_operation_finish (mount, result, error); |
1964 | +} |
1965 | + |
1966 | +typedef struct { |
1967 | + GObject *object; |
1968 | + GAsyncReadyCallback callback; |
1969 | + gpointer user_data; |
1970 | +} EjectWrapperOp; |
1971 | + |
1972 | +static void |
1973 | +eject_wrapper_callback (GObject *source_object, |
1974 | + GAsyncResult *res, |
1975 | + gpointer user_data) |
1976 | +{ |
1977 | + EjectWrapperOp *data = user_data; |
1978 | + data->callback (data->object, res, data->user_data); |
1979 | + g_object_unref (data->object); |
1980 | + g_free (data); |
1981 | +} |
1982 | + |
1983 | +static void |
1984 | +g_hal_mount_eject_with_operation (GMount *mount, |
1985 | + GMountUnmountFlags flags, |
1986 | + GMountOperation *mount_operation, |
1987 | + GCancellable *cancellable, |
1988 | + GAsyncReadyCallback callback, |
1989 | + gpointer user_data) |
1990 | +{ |
1991 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
1992 | + GDrive *drive; |
1993 | + |
1994 | + drive = NULL; |
1995 | + if (hal_mount->volume != NULL) |
1996 | + drive = g_volume_get_drive (G_VOLUME (hal_mount->volume)); |
1997 | + |
1998 | + if (drive != NULL) |
1999 | + { |
2000 | + EjectWrapperOp *data; |
2001 | + data = g_new0 (EjectWrapperOp, 1); |
2002 | + data->object = g_object_ref (mount); |
2003 | + data->callback = callback; |
2004 | + data->user_data = user_data; |
2005 | + g_drive_eject_with_operation (drive, flags, mount_operation, cancellable, eject_wrapper_callback, data); |
2006 | + g_object_unref (drive); |
2007 | + } |
2008 | +} |
2009 | + |
2010 | +static gboolean |
2011 | +g_hal_mount_eject_with_operation_finish (GMount *mount, |
2012 | + GAsyncResult *result, |
2013 | + GError **error) |
2014 | +{ |
2015 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
2016 | + GDrive *drive; |
2017 | + gboolean res; |
2018 | + |
2019 | + res = TRUE; |
2020 | + |
2021 | + drive = NULL; |
2022 | + if (hal_mount->volume != NULL) |
2023 | + drive = g_volume_get_drive (G_VOLUME (hal_mount->volume)); |
2024 | + |
2025 | + if (drive != NULL) |
2026 | + { |
2027 | + res = g_drive_eject_with_operation_finish (drive, result, error); |
2028 | + g_object_unref (drive); |
2029 | + } |
2030 | + return res; |
2031 | +} |
2032 | + |
2033 | +static void |
2034 | +g_hal_mount_eject (GMount *mount, |
2035 | + GMountUnmountFlags flags, |
2036 | + GCancellable *cancellable, |
2037 | + GAsyncReadyCallback callback, |
2038 | + gpointer user_data) |
2039 | +{ |
2040 | + return g_hal_mount_eject_with_operation (mount, flags, NULL, cancellable, callback, user_data); |
2041 | +} |
2042 | + |
2043 | +static gboolean |
2044 | +g_hal_mount_eject_finish (GMount *mount, |
2045 | + GAsyncResult *result, |
2046 | + GError **error) |
2047 | +{ |
2048 | + return g_hal_mount_eject_with_operation_finish (mount, result, error); |
2049 | +} |
2050 | + |
2051 | +/* TODO: handle force_rescan */ |
2052 | +static char ** |
2053 | +g_hal_mount_guess_content_type_sync (GMount *mount, |
2054 | + gboolean force_rescan, |
2055 | + GCancellable *cancellable, |
2056 | + GError **error) |
2057 | +{ |
2058 | + GHalMount *hal_mount = G_HAL_MOUNT (mount); |
2059 | + const char *disc_type; |
2060 | + char **x_content_types; |
2061 | + GFile *root; |
2062 | + GPtrArray *p; |
2063 | + char **result; |
2064 | + int n; |
2065 | + char **caps; |
2066 | + char *uri; |
2067 | + |
2068 | + p = g_ptr_array_new (); |
2069 | + |
2070 | + root = get_root (hal_mount); |
2071 | + uri = g_file_get_uri (root); |
2072 | + if (g_str_has_prefix (uri, "burn://")) |
2073 | + { |
2074 | + /* doesn't make sense to probe burn:/// - look at the disc type instead */ |
2075 | + if (hal_mount->device != NULL) |
2076 | + { |
2077 | + disc_type = hal_device_get_property_string (hal_mount->device, "volume.disc.type"); |
2078 | + if (disc_type != NULL) |
2079 | + { |
2080 | + if (g_str_has_prefix (disc_type, "dvd")) |
2081 | + g_ptr_array_add (p, g_strdup ("x-content/blank-dvd")); |
2082 | + else if (g_str_has_prefix (disc_type, "hddvd")) |
2083 | + g_ptr_array_add (p, g_strdup ("x-content/blank-hddvd")); |
2084 | + else if (g_str_has_prefix (disc_type, "bd")) |
2085 | + g_ptr_array_add (p, g_strdup ("x-content/blank-bd")); |
2086 | + else |
2087 | + g_ptr_array_add (p, g_strdup ("x-content/blank-cd")); /* assume CD */ |
2088 | + } |
2089 | + } |
2090 | + } |
2091 | + else |
2092 | + { |
2093 | + /* sniff content type */ |
2094 | + x_content_types = g_content_type_guess_for_tree (root); |
2095 | + if (x_content_types != NULL) |
2096 | + { |
2097 | + for (n = 0; x_content_types[n] != NULL; n++) |
2098 | + g_ptr_array_add (p, g_strdup (x_content_types[n])); |
2099 | + g_strfreev (x_content_types); |
2100 | + } |
2101 | + } |
2102 | + g_object_unref (root); |
2103 | + g_free (uri); |
2104 | + |
2105 | + /* also add content types from hal capabilities */ |
2106 | + if (hal_mount->drive_device != NULL) |
2107 | + { |
2108 | + caps = dupv_and_uniqify (hal_device_get_property_strlist (hal_mount->drive_device, "info.capabilities")); |
2109 | + if (caps != NULL) |
2110 | + { |
2111 | + for (n = 0; caps[n] != NULL; n++) |
2112 | + { |
2113 | + if (strcmp (caps[n], "portable_audio_player") == 0) |
2114 | + g_ptr_array_add (p, g_strdup ("x-content/audio-player")); |
2115 | + } |
2116 | + g_strfreev (caps); |
2117 | + } |
2118 | + } |
2119 | + |
2120 | + if (p->len == 0) |
2121 | + { |
2122 | + result = NULL; |
2123 | + g_ptr_array_free (p, TRUE); |
2124 | + } |
2125 | + else |
2126 | + { |
2127 | + g_ptr_array_add (p, NULL); |
2128 | + result = (char **) g_ptr_array_free (p, FALSE); |
2129 | + } |
2130 | + |
2131 | + return result; |
2132 | +} |
2133 | + |
2134 | +/* since we're an out-of-process volume monitor we'll just do this sync */ |
2135 | +static void |
2136 | +g_hal_mount_guess_content_type (GMount *mount, |
2137 | + gboolean force_rescan, |
2138 | + GCancellable *cancellable, |
2139 | + GAsyncReadyCallback callback, |
2140 | + gpointer user_data) |
2141 | +{ |
2142 | + GSimpleAsyncResult *simple; |
2143 | + |
2144 | + /* TODO: handle force_rescan */ |
2145 | + simple = g_simple_async_result_new (G_OBJECT (mount), |
2146 | + callback, |
2147 | + user_data, |
2148 | + NULL); |
2149 | + g_simple_async_result_complete (simple); |
2150 | + g_object_unref (simple); |
2151 | +} |
2152 | + |
2153 | +static char ** |
2154 | +g_hal_mount_guess_content_type_finish (GMount *mount, |
2155 | + GAsyncResult *result, |
2156 | + GError **error) |
2157 | +{ |
2158 | + /* TODO: handle force_rescan */ |
2159 | + return g_hal_mount_guess_content_type_sync (mount, FALSE, NULL, error); |
2160 | +} |
2161 | + |
2162 | +static void |
2163 | +g_hal_mount_mount_iface_init (GMountIface *iface) |
2164 | +{ |
2165 | + iface->get_root = g_hal_mount_get_root; |
2166 | + iface->get_name = g_hal_mount_get_name; |
2167 | + iface->get_icon = g_hal_mount_get_icon; |
2168 | + iface->get_uuid = g_hal_mount_get_uuid; |
2169 | + iface->get_drive = g_hal_mount_get_drive; |
2170 | + iface->get_volume = g_hal_mount_get_volume; |
2171 | + iface->can_unmount = g_hal_mount_can_unmount; |
2172 | + iface->can_eject = g_hal_mount_can_eject; |
2173 | + iface->unmount = g_hal_mount_unmount; |
2174 | + iface->unmount_finish = g_hal_mount_unmount_finish; |
2175 | + iface->unmount_with_operation = g_hal_mount_unmount_with_operation; |
2176 | + iface->unmount_with_operation_finish = g_hal_mount_unmount_with_operation_finish; |
2177 | + iface->eject = g_hal_mount_eject; |
2178 | + iface->eject_finish = g_hal_mount_eject_finish; |
2179 | + iface->eject_with_operation = g_hal_mount_eject_with_operation; |
2180 | + iface->eject_with_operation_finish = g_hal_mount_eject_with_operation_finish; |
2181 | + iface->guess_content_type = g_hal_mount_guess_content_type; |
2182 | + iface->guess_content_type_finish = g_hal_mount_guess_content_type_finish; |
2183 | + iface->guess_content_type_sync = g_hal_mount_guess_content_type_sync; |
2184 | +} |
2185 | |
2186 | === added file '.pc/03_xdg-mount.patch/monitor/hal/ghalvolume.c' |
2187 | --- .pc/03_xdg-mount.patch/monitor/hal/ghalvolume.c 1970-01-01 00:00:00 +0000 |
2188 | +++ .pc/03_xdg-mount.patch/monitor/hal/ghalvolume.c 2011-09-27 06:17:30 +0000 |
2189 | @@ -0,0 +1,1007 @@ |
2190 | +/* GIO - GLib Input, Output and Streaming Library |
2191 | + * |
2192 | + * Copyright (C) 2006-2007 Red Hat, Inc. |
2193 | + * |
2194 | + * This library is free software; you can redistribute it and/or |
2195 | + * modify it under the terms of the GNU Lesser General Public |
2196 | + * License as published by the Free Software Foundation; either |
2197 | + * version 2 of the License, or (at your option) any later version. |
2198 | + * |
2199 | + * This library is distributed in the hope that it will be useful, |
2200 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2201 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2202 | + * Lesser General Public License for more details. |
2203 | + * |
2204 | + * You should have received a copy of the GNU Lesser General |
2205 | + * Public License along with this library; if not, write to the |
2206 | + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
2207 | + * Boston, MA 02111-1307, USA. |
2208 | + * |
2209 | + * Author: David Zeuthen <davidz@redhat.com> |
2210 | + */ |
2211 | + |
2212 | +#include <config.h> |
2213 | + |
2214 | +#include <string.h> |
2215 | +#include <sys/wait.h> |
2216 | +#include <unistd.h> |
2217 | + |
2218 | +#include <glib.h> |
2219 | +#include <glib/gi18n-lib.h> |
2220 | +#include <gio/gio.h> |
2221 | + |
2222 | +#include "ghaldrive.h" |
2223 | +#include "ghalvolume.h" |
2224 | +#include "ghalmount.h" |
2225 | + |
2226 | +#include "hal-utils.h" |
2227 | + |
2228 | +struct _GHalVolume { |
2229 | + GObject parent; |
2230 | + |
2231 | + GVolumeMonitor *volume_monitor; /* owned by volume monitor */ |
2232 | + GHalMount *mount; /* owned by volume monitor */ |
2233 | + GHalDrive *drive; /* owned by volume monitor */ |
2234 | + |
2235 | + char *device_path; |
2236 | + char *mount_path; |
2237 | + char *uuid; |
2238 | + HalDevice *device; |
2239 | + HalDevice *drive_device; |
2240 | + |
2241 | + /* set on creation if we won't create a GHalMount object ourselves |
2242 | + * and instead except to adopt one, with the given mount root, |
2243 | + * via adopt_orphan_mount() |
2244 | + */ |
2245 | + GFile *foreign_mount_root; |
2246 | + GMount *foreign_mount; |
2247 | + gboolean is_mountable; |
2248 | + gboolean ignore_automount; |
2249 | + |
2250 | + char *name; |
2251 | + char *icon; |
2252 | + char *icon_fallback; |
2253 | +}; |
2254 | + |
2255 | +static void g_hal_volume_volume_iface_init (GVolumeIface *iface); |
2256 | + |
2257 | +G_DEFINE_TYPE_EXTENDED (GHalVolume, g_hal_volume, G_TYPE_OBJECT, 0, |
2258 | + G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, |
2259 | + g_hal_volume_volume_iface_init)) |
2260 | + |
2261 | +static void |
2262 | +g_hal_volume_finalize (GObject *object) |
2263 | +{ |
2264 | + GHalVolume *volume; |
2265 | + |
2266 | + volume = G_HAL_VOLUME (object); |
2267 | + |
2268 | + if (volume->mount != NULL) |
2269 | + g_hal_mount_unset_volume (volume->mount, volume); |
2270 | + |
2271 | + if (volume->drive != NULL) |
2272 | + g_hal_drive_unset_volume (volume->drive, volume); |
2273 | + |
2274 | + g_free (volume->mount_path); |
2275 | + g_free (volume->device_path); |
2276 | + g_free (volume->uuid); |
2277 | + if (volume->device != NULL) |
2278 | + g_object_unref (volume->device); |
2279 | + if (volume->drive_device != NULL) |
2280 | + g_object_unref (volume->drive_device); |
2281 | + |
2282 | + if (volume->foreign_mount_root != NULL) |
2283 | + g_object_unref (volume->foreign_mount_root); |
2284 | + |
2285 | + if (volume->foreign_mount != NULL) |
2286 | + g_object_unref (volume->foreign_mount); |
2287 | + |
2288 | + if (volume->volume_monitor != NULL) |
2289 | + g_object_remove_weak_pointer (G_OBJECT (volume->volume_monitor), (gpointer) &(volume->volume_monitor)); |
2290 | + |
2291 | + g_free (volume->name); |
2292 | + g_free (volume->icon); |
2293 | + g_free (volume->icon_fallback); |
2294 | + |
2295 | + if (G_OBJECT_CLASS (g_hal_volume_parent_class)->finalize) |
2296 | + (*G_OBJECT_CLASS (g_hal_volume_parent_class)->finalize) (object); |
2297 | +} |
2298 | + |
2299 | +static void |
2300 | +g_hal_volume_class_init (GHalVolumeClass *klass) |
2301 | +{ |
2302 | + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
2303 | + |
2304 | + gobject_class->finalize = g_hal_volume_finalize; |
2305 | +} |
2306 | + |
2307 | +static void |
2308 | +g_hal_volume_init (GHalVolume *hal_volume) |
2309 | +{ |
2310 | +} |
2311 | + |
2312 | +static void |
2313 | +emit_volume_changed (GHalVolume *volume) |
2314 | +{ |
2315 | + g_signal_emit_by_name (volume, "changed"); |
2316 | + if (volume->volume_monitor != NULL) |
2317 | + g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume); |
2318 | +} |
2319 | + |
2320 | +#define KILOBYTE_FACTOR 1000.0 |
2321 | +#define MEGABYTE_FACTOR (1000.0 * 1000.0) |
2322 | +#define GIGABYTE_FACTOR (1000.0 * 1000.0 * 1000.0) |
2323 | + |
2324 | +/** |
2325 | + * format_size_for_display: |
2326 | + * @size: a number of octects |
2327 | + * |
2328 | + * Format a human readable string that can conveys how much storage a |
2329 | + * user-visible drive or piece of media can hold. |
2330 | + * |
2331 | + * As a matter of policy, we want this string to resemble what's on |
2332 | + * the packaging of the drive/media. Since all manufacturers use |
2333 | + * powers of 10, g_format_size_for_display() is not suitable here. |
2334 | + * |
2335 | + * TODO: we probably want to round to nearest power of two if @size is |
2336 | + * "close" (e.g. within 5%) - this is to avoid e.g. 63.4G when the |
2337 | + * packaging says "64G drive". We could also use per-drive or |
2338 | + * per-media quirks to make a better guess. |
2339 | + * |
2340 | + * Returns: A human readable string, caller must free it using |
2341 | + * g_free(). |
2342 | + **/ |
2343 | +static char * |
2344 | +format_size_for_display (guint64 size) |
2345 | +{ |
2346 | + char *str; |
2347 | + gdouble displayed_size; |
2348 | + |
2349 | + if (size < MEGABYTE_FACTOR) |
2350 | + { |
2351 | + displayed_size = (double) size / KILOBYTE_FACTOR; |
2352 | + str = g_strdup_printf (_("%.1f kB"), displayed_size); |
2353 | + } |
2354 | + else if (size < GIGABYTE_FACTOR) |
2355 | + { |
2356 | + displayed_size = (double) size / MEGABYTE_FACTOR; |
2357 | + str = g_strdup_printf (_("%.1f MB"), displayed_size); |
2358 | + } |
2359 | + else |
2360 | + { |
2361 | + displayed_size = (double) size / GIGABYTE_FACTOR; |
2362 | + str = g_strdup_printf (_("%.1f GB"), displayed_size); |
2363 | + } |
2364 | + |
2365 | + return str; |
2366 | +} |
2367 | + |
2368 | +static void |
2369 | +do_update_from_hal (GHalVolume *mv) |
2370 | +{ |
2371 | + const char *drive_type; |
2372 | + const char *drive_bus; |
2373 | + gboolean drive_uses_removable_media; |
2374 | + const char *volume_fs_label; |
2375 | + guint64 volume_size; |
2376 | + gboolean volume_is_disc; |
2377 | + gboolean volume_disc_has_audio; |
2378 | + gboolean volume_disc_has_data; |
2379 | + const char *volume_disc_type; |
2380 | + gboolean volume_disc_is_blank; |
2381 | + const char *volume_fsusage; |
2382 | + const char *volume_fstype; |
2383 | + HalDevice *volume; |
2384 | + HalDevice *drive; |
2385 | + char *name; |
2386 | + char *size; |
2387 | + gboolean is_crypto; |
2388 | + gboolean is_crypto_cleartext; |
2389 | + |
2390 | + volume = mv->device; |
2391 | + drive = mv->drive_device; |
2392 | + |
2393 | + drive_type = hal_device_get_property_string (drive, "storage.drive_type"); |
2394 | + drive_bus = hal_device_get_property_string (drive, "storage.bus"); |
2395 | + drive_uses_removable_media = hal_device_get_property_bool (drive, "storage.removable"); |
2396 | + volume_fs_label = hal_device_get_property_string (volume, "volume.label"); |
2397 | + volume_size = hal_device_get_property_uint64 (volume, "volume.size"); |
2398 | + volume_is_disc = hal_device_get_property_bool (volume, "volume.is_disc"); |
2399 | + volume_disc_has_audio = hal_device_get_property_bool (volume, "volume.disc.has_audio"); |
2400 | + volume_disc_has_data = hal_device_get_property_bool (volume, "volume.disc.has_data"); |
2401 | + volume_disc_is_blank = hal_device_get_property_bool (volume, "volume.disc.is_blank"); |
2402 | + volume_disc_type = hal_device_get_property_string (volume, "volume.disc.type"); |
2403 | + volume_fsusage = hal_device_get_property_string (volume, "volume.fsusage"); |
2404 | + volume_fstype = hal_device_get_property_string (volume, "volume.fstype"); |
2405 | + |
2406 | + is_crypto = FALSE; |
2407 | + is_crypto_cleartext = FALSE; |
2408 | + if (strcmp (hal_device_get_property_string (volume, "volume.fsusage"), "crypto") == 0) |
2409 | + is_crypto = TRUE; |
2410 | + if (strlen (hal_device_get_property_string (volume, "volume.crypto_luks.clear.backing_volume")) > 0) |
2411 | + is_crypto_cleartext = TRUE; |
2412 | + |
2413 | + if (volume_is_disc && volume_disc_has_audio && mv->foreign_mount_root != NULL) |
2414 | + name = g_strdup (_("Audio Disc")); |
2415 | + else |
2416 | + { |
2417 | + if (strcmp (volume_fsusage, "crypto") == 0 && strcmp (volume_fstype, "crypto_LUKS") == 0) |
2418 | + { |
2419 | + size = format_size_for_display (volume_size); |
2420 | + /* Translators: %s is the size of the volume (e.g. 512 MB) */ |
2421 | + name = g_strdup_printf (_("%s Encrypted Data"), size); |
2422 | + g_free (size); |
2423 | + } |
2424 | + else |
2425 | + { |
2426 | + if (volume_fs_label != NULL && strlen (volume_fs_label) > 0) |
2427 | + name = g_strdup (volume_fs_label); |
2428 | + else if (volume_is_disc) |
2429 | + { |
2430 | + if (volume_disc_has_audio) |
2431 | + { |
2432 | + if (volume_disc_has_data) |
2433 | + name = g_strdup (_("Mixed Audio/Data Disc")); |
2434 | + else |
2435 | + name = g_strdup (_("Audio Disc")); |
2436 | + } |
2437 | + else |
2438 | + name = g_strdup (get_disc_name (volume_disc_type, volume_disc_is_blank)); |
2439 | + } |
2440 | + else |
2441 | + { |
2442 | + size = format_size_for_display (volume_size); |
2443 | + /* Translators: %s is the size of the volume (e.g. 512 MB) */ |
2444 | + name = g_strdup_printf (_("%s Media"), size); |
2445 | + g_free (size); |
2446 | + } |
2447 | + } |
2448 | + } |
2449 | + |
2450 | + mv->name = name; |
2451 | + mv->icon = _drive_get_icon (drive); /* use the drive icon since we're unmounted */ |
2452 | + |
2453 | + if (is_crypto || is_crypto_cleartext) |
2454 | + { |
2455 | + mv->icon_fallback = mv->icon; |
2456 | + mv->icon = g_strdup ("drive-encrypted"); |
2457 | + } |
2458 | + |
2459 | + if (hal_device_get_property_bool (volume, "volume.is_mounted")) |
2460 | + mv->mount_path = g_strdup (hal_device_get_property_string (volume, "volume.mount_point")); |
2461 | + else |
2462 | + mv->mount_path = NULL; |
2463 | + |
2464 | + g_object_set_data_full (G_OBJECT (mv), |
2465 | + "hal-storage-device-capabilities", |
2466 | + dupv_and_uniqify (hal_device_get_property_strlist (mv->drive_device, "info.capabilities")), |
2467 | + (GDestroyNotify) g_strfreev); |
2468 | + |
2469 | + if (volume_disc_type != NULL && strlen (volume_disc_type) == 0) |
2470 | + volume_disc_type = NULL; |
2471 | + g_object_set_data_full (G_OBJECT (mv), |
2472 | + "hal-volume.disc.type", |
2473 | + g_strdup (volume_disc_type), |
2474 | + (GDestroyNotify) g_free); |
2475 | +} |
2476 | + |
2477 | +static void |
2478 | +update_from_hal (GHalVolume *mv, gboolean emit_changed) |
2479 | +{ |
2480 | + char *old_name; |
2481 | + char *old_icon; |
2482 | + char *old_mount_path; |
2483 | + |
2484 | + old_name = g_strdup (mv->name); |
2485 | + old_icon = g_strdup (mv->icon); |
2486 | + old_mount_path = g_strdup (mv->mount_path); |
2487 | + |
2488 | + g_free (mv->name); |
2489 | + g_free (mv->icon); |
2490 | + g_free (mv->mount_path); |
2491 | + do_update_from_hal (mv); |
2492 | + |
2493 | + if (emit_changed) |
2494 | + { |
2495 | + gboolean mount_path_changed; |
2496 | + |
2497 | + if ((old_mount_path == NULL && mv->mount_path != NULL) || |
2498 | + (old_mount_path != NULL && mv->mount_path == NULL) || |
2499 | + (old_mount_path != NULL && mv->mount_path != NULL && strcmp (old_mount_path, mv->mount_path) != 0)) |
2500 | + mount_path_changed = TRUE; |
2501 | + else |
2502 | + mount_path_changed = FALSE; |
2503 | + |
2504 | + if (mount_path_changed || |
2505 | + (old_name == NULL || |
2506 | + old_icon == NULL || |
2507 | + strcmp (old_name, mv->name) != 0 || |
2508 | + strcmp (old_icon, mv->icon) != 0)) |
2509 | + emit_volume_changed (mv); |
2510 | + } |
2511 | + g_free (old_name); |
2512 | + g_free (old_icon); |
2513 | + g_free (old_mount_path); |
2514 | +} |
2515 | + |
2516 | +static void |
2517 | +hal_changed (HalDevice *device, const char *key, gpointer user_data) |
2518 | +{ |
2519 | + GHalVolume *hal_volume = G_HAL_VOLUME (user_data); |
2520 | + |
2521 | + /*g_warning ("hal modifying %s (property %s changed)", hal_volume->device_path, key);*/ |
2522 | + update_from_hal (hal_volume, TRUE); |
2523 | +} |
2524 | + |
2525 | +static void |
2526 | +compute_uuid (GHalVolume *volume) |
2527 | +{ |
2528 | + const char *fs_uuid; |
2529 | + const char *fs_label; |
2530 | + |
2531 | + /* use the FS uuid before falling back to the FS label */ |
2532 | + |
2533 | + fs_uuid = hal_device_get_property_string (volume->device, "volume.uuid"); |
2534 | + fs_label = hal_device_get_property_string (volume->device, "volume.label"); |
2535 | + |
2536 | + if (strlen (fs_uuid) == 0) |
2537 | + { |
2538 | + if (strlen (fs_label) == 0) |
2539 | + volume->uuid = NULL; |
2540 | + else |
2541 | + volume->uuid = g_strdup (fs_label); |
2542 | + } |
2543 | + else |
2544 | + volume->uuid = g_strdup (fs_uuid); |
2545 | +} |
2546 | + |
2547 | +GHalVolume * |
2548 | +g_hal_volume_new (GVolumeMonitor *volume_monitor, |
2549 | + HalDevice *device, |
2550 | + HalPool *pool, |
2551 | + GFile *foreign_mount_root, |
2552 | + gboolean is_mountable, |
2553 | + GHalDrive *drive) |
2554 | +{ |
2555 | + GHalVolume *volume; |
2556 | + HalDevice *drive_device; |
2557 | + const char *storage_udi; |
2558 | + const char *device_path; |
2559 | + gboolean ignore_automount; |
2560 | + |
2561 | + ignore_automount = FALSE; |
2562 | + |
2563 | + if (hal_device_has_capability (device, "block")) |
2564 | + { |
2565 | + storage_udi = hal_device_get_property_string (device, "block.storage_device"); |
2566 | + if (storage_udi == NULL) |
2567 | + return NULL; |
2568 | + |
2569 | + drive_device = hal_pool_get_device_by_udi (pool, storage_udi); |
2570 | + if (drive_device == NULL) |
2571 | + return NULL; |
2572 | + |
2573 | + device_path = hal_device_get_property_string (device, "block.device"); |
2574 | + } |
2575 | + else |
2576 | + { |
2577 | + return NULL; |
2578 | + } |
2579 | + |
2580 | + if (drive_device && |
2581 | + hal_device_has_property (drive_device, "storage.automount_enabled_hint") && |
2582 | + !hal_device_get_property_bool (drive_device, "storage.automount_enabled_hint")) |
2583 | + ignore_automount = TRUE; |
2584 | + |
2585 | + volume = g_object_new (G_TYPE_HAL_VOLUME, NULL); |
2586 | + volume->volume_monitor = volume_monitor; |
2587 | + g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(volume->volume_monitor)); |
2588 | + volume->mount_path = NULL; |
2589 | + volume->device_path = g_strdup (device_path); |
2590 | + volume->device = g_object_ref (device); |
2591 | + volume->drive_device = g_object_ref (drive_device); |
2592 | + volume->foreign_mount_root = foreign_mount_root != NULL ? g_object_ref (foreign_mount_root) : NULL; |
2593 | + volume->is_mountable = is_mountable; |
2594 | + volume->ignore_automount = ignore_automount || ! hal_device_is_recently_plugged_in (device); |
2595 | + |
2596 | + g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, volume, 0); |
2597 | + g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, volume, 0); |
2598 | + |
2599 | + compute_uuid (volume); |
2600 | + update_from_hal (volume, FALSE); |
2601 | + |
2602 | + /* need to do this last */ |
2603 | + volume->drive = drive; |
2604 | + if (drive != NULL) |
2605 | + g_hal_drive_set_volume (drive, volume); |
2606 | + |
2607 | + return volume; |
2608 | +} |
2609 | + |
2610 | +/** |
2611 | + * g_hal_volume_removed: |
2612 | + * @volume: |
2613 | + * |
2614 | + **/ |
2615 | +void |
2616 | +g_hal_volume_removed (GHalVolume *volume) |
2617 | +{ |
2618 | + |
2619 | + if (volume->mount != NULL) |
2620 | + { |
2621 | + g_hal_mount_unset_volume (volume->mount, volume); |
2622 | + volume->mount = NULL; |
2623 | + } |
2624 | + |
2625 | + if (volume->drive != NULL) |
2626 | + { |
2627 | + g_hal_drive_unset_volume (volume->drive, volume); |
2628 | + volume->drive = NULL; |
2629 | + } |
2630 | +} |
2631 | + |
2632 | +void |
2633 | +g_hal_volume_set_mount (GHalVolume *volume, |
2634 | + GHalMount *mount) |
2635 | +{ |
2636 | + if (volume->mount != mount) |
2637 | + { |
2638 | + |
2639 | + if (volume->mount != NULL) |
2640 | + g_hal_mount_unset_volume (volume->mount, volume); |
2641 | + |
2642 | + volume->mount = mount; |
2643 | + |
2644 | + emit_volume_changed (volume); |
2645 | + } |
2646 | +} |
2647 | + |
2648 | +void |
2649 | +g_hal_volume_unset_mount (GHalVolume *volume, |
2650 | + GHalMount *mount) |
2651 | +{ |
2652 | + if (volume->mount == mount) |
2653 | + { |
2654 | + volume->mount = NULL; |
2655 | + emit_volume_changed (volume); |
2656 | + } |
2657 | +} |
2658 | + |
2659 | +void |
2660 | +g_hal_volume_set_drive (GHalVolume *volume, |
2661 | + GHalDrive *drive) |
2662 | +{ |
2663 | + if (volume->drive != drive) |
2664 | + { |
2665 | + if (volume->drive != NULL) |
2666 | + g_hal_drive_unset_volume (volume->drive, volume); |
2667 | + |
2668 | + volume->drive = drive; |
2669 | + |
2670 | + emit_volume_changed (volume); |
2671 | + } |
2672 | +} |
2673 | + |
2674 | +void |
2675 | +g_hal_volume_unset_drive (GHalVolume *volume, |
2676 | + GHalDrive *drive) |
2677 | +{ |
2678 | + if (volume->drive == drive) |
2679 | + { |
2680 | + volume->drive = NULL; |
2681 | + emit_volume_changed (volume); |
2682 | + } |
2683 | +} |
2684 | + |
2685 | +static GIcon * |
2686 | +g_hal_volume_get_icon (GVolume *volume) |
2687 | +{ |
2688 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2689 | + GIcon *icon; |
2690 | + const char *name; |
2691 | + const char *fallback; |
2692 | + |
2693 | + name = hal_volume->icon; |
2694 | + |
2695 | + if (hal_volume->icon_fallback) |
2696 | + fallback = hal_volume->icon_fallback; |
2697 | + else /* if no custom fallbacks are set, use the icon to create them */ |
2698 | + fallback = name; |
2699 | + |
2700 | + icon = get_themed_icon_with_fallbacks (name, fallback); |
2701 | + return icon; |
2702 | +} |
2703 | + |
2704 | +static char * |
2705 | +g_hal_volume_get_name (GVolume *volume) |
2706 | +{ |
2707 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2708 | + |
2709 | + return g_strdup (hal_volume->name); |
2710 | +} |
2711 | + |
2712 | +static char * |
2713 | +g_hal_volume_get_uuid (GVolume *volume) |
2714 | +{ |
2715 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2716 | + |
2717 | + return g_strdup (hal_volume->uuid); |
2718 | +} |
2719 | + |
2720 | +static gboolean |
2721 | +g_hal_volume_can_mount (GVolume *volume) |
2722 | +{ |
2723 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2724 | + |
2725 | + return hal_volume->is_mountable; |
2726 | +} |
2727 | + |
2728 | +static gboolean |
2729 | +g_hal_volume_can_eject (GVolume *volume) |
2730 | +{ |
2731 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2732 | + gboolean res; |
2733 | + |
2734 | + res = FALSE; |
2735 | + if (hal_volume->drive != NULL) |
2736 | + res = g_drive_can_eject (G_DRIVE (hal_volume->drive)); |
2737 | + |
2738 | + return res; |
2739 | +} |
2740 | + |
2741 | +static gboolean |
2742 | +g_hal_volume_should_automount (GVolume *volume) |
2743 | +{ |
2744 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2745 | + |
2746 | + return ! (hal_volume->ignore_automount); |
2747 | +} |
2748 | + |
2749 | +static GDrive * |
2750 | +g_hal_volume_get_drive (GVolume *volume) |
2751 | +{ |
2752 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2753 | + GDrive *drive; |
2754 | + |
2755 | + drive = NULL; |
2756 | + if (hal_volume->drive != NULL) |
2757 | + drive = g_object_ref (hal_volume->drive); |
2758 | + |
2759 | + return drive; |
2760 | +} |
2761 | + |
2762 | +static GMount * |
2763 | +g_hal_volume_get_mount (GVolume *volume) |
2764 | +{ |
2765 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2766 | + GMount *mount; |
2767 | + |
2768 | + mount = NULL; |
2769 | + if (hal_volume->foreign_mount != NULL) |
2770 | + mount = g_object_ref (hal_volume->foreign_mount); |
2771 | + else if (hal_volume->mount != NULL) |
2772 | + mount = g_object_ref (hal_volume->mount); |
2773 | + |
2774 | + return mount; |
2775 | +} |
2776 | + |
2777 | +gboolean |
2778 | +g_hal_volume_has_mount_path (GHalVolume *volume, |
2779 | + const char *mount_path) |
2780 | +{ |
2781 | + gboolean res; |
2782 | + |
2783 | + res = FALSE; |
2784 | + if (volume->mount_path != NULL) |
2785 | + res = strcmp (volume->mount_path, mount_path) == 0; |
2786 | + |
2787 | + return res; |
2788 | +} |
2789 | + |
2790 | +gboolean |
2791 | +g_hal_volume_has_device_path (GHalVolume *volume, |
2792 | + const char *device_path) |
2793 | +{ |
2794 | + gboolean res; |
2795 | + |
2796 | + res = FALSE; |
2797 | + if (volume->device_path != NULL) |
2798 | + res = strcmp (volume->device_path, device_path) == 0; |
2799 | + return res; |
2800 | +} |
2801 | + |
2802 | +gboolean |
2803 | +g_hal_volume_has_udi (GHalVolume *volume, |
2804 | + const char *udi) |
2805 | +{ |
2806 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2807 | + gboolean res; |
2808 | + |
2809 | + res = FALSE; |
2810 | + if (hal_volume->device != NULL) |
2811 | + res = strcmp (hal_device_get_udi (hal_volume->device), udi) == 0; |
2812 | + return res; |
2813 | +} |
2814 | + |
2815 | +gboolean |
2816 | +g_hal_volume_has_uuid (GHalVolume *volume, |
2817 | + const char *uuid) |
2818 | +{ |
2819 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2820 | + gboolean res; |
2821 | + |
2822 | + res = FALSE; |
2823 | + if (hal_volume->uuid != NULL) |
2824 | + res = strcmp (hal_volume->uuid, uuid) == 0; |
2825 | + |
2826 | + return res; |
2827 | +} |
2828 | + |
2829 | +static void |
2830 | +foreign_mount_unmounted (GMount *mount, gpointer user_data) |
2831 | +{ |
2832 | + GHalVolume *volume = G_HAL_VOLUME (user_data); |
2833 | + gboolean check; |
2834 | + |
2835 | + check = volume->foreign_mount == mount; |
2836 | + if (check) |
2837 | + g_hal_volume_adopt_foreign_mount (volume, NULL); |
2838 | +} |
2839 | + |
2840 | +void |
2841 | +g_hal_volume_adopt_foreign_mount (GHalVolume *volume, GMount *foreign_mount) |
2842 | +{ |
2843 | + if (volume->foreign_mount != NULL) |
2844 | + g_object_unref (volume->foreign_mount); |
2845 | + |
2846 | + if (foreign_mount != NULL) |
2847 | + { |
2848 | + volume->foreign_mount = g_object_ref (foreign_mount); |
2849 | + g_signal_connect_object (foreign_mount, "unmounted", (GCallback) foreign_mount_unmounted, volume, 0); |
2850 | + } |
2851 | + else |
2852 | + volume->foreign_mount = NULL; |
2853 | + |
2854 | + emit_volume_changed (volume); |
2855 | +} |
2856 | + |
2857 | +gboolean |
2858 | +g_hal_volume_has_foreign_mount_root (GHalVolume *volume, |
2859 | + GFile *mount_root) |
2860 | +{ |
2861 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2862 | + gboolean res; |
2863 | + |
2864 | + res = FALSE; |
2865 | + if (hal_volume->foreign_mount_root != NULL) |
2866 | + res = g_file_equal (hal_volume->foreign_mount_root, mount_root); |
2867 | + |
2868 | + return res; |
2869 | +} |
2870 | + |
2871 | + |
2872 | +typedef struct { |
2873 | + GObject *object; |
2874 | + GAsyncReadyCallback callback; |
2875 | + gpointer user_data; |
2876 | + GCancellable *cancellable; |
2877 | +} SpawnOp; |
2878 | + |
2879 | +static void |
2880 | +spawn_cb (GPid pid, gint status, gpointer user_data) |
2881 | +{ |
2882 | + SpawnOp *data = user_data; |
2883 | + GSimpleAsyncResult *simple; |
2884 | + |
2885 | + /* ensure that the #GHalMount corrosponding to the #GHalVolume we've |
2886 | + * mounted is made available before returning to the user (make sure |
2887 | + * we don't emit the signals in idle; see #552168). |
2888 | + */ |
2889 | + g_hal_volume_monitor_force_update (G_HAL_VOLUME_MONITOR (G_HAL_VOLUME (data->object)->volume_monitor), FALSE); |
2890 | + |
2891 | + if (WEXITSTATUS (status) != 0) |
2892 | + { |
2893 | + GError *error; |
2894 | + error = g_error_new_literal (G_IO_ERROR, |
2895 | + G_IO_ERROR_FAILED_HANDLED, |
2896 | + "You are not supposed to show G_IO_ERROR_FAILED_HANDLED in the UI"); |
2897 | + simple = g_simple_async_result_new_from_error (data->object, |
2898 | + data->callback, |
2899 | + data->user_data, |
2900 | + error); |
2901 | + g_error_free (error); |
2902 | + } |
2903 | + else |
2904 | + { |
2905 | + simple = g_simple_async_result_new (data->object, |
2906 | + data->callback, |
2907 | + data->user_data, |
2908 | + NULL); |
2909 | + } |
2910 | + |
2911 | + g_simple_async_result_complete (simple); |
2912 | + g_object_unref (simple); |
2913 | + g_object_unref (data->object); |
2914 | + g_free (data); |
2915 | +} |
2916 | + |
2917 | +static void |
2918 | +spawn_do (GVolume *volume, |
2919 | + GCancellable *cancellable, |
2920 | + GAsyncReadyCallback callback, |
2921 | + gpointer user_data, |
2922 | + char **argv) |
2923 | +{ |
2924 | + SpawnOp *data; |
2925 | + GPid child_pid; |
2926 | + GError *error; |
2927 | + |
2928 | + data = g_new0 (SpawnOp, 1); |
2929 | + data->object = g_object_ref (volume); |
2930 | + data->callback = callback; |
2931 | + data->user_data = user_data; |
2932 | + data->cancellable = cancellable; |
2933 | + |
2934 | + error = NULL; |
2935 | + if (!g_spawn_async (NULL, /* working dir */ |
2936 | + argv, |
2937 | + NULL, /* envp */ |
2938 | + G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH, |
2939 | + NULL, /* child_setup */ |
2940 | + NULL, /* user_data for child_setup */ |
2941 | + &child_pid, |
2942 | + &error)) |
2943 | + { |
2944 | + g_simple_async_report_gerror_in_idle (data->object, |
2945 | + data->callback, |
2946 | + data->user_data, |
2947 | + error); |
2948 | + g_object_unref (data->object); |
2949 | + g_error_free (error); |
2950 | + g_free (data); |
2951 | + return; |
2952 | + } |
2953 | + |
2954 | + g_child_watch_add (child_pid, spawn_cb, data); |
2955 | +} |
2956 | + |
2957 | +typedef struct |
2958 | +{ |
2959 | + GHalVolume *enclosing_volume; |
2960 | + GAsyncReadyCallback callback; |
2961 | + gpointer user_data; |
2962 | +} ForeignMountOp; |
2963 | + |
2964 | +static void |
2965 | +mount_foreign_callback (GObject *source_object, |
2966 | + GAsyncResult *res, |
2967 | + gpointer user_data) |
2968 | +{ |
2969 | + ForeignMountOp *data = user_data; |
2970 | + data->callback (G_OBJECT (data->enclosing_volume), res, data->user_data); |
2971 | + g_object_unref (data->enclosing_volume); |
2972 | + g_free (data); |
2973 | +} |
2974 | + |
2975 | +static void |
2976 | +g_hal_volume_mount (GVolume *volume, |
2977 | + GMountMountFlags flags, |
2978 | + GMountOperation *mount_operation, |
2979 | + GCancellable *cancellable, |
2980 | + GAsyncReadyCallback callback, |
2981 | + gpointer user_data) |
2982 | +{ |
2983 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
2984 | + |
2985 | + /*g_warning ("hal_volume_mount (can_mount=%d foreign=%p device_path=%s)", |
2986 | + g_hal_volume_can_mount (volume), |
2987 | + hal_volume->foreign_mount_root, |
2988 | + hal_volume->device_path);*/ |
2989 | + |
2990 | + if (hal_volume->foreign_mount_root != NULL) |
2991 | + { |
2992 | + ForeignMountOp *data; |
2993 | + |
2994 | + data = g_new0 (ForeignMountOp, 1); |
2995 | + data->enclosing_volume = g_object_ref (hal_volume); |
2996 | + data->callback = callback; |
2997 | + data->user_data = user_data; |
2998 | + |
2999 | + g_file_mount_enclosing_volume (hal_volume->foreign_mount_root, |
3000 | + 0, |
3001 | + mount_operation, |
3002 | + cancellable, |
3003 | + mount_foreign_callback, |
3004 | + data); |
3005 | + } |
3006 | + else |
3007 | + { |
3008 | + char *argv[] = {"gnome-mount", "-b", "-d", NULL, NULL, NULL}; |
3009 | + argv[3] = hal_volume->device_path; |
3010 | + /* ask for no dialogs if mount_operation is NULL */ |
3011 | + if (mount_operation == NULL) |
3012 | + argv[4] = "-n"; |
3013 | + spawn_do (volume, cancellable, callback, user_data, argv); |
3014 | + } |
3015 | +} |
3016 | + |
3017 | +static gboolean |
3018 | +g_hal_volume_mount_finish (GVolume *volume, |
3019 | + GAsyncResult *result, |
3020 | + GError **error) |
3021 | +{ |
3022 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
3023 | + gboolean res; |
3024 | + |
3025 | + res = TRUE; |
3026 | + |
3027 | + if (hal_volume->foreign_mount_root != NULL) |
3028 | + res = g_file_mount_enclosing_volume_finish (hal_volume->foreign_mount_root, result, error); |
3029 | + |
3030 | + return res; |
3031 | +} |
3032 | + |
3033 | +typedef struct { |
3034 | + GObject *object; |
3035 | + GAsyncReadyCallback callback; |
3036 | + gpointer user_data; |
3037 | +} EjectWrapperOp; |
3038 | + |
3039 | +static void |
3040 | +eject_wrapper_callback (GObject *source_object, |
3041 | + GAsyncResult *res, |
3042 | + gpointer user_data) |
3043 | +{ |
3044 | + EjectWrapperOp *data = user_data; |
3045 | + data->callback (data->object, res, data->user_data); |
3046 | + g_object_unref (data->object); |
3047 | + g_free (data); |
3048 | +} |
3049 | + |
3050 | +static void |
3051 | +g_hal_volume_eject_with_operation (GVolume *volume, |
3052 | + GMountUnmountFlags flags, |
3053 | + GMountOperation *mount_operation, |
3054 | + GCancellable *cancellable, |
3055 | + GAsyncReadyCallback callback, |
3056 | + gpointer user_data) |
3057 | +{ |
3058 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
3059 | + GHalDrive *drive; |
3060 | + |
3061 | + /*g_warning ("hal_volume_eject");*/ |
3062 | + |
3063 | + drive = NULL; |
3064 | + if (hal_volume->drive != NULL) |
3065 | + drive = g_object_ref (hal_volume->drive); |
3066 | + |
3067 | + if (drive != NULL) |
3068 | + { |
3069 | + EjectWrapperOp *data; |
3070 | + data = g_new0 (EjectWrapperOp, 1); |
3071 | + data->object = g_object_ref (volume); |
3072 | + data->callback = callback; |
3073 | + data->user_data = user_data; |
3074 | + g_drive_eject_with_operation (G_DRIVE (drive), flags, mount_operation, cancellable, eject_wrapper_callback, data); |
3075 | + g_object_unref (drive); |
3076 | + } |
3077 | +} |
3078 | + |
3079 | +static gboolean |
3080 | +g_hal_volume_eject_with_operation_finish (GVolume *volume, |
3081 | + GAsyncResult *result, |
3082 | + GError **error) |
3083 | +{ |
3084 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
3085 | + gboolean res; |
3086 | + |
3087 | + res = TRUE; |
3088 | + if (hal_volume->drive != NULL) |
3089 | + res = g_drive_eject_with_operation_finish (G_DRIVE (hal_volume->drive), result, error); |
3090 | + return res; |
3091 | +} |
3092 | + |
3093 | +static void |
3094 | +g_hal_volume_eject (GVolume *volume, |
3095 | + GMountUnmountFlags flags, |
3096 | + GCancellable *cancellable, |
3097 | + GAsyncReadyCallback callback, |
3098 | + gpointer user_data) |
3099 | +{ |
3100 | + return g_hal_volume_eject_with_operation (volume, flags, NULL, cancellable, callback, user_data); |
3101 | +} |
3102 | + |
3103 | +static gboolean |
3104 | +g_hal_volume_eject_finish (GVolume *volume, |
3105 | + GAsyncResult *result, |
3106 | + GError **error) |
3107 | +{ |
3108 | + return g_hal_volume_eject_with_operation_finish (volume, result, error); |
3109 | +} |
3110 | + |
3111 | +static char * |
3112 | +g_hal_volume_get_identifier (GVolume *volume, |
3113 | + const char *kind) |
3114 | +{ |
3115 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
3116 | + char *id; |
3117 | + |
3118 | + id = NULL; |
3119 | + if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0) |
3120 | + id = g_strdup (hal_device_get_udi (hal_volume->device)); |
3121 | + else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0) |
3122 | + id = g_strdup (hal_volume->device_path); |
3123 | + else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0) |
3124 | + id = g_strdup (hal_device_get_property_string (hal_volume->device, "volume.label")); |
3125 | + else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0) |
3126 | + id = g_strdup (hal_device_get_property_string (hal_volume->device, "volume.uuid")); |
3127 | + |
3128 | + return id; |
3129 | +} |
3130 | + |
3131 | +static char ** |
3132 | +g_hal_volume_enumerate_identifiers (GVolume *volume) |
3133 | +{ |
3134 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
3135 | + GPtrArray *res; |
3136 | + const char *label, *uuid; |
3137 | + |
3138 | + res = g_ptr_array_new (); |
3139 | + |
3140 | + g_ptr_array_add (res, |
3141 | + g_strdup (G_VOLUME_IDENTIFIER_KIND_HAL_UDI)); |
3142 | + |
3143 | + if (hal_volume->device_path && *hal_volume->device_path != 0) |
3144 | + g_ptr_array_add (res, |
3145 | + g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE)); |
3146 | + |
3147 | + label = hal_device_get_property_string (hal_volume->device, "volume.label"); |
3148 | + uuid = hal_device_get_property_string (hal_volume->device, "volume.uuid"); |
3149 | + |
3150 | + if (label && *label != 0) |
3151 | + g_ptr_array_add (res, |
3152 | + g_strdup (G_VOLUME_IDENTIFIER_KIND_LABEL)); |
3153 | + |
3154 | + if (uuid && *uuid != 0) |
3155 | + g_ptr_array_add (res, |
3156 | + g_strdup (G_VOLUME_IDENTIFIER_KIND_UUID)); |
3157 | + |
3158 | + /* Null-terminate */ |
3159 | + g_ptr_array_add (res, NULL); |
3160 | + |
3161 | + return (char **)g_ptr_array_free (res, FALSE); |
3162 | +} |
3163 | + |
3164 | +static GFile * |
3165 | +g_hal_volume_get_activation_root (GVolume *volume) |
3166 | +{ |
3167 | + GHalVolume *hal_volume = G_HAL_VOLUME (volume); |
3168 | + GFile *root = NULL; |
3169 | + |
3170 | + if (hal_volume->foreign_mount_root != NULL) |
3171 | + root = g_object_ref (hal_volume->foreign_mount_root); |
3172 | + |
3173 | + return root; |
3174 | +} |
3175 | + |
3176 | +static void |
3177 | +g_hal_volume_volume_iface_init (GVolumeIface *iface) |
3178 | +{ |
3179 | + iface->get_name = g_hal_volume_get_name; |
3180 | + iface->get_icon = g_hal_volume_get_icon; |
3181 | + iface->get_uuid = g_hal_volume_get_uuid; |
3182 | + iface->get_drive = g_hal_volume_get_drive; |
3183 | + iface->get_mount = g_hal_volume_get_mount; |
3184 | + iface->can_mount = g_hal_volume_can_mount; |
3185 | + iface->can_eject = g_hal_volume_can_eject; |
3186 | + iface->should_automount = g_hal_volume_should_automount; |
3187 | + iface->mount_fn = g_hal_volume_mount; |
3188 | + iface->mount_finish = g_hal_volume_mount_finish; |
3189 | + iface->eject = g_hal_volume_eject; |
3190 | + iface->eject_finish = g_hal_volume_eject_finish; |
3191 | + iface->eject_with_operation = g_hal_volume_eject_with_operation; |
3192 | + iface->eject_with_operation_finish = g_hal_volume_eject_with_operation_finish; |
3193 | + iface->get_identifier = g_hal_volume_get_identifier; |
3194 | + iface->enumerate_identifiers = g_hal_volume_enumerate_identifiers; |
3195 | + iface->get_activation_root = g_hal_volume_get_activation_root; |
3196 | +} |
3197 | |
3198 | === added directory '.pc/04_hurd_path_max.patch' |
3199 | === added file '.pc/04_hurd_path_max.patch/.timestamp' |
3200 | === added directory '.pc/04_hurd_path_max.patch/monitor' |
3201 | === added directory '.pc/04_hurd_path_max.patch/monitor/gdu' |
3202 | === added file '.pc/04_hurd_path_max.patch/monitor/gdu/ggduvolumemonitor.c' |
3203 | --- .pc/04_hurd_path_max.patch/monitor/gdu/ggduvolumemonitor.c 1970-01-01 00:00:00 +0000 |
3204 | +++ .pc/04_hurd_path_max.patch/monitor/gdu/ggduvolumemonitor.c 2011-09-27 06:17:30 +0000 |
3205 | @@ -0,0 +1,1799 @@ |
3206 | +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ |
3207 | +/* gvfs - extensions for gio |
3208 | + * |
3209 | + * Copyright (C) 2006-2009 Red Hat, Inc. |
3210 | + * |
3211 | + * This library is free software; you can redistribute it and/or |
3212 | + * modify it under the terms of the GNU Lesser General Public |
3213 | + * License as published by the Free Software Foundation; either |
3214 | + * version 2 of the License, or (at your option) any later version. |
3215 | + * |
3216 | + * This library is distributed in the hope that it will be useful, |
3217 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3218 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3219 | + * Lesser General Public License for more details. |
3220 | + * |
3221 | + * You should have received a copy of the GNU Lesser General |
3222 | + * Public License along with this library; if not, write to the |
3223 | + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
3224 | + * Boston, MA 02111-1307, USA. |
3225 | + * |
3226 | + * Author: David Zeuthen <davidz@redhat.com> |
3227 | + */ |
3228 | + |
3229 | +#include <config.h> |
3230 | + |
3231 | +#include <limits.h> |
3232 | +#include <string.h> |
3233 | +#include <stdlib.h> |
3234 | + |
3235 | +#include <glib.h> |
3236 | +#include <glib/gi18n-lib.h> |
3237 | +#include <gio/gio.h> |
3238 | + |
3239 | +#include "ggduvolumemonitor.h" |
3240 | +#include "ggdumount.h" |
3241 | +#include "ggduvolume.h" |
3242 | +#include "ggdudrive.h" |
3243 | + |
3244 | +static GGduVolumeMonitor *the_volume_monitor = NULL; |
3245 | + |
3246 | +struct _GGduVolumeMonitor { |
3247 | + GNativeVolumeMonitor parent; |
3248 | + |
3249 | + GUnixMountMonitor *mount_monitor; |
3250 | + |
3251 | + GduPool *pool; |
3252 | + |
3253 | + GList *last_optical_disc_devices; |
3254 | + GList *last_mountpoints; |
3255 | + GList *last_mounts; |
3256 | + |
3257 | + GList *drives; |
3258 | + GList *volumes; |
3259 | + GList *fstab_volumes; |
3260 | + GList *mounts; |
3261 | + |
3262 | + /* we keep volumes/mounts for blank and audio discs separate to handle e.g. mixed discs properly */ |
3263 | + GList *disc_volumes; |
3264 | + GList *disc_mounts; |
3265 | + |
3266 | +}; |
3267 | + |
3268 | +static void mountpoints_changed (GUnixMountMonitor *mount_monitor, |
3269 | + gpointer user_data); |
3270 | +static void mounts_changed (GUnixMountMonitor *mount_monitor, |
3271 | + gpointer user_data); |
3272 | + |
3273 | +static void presentable_added (GduPool *pool, |
3274 | + GduPresentable *presentable, |
3275 | + gpointer user_data); |
3276 | +static void presentable_removed (GduPool *pool, |
3277 | + GduPresentable *presentable, |
3278 | + gpointer user_data); |
3279 | + |
3280 | +static void update_all (GGduVolumeMonitor *monitor, |
3281 | + gboolean emit_changes); |
3282 | + |
3283 | +static void update_drives (GGduVolumeMonitor *monitor, |
3284 | + GList **added_drives, |
3285 | + GList **removed_drives); |
3286 | +static void update_volumes (GGduVolumeMonitor *monitor, |
3287 | + GList **added_volumes, |
3288 | + GList **removed_volumes); |
3289 | +static void update_fstab_volumes (GGduVolumeMonitor *monitor, |
3290 | + GList **added_volumes, |
3291 | + GList **removed_volumes); |
3292 | +static void update_mounts (GGduVolumeMonitor *monitor, |
3293 | + GList **added_mounts, |
3294 | + GList **removed_mounts); |
3295 | +static void update_discs (GGduVolumeMonitor *monitor, |
3296 | + GList **added_volumes, |
3297 | + GList **removed_volumes, |
3298 | + GList **added_mounts, |
3299 | + GList **removed_mounts); |
3300 | + |
3301 | + |
3302 | +G_DEFINE_TYPE (GGduVolumeMonitor, g_gdu_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR) |
3303 | + |
3304 | +static void |
3305 | +list_free (GList *objects) |
3306 | +{ |
3307 | + g_list_foreach (objects, (GFunc)g_object_unref, NULL); |
3308 | + g_list_free (objects); |
3309 | +} |
3310 | + |
3311 | +static void |
3312 | +g_gdu_volume_monitor_dispose (GObject *object) |
3313 | +{ |
3314 | + the_volume_monitor = NULL; |
3315 | + |
3316 | + if (G_OBJECT_CLASS (g_gdu_volume_monitor_parent_class)->dispose) |
3317 | + (*G_OBJECT_CLASS (g_gdu_volume_monitor_parent_class)->dispose) (object); |
3318 | +} |
3319 | + |
3320 | +static void |
3321 | +g_gdu_volume_monitor_finalize (GObject *object) |
3322 | +{ |
3323 | + GGduVolumeMonitor *monitor; |
3324 | + |
3325 | + monitor = G_GDU_VOLUME_MONITOR (object); |
3326 | + |
3327 | + g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mountpoints_changed, monitor); |
3328 | + g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mounts_changed, monitor); |
3329 | + g_signal_handlers_disconnect_by_func (monitor->mount_monitor, presentable_added, monitor); |
3330 | + g_signal_handlers_disconnect_by_func (monitor->mount_monitor, presentable_removed, monitor); |
3331 | + |
3332 | + g_object_unref (monitor->mount_monitor); |
3333 | + |
3334 | + g_object_unref (monitor->pool); |
3335 | + |
3336 | + list_free (monitor->last_optical_disc_devices); |
3337 | + list_free (monitor->last_mountpoints); |
3338 | + g_list_foreach (monitor->last_mounts, |
3339 | + (GFunc)g_unix_mount_free, NULL); |
3340 | + g_list_free (monitor->last_mounts); |
3341 | + |
3342 | + list_free (monitor->drives); |
3343 | + list_free (monitor->fstab_volumes); |
3344 | + list_free (monitor->volumes); |
3345 | + list_free (monitor->mounts); |
3346 | + |
3347 | + list_free (monitor->disc_volumes); |
3348 | + list_free (monitor->disc_mounts); |
3349 | + |
3350 | + if (G_OBJECT_CLASS (g_gdu_volume_monitor_parent_class)->finalize) |
3351 | + (*G_OBJECT_CLASS (g_gdu_volume_monitor_parent_class)->finalize) (object); |
3352 | +} |
3353 | + |
3354 | +static GList * |
3355 | +get_mounts (GVolumeMonitor *volume_monitor) |
3356 | +{ |
3357 | + GGduVolumeMonitor *monitor; |
3358 | + GList *l, *ll; |
3359 | + |
3360 | + monitor = G_GDU_VOLUME_MONITOR (volume_monitor); |
3361 | + |
3362 | + l = g_list_copy (monitor->mounts); |
3363 | + ll = g_list_copy (monitor->disc_mounts); |
3364 | + l = g_list_concat (l, ll); |
3365 | + |
3366 | + g_list_foreach (l, (GFunc)g_object_ref, NULL); |
3367 | + |
3368 | + return l; |
3369 | +} |
3370 | + |
3371 | +static GList * |
3372 | +get_volumes (GVolumeMonitor *volume_monitor) |
3373 | +{ |
3374 | + GGduVolumeMonitor *monitor; |
3375 | + GList *l, *ll; |
3376 | + |
3377 | + monitor = G_GDU_VOLUME_MONITOR (volume_monitor); |
3378 | + |
3379 | + l = g_list_copy (monitor->volumes); |
3380 | + ll = g_list_copy (monitor->fstab_volumes); |
3381 | + l = g_list_concat (l, ll); |
3382 | + ll = g_list_copy (monitor->disc_volumes); |
3383 | + l = g_list_concat (l, ll); |
3384 | + |
3385 | + g_list_foreach (l, (GFunc)g_object_ref, NULL); |
3386 | + |
3387 | + return l; |
3388 | +} |
3389 | + |
3390 | +static GList * |
3391 | +get_connected_drives (GVolumeMonitor *volume_monitor) |
3392 | +{ |
3393 | + GGduVolumeMonitor *monitor; |
3394 | + GList *l; |
3395 | + |
3396 | + monitor = G_GDU_VOLUME_MONITOR (volume_monitor); |
3397 | + |
3398 | + l = g_list_copy (monitor->drives); |
3399 | + g_list_foreach (l, (GFunc)g_object_ref, NULL); |
3400 | + |
3401 | + return l; |
3402 | +} |
3403 | + |
3404 | +static GVolume * |
3405 | +get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) |
3406 | +{ |
3407 | + GGduVolumeMonitor *monitor; |
3408 | + GGduVolume *volume; |
3409 | + GList *l; |
3410 | + |
3411 | + monitor = G_GDU_VOLUME_MONITOR (volume_monitor); |
3412 | + |
3413 | + volume = NULL; |
3414 | + |
3415 | + for (l = monitor->volumes; l != NULL; l = l->next) |
3416 | + { |
3417 | + volume = l->data; |
3418 | + if (g_gdu_volume_has_uuid (volume, uuid)) |
3419 | + goto found; |
3420 | + } |
3421 | + |
3422 | + for (l = monitor->fstab_volumes; l != NULL; l = l->next) |
3423 | + { |
3424 | + volume = l->data; |
3425 | + if (g_gdu_volume_has_uuid (volume, uuid)) |
3426 | + goto found; |
3427 | + } |
3428 | + |
3429 | + for (l = monitor->disc_volumes; l != NULL; l = l->next) |
3430 | + { |
3431 | + volume = l->data; |
3432 | + if (g_gdu_volume_has_uuid (volume, uuid)) |
3433 | + goto found; |
3434 | + } |
3435 | + |
3436 | + return NULL; |
3437 | + |
3438 | + found: |
3439 | + |
3440 | + g_object_ref (volume); |
3441 | + |
3442 | + return (GVolume *)volume; |
3443 | +} |
3444 | + |
3445 | +static GMount * |
3446 | +get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) |
3447 | +{ |
3448 | + GGduVolumeMonitor *monitor; |
3449 | + GGduMount *mount; |
3450 | + GList *l; |
3451 | + |
3452 | + monitor = G_GDU_VOLUME_MONITOR (volume_monitor); |
3453 | + |
3454 | + mount = NULL; |
3455 | + |
3456 | + for (l = monitor->mounts; l != NULL; l = l->next) |
3457 | + { |
3458 | + mount = l->data; |
3459 | + if (g_gdu_mount_has_uuid (mount, uuid)) |
3460 | + goto found; |
3461 | + } |
3462 | + |
3463 | + for (l = monitor->disc_mounts; l != NULL; l = l->next) |
3464 | + { |
3465 | + mount = l->data; |
3466 | + if (g_gdu_mount_has_uuid (mount, uuid)) |
3467 | + goto found; |
3468 | + } |
3469 | + |
3470 | + return NULL; |
3471 | + |
3472 | + found: |
3473 | + |
3474 | + g_object_ref (mount); |
3475 | + |
3476 | + return (GMount *)mount; |
3477 | +} |
3478 | + |
3479 | +static GMount * |
3480 | +get_mount_for_mount_path (const char *mount_path, |
3481 | + GCancellable *cancellable) |
3482 | +{ |
3483 | + GMount *mount; |
3484 | + GGduMount *gdu_mount; |
3485 | + GGduVolumeMonitor *volume_monitor; |
3486 | + |
3487 | + if (the_volume_monitor == NULL) |
3488 | + { |
3489 | + /* Dammit, no monitor is set up.. so we have to create one, find |
3490 | + * what the user asks for and throw it away again. |
3491 | + * |
3492 | + * What a waste - especially considering that there's IO |
3493 | + * involved in doing this: connect to the system message bus; |
3494 | + * IPC to DeviceKit-disks etc etc |
3495 | + */ |
3496 | + volume_monitor = G_GDU_VOLUME_MONITOR (g_gdu_volume_monitor_new ()); |
3497 | + } |
3498 | + else |
3499 | + { |
3500 | + volume_monitor = g_object_ref (the_volume_monitor); |
3501 | + } |
3502 | + |
3503 | + mount = NULL; |
3504 | + |
3505 | + /* creation of the volume monitor might actually fail */ |
3506 | + if (volume_monitor != NULL) |
3507 | + { |
3508 | + GList *l; |
3509 | + |
3510 | + for (l = volume_monitor->mounts; l != NULL; l = l->next) |
3511 | + { |
3512 | + gdu_mount = l->data; |
3513 | + |
3514 | + if (g_gdu_mount_has_mount_path (gdu_mount, mount_path)) |
3515 | + { |
3516 | + mount = g_object_ref (gdu_mount); |
3517 | + break; |
3518 | + } |
3519 | + } |
3520 | + } |
3521 | + |
3522 | + g_object_unref (volume_monitor); |
3523 | + |
3524 | + return (GMount *) mount; |
3525 | +} |
3526 | + |
3527 | +static void |
3528 | +mountpoints_changed (GUnixMountMonitor *mount_monitor, |
3529 | + gpointer user_data) |
3530 | +{ |
3531 | + GGduVolumeMonitor *monitor = G_GDU_VOLUME_MONITOR (user_data); |
3532 | + |
3533 | + update_all (monitor, TRUE); |
3534 | +} |
3535 | + |
3536 | +static void |
3537 | +mounts_changed (GUnixMountMonitor *mount_monitor, |
3538 | + gpointer user_data) |
3539 | +{ |
3540 | + GGduVolumeMonitor *monitor = G_GDU_VOLUME_MONITOR (user_data); |
3541 | + |
3542 | + update_all (monitor, TRUE); |
3543 | +} |
3544 | + |
3545 | +static void |
3546 | +presentable_added (GduPool *pool, |
3547 | + GduPresentable *presentable, |
3548 | + gpointer user_data) |
3549 | +{ |
3550 | + GGduVolumeMonitor *monitor = G_GDU_VOLUME_MONITOR (user_data); |
3551 | + |
3552 | + /*g_debug ("presentable_added %p: %s", presentable, gdu_presentable_get_id (presentable));*/ |
3553 | + |
3554 | + update_all (monitor, TRUE); |
3555 | +} |
3556 | + |
3557 | +static void |
3558 | +presentable_removed (GduPool *pool, |
3559 | + GduPresentable *presentable, |
3560 | + gpointer user_data) |
3561 | +{ |
3562 | + GGduVolumeMonitor *monitor = G_GDU_VOLUME_MONITOR (user_data); |
3563 | + |
3564 | + /*g_debug ("presentable_removed %p: %s", presentable, gdu_presentable_get_id (presentable));*/ |
3565 | + |
3566 | + update_all (monitor, TRUE); |
3567 | +} |
3568 | + |
3569 | +static void |
3570 | +presentable_changed (GduPool *pool, |
3571 | + GduPresentable *presentable, |
3572 | + gpointer user_data) |
3573 | +{ |
3574 | + GGduVolumeMonitor *monitor = G_GDU_VOLUME_MONITOR (user_data); |
3575 | + |
3576 | + /*g_debug ("presentable_changed %p: %s", presentable, gdu_presentable_get_id (presentable));*/ |
3577 | + |
3578 | + update_all (monitor, TRUE); |
3579 | +} |
3580 | + |
3581 | +static void |
3582 | +presentable_job_changed (GduPool *pool, |
3583 | + GduPresentable *presentable, |
3584 | + gpointer user_data) |
3585 | +{ |
3586 | + GGduVolumeMonitor *monitor = G_GDU_VOLUME_MONITOR (user_data); |
3587 | + |
3588 | + /*g_debug ("presentable_job_changed %p: %s", presentable, gdu_presentable_get_id (presentable));*/ |
3589 | + |
3590 | + update_all (monitor, TRUE); |
3591 | +} |
3592 | + |
3593 | +static GObject * |
3594 | +g_gdu_volume_monitor_constructor (GType type, |
3595 | + guint n_construct_properties, |
3596 | + GObjectConstructParam *construct_properties) |
3597 | +{ |
3598 | + GObject *object; |
3599 | + GGduVolumeMonitor *monitor; |
3600 | + GGduVolumeMonitorClass *klass; |
3601 | + GObjectClass *parent_class; |
3602 | + |
3603 | + if (the_volume_monitor != NULL) |
3604 | + { |
3605 | + object = g_object_ref (the_volume_monitor); |
3606 | + return object; |
3607 | + } |
3608 | + |
3609 | + /*g_warning ("creating gdu vm");*/ |
3610 | + |
3611 | + object = NULL; |
3612 | + |
3613 | + /* Invoke parent constructor. */ |
3614 | + klass = G_GDU_VOLUME_MONITOR_CLASS (g_type_class_peek (G_TYPE_GDU_VOLUME_MONITOR)); |
3615 | + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); |
3616 | + object = parent_class->constructor (type, |
3617 | + n_construct_properties, |
3618 | + construct_properties); |
3619 | + |
3620 | + monitor = G_GDU_VOLUME_MONITOR (object); |
3621 | + |
3622 | + monitor->mount_monitor = g_unix_mount_monitor_new (); |
3623 | + |
3624 | + g_signal_connect (monitor->mount_monitor, |
3625 | + "mounts_changed", |
3626 | + G_CALLBACK (mounts_changed), |
3627 | + monitor); |
3628 | + |
3629 | + g_signal_connect (monitor->mount_monitor, |
3630 | + "mountpoints_changed", |
3631 | + G_CALLBACK (mountpoints_changed), |
3632 | + monitor); |
3633 | + |
3634 | + monitor->pool = gdu_pool_new (); |
3635 | + |
3636 | + g_signal_connect (monitor->pool, |
3637 | + "presentable_added", |
3638 | + G_CALLBACK (presentable_added), |
3639 | + monitor); |
3640 | + |
3641 | + g_signal_connect (monitor->pool, |
3642 | + "presentable_removed", |
3643 | + G_CALLBACK (presentable_removed), |
3644 | + monitor); |
3645 | + |
3646 | + g_signal_connect (monitor->pool, |
3647 | + "presentable_changed", |
3648 | + G_CALLBACK (presentable_changed), |
3649 | + monitor); |
3650 | + |
3651 | + g_signal_connect (monitor->pool, |
3652 | + "presentable_job_changed", |
3653 | + G_CALLBACK (presentable_job_changed), |
3654 | + monitor); |
3655 | + |
3656 | + update_all (monitor, FALSE); |
3657 | + |
3658 | + the_volume_monitor = monitor; |
3659 | + |
3660 | + return object; |
3661 | +} |
3662 | + |
3663 | +static void |
3664 | +g_gdu_volume_monitor_init (GGduVolumeMonitor *monitor) |
3665 | +{ |
3666 | +} |
3667 | + |
3668 | +static gboolean |
3669 | +is_supported (void) |
3670 | +{ |
3671 | + /* TODO: return FALSE if DeviceKit-disks is not available */ |
3672 | + return TRUE; |
3673 | +} |
3674 | + |
3675 | +static void |
3676 | +g_gdu_volume_monitor_class_init (GGduVolumeMonitorClass *klass) |
3677 | +{ |
3678 | + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
3679 | + GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); |
3680 | + GNativeVolumeMonitorClass *native_class = G_NATIVE_VOLUME_MONITOR_CLASS (klass); |
3681 | + |
3682 | + gobject_class->constructor = g_gdu_volume_monitor_constructor; |
3683 | + gobject_class->finalize = g_gdu_volume_monitor_finalize; |
3684 | + gobject_class->dispose = g_gdu_volume_monitor_dispose; |
3685 | + |
3686 | + monitor_class->get_mounts = get_mounts; |
3687 | + monitor_class->get_volumes = get_volumes; |
3688 | + monitor_class->get_connected_drives = get_connected_drives; |
3689 | + monitor_class->get_volume_for_uuid = get_volume_for_uuid; |
3690 | + monitor_class->get_mount_for_uuid = get_mount_for_uuid; |
3691 | + monitor_class->is_supported = is_supported; |
3692 | + |
3693 | + native_class->get_mount_for_mount_path = get_mount_for_mount_path; |
3694 | +} |
3695 | + |
3696 | +/** |
3697 | + * g_gdu_volume_monitor_new: |
3698 | + * |
3699 | + * Returns: a new #GVolumeMonitor. |
3700 | + **/ |
3701 | +GVolumeMonitor * |
3702 | +g_gdu_volume_monitor_new (void) |
3703 | +{ |
3704 | + GGduVolumeMonitor *monitor; |
3705 | + |
3706 | + monitor = g_object_new (G_TYPE_GDU_VOLUME_MONITOR, NULL); |
3707 | + |
3708 | + return G_VOLUME_MONITOR (monitor); |
3709 | +} |
3710 | + |
3711 | +static void |
3712 | +diff_sorted_lists (GList *list1, |
3713 | + GList *list2, |
3714 | + GCompareFunc compare, |
3715 | + GList **added, |
3716 | + GList **removed) |
3717 | +{ |
3718 | + int order; |
3719 | + |
3720 | + *added = *removed = NULL; |
3721 | + |
3722 | + while (list1 != NULL && |
3723 | + list2 != NULL) |
3724 | + { |
3725 | + order = (*compare) (list1->data, list2->data); |
3726 | + if (order < 0) |
3727 | + { |
3728 | + *removed = g_list_prepend (*removed, list1->data); |
3729 | + list1 = list1->next; |
3730 | + } |
3731 | + else if (order > 0) |
3732 | + { |
3733 | + *added = g_list_prepend (*added, list2->data); |
3734 | + list2 = list2->next; |
3735 | + } |
3736 | + else |
3737 | + { /* same item */ |
3738 | + list1 = list1->next; |
3739 | + list2 = list2->next; |
3740 | + } |
3741 | + } |
3742 | + |
3743 | + while (list1 != NULL) |
3744 | + { |
3745 | + *removed = g_list_prepend (*removed, list1->data); |
3746 | + list1 = list1->next; |
3747 | + } |
3748 | + while (list2 != NULL) |
3749 | + { |
3750 | + *added = g_list_prepend (*added, list2->data); |
3751 | + list2 = list2->next; |
3752 | + } |
3753 | +} |
3754 | + |
3755 | +static GGduVolume * |
3756 | +find_volume_for_mount_path (GGduVolumeMonitor *monitor, |
3757 | + const char *mount_path) |
3758 | +{ |
3759 | + GList *l; |
3760 | + GGduVolume *found; |
3761 | + |
3762 | + found = NULL; |
3763 | + |
3764 | + for (l = monitor->volumes; l != NULL; l = l->next) |
3765 | + { |
3766 | + GGduVolume *volume = l->data; |
3767 | + if (g_gdu_volume_has_mount_path (volume, mount_path)) |
3768 | + { |
3769 | + found = volume; |
3770 | + goto out; |
3771 | + } |
3772 | + } |
3773 | + |
3774 | + for (l = monitor->fstab_volumes; l != NULL; l = l->next) |
3775 | + { |
3776 | + GGduVolume *volume = l->data; |
3777 | + if (g_gdu_volume_has_mount_path (volume, mount_path)) |
3778 | + { |
3779 | + found = volume; |
3780 | + goto out; |
3781 | + } |
3782 | + } |
3783 | + |
3784 | + out: |
3785 | + return found; |
3786 | +} |
3787 | + |
3788 | +static GGduVolume * |
3789 | +find_volume_for_unix_mount_point (GGduVolumeMonitor *monitor, |
3790 | + GUnixMountPoint *unix_mount_point) |
3791 | +{ |
3792 | + GList *l; |
3793 | + GGduVolume *found; |
3794 | + |
3795 | + found = NULL; |
3796 | + for (l = monitor->fstab_volumes; l != NULL; l = l->next) |
3797 | + { |
3798 | + GGduVolume *volume = l->data; |
3799 | + GUnixMountPoint *volume_mount_point; |
3800 | + |
3801 | + volume_mount_point = g_gdu_volume_get_unix_mount_point (volume); |
3802 | + if (g_unix_mount_point_compare (unix_mount_point, volume_mount_point) == 0) |
3803 | + { |
3804 | + found = volume; |
3805 | + goto out; |
3806 | + } |
3807 | + } |
3808 | + |
3809 | + out: |
3810 | + return found; |
3811 | +} |
3812 | + |
3813 | +static GGduMount * |
3814 | +find_mount_by_mount_path (GGduVolumeMonitor *monitor, |
3815 | + const char *mount_path) |
3816 | +{ |
3817 | + GList *l; |
3818 | + |
3819 | + for (l = monitor->mounts; l != NULL; l = l->next) |
3820 | + { |
3821 | + GGduMount *mount = l->data; |
3822 | + |
3823 | + if (g_gdu_mount_has_mount_path (mount, mount_path)) |
3824 | + return mount; |
3825 | + } |
3826 | + |
3827 | + return NULL; |
3828 | +} |
3829 | + |
3830 | +/* TODO: move to gio */ |
3831 | +static gboolean |
3832 | +_g_unix_mount_point_guess_should_display (GUnixMountPoint *mount_point) |
3833 | +{ |
3834 | + const char *mount_path; |
3835 | + |
3836 | + mount_path = g_unix_mount_point_get_mount_path (mount_point); |
3837 | + |
3838 | + /* Never display internal mountpoints */ |
3839 | + if (g_unix_is_mount_path_system_internal (mount_path)) |
3840 | + return FALSE; |
3841 | + |
3842 | + /* Hide mounts within a dot path, suppose it was a purpose to hide this mount */ |
3843 | + if (g_strstr_len (mount_path, -1, "/.") != NULL) |
3844 | + return FALSE; |
3845 | + |
3846 | + /* Only display things in /media (which are generally user mountable) |
3847 | + and home dir (fuse stuff) */ |
3848 | + if (g_str_has_prefix (mount_path, "/media/")) |
3849 | + return TRUE; |
3850 | + |
3851 | + if (g_str_has_prefix (mount_path, g_get_home_dir ())) |
3852 | + return TRUE; |
3853 | + |
3854 | + return FALSE; |
3855 | +} |
3856 | + |
3857 | +static GUnixMountPoint * |
3858 | +get_mount_point_for_device (GduDevice *d, GList *fstab_mount_points) |
3859 | +{ |
3860 | + GList *l; |
3861 | + const gchar *device_file; |
3862 | + const gchar *mount_path; |
3863 | + GUnixMountPoint *ret; |
3864 | + |
3865 | + ret = NULL; |
3866 | + |
3867 | + mount_path = gdu_device_get_mount_path (d); |
3868 | + |
3869 | + device_file = gdu_device_get_device_file (d); |
3870 | + |
3871 | + for (l = fstab_mount_points; l != NULL; l = l->next) |
3872 | + { |
3873 | + GUnixMountPoint *mount_point = l->data; |
3874 | + const gchar *fstab_device_file; |
3875 | + const gchar *fstab_mount_path; |
3876 | + |
3877 | + fstab_mount_path = g_unix_mount_point_get_mount_path (mount_point); |
3878 | + if (g_strcmp0 (mount_path, fstab_mount_path) == 0) |
3879 | + { |
3880 | + ret = mount_point; |
3881 | + goto out; |
3882 | + } |
3883 | + |
3884 | + fstab_device_file = g_unix_mount_point_get_device_path (mount_point); |
3885 | + if (g_str_has_prefix (fstab_device_file, "LABEL=")) |
3886 | + { |
3887 | + if (g_strcmp0 (fstab_device_file + 6, gdu_device_id_get_label (d)) == 0) |
3888 | + { |
3889 | + ret = mount_point; |
3890 | + goto out; |
3891 | + } |
3892 | + } |
3893 | + else if (g_str_has_prefix (fstab_device_file, "UUID=")) |
3894 | + { |
3895 | + if (g_ascii_strcasecmp (fstab_device_file + 5, gdu_device_id_get_uuid (d)) == 0) |
3896 | + { |
3897 | + ret = mount_point; |
3898 | + goto out; |
3899 | + } |
3900 | + } |
3901 | + else |
3902 | + { |
3903 | + char resolved_fstab_device_file[PATH_MAX]; |
3904 | + |
3905 | + /* handle symlinks such as /dev/disk/by-uuid/47C2-1994 */ |
3906 | + if (realpath (fstab_device_file, resolved_fstab_device_file) != NULL && |
3907 | + g_strcmp0 (resolved_fstab_device_file, device_file) == 0) |
3908 | + { |
3909 | + ret = mount_point; |
3910 | + goto out; |
3911 | + } |
3912 | + } |
3913 | + } |
3914 | + |
3915 | + out: |
3916 | + return ret; |
3917 | +} |
3918 | + |
3919 | +static gboolean |
3920 | +should_mount_be_ignored (GduPool *pool, GduDevice *d) |
3921 | +{ |
3922 | + gboolean ret; |
3923 | + const gchar *mount_path; |
3924 | + GUnixMountEntry *mount_entry; |
3925 | + |
3926 | + ret = FALSE; |
3927 | + |
3928 | + if (gdu_device_get_presentation_hide (d)) |
3929 | + { |
3930 | + ret = TRUE; |
3931 | + goto out; |
3932 | + } |
3933 | + |
3934 | + mount_path = gdu_device_get_mount_path (d); |
3935 | + if (mount_path == NULL || strlen (mount_path) == 0) |
3936 | + goto out; |
3937 | + |
3938 | + mount_entry = g_unix_mount_at (mount_path, NULL); |
3939 | + if (mount_entry != NULL) |
3940 | + { |
3941 | + if (!g_unix_mount_guess_should_display (mount_entry)) |
3942 | + { |
3943 | + ret = TRUE; |
3944 | + } |
3945 | + g_unix_mount_free (mount_entry); |
3946 | + } |
3947 | + |
3948 | + out: |
3949 | + return ret; |
3950 | +} |
3951 | + |
3952 | +gboolean |
3953 | +_is_pc_floppy_drive (GduDevice *device) |
3954 | +{ |
3955 | + gboolean ret; |
3956 | + gchar **drive_media_compat; |
3957 | + const gchar *drive_connection_interface; |
3958 | + |
3959 | + ret = FALSE; |
3960 | + |
3961 | + if (device != NULL) |
3962 | + { |
3963 | + drive_media_compat = gdu_device_drive_get_media_compatibility (device); |
3964 | + drive_connection_interface = gdu_device_drive_get_connection_interface (device); |
3965 | + |
3966 | + if (g_strcmp0 (drive_connection_interface, "platform") == 0 && |
3967 | + (drive_media_compat != NULL && |
3968 | + g_strv_length (drive_media_compat) > 0 && |
3969 | + g_strcmp0 (drive_media_compat[0], "floppy") == 0)) |
3970 | + { |
3971 | + ret = TRUE; |
3972 | + } |
3973 | + } |
3974 | + |
3975 | + return ret; |
3976 | +} |
3977 | + |
3978 | +static gboolean |
3979 | +should_volume_be_ignored (GduPool *pool, GduVolume *volume, GList *fstab_mount_points) |
3980 | +{ |
3981 | + GduDevice *device; |
3982 | + gboolean ret; |
3983 | + const gchar *usage; |
3984 | + const gchar *type; |
3985 | + |
3986 | + ret = TRUE; |
3987 | + |
3988 | + device = gdu_presentable_get_device (GDU_PRESENTABLE (volume)); |
3989 | + if (device == NULL) |
3990 | + goto out; |
3991 | + |
3992 | + if (gdu_device_get_presentation_hide (device)) |
3993 | + goto out; |
3994 | + |
3995 | + usage = gdu_device_id_get_usage (device); |
3996 | + type = gdu_device_id_get_type (device); |
3997 | + |
3998 | + if (_is_pc_floppy_drive (device) || g_strcmp0 (usage, "filesystem") == 0) |
3999 | + { |
4000 | + GUnixMountPoint *mount_point; |
4001 | + |
4002 | + /* don't ignore volumes with a mountable filesystem unless |
4003 | + * |
4004 | + * - volume is referenced in /etc/fstab and deemed to be ignored |
4005 | + * |
4006 | + * - volume is mounted and should_mount_be_ignored() deems it should be ignored |
4007 | + * |
4008 | + * - volume is a cleartext LUKS device as the cryptotext LUKS volume will morph |
4009 | + * into the cleartext volume when unlocked (see ggduvolume.c) |
4010 | + */ |
4011 | + |
4012 | + if (gdu_device_is_luks_cleartext (device)) |
4013 | + goto out; |
4014 | + |
4015 | + mount_point = get_mount_point_for_device (device, fstab_mount_points); |
4016 | + if (mount_point != NULL && !_g_unix_mount_point_guess_should_display (mount_point)) |
4017 | + goto out; |
4018 | + |
4019 | + if (gdu_device_is_mounted (device)) |
4020 | + { |
4021 | + ret = should_mount_be_ignored (pool, device); |
4022 | + goto out; |
4023 | + } |
4024 | + |
4025 | + ret = FALSE; |
4026 | + |
4027 | + } |
4028 | + else if (g_strcmp0 (usage, "crypto") == 0 && g_strcmp0 (type, "crypto_LUKS") == 0) |
4029 | + { |
4030 | + /* don't ignore LUKS volumes */ |
4031 | + ret = FALSE; |
4032 | + } |
4033 | + |
4034 | + out: |
4035 | + |
4036 | + if (device != NULL) |
4037 | + g_object_unref (device); |
4038 | + return ret; |
4039 | +} |
4040 | + |
4041 | +static gboolean |
4042 | +should_drive_be_ignored (GduPool *pool, GduDrive *d, GList *fstab_mount_points) |
4043 | +{ |
4044 | + GduDevice *device; |
4045 | + gboolean ignored; |
4046 | + gboolean have_volumes; |
4047 | + gboolean all_volumes_are_ignored; |
4048 | + GList *enclosed; |
4049 | + GList *l; |
4050 | + |
4051 | + ignored = FALSE; |
4052 | + enclosed = NULL; |
4053 | + |
4054 | + device = gdu_presentable_get_device (GDU_PRESENTABLE (d)); |
4055 | + |
4056 | + /* If there is no GduDevice for a drive, then ignore it unless |
4057 | + * we know how to start it (e.g. RAID arrays, Volume Groups) |
4058 | + */ |
4059 | + if (device == NULL) |
4060 | + { |
4061 | + if (!gdu_drive_is_activatable (d)) |
4062 | + { |
4063 | + ignored = TRUE; |
4064 | + goto out; |
4065 | + } |
4066 | + } |
4067 | + |
4068 | + if (device != NULL && gdu_device_get_presentation_hide (device)) { |
4069 | + ignored = TRUE; |
4070 | + goto out; |
4071 | + } |
4072 | + |
4073 | + have_volumes = FALSE; |
4074 | + all_volumes_are_ignored = TRUE; |
4075 | + |
4076 | + /* never ignore a drive if it has volumes that we don't want to ignore */ |
4077 | + enclosed = gdu_pool_get_enclosed_presentables (pool, GDU_PRESENTABLE (d)); |
4078 | + for (l = enclosed; l != NULL && all_volumes_are_ignored; l = l->next) |
4079 | + { |
4080 | + GduPresentable *enclosed_presentable = GDU_PRESENTABLE (l->data); |
4081 | + |
4082 | + /* There might be other presentables that GduVolume objects; for example GduVolumeHole */ |
4083 | + if (GDU_IS_VOLUME (enclosed_presentable)) |
4084 | + { |
4085 | + GduVolume *volume = GDU_VOLUME (enclosed_presentable); |
4086 | + GduDevice *volume_device; |
4087 | + |
4088 | + have_volumes = TRUE; |
4089 | + |
4090 | + if (!should_volume_be_ignored (pool, volume, fstab_mount_points)) |
4091 | + { |
4092 | + all_volumes_are_ignored = FALSE; |
4093 | + break; |
4094 | + } |
4095 | + |
4096 | + /* The volume may be an extended partition - we need to check all logical |
4097 | + * partitions as well (#597041) |
4098 | + */ |
4099 | + volume_device = gdu_presentable_get_device (GDU_PRESENTABLE (volume)); |
4100 | + if (volume_device != NULL) |
4101 | + { |
4102 | + if (g_strcmp0 (gdu_device_partition_get_scheme (volume_device), "mbr") == 0) |
4103 | + { |
4104 | + gint type; |
4105 | + |
4106 | + type = strtol (gdu_device_partition_get_type (volume_device), NULL, 0); |
4107 | + if (type == 0x05 || type == 0x0f || type == 0x85) |
4108 | + { |
4109 | + GList *enclosed_logical; |
4110 | + GList *ll; |
4111 | + |
4112 | + enclosed_logical = gdu_pool_get_enclosed_presentables (pool, GDU_PRESENTABLE (volume)); |
4113 | + for (ll = enclosed_logical; ll != NULL && all_volumes_are_ignored; ll = ll->next) |
4114 | + { |
4115 | + GduPresentable *enclosed_logical_presentable = GDU_PRESENTABLE (ll->data); |
4116 | + |
4117 | + if (GDU_IS_VOLUME (enclosed_logical_presentable)) |
4118 | + { |
4119 | + if (!should_volume_be_ignored (pool, |
4120 | + GDU_VOLUME (enclosed_logical_presentable), |
4121 | + fstab_mount_points)) |
4122 | + { |
4123 | + all_volumes_are_ignored = FALSE; |
4124 | + } |
4125 | + } |
4126 | + } |
4127 | + g_list_foreach (enclosed_logical, (GFunc) g_object_unref, NULL); |
4128 | + g_list_free (enclosed_logical); |
4129 | + } |
4130 | + } |
4131 | + g_object_unref (volume_device); |
4132 | + } |
4133 | + } |
4134 | + } |
4135 | + |
4136 | + /* we ignore a drive if |
4137 | + * |
4138 | + * a) no volumes are available AND media is available; OR |
4139 | + * |
4140 | + * b) the volumes of the drive are all ignored |
4141 | + */ |
4142 | + if (device != NULL) |
4143 | + { |
4144 | + if (!have_volumes) |
4145 | + { |
4146 | + if (gdu_device_is_media_available (device)) |
4147 | + ignored = TRUE; |
4148 | + } |
4149 | + else |
4150 | + { |
4151 | + if (all_volumes_are_ignored) |
4152 | + ignored = TRUE; |
4153 | + } |
4154 | + |
4155 | + /* special case for audio and blank discs: don't ignore the drive since we'll create |
4156 | + * a cdda:// or burn:// mount for the drive |
4157 | + */ |
4158 | + if (gdu_device_is_optical_disc (device) && (gdu_device_optical_disc_get_num_audio_tracks (device) > 0 || |
4159 | + gdu_device_optical_disc_get_is_blank (device))) |
4160 | + { |
4161 | + ignored = FALSE; |
4162 | + } |
4163 | + } |
4164 | + |
4165 | + out: |
4166 | + g_list_foreach (enclosed, (GFunc) g_object_unref, NULL); |
4167 | + g_list_free (enclosed); |
4168 | + |
4169 | + if (device != NULL) |
4170 | + g_object_unref (device); |
4171 | + |
4172 | + return ignored; |
4173 | +} |
4174 | + |
4175 | +static void |
4176 | +list_emit (GGduVolumeMonitor *monitor, |
4177 | + const char *monitor_signal, |
4178 | + const char *object_signal, |
4179 | + GList *objects) |
4180 | +{ |
4181 | + GList *l; |
4182 | + |
4183 | + for (l = objects; l != NULL; l = l->next) |
4184 | + { |
4185 | + g_signal_emit_by_name (monitor, monitor_signal, l->data); |
4186 | + if (object_signal) |
4187 | + g_signal_emit_by_name (l->data, object_signal); |
4188 | + } |
4189 | +} |
4190 | + |
4191 | +static void |
4192 | +update_all (GGduVolumeMonitor *monitor, |
4193 | + gboolean emit_changes) |
4194 | +{ |
4195 | + GList *added_drives, *removed_drives; |
4196 | + GList *added_volumes, *removed_volumes; |
4197 | + GList *added_mounts, *removed_mounts; |
4198 | + |
4199 | + added_drives = NULL; |
4200 | + removed_drives = NULL; |
4201 | + added_volumes = NULL; |
4202 | + removed_volumes = NULL; |
4203 | + added_mounts = NULL; |
4204 | + removed_mounts = NULL; |
4205 | + |
4206 | + update_drives (monitor, &added_drives, &removed_drives); |
4207 | + update_volumes (monitor, &added_volumes, &removed_volumes); |
4208 | + update_fstab_volumes (monitor, &added_volumes, &removed_volumes); |
4209 | + update_mounts (monitor, &added_mounts, &removed_mounts); |
4210 | + update_discs (monitor, |
4211 | + &added_volumes, &removed_volumes, |
4212 | + &added_mounts, &removed_mounts); |
4213 | + |
4214 | + if (emit_changes) |
4215 | + { |
4216 | + list_emit (monitor, |
4217 | + "drive_disconnected", NULL, |
4218 | + removed_drives); |
4219 | + list_emit (monitor, |
4220 | + "drive_connected", NULL, |
4221 | + added_drives); |
4222 | + |
4223 | + list_emit (monitor, |
4224 | + "volume_removed", "removed", |
4225 | + removed_volumes); |
4226 | + list_emit (monitor, |
4227 | + "volume_added", NULL, |
4228 | + added_volumes); |
4229 | + |
4230 | + list_emit (monitor, |
4231 | + "mount_removed", "unmounted", |
4232 | + removed_mounts); |
4233 | + list_emit (monitor, |
4234 | + "mount_added", NULL, |
4235 | + added_mounts); |
4236 | + } |
4237 | + |
4238 | + list_free (removed_drives); |
4239 | + list_free (added_drives); |
4240 | + list_free (removed_volumes); |
4241 | + list_free (added_volumes); |
4242 | + list_free (removed_mounts); |
4243 | + list_free (added_mounts); |
4244 | +} |
4245 | + |
4246 | +static GGduMount * |
4247 | +find_disc_mount_for_volume (GGduVolumeMonitor *monitor, |
4248 | + GGduVolume *volume) |
4249 | +{ |
4250 | + GList *l; |
4251 | + |
4252 | + for (l = monitor->disc_mounts; l != NULL; l = l->next) |
4253 | + { |
4254 | + GGduMount *mount = G_GDU_MOUNT (l->data); |
4255 | + |
4256 | + if (g_gdu_mount_has_volume (mount, volume)) |
4257 | + return mount; |
4258 | + } |
4259 | + |
4260 | + return NULL; |
4261 | +} |
4262 | + |
4263 | +static GGduVolume * |
4264 | +find_disc_volume_for_device_file (GGduVolumeMonitor *monitor, |
4265 | + const gchar *device_file) |
4266 | +{ |
4267 | + GList *l; |
4268 | + GGduVolume *ret; |
4269 | + struct stat stat_buf; |
4270 | + |
4271 | + ret = NULL; |
4272 | + |
4273 | + if (stat (device_file, &stat_buf) == 0) |
4274 | + { |
4275 | + for (l = monitor->disc_volumes; l != NULL; l = l->next) |
4276 | + { |
4277 | + GGduVolume *volume = G_GDU_VOLUME (l->data); |
4278 | + if (g_gdu_volume_has_dev (volume, stat_buf.st_rdev)) |
4279 | + { |
4280 | + ret = volume; |
4281 | + goto out; |
4282 | + } |
4283 | + } |
4284 | + } |
4285 | + |
4286 | + for (l = monitor->disc_volumes; l != NULL; l = l->next) |
4287 | + { |
4288 | + GGduVolume *volume = G_GDU_VOLUME (l->data); |
4289 | + |
4290 | + if (g_gdu_volume_has_device_file (volume, device_file)) |
4291 | + { |
4292 | + ret = volume; |
4293 | + goto out; |
4294 | + } |
4295 | + } |
4296 | + |
4297 | + out: |
4298 | + return ret; |
4299 | +} |
4300 | + |
4301 | +static GGduVolume * |
4302 | +find_volume_for_device_file (GGduVolumeMonitor *monitor, |
4303 | + const gchar *device_file) |
4304 | +{ |
4305 | + GList *l; |
4306 | + GGduVolume *ret; |
4307 | + struct stat stat_buf; |
4308 | + |
4309 | + ret = NULL; |
4310 | + |
4311 | + if (stat (device_file, &stat_buf) == 0) |
4312 | + { |
4313 | + for (l = monitor->volumes; l != NULL; l = l->next) |
4314 | + { |
4315 | + GGduVolume *volume = G_GDU_VOLUME (l->data); |
4316 | + if (g_gdu_volume_has_dev (volume, stat_buf.st_rdev)) |
4317 | + { |
4318 | + ret = volume; |
4319 | + goto out; |
4320 | + } |
4321 | + } |
4322 | + } |
4323 | + |
4324 | + for (l = monitor->volumes; l != NULL; l = l->next) |
4325 | + { |
4326 | + GGduVolume *volume = G_GDU_VOLUME (l->data); |
4327 | + |
4328 | + if (g_gdu_volume_has_device_file (volume, device_file)) |
4329 | + { |
4330 | + ret = volume; |
4331 | + goto out; |
4332 | + } |
4333 | + } |
4334 | + |
4335 | + ret = NULL; |
4336 | + for (l = monitor->fstab_volumes; l != NULL; l = l->next) |
4337 | + { |
4338 | + GGduVolume *volume = G_GDU_VOLUME (l->data); |
4339 | + |
4340 | + if (g_gdu_volume_has_device_file (volume, device_file)) |
4341 | + { |
4342 | + ret = volume; |
4343 | + goto out; |
4344 | + } |
4345 | + } |
4346 | + |
4347 | + out: |
4348 | + return ret; |
4349 | +} |
4350 | + |
4351 | +static GGduVolume * |
4352 | +find_volume_for_presentable (GGduVolumeMonitor *monitor, |
4353 | + GduPresentable *presentable) |
4354 | +{ |
4355 | + GList *l; |
4356 | + |
4357 | + for (l = monitor->volumes; l != NULL; l = l->next) |
4358 | + { |
4359 | + GGduVolume *volume = G_GDU_VOLUME (l->data); |
4360 | + |
4361 | + if (g_gdu_volume_has_presentable (volume, presentable)) |
4362 | + return volume; |
4363 | + } |
4364 | + |
4365 | + return NULL; |
4366 | +} |
4367 | + |
4368 | +static GGduDrive * |
4369 | +find_drive_by_device_file (GGduVolumeMonitor *monitor, |
4370 | + const gchar *device_file) |
4371 | +{ |
4372 | + GList *l; |
4373 | + struct stat stat_buf; |
4374 | + |
4375 | + if (stat (device_file, &stat_buf) != 0) |
4376 | + { |
4377 | + g_warning ("%s:%s: Error statting %s: %m", G_STRLOC, G_STRFUNC, device_file); |
4378 | + return NULL; |
4379 | + } |
4380 | + |
4381 | + for (l = monitor->drives; l != NULL; l = l->next) |
4382 | + { |
4383 | + GGduDrive *drive = G_GDU_DRIVE (l->data); |
4384 | + |
4385 | + if (g_gdu_drive_has_dev (drive, stat_buf.st_rdev)) |
4386 | + return drive; |
4387 | + } |
4388 | + |
4389 | + return NULL; |
4390 | +} |
4391 | + |
4392 | +static GGduDrive * |
4393 | +find_drive_by_presentable (GGduVolumeMonitor *monitor, |
4394 | + GduPresentable *presentable) |
4395 | +{ |
4396 | + GList *l; |
4397 | + |
4398 | + for (l = monitor->drives; l != NULL; l = l->next) |
4399 | + { |
4400 | + GGduDrive *drive = G_GDU_DRIVE (l->data); |
4401 | + |
4402 | + if (g_gdu_drive_has_presentable (drive, presentable)) |
4403 | + return drive; |
4404 | + } |
4405 | + |
4406 | + return NULL; |
4407 | +} |
4408 | + |
4409 | +static void |
4410 | +update_drives (GGduVolumeMonitor *monitor, |
4411 | + GList **added_drives, |
4412 | + GList **removed_drives) |
4413 | +{ |
4414 | + GList *cur_drives; |
4415 | + GList *new_drives; |
4416 | + GList *removed, *added; |
4417 | + GList *l, *ll; |
4418 | + GGduDrive *drive; |
4419 | + GList *fstab_mount_points; |
4420 | + |
4421 | + fstab_mount_points = g_unix_mount_points_get (NULL); |
4422 | + |
4423 | + cur_drives = NULL; |
4424 | + for (l = monitor->drives; l != NULL; l = l->next) |
4425 | + cur_drives = g_list_prepend (cur_drives, g_gdu_drive_get_presentable (G_GDU_DRIVE (l->data))); |
4426 | + |
4427 | + /* remove devices we want to ignore - we do it here so we get to reevaluate |
4428 | + * on the next update whether they should still be ignored |
4429 | + */ |
4430 | + new_drives = gdu_pool_get_presentables (monitor->pool); |
4431 | + for (l = new_drives; l != NULL; l = ll) |
4432 | + { |
4433 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4434 | + ll = l->next; |
4435 | + if (!GDU_IS_DRIVE (p) || should_drive_be_ignored (monitor->pool, GDU_DRIVE (p), fstab_mount_points)) |
4436 | + { |
4437 | + g_object_unref (p); |
4438 | + new_drives = g_list_delete_link (new_drives, l); |
4439 | + } |
4440 | + } |
4441 | + |
4442 | + cur_drives = g_list_sort (cur_drives, (GCompareFunc) gdu_presentable_compare); |
4443 | + new_drives = g_list_sort (new_drives, (GCompareFunc) gdu_presentable_compare); |
4444 | + diff_sorted_lists (cur_drives, |
4445 | + new_drives, (GCompareFunc) gdu_presentable_compare, |
4446 | + &added, &removed); |
4447 | + |
4448 | + for (l = removed; l != NULL; l = l->next) |
4449 | + { |
4450 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4451 | + |
4452 | + drive = find_drive_by_presentable (monitor, p); |
4453 | + if (drive != NULL) |
4454 | + { |
4455 | + /*g_debug ("removing drive %s", gdu_presentable_get_id (p));*/ |
4456 | + g_gdu_drive_disconnected (drive); |
4457 | + monitor->drives = g_list_remove (monitor->drives, drive); |
4458 | + *removed_drives = g_list_prepend (*removed_drives, drive); |
4459 | + } |
4460 | + } |
4461 | + |
4462 | + for (l = added; l != NULL; l = l->next) |
4463 | + { |
4464 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4465 | + |
4466 | + drive = find_drive_by_presentable (monitor, p); |
4467 | + if (drive == NULL) |
4468 | + { |
4469 | + /*g_debug ("adding drive %s", gdu_presentable_get_id (p));*/ |
4470 | + drive = g_gdu_drive_new (G_VOLUME_MONITOR (monitor), p); |
4471 | + if (drive != NULL) |
4472 | + { |
4473 | + monitor->drives = g_list_prepend (monitor->drives, drive); |
4474 | + *added_drives = g_list_prepend (*added_drives, g_object_ref (drive)); |
4475 | + } |
4476 | + } |
4477 | + } |
4478 | + |
4479 | + g_list_free (added); |
4480 | + g_list_free (removed); |
4481 | + |
4482 | + g_list_free (cur_drives); |
4483 | + |
4484 | + g_list_foreach (new_drives, (GFunc) g_object_unref, NULL); |
4485 | + g_list_free (new_drives); |
4486 | + |
4487 | + g_list_foreach (fstab_mount_points, (GFunc) g_unix_mount_point_free, NULL); |
4488 | + g_list_free (fstab_mount_points); |
4489 | +} |
4490 | + |
4491 | +static void |
4492 | +update_volumes (GGduVolumeMonitor *monitor, |
4493 | + GList **added_volumes, |
4494 | + GList **removed_volumes) |
4495 | +{ |
4496 | + GList *cur_volumes; |
4497 | + GList *new_volumes; |
4498 | + GList *removed, *added; |
4499 | + GList *l, *ll; |
4500 | + GGduVolume *volume; |
4501 | + GGduDrive *drive; |
4502 | + GList *fstab_mount_points; |
4503 | + |
4504 | + fstab_mount_points = g_unix_mount_points_get (NULL); |
4505 | + |
4506 | + cur_volumes = NULL; |
4507 | + for (l = monitor->volumes; l != NULL; l = l->next) |
4508 | + cur_volumes = g_list_prepend (cur_volumes, g_gdu_volume_get_presentable (G_GDU_VOLUME (l->data))); |
4509 | + |
4510 | + /* remove devices we want to ignore - we do it here so we get to reevaluate |
4511 | + * on the next update whether they should still be ignored |
4512 | + */ |
4513 | + new_volumes = gdu_pool_get_presentables (monitor->pool); |
4514 | + for (l = new_volumes; l != NULL; l = ll) |
4515 | + { |
4516 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4517 | + ll = l->next; |
4518 | + if (!GDU_IS_VOLUME (p) || should_volume_be_ignored (monitor->pool, GDU_VOLUME (p), fstab_mount_points)) |
4519 | + { |
4520 | + g_object_unref (p); |
4521 | + new_volumes = g_list_delete_link (new_volumes, l); |
4522 | + } |
4523 | + } |
4524 | + |
4525 | + cur_volumes = g_list_sort (cur_volumes, (GCompareFunc) gdu_presentable_compare); |
4526 | + new_volumes = g_list_sort (new_volumes, (GCompareFunc) gdu_presentable_compare); |
4527 | + diff_sorted_lists (cur_volumes, |
4528 | + new_volumes, (GCompareFunc) gdu_presentable_compare, |
4529 | + &added, &removed); |
4530 | + |
4531 | + for (l = removed; l != NULL; l = l->next) |
4532 | + { |
4533 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4534 | + |
4535 | + volume = find_volume_for_presentable (monitor, p); |
4536 | + if (volume != NULL) |
4537 | + { |
4538 | + /*g_debug ("removing volume %s", gdu_device_get_device_file (d));*/ |
4539 | + g_gdu_volume_removed (volume); |
4540 | + monitor->volumes = g_list_remove (monitor->volumes, volume); |
4541 | + *removed_volumes = g_list_prepend (*removed_volumes, volume); |
4542 | + } |
4543 | + } |
4544 | + |
4545 | + for (l = added; l != NULL; l = l->next) |
4546 | + { |
4547 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4548 | + GduDevice *d; |
4549 | + |
4550 | + volume = NULL; |
4551 | + d = gdu_presentable_get_device (p); |
4552 | + |
4553 | + if (d != NULL) |
4554 | + volume = find_volume_for_device_file (monitor, gdu_device_get_device_file (d)); |
4555 | + |
4556 | + if (volume == NULL) |
4557 | + { |
4558 | + GduDrive *gdu_drive; |
4559 | + |
4560 | + drive = NULL; |
4561 | + gdu_drive = gdu_volume_get_drive (GDU_VOLUME (p)); |
4562 | + if (gdu_drive != NULL) |
4563 | + { |
4564 | + drive = find_drive_by_presentable (monitor, GDU_PRESENTABLE (gdu_drive)); |
4565 | + g_object_unref (gdu_drive); |
4566 | + } |
4567 | + |
4568 | + volume = g_gdu_volume_new (G_VOLUME_MONITOR (monitor), |
4569 | + GDU_VOLUME (p), |
4570 | + drive, |
4571 | + NULL); |
4572 | + if (volume != NULL) |
4573 | + { |
4574 | + monitor->volumes = g_list_prepend (monitor->volumes, volume); |
4575 | + *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume)); |
4576 | + } |
4577 | + } |
4578 | + |
4579 | + if (d != NULL) |
4580 | + g_object_unref (d); |
4581 | + } |
4582 | + |
4583 | + g_list_free (added); |
4584 | + g_list_free (removed); |
4585 | + |
4586 | + g_list_foreach (new_volumes, (GFunc) g_object_unref, NULL); |
4587 | + g_list_free (new_volumes); |
4588 | + |
4589 | + g_list_free (cur_volumes); |
4590 | + |
4591 | + g_list_foreach (fstab_mount_points, (GFunc) g_unix_mount_point_free, NULL); |
4592 | + g_list_free (fstab_mount_points); |
4593 | +} |
4594 | + |
4595 | +static void |
4596 | +update_fstab_volumes (GGduVolumeMonitor *monitor, |
4597 | + GList **added_volumes, |
4598 | + GList **removed_volumes) |
4599 | +{ |
4600 | + GList *fstab_mount_points; |
4601 | + GList *cur_fstab_mount_points; |
4602 | + GList *new_fstab_mount_points; |
4603 | + GList *removed, *added; |
4604 | + GList *l; |
4605 | + GGduVolume *volume; |
4606 | + |
4607 | + fstab_mount_points = g_unix_mount_points_get (NULL); |
4608 | + |
4609 | + cur_fstab_mount_points = NULL; |
4610 | + for (l = monitor->fstab_volumes; l != NULL; l = l->next) |
4611 | + cur_fstab_mount_points = g_list_prepend (cur_fstab_mount_points, g_gdu_volume_get_unix_mount_point (G_GDU_VOLUME (l->data))); |
4612 | + |
4613 | + new_fstab_mount_points = NULL; |
4614 | + for (l = fstab_mount_points; l != NULL; l = l->next) |
4615 | + { |
4616 | + GUnixMountPoint *mount_point = l->data; |
4617 | + const gchar *device_file; |
4618 | + |
4619 | + /* only show user mountable mount points */ |
4620 | + if (!g_unix_mount_point_is_user_mountable (mount_point)) |
4621 | + continue; |
4622 | + |
4623 | + /* only show stuff that can be mounted in user-visible locations */ |
4624 | + if (!_g_unix_mount_point_guess_should_display (mount_point)) |
4625 | + continue; |
4626 | + |
4627 | + /* ignore mount point if the device doesn't exist or is handled by DeviceKit-disks */ |
4628 | + device_file = g_unix_mount_point_get_device_path (mount_point); |
4629 | + if (g_str_has_prefix (device_file, "/dev/")) |
4630 | + { |
4631 | + gchar resolved_path[PATH_MAX]; |
4632 | + GduDevice *device; |
4633 | + |
4634 | + /* doesn't exist */ |
4635 | + if (realpath (device_file, resolved_path) == NULL) |
4636 | + continue; |
4637 | + |
4638 | + /* is handled by DKD */ |
4639 | + device = gdu_pool_get_by_device_file (monitor->pool, resolved_path); |
4640 | + if (device != NULL) |
4641 | + { |
4642 | + g_object_unref (device); |
4643 | + continue; |
4644 | + } |
4645 | + } |
4646 | + |
4647 | + new_fstab_mount_points = g_list_prepend (new_fstab_mount_points, mount_point); |
4648 | + } |
4649 | + |
4650 | + diff_sorted_lists (cur_fstab_mount_points, |
4651 | + new_fstab_mount_points, (GCompareFunc) g_unix_mount_point_compare, |
4652 | + &added, &removed); |
4653 | + |
4654 | + for (l = removed; l != NULL; l = l->next) |
4655 | + { |
4656 | + GUnixMountPoint *mount_point = l->data; |
4657 | + volume = find_volume_for_unix_mount_point (monitor, mount_point); |
4658 | + if (volume != NULL) |
4659 | + { |
4660 | + g_gdu_volume_removed (volume); |
4661 | + monitor->fstab_volumes = g_list_remove (monitor->fstab_volumes, volume); |
4662 | + *removed_volumes = g_list_prepend (*removed_volumes, volume); |
4663 | + /*g_debug ("removed volume for /etc/fstab mount point %s", g_unix_mount_point_get_mount_path (mount_point));*/ |
4664 | + } |
4665 | + } |
4666 | + |
4667 | + for (l = added; l != NULL; l = l->next) |
4668 | + { |
4669 | + GUnixMountPoint *mount_point = l->data; |
4670 | + |
4671 | + volume = g_gdu_volume_new_for_unix_mount_point (G_VOLUME_MONITOR (monitor), mount_point); |
4672 | + if (volume != NULL) |
4673 | + { |
4674 | + /* steal mount_point since g_gdu_volume_new_for_unix_mount_point() takes ownership of it */ |
4675 | + fstab_mount_points = g_list_remove (fstab_mount_points, mount_point); |
4676 | + monitor->fstab_volumes = g_list_prepend (monitor->fstab_volumes, volume); |
4677 | + *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume)); |
4678 | + /*g_debug ("added volume for /etc/fstab mount point %s", g_unix_mount_point_get_mount_path (mount_point));*/ |
4679 | + } |
4680 | + else |
4681 | + { |
4682 | + g_unix_mount_point_free (mount_point); |
4683 | + } |
4684 | + } |
4685 | + |
4686 | + g_list_free (added); |
4687 | + g_list_free (removed); |
4688 | + |
4689 | + g_list_free (cur_fstab_mount_points); |
4690 | + |
4691 | + g_list_foreach (fstab_mount_points, (GFunc) g_unix_mount_point_free, NULL); |
4692 | + g_list_free (fstab_mount_points); |
4693 | +} |
4694 | + |
4695 | +static gboolean |
4696 | +unix_mount_is_cleartext (GGduVolumeMonitor *monitor, |
4697 | + GUnixMountEntry *mount_entry) |
4698 | +{ |
4699 | + const char *device_file; |
4700 | + const char *mount_path; |
4701 | + GGduVolume *volume; |
4702 | + GduPresentable *presentable; |
4703 | + |
4704 | + device_file = g_unix_mount_get_device_path (mount_entry); |
4705 | + mount_path = g_unix_mount_get_mount_path (mount_entry); |
4706 | + volume = find_volume_for_device_file (monitor, device_file); |
4707 | + if (volume == NULL) |
4708 | + volume = find_volume_for_mount_path (monitor, mount_path); |
4709 | + |
4710 | + if (volume != NULL) |
4711 | + { |
4712 | + presentable = g_gdu_volume_get_presentable_with_cleartext (volume); |
4713 | + return presentable != NULL; |
4714 | + } |
4715 | + |
4716 | + return FALSE; |
4717 | +} |
4718 | + |
4719 | +static void |
4720 | +update_mounts (GGduVolumeMonitor *monitor, |
4721 | + GList **added_mounts, |
4722 | + GList **removed_mounts) |
4723 | +{ |
4724 | + GList *new_mounts; |
4725 | + GList *removed, *added; |
4726 | + GList *l, *ll; |
4727 | + GGduMount *mount; |
4728 | + GGduVolume *volume; |
4729 | + const char *device_file; |
4730 | + const char *mount_path; |
4731 | + |
4732 | + new_mounts = g_unix_mounts_get (NULL); |
4733 | + |
4734 | + /* remove mounts we want to ignore - we do it here so we get to reevaluate |
4735 | + * on the next update whether they should still be ignored |
4736 | + */ |
4737 | + for (l = new_mounts; l != NULL; l = ll) |
4738 | + { |
4739 | + GUnixMountEntry *mount_entry = l->data; |
4740 | + ll = l->next; |
4741 | + |
4742 | + /* since we always show crypto volumes, we should also never ignore their mounts */ |
4743 | + /* keep in sync with should_mount_be_ignored() */ |
4744 | + if (!g_unix_mount_guess_should_display (mount_entry) && |
4745 | + !unix_mount_is_cleartext (monitor, mount_entry)) |
4746 | + { |
4747 | + g_unix_mount_free (mount_entry); |
4748 | + new_mounts = g_list_delete_link (new_mounts, l); |
4749 | + } |
4750 | + } |
4751 | + |
4752 | + new_mounts = g_list_sort (new_mounts, (GCompareFunc) g_unix_mount_compare); |
4753 | + |
4754 | + diff_sorted_lists (monitor->last_mounts, |
4755 | + new_mounts, (GCompareFunc) g_unix_mount_compare, |
4756 | + &added, &removed); |
4757 | + |
4758 | + for (l = removed; l != NULL; l = l->next) |
4759 | + { |
4760 | + GUnixMountEntry *mount_entry = l->data; |
4761 | + |
4762 | + mount = find_mount_by_mount_path (monitor, g_unix_mount_get_mount_path (mount_entry)); |
4763 | + if (mount) |
4764 | + { |
4765 | + /*g_debug ("removing mount %s", g_unix_mount_get_device_path (mount_entry));*/ |
4766 | + g_gdu_mount_unmounted (mount); |
4767 | + monitor->mounts = g_list_remove (monitor->mounts, mount); |
4768 | + |
4769 | + *removed_mounts = g_list_prepend (*removed_mounts, mount); |
4770 | + } |
4771 | + } |
4772 | + |
4773 | + for (l = added; l != NULL; l = l->next) |
4774 | + { |
4775 | + GUnixMountEntry *mount_entry = l->data; |
4776 | + |
4777 | + device_file = g_unix_mount_get_device_path (mount_entry); |
4778 | + mount_path = g_unix_mount_get_mount_path (mount_entry); |
4779 | + volume = find_volume_for_device_file (monitor, device_file); |
4780 | + if (volume == NULL) |
4781 | + volume = find_volume_for_mount_path (monitor, mount_path); |
4782 | + |
4783 | + /*g_debug ("adding mount %s (vol %p) (device %s, mount_path %s)", g_unix_mount_get_device_path (mount_entry), volume, device_file, mount_path);*/ |
4784 | + mount = g_gdu_mount_new (G_VOLUME_MONITOR (monitor), mount_entry, volume); |
4785 | + if (mount) |
4786 | + { |
4787 | + monitor->mounts = g_list_prepend (monitor->mounts, mount); |
4788 | + *added_mounts = g_list_prepend (*added_mounts, g_object_ref (mount)); |
4789 | + } |
4790 | + } |
4791 | + |
4792 | + g_list_free (added); |
4793 | + g_list_free (removed); |
4794 | + g_list_foreach (monitor->last_mounts, |
4795 | + (GFunc)g_unix_mount_free, NULL); |
4796 | + g_list_free (monitor->last_mounts); |
4797 | + monitor->last_mounts = new_mounts; |
4798 | +} |
4799 | + |
4800 | +static void |
4801 | +update_discs (GGduVolumeMonitor *monitor, |
4802 | + GList **added_volumes, |
4803 | + GList **removed_volumes, |
4804 | + GList **added_mounts, |
4805 | + GList **removed_mounts) |
4806 | +{ |
4807 | + GList *cur_discs; |
4808 | + GList *new_discs; |
4809 | + GList *removed, *added; |
4810 | + GList *l, *ll; |
4811 | + GGduDrive *drive = NULL; |
4812 | + GGduVolume *volume; |
4813 | + GGduMount *mount; |
4814 | + |
4815 | + /* we also need to generate GVolume + GMount objects for |
4816 | + * |
4817 | + * - optical discs that have audio |
4818 | + * - optical discs that are blank |
4819 | + * |
4820 | + */ |
4821 | + |
4822 | + cur_discs = NULL; |
4823 | + for (l = monitor->disc_volumes; l != NULL; l = l->next) |
4824 | + cur_discs = g_list_prepend (cur_discs, g_gdu_volume_get_presentable (G_GDU_VOLUME (l->data))); |
4825 | + |
4826 | + new_discs = gdu_pool_get_presentables (monitor->pool); |
4827 | + for (l = new_discs; l != NULL; l = ll) |
4828 | + { |
4829 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4830 | + GduDevice *d; |
4831 | + gboolean ignore; |
4832 | + |
4833 | + ll = l->next; |
4834 | + ignore = TRUE; |
4835 | + |
4836 | + /* filter out everything but discs that are blank or has audio */ |
4837 | + d = gdu_presentable_get_device (p); |
4838 | + if (GDU_IS_VOLUME (p) && d != NULL && gdu_device_is_optical_disc (d)) |
4839 | + { |
4840 | + if (gdu_device_optical_disc_get_num_audio_tracks (d) > 0 || gdu_device_optical_disc_get_is_blank (d)) |
4841 | + ignore = FALSE; |
4842 | + } |
4843 | + |
4844 | + if (ignore) |
4845 | + { |
4846 | + g_object_unref (p); |
4847 | + new_discs = g_list_delete_link (new_discs, l); |
4848 | + } |
4849 | + |
4850 | + if (d != NULL) |
4851 | + g_object_unref (d); |
4852 | + } |
4853 | + |
4854 | + cur_discs = g_list_sort (cur_discs, (GCompareFunc) gdu_presentable_compare); |
4855 | + new_discs = g_list_sort (new_discs, (GCompareFunc) gdu_presentable_compare); |
4856 | + diff_sorted_lists (cur_discs, new_discs, (GCompareFunc) gdu_presentable_compare, &added, &removed); |
4857 | + |
4858 | + for (l = removed; l != NULL; l = l->next) |
4859 | + { |
4860 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4861 | + GduDevice *d; |
4862 | + |
4863 | + volume = NULL; |
4864 | + mount = NULL; |
4865 | + d = gdu_presentable_get_device (p); |
4866 | + |
4867 | + if (d != NULL) |
4868 | + { |
4869 | + volume = find_disc_volume_for_device_file (monitor, gdu_device_get_device_file (d)); |
4870 | + mount = find_disc_mount_for_volume (monitor, volume); |
4871 | + } |
4872 | + |
4873 | + if (mount != NULL) |
4874 | + { |
4875 | + /*g_debug ("removing disc mount %s", gdu_device_get_device_file (d));*/ |
4876 | + g_gdu_mount_unmounted (mount); |
4877 | + monitor->disc_mounts = g_list_remove (monitor->disc_mounts, mount); |
4878 | + *removed_mounts = g_list_prepend (*removed_mounts, mount); |
4879 | + } |
4880 | + |
4881 | + if (volume != NULL) |
4882 | + { |
4883 | + /*g_debug ("removing disc volume %s", gdu_device_get_device_file (d));*/ |
4884 | + g_gdu_volume_removed (volume); |
4885 | + monitor->disc_volumes = g_list_remove (monitor->disc_volumes, volume); |
4886 | + *removed_volumes = g_list_prepend (*removed_volumes, volume); |
4887 | + } |
4888 | + |
4889 | + if (d != NULL) |
4890 | + g_object_unref (d); |
4891 | + } |
4892 | + |
4893 | + for (l = added; l != NULL; l = l->next) |
4894 | + { |
4895 | + GduPresentable *p = GDU_PRESENTABLE (l->data); |
4896 | + GduDevice *d; |
4897 | + gboolean is_blank; |
4898 | + |
4899 | + volume = NULL; |
4900 | + is_blank = TRUE; |
4901 | + d = gdu_presentable_get_device (p); |
4902 | + |
4903 | + if (d != NULL) |
4904 | + { |
4905 | + is_blank = gdu_device_optical_disc_get_is_blank (d); |
4906 | + volume = find_disc_volume_for_device_file (monitor, gdu_device_get_device_file (d)); |
4907 | + } |
4908 | + |
4909 | + if (volume == NULL) |
4910 | + { |
4911 | + GduPresentable *toplevel_drive; |
4912 | + |
4913 | + toplevel_drive = gdu_presentable_get_enclosing_presentable (p); |
4914 | + /* handle logical partitions enclosed by an extented partition */ |
4915 | + if (GDU_IS_VOLUME (toplevel_drive)) |
4916 | + { |
4917 | + GduPresentable *temp; |
4918 | + temp = toplevel_drive; |
4919 | + toplevel_drive = gdu_presentable_get_enclosing_presentable (toplevel_drive); |
4920 | + g_object_unref (temp); |
4921 | + } |
4922 | + |
4923 | + if (toplevel_drive != NULL) |
4924 | + { |
4925 | + if (GDU_IS_DRIVE (toplevel_drive)) |
4926 | + { |
4927 | + GduDevice *toplevel_drive_device; |
4928 | + |
4929 | + drive = NULL; |
4930 | + toplevel_drive_device = gdu_presentable_get_device (toplevel_drive); |
4931 | + if (toplevel_drive_device != NULL) |
4932 | + { |
4933 | + drive = find_drive_by_device_file (monitor, gdu_device_get_device_file (toplevel_drive_device)); |
4934 | + /*g_debug ("adding volume %s (drive %s)", |
4935 | + gdu_device_get_device_file (d), |
4936 | + gdu_device_get_device_file (toplevel_device));*/ |
4937 | + g_object_unref (toplevel_drive_device); |
4938 | + } |
4939 | + } |
4940 | + g_object_unref (toplevel_drive); |
4941 | + } |
4942 | + else |
4943 | + { |
4944 | + drive = NULL; |
4945 | + /*g_debug ("adding volume %s (no drive)", gdu_device_get_device_file (d));*/ |
4946 | + } |
4947 | + |
4948 | + mount = NULL; |
4949 | + if (is_blank) |
4950 | + { |
4951 | + volume = g_gdu_volume_new (G_VOLUME_MONITOR (monitor), |
4952 | + GDU_VOLUME (p), |
4953 | + drive, |
4954 | + NULL); |
4955 | + mount = g_gdu_mount_new (G_VOLUME_MONITOR (monitor), |
4956 | + NULL, |
4957 | + volume); |
4958 | + } |
4959 | + else |
4960 | + { |
4961 | + gchar *uri; |
4962 | + gchar *device_basename; |
4963 | + GFile *activation_root; |
4964 | + |
4965 | + /* the gvfsd-cdda backend uses URI's like these */ |
4966 | + device_basename = g_path_get_basename (gdu_device_get_device_file (d)); |
4967 | + uri = g_strdup_printf ("cdda://%s", device_basename); |
4968 | + activation_root = g_file_new_for_uri (uri); |
4969 | + g_free (device_basename); |
4970 | + g_free (uri); |
4971 | + |
4972 | + volume = g_gdu_volume_new (G_VOLUME_MONITOR (monitor), |
4973 | + GDU_VOLUME (p), |
4974 | + drive, |
4975 | + activation_root); |
4976 | + |
4977 | + g_object_unref (activation_root); |
4978 | + } |
4979 | + |
4980 | + if (volume != NULL) |
4981 | + { |
4982 | + monitor->disc_volumes = g_list_prepend (monitor->disc_volumes, volume); |
4983 | + *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume)); |
4984 | + |
4985 | + if (mount != NULL) |
4986 | + { |
4987 | + monitor->disc_mounts = g_list_prepend (monitor->disc_mounts, mount); |
4988 | + *added_mounts = g_list_prepend (*added_mounts, g_object_ref (mount)); |
4989 | + } |
4990 | + } |
4991 | + } |
4992 | + |
4993 | + if (d != NULL) |
4994 | + g_object_unref (d); |
4995 | + } |
4996 | + |
4997 | + g_list_free (added); |
4998 | + g_list_free (removed); |
4999 | + |
5000 | + g_list_foreach (new_discs, (GFunc) g_object_unref, NULL); |