Merge lp:~ubuntu-branches/ubuntu/oneiric/gvfs/oneiric-201109270612 into lp:ubuntu/oneiric/gvfs

Proposed by Ubuntu Package Importer
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
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+77098@code.launchpad.net

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://bugs.launchpad.net/udd linking to this merge proposal.

(this is an automatically generated message)

To post a comment you must log in.

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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);
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: