Merge lp:~mdz/ubuntu/lucid/udisks/udisks-cli-eject into lp:ubuntu/lucid/udisks

Proposed by Matt Zimmerman
Status: Rejected
Rejected by: Martin Pitt
Proposed branch: lp:~mdz/ubuntu/lucid/udisks/udisks-cli-eject
Merge into: lp:ubuntu/lucid/udisks
Diff against target: 26452 lines (+18821/-1645)
57 files modified
.pc/.version (+1/-0)
.pc/01-mkfs-tempdir.patch/src/helpers/job-mkfs.c (+509/-0)
.pc/02-defer_smart_probing.patch/src/device.c (+13798/-0)
.pc/02-defer_smart_probing.patch/tests/run (+1482/-0)
.pc/05-german-translations.patch/po/LINGUAS (+3/-0)
.pc/10-ide-cd-support.patch/data/80-udisks.rules (+227/-0)
.pc/10-ide-cd-support.patch/src/poller.c (+353/-0)
.pc/11-remove-unused-probers.patch/data/80-udisks.rules (+243/-0)
.pc/applied-patches (+5/-0)
NEWS (+23/-0)
aclocal.m4 (+43/-24)
config.guess (+87/-55)
config.sub (+9/-21)
configure (+272/-210)
configure.ac (+3/-3)
data/80-udisks.rules (+20/-23)
data/org.freedesktop.UDisks.Adapter.xml (+1/-12)
data/org.freedesktop.UDisks.Device.xml (+108/-119)
data/org.freedesktop.UDisks.Expander.xml (+1/-12)
data/org.freedesktop.UDisks.Port.xml (+1/-12)
data/org.freedesktop.UDisks.xml (+56/-65)
debian/changelog (+33/-6)
debian/control (+4/-11)
debian/patches/02-defer_smart_probing.patch (+8/-8)
debian/patches/08-dont-probe-dm-devices.patch (+74/-85)
debian/patches/10-ide-cd-support.patch (+8/-8)
debian/rules (+0/-5)
debian/source/format (+1/-0)
doc/dbus/org.freedesktop.UDisks.Device.ref.xml (+30/-30)
doc/dbus/org.freedesktop.UDisks.ref.xml (+17/-17)
doc/html/Adapter.html (+16/-20)
doc/html/Device.html (+311/-315)
doc/html/Expander.html (+17/-21)
doc/html/Port.html (+15/-19)
doc/html/UDisks.html (+122/-126)
doc/html/index.html (+4/-8)
doc/html/ix01.html (+235/-239)
doc/html/license.html (+2/-6)
doc/html/ref-dbus.html (+2/-6)
doc/html/style.css (+13/-13)
doc/html/tools-fileformats.html (+2/-6)
doc/html/udisks-daemon.8.html (+7/-11)
doc/html/udisks-tcp-bridge.1.html (+6/-10)
doc/html/udisks.1.html (+7/-11)
doc/html/udisks.7.html (+8/-12)
doc/man/udisks.xml (+16/-0)
doc/version.xml (+1/-1)
ltmain.sh (+20/-13)
po/LINGUAS (+1/-0)
po/de.po (+259/-0)
src/device.c (+26/-7)
src/helpers/job-mkfs.c (+1/-1)
src/poller.c (+202/-22)
src/probers/udisks-lvm-pv-export.c (+10/-20)
tests/run (+60/-31)
tools/udisks-bash-completion.sh (+3/-1)
tools/udisks.c (+35/-0)
To merge this branch: bzr merge lp:~mdz/ubuntu/lucid/udisks/udisks-cli-eject
Reviewer Review Type Date Requested Status
Martin Pitt Disapprove
Review via email: mp+28591@code.launchpad.net

Description of the change

Simple patch to add a --eject option to the udisks CLI utility. As a companion to --mount and --unmount, it's useful for testing and provides a policykit-authenticated alternative to eject(1).

I've proposed this for merging in order to get review, but it should almost certainly be submitted upstream after review, rather than merged.

To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

This looks and works fine to/for me. I committed it upstream:

  http://cgit.freedesktop.org/udisks/commit/?id=dd622d307b6945893ccd04f89ff5534d713a6eec

Indeed I wouldn't like to merge it into the maverick branch directly, but commit most changes to upstream, upload to Debian, and sync to Ubuntu (I'll do that soon again). Therefore I will close this MP now.

Thank you!

review: Disapprove
Revision history for this message
Matt Zimmerman (mdz) wrote :

This doesn't seem to have made it into maverick. Was there a problem with it upstream, or is it just waiting to be merged?

Revision history for this message
Martin Pitt (pitti) wrote :

Ah, sorry. I committed it upstream right away, but we didn't get a new upstream release during the maverick time frame. I'll ask David for an 1.0.2, or cherrypick the patch into our packages.

Revision history for this message
Matt Zimmerman (mdz) wrote :

On Mon, Oct 18, 2010 at 06:48:46AM -0000, Martin Pitt wrote:
> Ah, sorry. I committed it upstream right away, but we didn't get a new
> upstream release during the maverick time frame. I'll ask David for an
> 1.0.2, or cherrypick the patch into our packages.

No worries, I just wanted to make sure it didn't get lost somehow.

--
 - mdz

Unmerged revisions

16. By Matt Zimmerman

Add --eject and --eject-options to udisks(1)

15. By Martin Pitt

* Upgrade to current git HEAD:
  - Update to latest LVM2 API (currently not used in Debian)
  - Fix long hangs on probing nonexistant floppy drives. (LP: #539515)
  - Do not have files executable on NTFS.
  - Some test suite updates.
* Remove debian/patches/00git-*.
* Drop transitional devicekit-disks-doc package. It's been in testing long
  enough, and we do not want to carry it into the squeeze release.
* debian/control: Have udisks Conflicts:/Replaces: devicekit-disks, to
  properly clean up. (Closes: #585169)
* 02-defer_smart_probing.patch, 10-ide-cd-support.patch: Refresh to apply
  cleanly.
* Switch to "3.0 (quilt)" format. Drop quilt build dependency.
* 08-dont-probe-dm-devices.patch: Update for udisks and to current code, but
  still keep it disabled. Proper handling of linear DMs and DMMP devices
  (which are disabled right now, though) still require finding out the
  parent devices through UDISKS_DM_TARGETS_{PARAMS,TYPE} and there is
  currently no equivalent from the dmsetup rules.

14. By Martin Pitt

* Add 00git-vfat-showexec.patch: Enable the "showexec" vfat mount option, to
  avoid data files being executable (which causes confusing question dialogs
  in nautilus which only have one sensible answer). Patch taken from
  upstream git head. (LP: #14335)
* Add 00git-dont-probe-nondata-cdroms.patch: Don't probe non-data CD-ROMs
  for partition tables. Patch taken from upstream git head.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc'
2=== added file '.pc/.version'
3--- .pc/.version 1970-01-01 00:00:00 +0000
4+++ .pc/.version 2010-06-27 14:33:32 +0000
5@@ -0,0 +1,1 @@
6+2
7
8=== added directory '.pc/01-mkfs-tempdir.patch'
9=== added directory '.pc/01-mkfs-tempdir.patch/src'
10=== added directory '.pc/01-mkfs-tempdir.patch/src/helpers'
11=== added file '.pc/01-mkfs-tempdir.patch/src/helpers/job-mkfs.c'
12--- .pc/01-mkfs-tempdir.patch/src/helpers/job-mkfs.c 1970-01-01 00:00:00 +0000
13+++ .pc/01-mkfs-tempdir.patch/src/helpers/job-mkfs.c 2010-06-27 14:33:32 +0000
14@@ -0,0 +1,509 @@
15+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
16+ *
17+ * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
18+ *
19+ * This program is free software; you can redistribute it and/or modify
20+ * it under the terms of the GNU General Public License as published by
21+ * the Free Software Foundation; either version 2 of the License, or
22+ * (at your option) any later version.
23+ *
24+ * This program is distributed in the hope that it will be useful,
25+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27+ * GNU General Public License for more details.
28+ *
29+ * You should have received a copy of the GNU General Public License
30+ * along with this program; if not, write to the Free Software
31+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32+ *
33+ */
34+
35+#ifdef HAVE_CONFIG_H
36+# include "config.h"
37+#endif
38+
39+#define _LARGEFILE64_SOURCE
40+
41+#include <stdlib.h>
42+#include <stdio.h>
43+#include <unistd.h>
44+#include <signal.h>
45+#include <errno.h>
46+#include <string.h>
47+#include <sys/types.h>
48+#include <sys/stat.h>
49+#include <fcntl.h>
50+#include <sys/wait.h>
51+#include <sys/mount.h>
52+
53+#include <glib.h>
54+
55+#include "job-shared.h"
56+
57+int
58+main (int argc,
59+ char **argv)
60+{
61+ int fd;
62+ int ret;
63+ int exit_status;
64+ GError *error;
65+ const char *fstype;
66+ const char *device;
67+ char *command_line;
68+ char *standard_error;
69+ char **options;
70+ GString *s;
71+ char *label;
72+ int n;
73+ gboolean is_kernel_partitioned;
74+ GIOChannel *stdin_channel;
75+ GPtrArray *options_array;
76+ char *option;
77+ gsize option_len;
78+ char *endp;
79+ uid_t take_ownership_uid;
80+ gid_t take_ownership_gid;
81+
82+ ret = 1;
83+ command_line = NULL;
84+ standard_error = NULL;
85+ take_ownership_uid = 0;
86+ take_ownership_gid = 0;
87+ label = NULL;
88+
89+ if (argc != 4)
90+ {
91+ g_printerr ("wrong usage\n");
92+ goto out;
93+ }
94+ fstype = argv[1];
95+ device = argv[2];
96+ is_kernel_partitioned = (strcmp (argv[3], "1") == 0);
97+
98+ options_array = g_ptr_array_new ();
99+ stdin_channel = g_io_channel_unix_new (0);
100+ if (stdin_channel == NULL)
101+ {
102+ g_printerr ("cannot open stdin\n");
103+ goto out;
104+ }
105+ while (g_io_channel_read_line (stdin_channel, &option, &option_len, NULL, NULL) == G_IO_STATUS_NORMAL)
106+ {
107+ option[option_len - 1] = '\0';
108+ if (strlen (option) == 0)
109+ break;
110+ g_ptr_array_add (options_array, option);
111+ }
112+ g_io_channel_unref (stdin_channel);
113+ g_ptr_array_add (options_array, NULL);
114+ options = (char **) g_ptr_array_free (options_array, FALSE);
115+
116+ if (strcmp (fstype, "vfat") == 0)
117+ {
118+
119+ /* allow to create an fs on the main block device */
120+ s = g_string_new ("mkfs.vfat -I");
121+ for (n = 0; options[n] != NULL; n++)
122+ {
123+ if (g_str_has_prefix (options[n], "label="))
124+ {
125+ label = strdup (options[n] + sizeof("label=") - 1);
126+ if (!validate_and_escape_label (&label, 254))
127+ {
128+ g_string_free (s, TRUE);
129+ goto out;
130+ }
131+ if (strlen (label) <= 11)
132+ {
133+ g_string_append_printf (s, " -n \"%s\"", label);
134+ g_free (label);
135+ label = NULL;
136+ }
137+ }
138+ else
139+ {
140+ g_printerr ("option %s not supported\n", options[n]);
141+ goto out;
142+ }
143+ }
144+ g_string_append_printf (s, " %s", device);
145+ command_line = g_string_free (s, FALSE);
146+
147+ }
148+ else if (strcmp (fstype, "ext2") == 0 || strcmp (fstype, "ext3") == 0 || strcmp (fstype, "ext4") == 0)
149+ {
150+
151+ s = g_string_new ("mkfs.");
152+ g_string_append (s, fstype);
153+ for (n = 0; options[n] != NULL; n++)
154+ {
155+ g_string_append (s, " -F ");
156+ if (g_str_has_prefix (options[n], "label="))
157+ {
158+ label = strdup (options[n] + sizeof("label=") - 1);
159+ if (!validate_and_escape_label (&label, 16))
160+ {
161+ g_string_free (s, TRUE);
162+ goto out;
163+ }
164+ g_string_append_printf (s, " -L \"%s\"", label);
165+ g_free (label);
166+ label = NULL;
167+ }
168+ else if (g_str_has_prefix (options[n], "take_ownership_uid="))
169+ {
170+ take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
171+ if (endp == NULL || *endp != '\0')
172+ {
173+ g_printerr ("option %s is malformed\n", options[n]);
174+ goto out;
175+ }
176+ }
177+ else if (g_str_has_prefix (options[n], "take_ownership_gid="))
178+ {
179+ take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
180+ if (endp == NULL || *endp != '\0')
181+ {
182+ g_printerr ("option %s is malformed\n", options[n]);
183+ goto out;
184+ }
185+ }
186+ else
187+ {
188+ g_printerr ("option %s not supported\n", options[n]);
189+ goto out;
190+ }
191+ }
192+ g_string_append_printf (s, " %s", device);
193+ command_line = g_string_free (s, FALSE);
194+
195+ }
196+ else if (strcmp (fstype, "xfs") == 0)
197+ {
198+
199+ s = g_string_new ("mkfs.xfs");
200+ for (n = 0; options[n] != NULL; n++)
201+ {
202+ if (g_str_has_prefix (options[n], "label="))
203+ {
204+ label = strdup (options[n] + sizeof("label=") - 1);
205+ if (!validate_and_escape_label (&label, 12))
206+ {
207+ g_string_free (s, TRUE);
208+ goto out;
209+ }
210+ g_string_append_printf (s, " -L \"%s\"", label);
211+ g_free (label);
212+ label = NULL;
213+ }
214+ else if (g_str_has_prefix (options[n], "take_ownership_uid="))
215+ {
216+ take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
217+ if (endp == NULL || *endp != '\0')
218+ {
219+ g_printerr ("option %s is malformed\n", options[n]);
220+ goto out;
221+ }
222+ }
223+ else if (g_str_has_prefix (options[n], "take_ownership_gid="))
224+ {
225+ take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
226+ if (endp == NULL || *endp != '\0')
227+ {
228+ g_printerr ("option %s is malformed\n", options[n]);
229+ goto out;
230+ }
231+ }
232+ else
233+ {
234+ g_printerr ("option %s not supported\n", options[n]);
235+ goto out;
236+ }
237+ }
238+ g_string_append_printf (s, " %s", device);
239+ command_line = g_string_free (s, FALSE);
240+
241+ }
242+ else if (strcmp (fstype, "ntfs") == 0)
243+ {
244+
245+ /* skip zeroing (we do that ourselves) and bad sector checking (will
246+ * eventually be handled on a higher level)
247+ */
248+ s = g_string_new ("mkntfs -f");
249+ for (n = 0; options[n] != NULL; n++)
250+ {
251+ if (g_str_has_prefix (options[n], "label="))
252+ {
253+ label = strdup (options[n] + sizeof("label=") - 1);
254+ if (!validate_and_escape_label (&label, 255))
255+ {
256+ g_string_free (s, TRUE);
257+ goto out;
258+ }
259+ g_string_append_printf (s, " -L \"%s\"", label);
260+ g_free (label);
261+ label = NULL;
262+ }
263+ else
264+ {
265+ g_printerr ("option %s not supported\n", options[n]);
266+ goto out;
267+ }
268+ }
269+ g_string_append_printf (s, " %s", device);
270+ command_line = g_string_free (s, FALSE);
271+
272+ }
273+ else if (strcmp (fstype, "reiserfs") == 0)
274+ {
275+
276+ s = g_string_new ("mkfs.reiserfs -q");
277+ for (n = 0; options[n] != NULL; n++)
278+ {
279+ if (g_str_has_prefix (options[n], "label="))
280+ {
281+ label = strdup (options[n] + sizeof("label=") - 1);
282+ if (!validate_and_escape_label (&label, 16))
283+ {
284+ g_string_free (s, TRUE);
285+ goto out;
286+ }
287+ g_string_append_printf (s, " -l \"%s\"", label);
288+ g_free (label);
289+ label = NULL;
290+ }
291+ else if (g_str_has_prefix (options[n], "take_ownership_uid="))
292+ {
293+ take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
294+ if (endp == NULL || *endp != '\0')
295+ {
296+ g_printerr ("option %s is malformed\n", options[n]);
297+ goto out;
298+ }
299+ }
300+ else if (g_str_has_prefix (options[n], "take_ownership_gid="))
301+ {
302+ take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
303+ if (endp == NULL || *endp != '\0')
304+ {
305+ g_printerr ("option %s is malformed\n", options[n]);
306+ goto out;
307+ }
308+ }
309+ else
310+ {
311+ g_printerr ("option %s not supported\n", options[n]);
312+ goto out;
313+ }
314+ }
315+ g_string_append_printf (s, " %s", device);
316+ command_line = g_string_free (s, FALSE);
317+
318+ }
319+ else if (strcmp (fstype, "minix") == 0)
320+ {
321+
322+ s = g_string_new ("mkfs.minix");
323+ /* minix does not support labels */
324+ for (n = 0; options[n] != NULL; n++)
325+ {
326+ if (g_str_has_prefix (options[n], "take_ownership_uid="))
327+ {
328+ take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
329+ if (endp == NULL || *endp != '\0')
330+ {
331+ g_printerr ("option %s is malformed\n", options[n]);
332+ goto out;
333+ }
334+ }
335+ else if (g_str_has_prefix (options[n], "take_ownership_gid="))
336+ {
337+ take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
338+ if (endp == NULL || *endp != '\0')
339+ {
340+ g_printerr ("option %s is malformed\n", options[n]);
341+ goto out;
342+ }
343+ }
344+ else
345+ {
346+ g_printerr ("option %s not supported\n", options[n]);
347+ goto out;
348+ }
349+ }
350+ g_string_append_printf (s, " %s", device);
351+ command_line = g_string_free (s, FALSE);
352+
353+ }
354+ else if (strcmp (fstype, "swap") == 0)
355+ {
356+
357+ s = g_string_new ("mkswap");
358+ for (n = 0; options[n] != NULL; n++)
359+ {
360+ if (g_str_has_prefix (options[n], "label="))
361+ {
362+ label = strdup (options[n] + sizeof("label=") - 1);
363+ if (!validate_and_escape_label (&label, 15))
364+ {
365+ g_string_free (s, TRUE);
366+ goto out;
367+ }
368+ g_string_append_printf (s, " -L \"%s\"", label);
369+ g_free (label);
370+ label = NULL;
371+ }
372+ else
373+ {
374+ g_printerr ("option %s not supported\n", options[n]);
375+ goto out;
376+ }
377+ }
378+ g_string_append_printf (s, " %s", device);
379+ command_line = g_string_free (s, FALSE);
380+
381+ }
382+ else if (strcmp (fstype, "empty") == 0)
383+ {
384+ command_line = NULL;
385+ for (n = 0; options[n] != NULL; n++)
386+ {
387+ g_printerr ("option %s not supported\n", options[n]);
388+ goto out;
389+ }
390+ }
391+ else
392+ {
393+ g_printerr ("fstype %s not supported\n", fstype);
394+ goto out;
395+ }
396+
397+ /* scrub signatures */
398+ if (!scrub_signatures (device, 0, 0))
399+ goto out;
400+
401+ if (command_line != NULL)
402+ {
403+ error = NULL;
404+ if (!g_spawn_command_line_sync (command_line, NULL, &standard_error, &exit_status, &error))
405+ {
406+ g_printerr ("cannot spawn '%s': %s\n", command_line, error->message);
407+ ret = 3; /* indicate FilesystemToolsMissing error */
408+ g_error_free (error);
409+ goto out;
410+ }
411+ if (WEXITSTATUS (exit_status) != 0)
412+ {
413+ g_printerr ("helper failed with:\n%s", standard_error);
414+ goto out;
415+ }
416+ }
417+
418+ if (label != NULL)
419+ {
420+ g_free (command_line);
421+
422+ if (strcmp (fstype, "vfat") == 0)
423+ {
424+ command_line = g_strdup_printf ("mlabel -i %s \"::%s\"", device, label);
425+ }
426+ else
427+ {
428+ g_printerr ("label change for fstype '%s' requested but not implemented", fstype);
429+ goto out;
430+ }
431+
432+ error = NULL;
433+ if (!g_spawn_command_line_sync (command_line, NULL, &standard_error, &exit_status, &error))
434+ {
435+ g_printerr ("cannot spawn '%s': %s\n", command_line, error->message);
436+ g_error_free (error);
437+ ret = 3; /* indicate FilesystemToolsMissing error */
438+ goto out;
439+ }
440+ if (WEXITSTATUS (exit_status) != 0)
441+ {
442+ g_printerr ("helper failed with:\n%s", standard_error);
443+ goto out;
444+ }
445+
446+ g_free (label);
447+ }
448+
449+ /* If we've created an fs on a partitioned device, then signal the
450+ * kernel to reread the (now missing) partition table.
451+ */
452+ if (is_kernel_partitioned)
453+ {
454+ fd = open (device, O_RDONLY);
455+ if (fd < 0)
456+ {
457+ g_printerr ("cannot open %s (for BLKRRPART): %m\n", device);
458+ goto out;
459+ }
460+ if (ioctl (fd, BLKRRPART) != 0)
461+ {
462+ close (fd);
463+ g_printerr ("BLKRRPART ioctl failed for %s: %m\n", device);
464+ goto out;
465+ }
466+ close (fd);
467+ }
468+
469+ /* take ownership of the device if requested */
470+ if (take_ownership_uid != 0 || take_ownership_gid != 0)
471+ {
472+ char dir[256] = PACKAGE_LOCALSTATE_DIR "/run/udisks/job-mkfs-XXXXXX";
473+
474+ if (mkdtemp (dir) == NULL)
475+ {
476+ g_printerr ("cannot create directory %s: %m\n", dir);
477+ goto out;
478+ }
479+
480+ if (mount (device, dir, fstype, 0, NULL) != 0)
481+ {
482+ g_printerr ("cannot mount %s at %s: %m\n", device, dir);
483+ ret = 2;
484+ goto tos_err0;
485+ }
486+
487+ if (chown (dir, take_ownership_uid, take_ownership_gid) != 0)
488+ {
489+ g_printerr ("cannot chown %s to uid=%d and gid=%d: %m\n", dir, take_ownership_uid, take_ownership_gid);
490+ ret = 2;
491+ }
492+
493+ if (chmod (dir, 0700) != 0)
494+ {
495+ g_printerr ("cannot chmod %s to mode 0700: %m\n", dir);
496+ ret = 2;
497+ }
498+
499+ if (umount (dir) != 0)
500+ {
501+ g_printerr ("cannot unmount %s: %m\n", dir);
502+ ret = 2;
503+ goto tos_err0;
504+ }
505+
506+ tos_err0:
507+ if (rmdir (dir) != 0)
508+ {
509+ g_printerr ("cannot remove directory %s: %m\n", dir);
510+ goto out;
511+ }
512+ }
513+
514+ if (ret == 2)
515+ ret = 1;
516+ else
517+ ret = 0;
518+
519+ out:
520+ g_free (standard_error);
521+ g_free (command_line);
522+ return ret;
523+}
524
525=== added directory '.pc/02-defer_smart_probing.patch'
526=== added directory '.pc/02-defer_smart_probing.patch/src'
527=== added file '.pc/02-defer_smart_probing.patch/src/device.c'
528--- .pc/02-defer_smart_probing.patch/src/device.c 1970-01-01 00:00:00 +0000
529+++ .pc/02-defer_smart_probing.patch/src/device.c 2010-06-27 14:33:32 +0000
530@@ -0,0 +1,13798 @@
531+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
532+ *
533+ * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
534+ *
535+ * This program is free software; you can redistribute it and/or modify
536+ * it under the terms of the GNU General Public License as published by
537+ * the Free Software Foundation; either version 2 of the License, or
538+ * (at your option) any later version.
539+ *
540+ * This program is distributed in the hope that it will be useful,
541+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
542+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
543+ * GNU General Public License for more details.
544+ *
545+ * You should have received a copy of the GNU General Public License
546+ * along with this program; if not, write to the Free Software
547+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
548+ *
549+ */
550+
551+#ifdef HAVE_CONFIG_H
552+# include "config.h"
553+#endif
554+
555+#include <stdlib.h>
556+#include <stdio.h>
557+#include <unistd.h>
558+#include <signal.h>
559+#include <errno.h>
560+#include <string.h>
561+#include <sys/types.h>
562+#include <sys/wait.h>
563+#include <sys/stat.h>
564+#include <sys/time.h>
565+#include <sys/resource.h>
566+#include <fcntl.h>
567+#include <pwd.h>
568+#include <grp.h>
569+#include <linux/fs.h>
570+#include <sys/ioctl.h>
571+#include <linux/cdrom.h>
572+#include <linux/loop.h>
573+
574+#include <glib.h>
575+#include <glib/gstdio.h>
576+#include <glib/gi18n-lib.h>
577+#include <glib-object.h>
578+#include <gio/gunixmounts.h>
579+#include <dbus/dbus-glib.h>
580+#include <dbus/dbus-glib-lowlevel.h>
581+#include <gudev/gudev.h>
582+#include <atasmart.h>
583+
584+#include "daemon.h"
585+#include "device.h"
586+#include "device-private.h"
587+#include "marshal.h"
588+#include "mount.h"
589+#include "mount-monitor.h"
590+#include "mount-file.h"
591+#include "inhibitor.h"
592+#include "poller.h"
593+#include "adapter.h"
594+#include "port.h"
595+
596+#include "profile.h"
597+
598+/*--------------------------------------------------------------------------------------------------------------*/
599+#include "device-glue.h"
600+
601+static void device_class_init (DeviceClass *klass);
602+static void device_init (Device *seat);
603+static void device_finalize (GObject *object);
604+
605+static void polling_inhibitor_disconnected_cb (Inhibitor *inhibitor,
606+ Device *device);
607+
608+static void spindown_inhibitor_disconnected_cb (Inhibitor *inhibitor,
609+ Device *device);
610+
611+static gboolean update_info (Device *device);
612+static void update_info_in_idle (Device *device);
613+
614+static void drain_pending_changes (Device *device,
615+ gboolean force_update);
616+
617+static gboolean device_local_is_busy (Device *device,
618+ gboolean check_partitions,
619+ GError **error);
620+
621+static gboolean device_local_partitions_are_busy (Device *device);
622+static gboolean device_local_logical_partitions_are_busy (Device *device);
623+static gboolean device_has_logical_partitions (Device *device);
624+
625+static gboolean luks_get_uid_from_dm_name (const char *dm_name,
626+ uid_t *out_uid);
627+
628+/* Returns the cleartext device. If device==NULL, unlocking failed and an error has
629+ * been reported back to the caller
630+ */
631+typedef void (*UnlockEncryptionHookFunc) (DBusGMethodInvocation *context,
632+ Device *device,
633+ gpointer user_data);
634+
635+static gboolean device_luks_unlock_internal (Device *device,
636+ const char *secret,
637+ char **options,
638+ UnlockEncryptionHookFunc hook_func,
639+ gpointer hook_user_data,
640+ DBusGMethodInvocation *context);
641+
642+/* if filesystem_create_succeeded==FALSE, mkfs failed and an error has been reported back to the caller */
643+typedef void (*FilesystemCreateHookFunc) (DBusGMethodInvocation *context,
644+ Device *device,
645+ gboolean filesystem_create_succeeded,
646+ gpointer user_data);
647+
648+static gboolean device_filesystem_create_internal (Device *device,
649+ const char *fstype,
650+ char **options,
651+ FilesystemCreateHookFunc hook_func,
652+ gpointer hook_user_data,
653+ DBusGMethodInvocation *context);
654+
655+typedef void (*ForceRemovalCompleteFunc) (Device *device,
656+ gboolean success,
657+ gpointer user_data);
658+
659+static void force_removal (Device *device,
660+ ForceRemovalCompleteFunc callback,
661+ gpointer user_data);
662+
663+static void force_unmount (Device *device,
664+ ForceRemovalCompleteFunc callback,
665+ gpointer user_data);
666+
667+static void force_luks_teardown (Device *device,
668+ Device *cleartext_device,
669+ ForceRemovalCompleteFunc callback,
670+ gpointer user_data);
671+
672+static gboolean
673+ptr_array_has_string (GPtrArray *p, const gchar *str)
674+{
675+ guint n;
676+ gboolean ret;
677+
678+ ret = FALSE;
679+ for (n = 0; n < p->len; n++)
680+ {
681+ if (g_strcmp0 (p->pdata[n], str) == 0)
682+ {
683+ ret = TRUE;
684+ goto out;
685+ }
686+ }
687+
688+ out:
689+ return ret;
690+}
691+
692+/* TODO: this is kinda a hack */
693+static const gchar *
694+get_dmmp_device_node (Device *device)
695+{
696+ static gchar buf[1024];
697+
698+ g_assert (device->priv->device_is_linux_dmmp);
699+ g_snprintf (buf, sizeof (buf), "/dev/mapper/%s", device->priv->linux_dmmp_name);
700+ return buf;
701+}
702+
703+enum
704+ {
705+ PROP_0,
706+ PROP_NATIVE_PATH,
707+
708+ PROP_DEVICE_DETECTION_TIME,
709+ PROP_DEVICE_MEDIA_DETECTION_TIME,
710+ PROP_DEVICE_MAJOR,
711+ PROP_DEVICE_MINOR,
712+ PROP_DEVICE_FILE,
713+ PROP_DEVICE_FILE_PRESENTATION,
714+ PROP_DEVICE_FILE_BY_ID,
715+ PROP_DEVICE_FILE_BY_PATH,
716+ PROP_DEVICE_IS_SYSTEM_INTERNAL,
717+ PROP_DEVICE_IS_PARTITION,
718+ PROP_DEVICE_IS_PARTITION_TABLE,
719+ PROP_DEVICE_IS_REMOVABLE,
720+ PROP_DEVICE_IS_MEDIA_AVAILABLE,
721+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTED,
722+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_POLLING,
723+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITABLE,
724+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITED,
725+ PROP_DEVICE_IS_READ_ONLY,
726+ PROP_DEVICE_IS_DRIVE,
727+ PROP_DEVICE_IS_OPTICAL_DISC,
728+ PROP_DEVICE_IS_LUKS,
729+ PROP_DEVICE_IS_LUKS_CLEARTEXT,
730+ PROP_DEVICE_IS_LINUX_MD_COMPONENT,
731+ PROP_DEVICE_IS_LINUX_MD,
732+ PROP_DEVICE_IS_LINUX_LVM2_LV,
733+ PROP_DEVICE_IS_LINUX_LVM2_PV,
734+ PROP_DEVICE_IS_LINUX_DMMP,
735+ PROP_DEVICE_IS_LINUX_DMMP_COMPONENT,
736+ PROP_DEVICE_IS_LINUX_LOOP,
737+ PROP_DEVICE_SIZE,
738+ PROP_DEVICE_BLOCK_SIZE,
739+ PROP_DEVICE_IS_MOUNTED,
740+ PROP_DEVICE_MOUNT_PATHS,
741+ PROP_DEVICE_MOUNTED_BY_UID,
742+ PROP_DEVICE_PRESENTATION_HIDE,
743+ PROP_DEVICE_PRESENTATION_NOPOLICY,
744+ PROP_DEVICE_PRESENTATION_NAME,
745+ PROP_DEVICE_PRESENTATION_ICON_NAME,
746+
747+ PROP_JOB_IN_PROGRESS,
748+ PROP_JOB_ID,
749+ PROP_JOB_INITIATED_BY_UID,
750+ PROP_JOB_IS_CANCELLABLE,
751+ PROP_JOB_PERCENTAGE,
752+
753+ PROP_ID_USAGE,
754+ PROP_ID_TYPE,
755+ PROP_ID_VERSION,
756+ PROP_ID_UUID,
757+ PROP_ID_LABEL,
758+
759+ PROP_PARTITION_SLAVE,
760+ PROP_PARTITION_SCHEME,
761+ PROP_PARTITION_TYPE,
762+ PROP_PARTITION_LABEL,
763+ PROP_PARTITION_UUID,
764+ PROP_PARTITION_FLAGS,
765+ PROP_PARTITION_NUMBER,
766+ PROP_PARTITION_OFFSET,
767+ PROP_PARTITION_SIZE,
768+ PROP_PARTITION_ALIGNMENT_OFFSET,
769+
770+ PROP_PARTITION_TABLE_SCHEME,
771+ PROP_PARTITION_TABLE_COUNT,
772+
773+ PROP_LUKS_HOLDER,
774+
775+ PROP_LUKS_CLEARTEXT_SLAVE,
776+ PROP_LUKS_CLEARTEXT_UNLOCKED_BY_UID,
777+
778+ PROP_DRIVE_VENDOR,
779+ PROP_DRIVE_MODEL,
780+ PROP_DRIVE_REVISION,
781+ PROP_DRIVE_SERIAL,
782+ PROP_DRIVE_WWN,
783+ PROP_DRIVE_CONNECTION_INTERFACE,
784+ PROP_DRIVE_CONNECTION_SPEED,
785+ PROP_DRIVE_MEDIA_COMPATIBILITY,
786+ PROP_DRIVE_MEDIA,
787+ PROP_DRIVE_IS_MEDIA_EJECTABLE,
788+ PROP_DRIVE_CAN_DETACH,
789+ PROP_DRIVE_CAN_SPINDOWN,
790+ PROP_DRIVE_IS_ROTATIONAL,
791+ PROP_DRIVE_ROTATION_RATE,
792+ PROP_DRIVE_WRITE_CACHE,
793+ PROP_DRIVE_ADAPTER,
794+ PROP_DRIVE_PORTS,
795+ PROP_DRIVE_SIMILAR_DEVICES,
796+
797+ PROP_OPTICAL_DISC_IS_BLANK,
798+ PROP_OPTICAL_DISC_IS_APPENDABLE,
799+ PROP_OPTICAL_DISC_IS_CLOSED,
800+ PROP_OPTICAL_DISC_NUM_TRACKS,
801+ PROP_OPTICAL_DISC_NUM_AUDIO_TRACKS,
802+ PROP_OPTICAL_DISC_NUM_SESSIONS,
803+
804+ PROP_DRIVE_ATA_SMART_IS_AVAILABLE,
805+ PROP_DRIVE_ATA_SMART_TIME_COLLECTED,
806+ PROP_DRIVE_ATA_SMART_STATUS,
807+ PROP_DRIVE_ATA_SMART_BLOB,
808+
809+ PROP_LINUX_MD_COMPONENT_LEVEL,
810+ PROP_LINUX_MD_COMPONENT_POSITION,
811+ PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES,
812+ PROP_LINUX_MD_COMPONENT_UUID,
813+ PROP_LINUX_MD_COMPONENT_HOME_HOST,
814+ PROP_LINUX_MD_COMPONENT_NAME,
815+ PROP_LINUX_MD_COMPONENT_VERSION,
816+ PROP_LINUX_MD_COMPONENT_HOLDER,
817+ PROP_LINUX_MD_COMPONENT_STATE,
818+
819+ PROP_LINUX_MD_STATE,
820+ PROP_LINUX_MD_LEVEL,
821+ PROP_LINUX_MD_NUM_RAID_DEVICES,
822+ PROP_LINUX_MD_UUID,
823+ PROP_LINUX_MD_HOME_HOST,
824+ PROP_LINUX_MD_NAME,
825+ PROP_LINUX_MD_VERSION,
826+ PROP_LINUX_MD_SLAVES,
827+ PROP_LINUX_MD_IS_DEGRADED,
828+ PROP_LINUX_MD_SYNC_ACTION,
829+ PROP_LINUX_MD_SYNC_PERCENTAGE,
830+ PROP_LINUX_MD_SYNC_SPEED,
831+
832+ PROP_LINUX_LVM2_LV_NAME,
833+ PROP_LINUX_LVM2_LV_UUID,
834+ PROP_LINUX_LVM2_LV_GROUP_NAME,
835+ PROP_LINUX_LVM2_LV_GROUP_UUID,
836+
837+ PROP_LINUX_LVM2_PV_UUID,
838+ PROP_LINUX_LVM2_PV_NUM_METADATA_AREAS,
839+ PROP_LINUX_LVM2_PV_GROUP_NAME,
840+ PROP_LINUX_LVM2_PV_GROUP_UUID,
841+ PROP_LINUX_LVM2_PV_GROUP_SIZE,
842+ PROP_LINUX_LVM2_PV_GROUP_UNALLOCATED_SIZE,
843+ PROP_LINUX_LVM2_PV_GROUP_SEQUENCE_NUMBER,
844+ PROP_LINUX_LVM2_PV_GROUP_EXTENT_SIZE,
845+ PROP_LINUX_LVM2_PV_GROUP_PHYSICAL_VOLUMES,
846+ PROP_LINUX_LVM2_PV_GROUP_LOGICAL_VOLUMES,
847+
848+ PROP_LINUX_DMMP_COMPONENT_HOLDER,
849+
850+ PROP_LINUX_DMMP_NAME,
851+ PROP_LINUX_DMMP_SLAVES,
852+ PROP_LINUX_DMMP_PARAMETERS,
853+
854+ PROP_LINUX_LOOP_FILENAME,
855+ };
856+
857+enum
858+ {
859+ CHANGED_SIGNAL,
860+ JOB_CHANGED_SIGNAL,
861+ LAST_SIGNAL,
862+ };
863+
864+static guint signals[LAST_SIGNAL] = { 0 };
865+
866+G_DEFINE_TYPE (Device, device, G_TYPE_OBJECT)
867+
868+#define DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DEVICE, DevicePrivate))
869+
870+static GObject *
871+device_constructor (GType type,
872+ guint n_construct_properties,
873+ GObjectConstructParam *construct_properties)
874+{
875+ Device *device;
876+ DeviceClass *klass;
877+
878+ klass = DEVICE_CLASS (g_type_class_peek (TYPE_DEVICE));
879+
880+ device = DEVICE (G_OBJECT_CLASS (device_parent_class)->constructor (type,
881+ n_construct_properties,
882+ construct_properties));
883+ return G_OBJECT (device);
884+}
885+
886+static void
887+get_property (GObject *object,
888+ guint prop_id,
889+ GValue *value,
890+ GParamSpec *pspec)
891+{
892+ Device *device = DEVICE (object);
893+
894+ switch (prop_id)
895+ {
896+ case PROP_NATIVE_PATH:
897+ g_value_set_string (value, device->priv->native_path);
898+ break;
899+
900+ case PROP_DEVICE_DETECTION_TIME:
901+ g_value_set_uint64 (value, device->priv->device_detection_time);
902+ break;
903+ case PROP_DEVICE_MEDIA_DETECTION_TIME:
904+ g_value_set_uint64 (value, device->priv->device_media_detection_time);
905+ break;
906+ case PROP_DEVICE_MAJOR:
907+ g_value_set_int64 (value, major (device->priv->dev));
908+ break;
909+ case PROP_DEVICE_MINOR:
910+ g_value_set_int64 (value, minor (device->priv->dev));
911+ break;
912+ case PROP_DEVICE_FILE:
913+ g_value_set_string (value, device->priv->device_file);
914+ break;
915+ case PROP_DEVICE_FILE_PRESENTATION:
916+ if (device->priv->device_file_presentation != NULL)
917+ g_value_set_string (value, device->priv->device_file_presentation);
918+ else
919+ g_value_set_string (value, device->priv->device_file);
920+ break;
921+ case PROP_DEVICE_FILE_BY_ID:
922+ g_value_set_boxed (value, device->priv->device_file_by_id);
923+ break;
924+ case PROP_DEVICE_FILE_BY_PATH:
925+ g_value_set_boxed (value, device->priv->device_file_by_path);
926+ break;
927+ case PROP_DEVICE_IS_SYSTEM_INTERNAL:
928+ g_value_set_boolean (value, device->priv->device_is_system_internal);
929+ break;
930+ case PROP_DEVICE_IS_PARTITION:
931+ g_value_set_boolean (value, device->priv->device_is_partition);
932+ break;
933+ case PROP_DEVICE_IS_PARTITION_TABLE:
934+ g_value_set_boolean (value, device->priv->device_is_partition_table);
935+ break;
936+ case PROP_DEVICE_IS_REMOVABLE:
937+ g_value_set_boolean (value, device->priv->device_is_removable);
938+ break;
939+ case PROP_DEVICE_IS_MEDIA_AVAILABLE:
940+ g_value_set_boolean (value, device->priv->device_is_media_available);
941+ break;
942+ case PROP_DEVICE_IS_MEDIA_CHANGE_DETECTED:
943+ g_value_set_boolean (value, device->priv->device_is_media_change_detected);
944+ break;
945+ case PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_POLLING:
946+ g_value_set_boolean (value, device->priv->device_is_media_change_detection_polling);
947+ break;
948+ case PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITABLE:
949+ g_value_set_boolean (value, device->priv->device_is_media_change_detection_inhibitable);
950+ break;
951+ case PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITED:
952+ g_value_set_boolean (value, device->priv->device_is_media_change_detection_inhibited);
953+ break;
954+ case PROP_DEVICE_IS_READ_ONLY:
955+ g_value_set_boolean (value, device->priv->device_is_read_only);
956+ break;
957+ case PROP_DEVICE_IS_DRIVE:
958+ g_value_set_boolean (value, device->priv->device_is_drive);
959+ break;
960+ case PROP_DEVICE_IS_OPTICAL_DISC:
961+ g_value_set_boolean (value, device->priv->device_is_optical_disc);
962+ break;
963+ case PROP_DEVICE_IS_LUKS:
964+ g_value_set_boolean (value, device->priv->device_is_luks);
965+ break;
966+ case PROP_DEVICE_IS_LUKS_CLEARTEXT:
967+ g_value_set_boolean (value, device->priv->device_is_luks_cleartext);
968+ break;
969+ case PROP_DEVICE_IS_LINUX_MD_COMPONENT:
970+ g_value_set_boolean (value, device->priv->device_is_linux_md_component);
971+ break;
972+ case PROP_DEVICE_IS_LINUX_MD:
973+ g_value_set_boolean (value, device->priv->device_is_linux_md);
974+ break;
975+ case PROP_DEVICE_IS_LINUX_LVM2_LV:
976+ g_value_set_boolean (value, device->priv->device_is_linux_lvm2_lv);
977+ break;
978+ case PROP_DEVICE_IS_LINUX_LVM2_PV:
979+ g_value_set_boolean (value, device->priv->device_is_linux_lvm2_pv);
980+ break;
981+ case PROP_DEVICE_IS_LINUX_DMMP:
982+ g_value_set_boolean (value, device->priv->device_is_linux_dmmp);
983+ break;
984+ case PROP_DEVICE_IS_LINUX_DMMP_COMPONENT:
985+ g_value_set_boolean (value, device->priv->device_is_linux_dmmp_component);
986+ break;
987+ case PROP_DEVICE_IS_LINUX_LOOP:
988+ g_value_set_boolean (value, device->priv->device_is_linux_loop);
989+ break;
990+ case PROP_DEVICE_SIZE:
991+ g_value_set_uint64 (value, device->priv->device_size);
992+ break;
993+ case PROP_DEVICE_BLOCK_SIZE:
994+ g_value_set_uint64 (value, device->priv->device_block_size);
995+ break;
996+ case PROP_DEVICE_IS_MOUNTED:
997+ g_value_set_boolean (value, device->priv->device_is_mounted);
998+ break;
999+ case PROP_DEVICE_MOUNT_PATHS:
1000+ g_value_set_boxed (value, device->priv->device_mount_paths);
1001+ break;
1002+ case PROP_DEVICE_MOUNTED_BY_UID:
1003+ g_value_set_uint (value, device->priv->device_mounted_by_uid);
1004+ break;
1005+ case PROP_DEVICE_PRESENTATION_HIDE:
1006+ g_value_set_boolean (value, device->priv->device_presentation_hide);
1007+ break;
1008+ case PROP_DEVICE_PRESENTATION_NOPOLICY:
1009+ g_value_set_boolean (value, device->priv->device_presentation_nopolicy);
1010+ break;
1011+ case PROP_DEVICE_PRESENTATION_NAME:
1012+ g_value_set_string (value, device->priv->device_presentation_name);
1013+ break;
1014+ case PROP_DEVICE_PRESENTATION_ICON_NAME:
1015+ g_value_set_string (value, device->priv->device_presentation_icon_name);
1016+ break;
1017+
1018+ case PROP_JOB_IN_PROGRESS:
1019+ g_value_set_boolean (value, device->priv->job_in_progress);
1020+ break;
1021+ case PROP_JOB_ID:
1022+ g_value_set_string (value, device->priv->job_id);
1023+ break;
1024+ case PROP_JOB_INITIATED_BY_UID:
1025+ g_value_set_uint (value, device->priv->job_initiated_by_uid);
1026+ break;
1027+ case PROP_JOB_IS_CANCELLABLE:
1028+ g_value_set_boolean (value, device->priv->job_is_cancellable);
1029+ break;
1030+ case PROP_JOB_PERCENTAGE:
1031+ g_value_set_double (value, device->priv->job_percentage);
1032+ break;
1033+
1034+ case PROP_ID_USAGE:
1035+ g_value_set_string (value, device->priv->id_usage);
1036+ break;
1037+ case PROP_ID_TYPE:
1038+ g_value_set_string (value, device->priv->id_type);
1039+ break;
1040+ case PROP_ID_VERSION:
1041+ g_value_set_string (value, device->priv->id_version);
1042+ break;
1043+ case PROP_ID_UUID:
1044+ g_value_set_string (value, device->priv->id_uuid);
1045+ break;
1046+ case PROP_ID_LABEL:
1047+ g_value_set_string (value, device->priv->id_label);
1048+ break;
1049+
1050+ case PROP_PARTITION_SLAVE:
1051+ if (device->priv->partition_slave != NULL)
1052+ g_value_set_boxed (value, device->priv->partition_slave);
1053+ else
1054+ g_value_set_boxed (value, "/");
1055+ break;
1056+ case PROP_PARTITION_SCHEME:
1057+ g_value_set_string (value, device->priv->partition_scheme);
1058+ break;
1059+ case PROP_PARTITION_TYPE:
1060+ g_value_set_string (value, device->priv->partition_type);
1061+ break;
1062+ case PROP_PARTITION_LABEL:
1063+ g_value_set_string (value, device->priv->partition_label);
1064+ break;
1065+ case PROP_PARTITION_UUID:
1066+ g_value_set_string (value, device->priv->partition_uuid);
1067+ break;
1068+ case PROP_PARTITION_FLAGS:
1069+ g_value_set_boxed (value, device->priv->partition_flags);
1070+ break;
1071+ case PROP_PARTITION_NUMBER:
1072+ g_value_set_int (value, device->priv->partition_number);
1073+ break;
1074+ case PROP_PARTITION_OFFSET:
1075+ g_value_set_uint64 (value, device->priv->partition_offset);
1076+ break;
1077+ case PROP_PARTITION_SIZE:
1078+ g_value_set_uint64 (value, device->priv->partition_size);
1079+ break;
1080+ case PROP_PARTITION_ALIGNMENT_OFFSET:
1081+ g_value_set_uint64 (value, device->priv->partition_alignment_offset);
1082+ break;
1083+
1084+ case PROP_PARTITION_TABLE_SCHEME:
1085+ g_value_set_string (value, device->priv->partition_table_scheme);
1086+ break;
1087+ case PROP_PARTITION_TABLE_COUNT:
1088+ g_value_set_int (value, device->priv->partition_table_count);
1089+ break;
1090+
1091+ case PROP_LUKS_HOLDER:
1092+ if (device->priv->luks_holder != NULL)
1093+ g_value_set_boxed (value, device->priv->luks_holder);
1094+ else
1095+ g_value_set_boxed (value, "/");
1096+ break;
1097+
1098+ case PROP_LUKS_CLEARTEXT_SLAVE:
1099+ if (device->priv->luks_cleartext_slave != NULL)
1100+ g_value_set_boxed (value, device->priv->luks_cleartext_slave);
1101+ else
1102+ g_value_set_boxed (value, "/");
1103+ break;
1104+ case PROP_LUKS_CLEARTEXT_UNLOCKED_BY_UID:
1105+ g_value_set_uint (value, device->priv->luks_cleartext_unlocked_by_uid);
1106+ break;
1107+
1108+ case PROP_DRIVE_VENDOR:
1109+ g_value_set_string (value, device->priv->drive_vendor);
1110+ break;
1111+ case PROP_DRIVE_MODEL:
1112+ g_value_set_string (value, device->priv->drive_model);
1113+ break;
1114+ case PROP_DRIVE_REVISION:
1115+ g_value_set_string (value, device->priv->drive_revision);
1116+ break;
1117+ case PROP_DRIVE_SERIAL:
1118+ g_value_set_string (value, device->priv->drive_serial);
1119+ break;
1120+ case PROP_DRIVE_WWN:
1121+ g_value_set_string (value, device->priv->drive_wwn);
1122+ break;
1123+ case PROP_DRIVE_CONNECTION_INTERFACE:
1124+ g_value_set_string (value, device->priv->drive_connection_interface);
1125+ break;
1126+ case PROP_DRIVE_CONNECTION_SPEED:
1127+ g_value_set_uint64 (value, device->priv->drive_connection_speed);
1128+ break;
1129+ case PROP_DRIVE_MEDIA_COMPATIBILITY:
1130+ g_value_set_boxed (value, device->priv->drive_media_compatibility);
1131+ break;
1132+ case PROP_DRIVE_MEDIA:
1133+ g_value_set_string (value, device->priv->drive_media);
1134+ break;
1135+ case PROP_DRIVE_IS_MEDIA_EJECTABLE:
1136+ g_value_set_boolean (value, device->priv->drive_is_media_ejectable);
1137+ break;
1138+ case PROP_DRIVE_CAN_DETACH:
1139+ g_value_set_boolean (value, device->priv->drive_can_detach);
1140+ break;
1141+ case PROP_DRIVE_CAN_SPINDOWN:
1142+ g_value_set_boolean (value, device->priv->drive_can_spindown);
1143+ break;
1144+ case PROP_DRIVE_IS_ROTATIONAL:
1145+ g_value_set_boolean (value, device->priv->drive_is_rotational);
1146+ break;
1147+ case PROP_DRIVE_WRITE_CACHE:
1148+ g_value_set_string (value, device->priv->drive_write_cache);
1149+ break;
1150+ case PROP_DRIVE_ROTATION_RATE:
1151+ g_value_set_uint (value, device->priv->drive_rotation_rate);
1152+ break;
1153+ case PROP_DRIVE_ADAPTER:
1154+ if (device->priv->drive_adapter != NULL)
1155+ g_value_set_boxed (value, device->priv->drive_adapter);
1156+ else
1157+ g_value_set_boxed (value, "/");
1158+ break;
1159+ case PROP_DRIVE_PORTS:
1160+ g_value_set_boxed (value, device->priv->drive_ports);
1161+ break;
1162+ case PROP_DRIVE_SIMILAR_DEVICES:
1163+ g_value_set_boxed (value, device->priv->drive_similar_devices);
1164+ break;
1165+
1166+ case PROP_OPTICAL_DISC_IS_BLANK:
1167+ g_value_set_boolean (value, device->priv->optical_disc_is_blank);
1168+ break;
1169+ case PROP_OPTICAL_DISC_IS_APPENDABLE:
1170+ g_value_set_boolean (value, device->priv->optical_disc_is_appendable);
1171+ break;
1172+ case PROP_OPTICAL_DISC_IS_CLOSED:
1173+ g_value_set_boolean (value, device->priv->optical_disc_is_closed);
1174+ break;
1175+ case PROP_OPTICAL_DISC_NUM_TRACKS:
1176+ g_value_set_uint (value, device->priv->optical_disc_num_tracks);
1177+ break;
1178+ case PROP_OPTICAL_DISC_NUM_AUDIO_TRACKS:
1179+ g_value_set_uint (value, device->priv->optical_disc_num_audio_tracks);
1180+ break;
1181+ case PROP_OPTICAL_DISC_NUM_SESSIONS:
1182+ g_value_set_uint (value, device->priv->optical_disc_num_sessions);
1183+ break;
1184+
1185+ case PROP_DRIVE_ATA_SMART_IS_AVAILABLE:
1186+ g_value_set_boolean (value, device->priv->drive_ata_smart_is_available);
1187+ break;
1188+ case PROP_DRIVE_ATA_SMART_TIME_COLLECTED:
1189+ g_value_set_uint64 (value, device->priv->drive_ata_smart_time_collected);
1190+ break;
1191+ case PROP_DRIVE_ATA_SMART_STATUS:
1192+ {
1193+ const gchar *status;
1194+ if (device->priv->drive_ata_smart_status == (SkSmartOverall) - 1)
1195+ status = "";
1196+ else
1197+ status = sk_smart_overall_to_string (device->priv->drive_ata_smart_status);
1198+ g_value_set_string (value, status);
1199+ }
1200+ break;
1201+ case PROP_DRIVE_ATA_SMART_BLOB:
1202+ {
1203+ GArray *a;
1204+ a = g_array_new (FALSE, FALSE, 1);
1205+ if (device->priv->drive_ata_smart_blob != NULL)
1206+ {
1207+ g_array_append_vals (a, device->priv->drive_ata_smart_blob, device->priv->drive_ata_smart_blob_size);
1208+ }
1209+ g_value_set_boxed (value, a);
1210+ g_array_unref (a);
1211+ }
1212+ break;
1213+
1214+ case PROP_LINUX_MD_COMPONENT_LEVEL:
1215+ g_value_set_string (value, device->priv->linux_md_component_level);
1216+ break;
1217+ case PROP_LINUX_MD_COMPONENT_POSITION:
1218+ g_value_set_int (value, device->priv->linux_md_component_position);
1219+ break;
1220+ case PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES:
1221+ g_value_set_int (value, device->priv->linux_md_component_num_raid_devices);
1222+ break;
1223+ case PROP_LINUX_MD_COMPONENT_UUID:
1224+ g_value_set_string (value, device->priv->linux_md_component_uuid);
1225+ break;
1226+ case PROP_LINUX_MD_COMPONENT_HOME_HOST:
1227+ g_value_set_string (value, device->priv->linux_md_component_home_host);
1228+ break;
1229+ case PROP_LINUX_MD_COMPONENT_NAME:
1230+ g_value_set_string (value, device->priv->linux_md_component_name);
1231+ break;
1232+ case PROP_LINUX_MD_COMPONENT_VERSION:
1233+ g_value_set_string (value, device->priv->linux_md_component_version);
1234+ break;
1235+ case PROP_LINUX_MD_COMPONENT_HOLDER:
1236+ if (device->priv->linux_md_component_holder != NULL)
1237+ g_value_set_boxed (value, device->priv->linux_md_component_holder);
1238+ else
1239+ g_value_set_boxed (value, "/");
1240+ break;
1241+ case PROP_LINUX_MD_COMPONENT_STATE:
1242+ g_value_set_boxed (value, device->priv->linux_md_component_state);
1243+ break;
1244+
1245+ case PROP_LINUX_MD_STATE:
1246+ g_value_set_string (value, device->priv->linux_md_state);
1247+ break;
1248+ case PROP_LINUX_MD_LEVEL:
1249+ g_value_set_string (value, device->priv->linux_md_level);
1250+ break;
1251+ case PROP_LINUX_MD_NUM_RAID_DEVICES:
1252+ g_value_set_int (value, device->priv->linux_md_num_raid_devices);
1253+ break;
1254+ case PROP_LINUX_MD_UUID:
1255+ g_value_set_string (value, device->priv->linux_md_uuid);
1256+ break;
1257+ case PROP_LINUX_MD_HOME_HOST:
1258+ g_value_set_string (value, device->priv->linux_md_home_host);
1259+ break;
1260+ case PROP_LINUX_MD_NAME:
1261+ g_value_set_string (value, device->priv->linux_md_name);
1262+ break;
1263+ case PROP_LINUX_MD_VERSION:
1264+ g_value_set_string (value, device->priv->linux_md_version);
1265+ break;
1266+ case PROP_LINUX_MD_SLAVES:
1267+ g_value_set_boxed (value, device->priv->linux_md_slaves);
1268+ break;
1269+ case PROP_LINUX_MD_IS_DEGRADED:
1270+ g_value_set_boolean (value, device->priv->linux_md_is_degraded);
1271+ break;
1272+ case PROP_LINUX_MD_SYNC_ACTION:
1273+ g_value_set_string (value, device->priv->linux_md_sync_action);
1274+ break;
1275+ case PROP_LINUX_MD_SYNC_PERCENTAGE:
1276+ g_value_set_double (value, device->priv->linux_md_sync_percentage);
1277+ break;
1278+ case PROP_LINUX_MD_SYNC_SPEED:
1279+ g_value_set_uint64 (value, device->priv->linux_md_sync_speed);
1280+ break;
1281+
1282+ case PROP_LINUX_LVM2_LV_NAME:
1283+ g_value_set_string (value, device->priv->linux_lvm2_lv_name);
1284+ break;
1285+ case PROP_LINUX_LVM2_LV_UUID:
1286+ g_value_set_string (value, device->priv->linux_lvm2_lv_uuid);
1287+ break;
1288+ case PROP_LINUX_LVM2_LV_GROUP_NAME:
1289+ g_value_set_string (value, device->priv->linux_lvm2_lv_group_name);
1290+ break;
1291+ case PROP_LINUX_LVM2_LV_GROUP_UUID:
1292+ g_value_set_string (value, device->priv->linux_lvm2_lv_group_uuid);
1293+ break;
1294+
1295+ case PROP_LINUX_LVM2_PV_UUID:
1296+ g_value_set_string (value, device->priv->linux_lvm2_pv_uuid);
1297+ break;
1298+ case PROP_LINUX_LVM2_PV_NUM_METADATA_AREAS:
1299+ g_value_set_uint (value, device->priv->linux_lvm2_pv_num_metadata_areas);
1300+ break;
1301+ case PROP_LINUX_LVM2_PV_GROUP_NAME:
1302+ g_value_set_string (value, device->priv->linux_lvm2_pv_group_name);
1303+ break;
1304+ case PROP_LINUX_LVM2_PV_GROUP_UUID:
1305+ g_value_set_string (value, device->priv->linux_lvm2_pv_group_uuid);
1306+ break;
1307+ case PROP_LINUX_LVM2_PV_GROUP_SIZE:
1308+ g_value_set_uint64 (value, device->priv->linux_lvm2_pv_group_size);
1309+ break;
1310+ case PROP_LINUX_LVM2_PV_GROUP_UNALLOCATED_SIZE:
1311+ g_value_set_uint64 (value, device->priv->linux_lvm2_pv_group_unallocated_size);
1312+ break;
1313+ case PROP_LINUX_LVM2_PV_GROUP_SEQUENCE_NUMBER:
1314+ g_value_set_uint64 (value, device->priv->linux_lvm2_pv_group_sequence_number);
1315+ break;
1316+ case PROP_LINUX_LVM2_PV_GROUP_EXTENT_SIZE:
1317+ g_value_set_uint64 (value, device->priv->linux_lvm2_pv_group_extent_size);
1318+ break;
1319+ case PROP_LINUX_LVM2_PV_GROUP_PHYSICAL_VOLUMES:
1320+ g_value_set_boxed (value, device->priv->linux_lvm2_pv_group_physical_volumes);
1321+ break;
1322+ case PROP_LINUX_LVM2_PV_GROUP_LOGICAL_VOLUMES:
1323+ g_value_set_boxed (value, device->priv->linux_lvm2_pv_group_logical_volumes);
1324+ break;
1325+
1326+ case PROP_LINUX_DMMP_COMPONENT_HOLDER:
1327+ if (device->priv->linux_dmmp_component_holder != NULL)
1328+ g_value_set_boxed (value, device->priv->linux_dmmp_component_holder);
1329+ else
1330+ g_value_set_boxed (value, "/");
1331+ break;
1332+
1333+ case PROP_LINUX_DMMP_NAME:
1334+ g_value_set_string (value, device->priv->linux_dmmp_name);
1335+ break;
1336+
1337+ case PROP_LINUX_DMMP_PARAMETERS:
1338+ g_value_set_string (value, device->priv->linux_dmmp_parameters);
1339+ break;
1340+
1341+ case PROP_LINUX_DMMP_SLAVES:
1342+ g_value_set_boxed (value, device->priv->linux_dmmp_slaves);
1343+ break;
1344+
1345+ case PROP_LINUX_LOOP_FILENAME:
1346+ g_value_set_string (value, device->priv->linux_loop_filename);
1347+ break;
1348+
1349+ default:
1350+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1351+ break;
1352+ }
1353+}
1354+
1355+static void
1356+device_class_init (DeviceClass *klass)
1357+{
1358+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
1359+
1360+ object_class->constructor = device_constructor;
1361+ object_class->finalize = device_finalize;
1362+ object_class->get_property = get_property;
1363+
1364+ g_type_class_add_private (klass, sizeof(DevicePrivate));
1365+
1366+ signals[CHANGED_SIGNAL] = g_signal_new ("changed",
1367+ G_OBJECT_CLASS_TYPE (klass),
1368+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
1369+ 0,
1370+ NULL,
1371+ NULL,
1372+ g_cclosure_marshal_VOID__VOID,
1373+ G_TYPE_NONE,
1374+ 0);
1375+
1376+ signals[JOB_CHANGED_SIGNAL] = g_signal_new ("job-changed",
1377+ G_OBJECT_CLASS_TYPE (klass),
1378+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
1379+ 0,
1380+ NULL,
1381+ NULL,
1382+ marshal_VOID__BOOLEAN_STRING_UINT_BOOLEAN_DOUBLE,
1383+ G_TYPE_NONE,
1384+ 5,
1385+ G_TYPE_BOOLEAN,
1386+ G_TYPE_STRING,
1387+ G_TYPE_UINT,
1388+ G_TYPE_BOOLEAN,
1389+ G_TYPE_DOUBLE);
1390+
1391+ dbus_g_object_type_install_info (TYPE_DEVICE, &dbus_glib_device_object_info);
1392+
1393+ g_object_class_install_property (object_class, PROP_NATIVE_PATH, g_param_spec_string ("native-path",
1394+ NULL,
1395+ NULL,
1396+ NULL,
1397+ G_PARAM_READABLE));
1398+ g_object_class_install_property (object_class,
1399+ PROP_DEVICE_DETECTION_TIME,
1400+ g_param_spec_uint64 ("device-detection-time",
1401+ NULL,
1402+ NULL,
1403+ 0,
1404+ G_MAXUINT64,
1405+ 0,
1406+ G_PARAM_READABLE));
1407+ g_object_class_install_property (object_class,
1408+ PROP_DEVICE_MEDIA_DETECTION_TIME,
1409+ g_param_spec_uint64 ("device-media-detection-time",
1410+ NULL,
1411+ NULL,
1412+ 0,
1413+ G_MAXUINT64,
1414+ 0,
1415+ G_PARAM_READABLE));
1416+ g_object_class_install_property (object_class, PROP_DEVICE_MAJOR, g_param_spec_int64 ("device-major",
1417+ NULL,
1418+ NULL,
1419+ -G_MAXINT64,
1420+ G_MAXINT64,
1421+ 0,
1422+ G_PARAM_READABLE));
1423+ g_object_class_install_property (object_class, PROP_DEVICE_MINOR, g_param_spec_int64 ("device-minor",
1424+ NULL,
1425+ NULL,
1426+ -G_MAXINT64,
1427+ G_MAXINT64,
1428+ 0,
1429+ G_PARAM_READABLE));
1430+ g_object_class_install_property (object_class,
1431+ PROP_DEVICE_FILE,
1432+ g_param_spec_string ("device-file",
1433+ NULL,
1434+ NULL,
1435+ NULL,
1436+ G_PARAM_READABLE));
1437+ g_object_class_install_property (object_class,
1438+ PROP_DEVICE_FILE_PRESENTATION,
1439+ g_param_spec_string ("device-file-presentation",
1440+ NULL,
1441+ NULL,
1442+ NULL,
1443+ G_PARAM_READABLE));
1444+ g_object_class_install_property (object_class,
1445+ PROP_DEVICE_FILE_BY_ID,
1446+ g_param_spec_boxed ("device-file-by-id",
1447+ NULL,
1448+ NULL,
1449+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
1450+ G_PARAM_READABLE));
1451+ g_object_class_install_property (object_class,
1452+ PROP_DEVICE_FILE_BY_PATH,
1453+ g_param_spec_boxed ("device-file-by-path",
1454+ NULL,
1455+ NULL,
1456+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
1457+ G_PARAM_READABLE));
1458+ g_object_class_install_property (object_class,
1459+ PROP_DEVICE_IS_SYSTEM_INTERNAL,
1460+ g_param_spec_boolean ("device-is-system-internal",
1461+ NULL,
1462+ NULL,
1463+ FALSE,
1464+ G_PARAM_READABLE));
1465+ g_object_class_install_property (object_class, PROP_DEVICE_IS_PARTITION, g_param_spec_boolean ("device-is-partition",
1466+ NULL,
1467+ NULL,
1468+ FALSE,
1469+ G_PARAM_READABLE));
1470+ g_object_class_install_property (object_class,
1471+ PROP_DEVICE_IS_PARTITION_TABLE,
1472+ g_param_spec_boolean ("device-is-partition-table",
1473+ NULL,
1474+ NULL,
1475+ FALSE,
1476+ G_PARAM_READABLE));
1477+ g_object_class_install_property (object_class, PROP_DEVICE_IS_REMOVABLE, g_param_spec_boolean ("device-is-removable",
1478+ NULL,
1479+ NULL,
1480+ FALSE,
1481+ G_PARAM_READABLE));
1482+ g_object_class_install_property (object_class,
1483+ PROP_DEVICE_IS_MEDIA_AVAILABLE,
1484+ g_param_spec_boolean ("device-is-media-available",
1485+ NULL,
1486+ NULL,
1487+ FALSE,
1488+ G_PARAM_READABLE));
1489+ g_object_class_install_property (object_class,
1490+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTED,
1491+ g_param_spec_boolean ("device-is-media-change-detected",
1492+ NULL,
1493+ NULL,
1494+ FALSE,
1495+ G_PARAM_READABLE));
1496+ g_object_class_install_property (object_class,
1497+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_POLLING,
1498+ g_param_spec_boolean ("device-is-media-change-detection-polling",
1499+ NULL,
1500+ NULL,
1501+ FALSE,
1502+ G_PARAM_READABLE));
1503+ g_object_class_install_property (object_class,
1504+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITABLE,
1505+ g_param_spec_boolean ("device-is-media-change-detection-inhibitable",
1506+ NULL,
1507+ NULL,
1508+ FALSE,
1509+ G_PARAM_READABLE));
1510+ g_object_class_install_property (object_class,
1511+ PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITED,
1512+ g_param_spec_boolean ("device-is-media-change-detection-inhibited",
1513+ NULL,
1514+ NULL,
1515+ FALSE,
1516+ G_PARAM_READABLE));
1517+ g_object_class_install_property (object_class, PROP_DEVICE_IS_READ_ONLY, g_param_spec_boolean ("device-is-read-only",
1518+ NULL,
1519+ NULL,
1520+ FALSE,
1521+ G_PARAM_READABLE));
1522+ g_object_class_install_property (object_class, PROP_DEVICE_IS_DRIVE, g_param_spec_boolean ("device-is-drive",
1523+ NULL,
1524+ NULL,
1525+ FALSE,
1526+ G_PARAM_READABLE));
1527+ g_object_class_install_property (object_class,
1528+ PROP_DEVICE_IS_OPTICAL_DISC,
1529+ g_param_spec_boolean ("device-is-optical-disc", NULL, NULL, FALSE, G_PARAM_READABLE));
1530+ g_object_class_install_property (object_class, PROP_DEVICE_IS_LUKS, g_param_spec_boolean ("device-is-luks",
1531+ NULL,
1532+ NULL,
1533+ FALSE,
1534+ G_PARAM_READABLE));
1535+ g_object_class_install_property (object_class,
1536+ PROP_DEVICE_IS_LUKS_CLEARTEXT,
1537+ g_param_spec_boolean ("device-is-luks-cleartext",
1538+ NULL,
1539+ NULL,
1540+ FALSE,
1541+ G_PARAM_READABLE));
1542+ g_object_class_install_property (object_class,
1543+ PROP_DEVICE_IS_LINUX_MD_COMPONENT,
1544+ g_param_spec_boolean ("device-is-linux-md-component",
1545+ NULL,
1546+ NULL,
1547+ FALSE,
1548+ G_PARAM_READABLE));
1549+ g_object_class_install_property (object_class, PROP_DEVICE_IS_LINUX_MD, g_param_spec_boolean ("device-is-linux-md",
1550+ NULL,
1551+ NULL,
1552+ FALSE,
1553+ G_PARAM_READABLE));
1554+ g_object_class_install_property (object_class,
1555+ PROP_DEVICE_IS_LINUX_LVM2_LV,
1556+ g_param_spec_boolean ("device-is-linux-lvm2-lv",
1557+ NULL,
1558+ NULL,
1559+ FALSE,
1560+ G_PARAM_READABLE));
1561+ g_object_class_install_property (object_class,
1562+ PROP_DEVICE_IS_LINUX_LVM2_PV,
1563+ g_param_spec_boolean ("device-is-linux-lvm2-pv",
1564+ NULL,
1565+ NULL,
1566+ FALSE,
1567+ G_PARAM_READABLE));
1568+ g_object_class_install_property (object_class,
1569+ PROP_DEVICE_IS_LINUX_DMMP,
1570+ g_param_spec_boolean ("device-is-linux-dmmp",
1571+ NULL,
1572+ NULL,
1573+ FALSE,
1574+ G_PARAM_READABLE));
1575+ g_object_class_install_property (object_class,
1576+ PROP_DEVICE_IS_LINUX_DMMP_COMPONENT,
1577+ g_param_spec_boolean ("device-is-linux-dmmp-component",
1578+ NULL,
1579+ NULL,
1580+ FALSE,
1581+ G_PARAM_READABLE));
1582+ g_object_class_install_property (object_class,
1583+ PROP_DEVICE_IS_LINUX_LOOP,
1584+ g_param_spec_boolean ("device-is-linux-loop",
1585+ NULL,
1586+ NULL,
1587+ FALSE,
1588+ G_PARAM_READABLE));
1589+
1590+ g_object_class_install_property (object_class, PROP_DEVICE_SIZE, g_param_spec_uint64 ("device-size",
1591+ NULL,
1592+ NULL,
1593+ 0,
1594+ G_MAXUINT64,
1595+ 0,
1596+ G_PARAM_READABLE));
1597+ g_object_class_install_property (object_class, PROP_DEVICE_BLOCK_SIZE, g_param_spec_uint64 ("device-block-size",
1598+ NULL,
1599+ NULL,
1600+ 0,
1601+ G_MAXUINT64,
1602+ 0,
1603+ G_PARAM_READABLE));
1604+ g_object_class_install_property (object_class, PROP_DEVICE_IS_MOUNTED, g_param_spec_boolean ("device-is-mounted",
1605+ NULL,
1606+ NULL,
1607+ FALSE,
1608+ G_PARAM_READABLE));
1609+ g_object_class_install_property (object_class,
1610+ PROP_DEVICE_MOUNT_PATHS,
1611+ g_param_spec_boxed ("device-mount-paths",
1612+ NULL,
1613+ NULL,
1614+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
1615+ G_PARAM_READABLE));
1616+ g_object_class_install_property (object_class,
1617+ PROP_DEVICE_MOUNTED_BY_UID,
1618+ g_param_spec_uint ("device-mounted-by-uid",
1619+ NULL,
1620+ NULL,
1621+ 0,
1622+ G_MAXUINT,
1623+ 0,
1624+ G_PARAM_READABLE));
1625+ g_object_class_install_property (object_class,
1626+ PROP_DEVICE_PRESENTATION_HIDE,
1627+ g_param_spec_boolean ("device-presentation-hide",
1628+ NULL,
1629+ NULL,
1630+ FALSE,
1631+ G_PARAM_READABLE));
1632+ g_object_class_install_property (object_class,
1633+ PROP_DEVICE_PRESENTATION_NOPOLICY,
1634+ g_param_spec_boolean ("device-presentation-nopolicy",
1635+ NULL,
1636+ NULL,
1637+ FALSE,
1638+ G_PARAM_READABLE));
1639+ g_object_class_install_property (object_class,
1640+ PROP_DEVICE_PRESENTATION_NAME,
1641+ g_param_spec_string ("device-presentation-name", NULL, NULL, NULL, G_PARAM_READABLE));
1642+ g_object_class_install_property (object_class,
1643+ PROP_DEVICE_PRESENTATION_ICON_NAME,
1644+ g_param_spec_string ("device-presentation-icon-name",
1645+ NULL,
1646+ NULL,
1647+ NULL,
1648+ G_PARAM_READABLE));
1649+
1650+ g_object_class_install_property (object_class, PROP_JOB_IN_PROGRESS, g_param_spec_boolean ("job-in-progress",
1651+ NULL,
1652+ NULL,
1653+ FALSE,
1654+ G_PARAM_READABLE));
1655+ g_object_class_install_property (object_class, PROP_JOB_ID, g_param_spec_string ("job-id",
1656+ NULL,
1657+ NULL,
1658+ NULL,
1659+ G_PARAM_READABLE));
1660+ g_object_class_install_property (object_class, PROP_JOB_INITIATED_BY_UID, g_param_spec_uint ("job-initiated-by-uid",
1661+ NULL,
1662+ NULL,
1663+ 0,
1664+ G_MAXUINT,
1665+ 0,
1666+ G_PARAM_READABLE));
1667+ g_object_class_install_property (object_class, PROP_JOB_IS_CANCELLABLE, g_param_spec_boolean ("job-is-cancellable",
1668+ NULL,
1669+ NULL,
1670+ FALSE,
1671+ G_PARAM_READABLE));
1672+ g_object_class_install_property (object_class, PROP_JOB_PERCENTAGE, g_param_spec_double ("job-percentage",
1673+ NULL,
1674+ NULL,
1675+ -1,
1676+ 100,
1677+ -1,
1678+ G_PARAM_READABLE));
1679+
1680+ g_object_class_install_property (object_class, PROP_ID_USAGE, g_param_spec_string ("id-usage",
1681+ NULL,
1682+ NULL,
1683+ NULL,
1684+ G_PARAM_READABLE));
1685+ g_object_class_install_property (object_class, PROP_ID_TYPE, g_param_spec_string ("id-type",
1686+ NULL,
1687+ NULL,
1688+ NULL,
1689+ G_PARAM_READABLE));
1690+ g_object_class_install_property (object_class, PROP_ID_VERSION, g_param_spec_string ("id-version",
1691+ NULL,
1692+ NULL,
1693+ NULL,
1694+ G_PARAM_READABLE));
1695+ g_object_class_install_property (object_class, PROP_ID_UUID, g_param_spec_string ("id-uuid",
1696+ NULL,
1697+ NULL,
1698+ NULL,
1699+ G_PARAM_READABLE));
1700+ g_object_class_install_property (object_class, PROP_ID_LABEL, g_param_spec_string ("id-label",
1701+ NULL,
1702+ NULL,
1703+ NULL,
1704+ G_PARAM_READABLE));
1705+
1706+ g_object_class_install_property (object_class, PROP_PARTITION_SLAVE, g_param_spec_boxed ("partition-slave",
1707+ NULL,
1708+ NULL,
1709+ DBUS_TYPE_G_OBJECT_PATH,
1710+ G_PARAM_READABLE));
1711+ g_object_class_install_property (object_class, PROP_PARTITION_SCHEME, g_param_spec_string ("partition-scheme",
1712+ NULL,
1713+ NULL,
1714+ NULL,
1715+ G_PARAM_READABLE));
1716+ g_object_class_install_property (object_class, PROP_PARTITION_TYPE, g_param_spec_string ("partition-type",
1717+ NULL,
1718+ NULL,
1719+ NULL,
1720+ G_PARAM_READABLE));
1721+ g_object_class_install_property (object_class, PROP_PARTITION_LABEL, g_param_spec_string ("partition-label",
1722+ NULL,
1723+ NULL,
1724+ NULL,
1725+ G_PARAM_READABLE));
1726+ g_object_class_install_property (object_class, PROP_PARTITION_UUID, g_param_spec_string ("partition-uuid",
1727+ NULL,
1728+ NULL,
1729+ NULL,
1730+ G_PARAM_READABLE));
1731+ g_object_class_install_property (object_class,
1732+ PROP_PARTITION_FLAGS,
1733+ g_param_spec_boxed ("partition-flags",
1734+ NULL,
1735+ NULL,
1736+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
1737+ G_PARAM_READABLE));
1738+ g_object_class_install_property (object_class, PROP_PARTITION_NUMBER, g_param_spec_int ("partition-number",
1739+ NULL,
1740+ NULL,
1741+ 0,
1742+ G_MAXINT,
1743+ 0,
1744+ G_PARAM_READABLE));
1745+ g_object_class_install_property (object_class, PROP_PARTITION_OFFSET, g_param_spec_uint64 ("partition-offset",
1746+ NULL,
1747+ NULL,
1748+ 0,
1749+ G_MAXUINT64,
1750+ 0,
1751+ G_PARAM_READABLE));
1752+ g_object_class_install_property (object_class, PROP_PARTITION_SIZE, g_param_spec_uint64 ("partition-size",
1753+ NULL,
1754+ NULL,
1755+ 0,
1756+ G_MAXUINT64,
1757+ 0,
1758+ G_PARAM_READABLE));
1759+ g_object_class_install_property (object_class,
1760+ PROP_PARTITION_ALIGNMENT_OFFSET,
1761+ g_param_spec_uint64 ("partition-alignment-offset",
1762+ NULL,
1763+ NULL,
1764+ 0,
1765+ G_MAXUINT64,
1766+ 0,
1767+ G_PARAM_READABLE));
1768+
1769+ g_object_class_install_property (object_class,
1770+ PROP_PARTITION_TABLE_SCHEME,
1771+ g_param_spec_string ("partition-table-scheme", NULL, NULL, NULL, G_PARAM_READABLE));
1772+ g_object_class_install_property (object_class, PROP_PARTITION_TABLE_COUNT, g_param_spec_int ("partition-table-count",
1773+ NULL,
1774+ NULL,
1775+ 0,
1776+ G_MAXINT,
1777+ 0,
1778+ G_PARAM_READABLE));
1779+
1780+ g_object_class_install_property (object_class, PROP_LUKS_HOLDER, g_param_spec_boxed ("luks-holder",
1781+ NULL,
1782+ NULL,
1783+ DBUS_TYPE_G_OBJECT_PATH,
1784+ G_PARAM_READABLE));
1785+
1786+ g_object_class_install_property (object_class,
1787+ PROP_LUKS_CLEARTEXT_SLAVE,
1788+ g_param_spec_boxed ("luks-cleartext-slave",
1789+ NULL,
1790+ NULL,
1791+ DBUS_TYPE_G_OBJECT_PATH,
1792+ G_PARAM_READABLE));
1793+ g_object_class_install_property (object_class,
1794+ PROP_LUKS_CLEARTEXT_UNLOCKED_BY_UID,
1795+ g_param_spec_uint ("luks-cleartext-unlocked-by-uid",
1796+ NULL,
1797+ NULL,
1798+ 0,
1799+ G_MAXUINT,
1800+ 0,
1801+ G_PARAM_READABLE));
1802+
1803+ g_object_class_install_property (object_class, PROP_DRIVE_VENDOR, g_param_spec_string ("drive-vendor",
1804+ NULL,
1805+ NULL,
1806+ NULL,
1807+ G_PARAM_READABLE));
1808+ g_object_class_install_property (object_class, PROP_DRIVE_MODEL, g_param_spec_string ("drive-model",
1809+ NULL,
1810+ NULL,
1811+ NULL,
1812+ G_PARAM_READABLE));
1813+ g_object_class_install_property (object_class, PROP_DRIVE_REVISION, g_param_spec_string ("drive-revision",
1814+ NULL,
1815+ NULL,
1816+ NULL,
1817+ G_PARAM_READABLE));
1818+ g_object_class_install_property (object_class, PROP_DRIVE_SERIAL, g_param_spec_string ("drive-serial",
1819+ NULL,
1820+ NULL,
1821+ NULL,
1822+ G_PARAM_READABLE));
1823+ g_object_class_install_property (object_class, PROP_DRIVE_WWN, g_param_spec_string ("drive-wwn",
1824+ NULL,
1825+ NULL,
1826+ NULL,
1827+ G_PARAM_READABLE));
1828+ g_object_class_install_property (object_class,
1829+ PROP_DRIVE_CONNECTION_INTERFACE,
1830+ g_param_spec_string ("drive-connection-interface",
1831+ NULL,
1832+ NULL,
1833+ NULL,
1834+ G_PARAM_READABLE));
1835+ g_object_class_install_property (object_class,
1836+ PROP_DRIVE_CONNECTION_SPEED,
1837+ g_param_spec_uint64 ("drive-connection-speed",
1838+ NULL,
1839+ NULL,
1840+ 0,
1841+ G_MAXUINT64,
1842+ 0,
1843+ G_PARAM_READABLE));
1844+ g_object_class_install_property (object_class,
1845+ PROP_DRIVE_MEDIA_COMPATIBILITY,
1846+ g_param_spec_boxed ("drive-media-compatibility",
1847+ NULL,
1848+ NULL,
1849+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
1850+ G_PARAM_READABLE));
1851+ g_object_class_install_property (object_class, PROP_DRIVE_MEDIA, g_param_spec_string ("drive-media",
1852+ NULL,
1853+ NULL,
1854+ NULL,
1855+ G_PARAM_READABLE));
1856+ g_object_class_install_property (object_class,
1857+ PROP_DRIVE_IS_MEDIA_EJECTABLE,
1858+ g_param_spec_boolean ("drive-is-media-ejectable",
1859+ NULL,
1860+ NULL,
1861+ FALSE,
1862+ G_PARAM_READABLE));
1863+ g_object_class_install_property (object_class, PROP_DRIVE_CAN_DETACH, g_param_spec_boolean ("drive-can-detach",
1864+ NULL,
1865+ NULL,
1866+ FALSE,
1867+ G_PARAM_READABLE));
1868+ g_object_class_install_property (object_class, PROP_DRIVE_CAN_SPINDOWN, g_param_spec_boolean ("drive-can-spindown",
1869+ NULL,
1870+ NULL,
1871+ FALSE,
1872+ G_PARAM_READABLE));
1873+ g_object_class_install_property (object_class, PROP_DRIVE_IS_ROTATIONAL, g_param_spec_boolean ("drive-is-rotational",
1874+ NULL,
1875+ NULL,
1876+ FALSE,
1877+ G_PARAM_READABLE));
1878+ g_object_class_install_property (object_class, PROP_DRIVE_ROTATION_RATE, g_param_spec_uint ("drive-rotation-rate",
1879+ NULL,
1880+ NULL,
1881+ 0,
1882+ G_MAXUINT,
1883+ 0,
1884+ G_PARAM_READABLE));
1885+ g_object_class_install_property (object_class, PROP_DRIVE_WRITE_CACHE, g_param_spec_string ("drive-write-cache",
1886+ NULL,
1887+ NULL,
1888+ FALSE,
1889+ G_PARAM_READABLE));
1890+ g_object_class_install_property (object_class, PROP_DRIVE_ADAPTER, g_param_spec_boxed ("drive-adapter",
1891+ NULL,
1892+ NULL,
1893+ DBUS_TYPE_G_OBJECT_PATH,
1894+ G_PARAM_READABLE));
1895+ g_object_class_install_property (object_class,
1896+ PROP_DRIVE_PORTS,
1897+ g_param_spec_boxed ("drive-ports",
1898+ NULL,
1899+ NULL,
1900+ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
1901+ G_PARAM_READABLE));
1902+ g_object_class_install_property (object_class,
1903+ PROP_DRIVE_SIMILAR_DEVICES,
1904+ g_param_spec_boxed ("drive-similar-devices",
1905+ NULL,
1906+ NULL,
1907+ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
1908+ G_PARAM_READABLE));
1909+
1910+ g_object_class_install_property (object_class,
1911+ PROP_OPTICAL_DISC_IS_BLANK,
1912+ g_param_spec_boolean ("optical-disc-is-blank", NULL, NULL, FALSE, G_PARAM_READABLE));
1913+ g_object_class_install_property (object_class,
1914+ PROP_OPTICAL_DISC_IS_APPENDABLE,
1915+ g_param_spec_boolean ("optical-disc-is-appendable",
1916+ NULL,
1917+ NULL,
1918+ FALSE,
1919+ G_PARAM_READABLE));
1920+ g_object_class_install_property (object_class,
1921+ PROP_OPTICAL_DISC_IS_CLOSED,
1922+ g_param_spec_boolean ("optical-disc-is-closed", NULL, NULL, FALSE, G_PARAM_READABLE));
1923+ g_object_class_install_property (object_class,
1924+ PROP_OPTICAL_DISC_NUM_TRACKS,
1925+ g_param_spec_uint ("optical-disc-num-tracks",
1926+ NULL,
1927+ NULL,
1928+ 0,
1929+ G_MAXUINT,
1930+ 0,
1931+ G_PARAM_READABLE));
1932+ g_object_class_install_property (object_class,
1933+ PROP_OPTICAL_DISC_NUM_AUDIO_TRACKS,
1934+ g_param_spec_uint ("optical-disc-num-audio-tracks",
1935+ NULL,
1936+ NULL,
1937+ 0,
1938+ G_MAXUINT,
1939+ 0,
1940+ G_PARAM_READABLE));
1941+ g_object_class_install_property (object_class,
1942+ PROP_OPTICAL_DISC_NUM_SESSIONS,
1943+ g_param_spec_uint ("optical-disc-num-sessions",
1944+ NULL,
1945+ NULL,
1946+ 0,
1947+ G_MAXUINT,
1948+ 0,
1949+ G_PARAM_READABLE));
1950+
1951+ g_object_class_install_property (object_class,
1952+ PROP_DRIVE_ATA_SMART_IS_AVAILABLE,
1953+ g_param_spec_boolean ("drive-ata-smart-is-available",
1954+ NULL,
1955+ NULL,
1956+ FALSE,
1957+ G_PARAM_READABLE));
1958+ g_object_class_install_property (object_class,
1959+ PROP_DRIVE_ATA_SMART_TIME_COLLECTED,
1960+ g_param_spec_uint64 ("drive-ata-smart-time-collected",
1961+ NULL,
1962+ NULL,
1963+ 0,
1964+ G_MAXUINT64,
1965+ 0,
1966+ G_PARAM_READABLE));
1967+ g_object_class_install_property (object_class,
1968+ PROP_DRIVE_ATA_SMART_STATUS,
1969+ g_param_spec_string ("drive-ata-smart-status", NULL, NULL, NULL, G_PARAM_READABLE));
1970+ g_object_class_install_property (object_class,
1971+ PROP_DRIVE_ATA_SMART_BLOB,
1972+ g_param_spec_boxed ("drive-ata-smart-blob",
1973+ NULL,
1974+ NULL,
1975+ dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR),
1976+ G_PARAM_READABLE));
1977+
1978+ g_object_class_install_property (object_class,
1979+ PROP_LINUX_MD_COMPONENT_LEVEL,
1980+ g_param_spec_string ("linux-md-component-level", NULL, NULL, NULL, G_PARAM_READABLE));
1981+ g_object_class_install_property (object_class,
1982+ PROP_LINUX_MD_COMPONENT_POSITION,
1983+ g_param_spec_int ("linux-md-component-position",
1984+ NULL,
1985+ NULL,
1986+ 0,
1987+ G_MAXINT,
1988+ 0,
1989+ G_PARAM_READABLE));
1990+ g_object_class_install_property (object_class,
1991+ PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES,
1992+ g_param_spec_int ("linux-md-component-num-raid-devices",
1993+ NULL,
1994+ NULL,
1995+ 0,
1996+ G_MAXINT,
1997+ 0,
1998+ G_PARAM_READABLE));
1999+ g_object_class_install_property (object_class,
2000+ PROP_LINUX_MD_COMPONENT_UUID,
2001+ g_param_spec_string ("linux-md-component-uuid", NULL, NULL, NULL, G_PARAM_READABLE));
2002+ g_object_class_install_property (object_class,
2003+ PROP_LINUX_MD_COMPONENT_HOME_HOST,
2004+ g_param_spec_string ("linux-md-component-home-host",
2005+ NULL,
2006+ NULL,
2007+ NULL,
2008+ G_PARAM_READABLE));
2009+ g_object_class_install_property (object_class,
2010+ PROP_LINUX_MD_COMPONENT_NAME,
2011+ g_param_spec_string ("linux-md-component-name", NULL, NULL, NULL, G_PARAM_READABLE));
2012+ g_object_class_install_property (object_class,
2013+ PROP_LINUX_MD_COMPONENT_VERSION,
2014+ g_param_spec_string ("linux-md-component-version",
2015+ NULL,
2016+ NULL,
2017+ NULL,
2018+ G_PARAM_READABLE));
2019+ g_object_class_install_property (object_class,
2020+ PROP_LINUX_MD_COMPONENT_HOLDER,
2021+ g_param_spec_boxed ("linux-md-component-holder",
2022+ NULL,
2023+ NULL,
2024+ DBUS_TYPE_G_OBJECT_PATH,
2025+ G_PARAM_READABLE));
2026+ g_object_class_install_property (object_class,
2027+ PROP_LINUX_MD_COMPONENT_STATE,
2028+ g_param_spec_boxed ("linux-md-component-state",
2029+ NULL,
2030+ NULL,
2031+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
2032+ G_PARAM_READABLE));
2033+
2034+ g_object_class_install_property (object_class, PROP_LINUX_MD_STATE, g_param_spec_string ("linux-md-state",
2035+ NULL,
2036+ NULL,
2037+ NULL,
2038+ G_PARAM_READABLE));
2039+ g_object_class_install_property (object_class, PROP_LINUX_MD_LEVEL, g_param_spec_string ("linux-md-level",
2040+ NULL,
2041+ NULL,
2042+ NULL,
2043+ G_PARAM_READABLE));
2044+ g_object_class_install_property (object_class,
2045+ PROP_LINUX_MD_NUM_RAID_DEVICES,
2046+ g_param_spec_int ("linux-md-num-raid-devices",
2047+ NULL,
2048+ NULL,
2049+ 0,
2050+ G_MAXINT,
2051+ 0,
2052+ G_PARAM_READABLE));
2053+ g_object_class_install_property (object_class, PROP_LINUX_MD_UUID, g_param_spec_string ("linux-md-uuid",
2054+ NULL,
2055+ NULL,
2056+ NULL,
2057+ G_PARAM_READABLE));
2058+ g_object_class_install_property (object_class, PROP_LINUX_MD_HOME_HOST, g_param_spec_string ("linux-md-home-host",
2059+ NULL,
2060+ NULL,
2061+ NULL,
2062+ G_PARAM_READABLE));
2063+ g_object_class_install_property (object_class, PROP_LINUX_MD_NAME, g_param_spec_string ("linux-md-name",
2064+ NULL,
2065+ NULL,
2066+ NULL,
2067+ G_PARAM_READABLE));
2068+ g_object_class_install_property (object_class, PROP_LINUX_MD_VERSION, g_param_spec_string ("linux-md-version",
2069+ NULL,
2070+ NULL,
2071+ NULL,
2072+ G_PARAM_READABLE));
2073+ g_object_class_install_property (object_class,
2074+ PROP_LINUX_MD_SLAVES,
2075+ g_param_spec_boxed ("linux-md-slaves",
2076+ NULL,
2077+ NULL,
2078+ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
2079+ G_PARAM_READABLE));
2080+ g_object_class_install_property (object_class,
2081+ PROP_LINUX_MD_IS_DEGRADED,
2082+ g_param_spec_boolean ("linux-md-is-degraded", NULL, NULL, FALSE, G_PARAM_READABLE));
2083+ g_object_class_install_property (object_class,
2084+ PROP_LINUX_MD_SYNC_ACTION,
2085+ g_param_spec_string ("linux-md-sync-action", NULL, NULL, NULL, G_PARAM_READABLE));
2086+ g_object_class_install_property (object_class,
2087+ PROP_LINUX_MD_SYNC_PERCENTAGE,
2088+ g_param_spec_double ("linux-md-sync-percentage",
2089+ NULL,
2090+ NULL,
2091+ 0.0,
2092+ 100.0,
2093+ 0.0,
2094+ G_PARAM_READABLE));
2095+ g_object_class_install_property (object_class, PROP_LINUX_MD_SYNC_SPEED, g_param_spec_uint64 ("linux-md-sync-speed",
2096+ NULL,
2097+ NULL,
2098+ 0,
2099+ G_MAXUINT64,
2100+ 0,
2101+ G_PARAM_READABLE));
2102+
2103+ g_object_class_install_property (object_class,
2104+ PROP_LINUX_LVM2_LV_NAME,
2105+ g_param_spec_string ("linux-lvm2-lv-name",
2106+ NULL,
2107+ NULL,
2108+ NULL,
2109+ G_PARAM_READABLE));
2110+ g_object_class_install_property (object_class,
2111+ PROP_LINUX_LVM2_LV_UUID,
2112+ g_param_spec_string ("linux-lvm2-lv-uuid",
2113+ NULL,
2114+ NULL,
2115+ NULL,
2116+ G_PARAM_READABLE));
2117+ g_object_class_install_property (object_class,
2118+ PROP_LINUX_LVM2_LV_GROUP_NAME,
2119+ g_param_spec_string ("linux-lvm2-lv-group-name",
2120+ NULL,
2121+ NULL,
2122+ NULL,
2123+ G_PARAM_READABLE));
2124+ g_object_class_install_property (object_class,
2125+ PROP_LINUX_LVM2_LV_GROUP_UUID,
2126+ g_param_spec_string ("linux-lvm2-lv-group-uuid",
2127+ NULL,
2128+ NULL,
2129+ NULL,
2130+ G_PARAM_READABLE));
2131+
2132+ g_object_class_install_property (object_class,
2133+ PROP_LINUX_LVM2_PV_UUID,
2134+ g_param_spec_string ("linux-lvm2-pv-uuid",
2135+ NULL,
2136+ NULL,
2137+ NULL,
2138+ G_PARAM_READABLE));
2139+ g_object_class_install_property (object_class,
2140+ PROP_LINUX_LVM2_PV_NUM_METADATA_AREAS,
2141+ g_param_spec_uint ("linux-lvm2-pv-num-metadata-areas",
2142+ NULL,
2143+ NULL,
2144+ 0,
2145+ G_MAXUINT,
2146+ 0,
2147+ G_PARAM_READABLE));
2148+ g_object_class_install_property (object_class,
2149+ PROP_LINUX_LVM2_PV_GROUP_NAME,
2150+ g_param_spec_string ("linux-lvm2-pv-group-name",
2151+ NULL,
2152+ NULL,
2153+ NULL,
2154+ G_PARAM_READABLE));
2155+ g_object_class_install_property (object_class,
2156+ PROP_LINUX_LVM2_PV_GROUP_UUID,
2157+ g_param_spec_string ("linux-lvm2-pv-group-uuid",
2158+ NULL,
2159+ NULL,
2160+ NULL,
2161+ G_PARAM_READABLE));
2162+ g_object_class_install_property (object_class,
2163+ PROP_LINUX_LVM2_PV_GROUP_SIZE,
2164+ g_param_spec_uint64 ("linux-lvm2-pv-group-size",
2165+ NULL,
2166+ NULL,
2167+ 0,
2168+ G_MAXUINT64,
2169+ 0,
2170+ G_PARAM_READABLE));
2171+ g_object_class_install_property (object_class,
2172+ PROP_LINUX_LVM2_PV_GROUP_UNALLOCATED_SIZE,
2173+ g_param_spec_uint64 ("linux-lvm2-pv-group-unallocated-size",
2174+ NULL,
2175+ NULL,
2176+ 0,
2177+ G_MAXUINT64,
2178+ 0,
2179+ G_PARAM_READABLE));
2180+ g_object_class_install_property (object_class,
2181+ PROP_LINUX_LVM2_PV_GROUP_SEQUENCE_NUMBER,
2182+ g_param_spec_uint64 ("linux-lvm2-pv-group-sequence-number",
2183+ NULL,
2184+ NULL,
2185+ 0,
2186+ G_MAXUINT64,
2187+ 0,
2188+ G_PARAM_READABLE));
2189+ g_object_class_install_property (object_class,
2190+ PROP_LINUX_LVM2_PV_GROUP_EXTENT_SIZE,
2191+ g_param_spec_uint64 ("linux-lvm2-pv-group-extent-size",
2192+ NULL,
2193+ NULL,
2194+ 0,
2195+ G_MAXUINT64,
2196+ 0,
2197+ G_PARAM_READABLE));
2198+ g_object_class_install_property (object_class,
2199+ PROP_LINUX_LVM2_PV_GROUP_PHYSICAL_VOLUMES,
2200+ g_param_spec_boxed ("linux-lvm2-pv-group-physical-volumes",
2201+ NULL,
2202+ NULL,
2203+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
2204+ G_PARAM_READABLE));
2205+ g_object_class_install_property (object_class,
2206+ PROP_LINUX_LVM2_PV_GROUP_LOGICAL_VOLUMES,
2207+ g_param_spec_boxed ("linux-lvm2-pv-group-logical-volumes",
2208+ NULL,
2209+ NULL,
2210+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
2211+ G_PARAM_READABLE));
2212+ g_object_class_install_property (object_class,
2213+ PROP_LINUX_DMMP_COMPONENT_HOLDER,
2214+ g_param_spec_boxed ("linux-dmmp-component-holder",
2215+ NULL,
2216+ NULL,
2217+ DBUS_TYPE_G_OBJECT_PATH,
2218+ G_PARAM_READABLE));
2219+
2220+ g_object_class_install_property (object_class,
2221+ PROP_LINUX_DMMP_NAME,
2222+ g_param_spec_string ("linux-dmmp-name",
2223+ NULL,
2224+ NULL,
2225+ NULL,
2226+ G_PARAM_READABLE));
2227+ g_object_class_install_property (object_class,
2228+ PROP_LINUX_DMMP_PARAMETERS,
2229+ g_param_spec_string ("linux-dmmp-parameters",
2230+ NULL,
2231+ NULL,
2232+ NULL,
2233+ G_PARAM_READABLE));
2234+ g_object_class_install_property (object_class,
2235+ PROP_LINUX_DMMP_SLAVES,
2236+ g_param_spec_boxed ("linux-dmmp-slaves",
2237+ NULL,
2238+ NULL,
2239+ dbus_g_type_get_collection ("GPtrArray",
2240+ DBUS_TYPE_G_OBJECT_PATH),
2241+ G_PARAM_READABLE));
2242+
2243+ g_object_class_install_property (object_class,
2244+ PROP_LINUX_LOOP_FILENAME,
2245+ g_param_spec_string ("linux-loop-filename",
2246+ NULL,
2247+ NULL,
2248+ NULL,
2249+ G_PARAM_READABLE));
2250+}
2251+
2252+static void
2253+device_init (Device *device)
2254+{
2255+ device->priv = DEVICE_GET_PRIVATE (device);
2256+
2257+ device->priv->device_file_by_id = g_ptr_array_new ();
2258+ device->priv->device_file_by_path = g_ptr_array_new ();
2259+ device->priv->device_mount_paths = g_ptr_array_new ();
2260+ device->priv->partition_flags = g_ptr_array_new ();
2261+ device->priv->drive_media_compatibility = g_ptr_array_new ();
2262+ device->priv->drive_ports = g_ptr_array_new ();
2263+ device->priv->drive_similar_devices = g_ptr_array_new ();
2264+ device->priv->linux_md_component_state = g_ptr_array_new ();
2265+ device->priv->linux_md_slaves = g_ptr_array_new ();
2266+ device->priv->linux_lvm2_pv_group_physical_volumes = g_ptr_array_new ();
2267+ device->priv->linux_lvm2_pv_group_logical_volumes = g_ptr_array_new ();
2268+ device->priv->linux_dmmp_slaves = g_ptr_array_new ();
2269+
2270+ device->priv->slaves_objpath = g_ptr_array_new ();
2271+ device->priv->holders_objpath = g_ptr_array_new ();
2272+
2273+ device->priv->drive_ata_smart_status = -1;
2274+}
2275+
2276+static void
2277+device_finalize (GObject *object)
2278+{
2279+ Device *device;
2280+ GList *l;
2281+
2282+ g_return_if_fail (object != NULL);
2283+ g_return_if_fail (IS_DEVICE (object));
2284+
2285+ device = DEVICE (object);
2286+ g_return_if_fail (device->priv != NULL);
2287+
2288+ /* g_debug ("finalizing %s", device->priv->native_path); */
2289+
2290+ g_object_unref (device->priv->d);
2291+ g_object_unref (device->priv->daemon);
2292+ g_free (device->priv->object_path);
2293+
2294+ g_free (device->priv->native_path);
2295+
2296+ for (l = device->priv->polling_inhibitors; l != NULL; l = l->next)
2297+ {
2298+ Inhibitor *inhibitor = INHIBITOR (l->data);
2299+ g_signal_handlers_disconnect_by_func (inhibitor, polling_inhibitor_disconnected_cb, device);
2300+ g_object_unref (inhibitor);
2301+ }
2302+ g_list_free (device->priv->polling_inhibitors);
2303+
2304+ for (l = device->priv->spindown_inhibitors; l != NULL; l = l->next)
2305+ {
2306+ Inhibitor *inhibitor = INHIBITOR (l->data);
2307+ g_signal_handlers_disconnect_by_func (inhibitor, spindown_inhibitor_disconnected_cb, device);
2308+ g_object_unref (inhibitor);
2309+ }
2310+ g_list_free (device->priv->spindown_inhibitors);
2311+
2312+ if (device->priv->linux_md_poll_timeout_id > 0)
2313+ g_source_remove (device->priv->linux_md_poll_timeout_id);
2314+
2315+ if (device->priv->emit_changed_idle_id > 0)
2316+ g_source_remove (device->priv->emit_changed_idle_id);
2317+
2318+ /* free properties */
2319+ g_free (device->priv->device_file);
2320+ g_free (device->priv->device_file_presentation);
2321+ g_ptr_array_foreach (device->priv->device_file_by_id, (GFunc) g_free, NULL);
2322+ g_ptr_array_foreach (device->priv->device_file_by_path, (GFunc) g_free, NULL);
2323+ g_ptr_array_free (device->priv->device_file_by_id, TRUE);
2324+ g_ptr_array_free (device->priv->device_file_by_path, TRUE);
2325+ g_ptr_array_free (device->priv->device_mount_paths, TRUE);
2326+ g_free (device->priv->device_presentation_name);
2327+ g_free (device->priv->device_presentation_icon_name);
2328+
2329+ g_free (device->priv->id_usage);
2330+ g_free (device->priv->id_type);
2331+ g_free (device->priv->id_version);
2332+ g_free (device->priv->id_uuid);
2333+ g_free (device->priv->id_label);
2334+
2335+ g_free (device->priv->partition_slave);
2336+ g_free (device->priv->partition_scheme);
2337+ g_free (device->priv->partition_type);
2338+ g_free (device->priv->partition_label);
2339+ g_free (device->priv->partition_uuid);
2340+ g_ptr_array_foreach (device->priv->partition_flags, (GFunc) g_free, NULL);
2341+ g_ptr_array_free (device->priv->partition_flags, TRUE);
2342+
2343+ g_free (device->priv->partition_table_scheme);
2344+
2345+ g_free (device->priv->luks_holder);
2346+
2347+ g_free (device->priv->luks_cleartext_slave);
2348+
2349+ g_free (device->priv->drive_vendor);
2350+ g_free (device->priv->drive_model);
2351+ g_free (device->priv->drive_revision);
2352+ g_free (device->priv->drive_serial);
2353+ g_free (device->priv->drive_wwn);
2354+ g_free (device->priv->drive_connection_interface);
2355+ g_ptr_array_foreach (device->priv->drive_media_compatibility, (GFunc) g_free, NULL);
2356+ g_ptr_array_free (device->priv->drive_media_compatibility, TRUE);
2357+ g_free (device->priv->drive_media);
2358+ g_free (device->priv->drive_write_cache);
2359+ g_free (device->priv->drive_adapter);
2360+ g_ptr_array_foreach (device->priv->drive_ports, (GFunc) g_free, NULL);
2361+ g_ptr_array_free (device->priv->drive_ports, TRUE);
2362+ g_ptr_array_foreach (device->priv->drive_similar_devices, (GFunc) g_free, NULL);
2363+ g_ptr_array_free (device->priv->drive_similar_devices, TRUE);
2364+
2365+ g_free (device->priv->linux_md_component_level);
2366+ g_free (device->priv->linux_md_component_uuid);
2367+ g_free (device->priv->linux_md_component_home_host);
2368+ g_free (device->priv->linux_md_component_name);
2369+ g_free (device->priv->linux_md_component_version);
2370+ g_free (device->priv->linux_md_component_holder);
2371+ g_ptr_array_foreach (device->priv->linux_md_component_state, (GFunc) g_free, NULL);
2372+ g_ptr_array_free (device->priv->linux_md_component_state, TRUE);
2373+
2374+ g_free (device->priv->linux_md_state);
2375+ g_free (device->priv->linux_md_level);
2376+ g_free (device->priv->linux_md_uuid);
2377+ g_free (device->priv->linux_md_home_host);
2378+ g_free (device->priv->linux_md_name);
2379+ g_free (device->priv->linux_md_version);
2380+ g_ptr_array_foreach (device->priv->linux_md_slaves, (GFunc) g_free, NULL);
2381+ g_ptr_array_free (device->priv->linux_md_slaves, TRUE);
2382+
2383+ g_free (device->priv->linux_dmmp_component_holder);
2384+
2385+ g_free (device->priv->linux_dmmp_name);
2386+ g_ptr_array_foreach (device->priv->linux_dmmp_slaves, (GFunc) g_free, NULL);
2387+ g_ptr_array_free (device->priv->linux_dmmp_slaves, TRUE);
2388+ g_free (device->priv->linux_dmmp_parameters);
2389+
2390+ g_free (device->priv->linux_loop_filename);
2391+
2392+ g_free (device->priv->linux_lvm2_lv_name);
2393+ g_free (device->priv->linux_lvm2_lv_uuid);
2394+ g_free (device->priv->linux_lvm2_lv_group_name);
2395+ g_free (device->priv->linux_lvm2_lv_group_uuid);
2396+
2397+ g_free (device->priv->linux_lvm2_pv_uuid);
2398+ g_free (device->priv->linux_lvm2_pv_group_name);
2399+ g_free (device->priv->linux_lvm2_pv_group_uuid);
2400+ g_ptr_array_foreach (device->priv->linux_lvm2_pv_group_physical_volumes, (GFunc) g_free, NULL);
2401+ g_ptr_array_free (device->priv->linux_lvm2_pv_group_physical_volumes, TRUE);
2402+ g_ptr_array_foreach (device->priv->linux_lvm2_pv_group_logical_volumes, (GFunc) g_free, NULL);
2403+ g_ptr_array_free (device->priv->linux_lvm2_pv_group_logical_volumes, TRUE);
2404+
2405+ g_free (device->priv->drive_ata_smart_blob);
2406+
2407+ g_free (device->priv->dm_name);
2408+ g_ptr_array_foreach (device->priv->slaves_objpath, (GFunc) g_free, NULL);
2409+ g_ptr_array_free (device->priv->slaves_objpath, TRUE);
2410+ g_ptr_array_foreach (device->priv->holders_objpath, (GFunc) g_free, NULL);
2411+ g_ptr_array_free (device->priv->holders_objpath, TRUE);
2412+
2413+ G_OBJECT_CLASS (device_parent_class)->finalize (object);
2414+}
2415+
2416+/**
2417+ * compute_object_path:
2418+ * @native_path: Either an absolute sysfs path or the basename
2419+ *
2420+ * Maps @native_path to the D-Bus object path for the device.
2421+ *
2422+ * Returns: A valid D-Bus object path. Free with g_free().
2423+ */
2424+static char *
2425+compute_object_path (const char *native_path)
2426+{
2427+ const gchar *basename;
2428+ GString *s;
2429+ guint n;
2430+
2431+ g_return_val_if_fail (native_path != NULL, NULL);
2432+
2433+ basename = strrchr (native_path, '/');
2434+ if (basename != NULL)
2435+ {
2436+ basename++;
2437+ }
2438+ else
2439+ {
2440+ basename = native_path;
2441+ }
2442+
2443+ s = g_string_new ("/org/freedesktop/UDisks/devices/");
2444+ for (n = 0; basename[n] != '\0'; n++)
2445+ {
2446+ gint c = basename[n];
2447+
2448+ /* D-Bus spec sez:
2449+ *
2450+ * Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
2451+ */
2452+ if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
2453+ {
2454+ g_string_append_c (s, c);
2455+ }
2456+ else
2457+ {
2458+ /* Escape bytes not in [A-Z][a-z][0-9] as _<hex-with-two-digits> */
2459+ g_string_append_printf (s, "_%02x", c);
2460+ }
2461+ }
2462+
2463+ return g_string_free (s, FALSE);
2464+}
2465+
2466+static gboolean
2467+register_disks_device (Device *device)
2468+{
2469+ DBusConnection *connection;
2470+ GError *error = NULL;
2471+
2472+ device->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
2473+ if (device->priv->system_bus_connection == NULL)
2474+ {
2475+ if (error != NULL)
2476+ {
2477+ g_critical ("error getting system bus: %s", error->message);
2478+ g_error_free (error);
2479+ }
2480+ goto error;
2481+ }
2482+ connection = dbus_g_connection_get_connection (device->priv->system_bus_connection);
2483+
2484+ device->priv->object_path = compute_object_path (device->priv->native_path);
2485+
2486+ /* safety first */
2487+ if (dbus_g_connection_lookup_g_object (device->priv->system_bus_connection, device->priv->object_path) != NULL)
2488+ {
2489+ g_error ("**** HACK: Wanting to register object at path `%s' but there is already an "
2490+ "object there. This is an internal error in the daemon. Aborting.\n", device->priv->object_path);
2491+ }
2492+
2493+ dbus_g_connection_register_g_object (device->priv->system_bus_connection,
2494+ device->priv->object_path,
2495+ G_OBJECT (device));
2496+
2497+ return TRUE;
2498+
2499+ error:
2500+ return FALSE;
2501+}
2502+
2503+static double
2504+sysfs_get_double (const char *dir,
2505+ const char *attribute)
2506+{
2507+ double result;
2508+ char *contents;
2509+ char *filename;
2510+
2511+ result = 0.0;
2512+ filename = g_build_filename (dir, attribute, NULL);
2513+ if (g_file_get_contents (filename, &contents, NULL, NULL))
2514+ {
2515+ result = atof (contents);
2516+ g_free (contents);
2517+ }
2518+ g_free (filename);
2519+
2520+ return result;
2521+}
2522+
2523+static char *
2524+sysfs_get_string (const char *dir,
2525+ const char *attribute)
2526+{
2527+ char *result;
2528+ char *filename;
2529+
2530+ result = NULL;
2531+ filename = g_build_filename (dir, attribute, NULL);
2532+ if (!g_file_get_contents (filename, &result, NULL, NULL))
2533+ {
2534+ result = g_strdup ("");
2535+ }
2536+ g_free (filename);
2537+
2538+ return result;
2539+}
2540+
2541+static int
2542+sysfs_get_int (const char *dir,
2543+ const char *attribute)
2544+{
2545+ int result;
2546+ char *contents;
2547+ char *filename;
2548+
2549+ result = 0;
2550+ filename = g_build_filename (dir, attribute, NULL);
2551+ if (g_file_get_contents (filename, &contents, NULL, NULL))
2552+ {
2553+ result = strtol (contents, NULL, 0);
2554+ g_free (contents);
2555+ }
2556+ g_free (filename);
2557+
2558+ return result;
2559+}
2560+
2561+static guint64
2562+sysfs_get_uint64 (const char *dir,
2563+ const char *attribute)
2564+{
2565+ guint64 result;
2566+ char *contents;
2567+ char *filename;
2568+
2569+ result = 0;
2570+ filename = g_build_filename (dir, attribute, NULL);
2571+ if (g_file_get_contents (filename, &contents, NULL, NULL))
2572+ {
2573+ result = strtoll (contents, NULL, 0);
2574+ g_free (contents);
2575+ }
2576+ g_free (filename);
2577+
2578+ return result;
2579+}
2580+
2581+static gboolean
2582+sysfs_file_exists (const char *dir,
2583+ const char *attribute)
2584+{
2585+ gboolean result;
2586+ char *filename;
2587+
2588+ result = FALSE;
2589+ filename = g_build_filename (dir, attribute, NULL);
2590+ if (g_file_test (filename, G_FILE_TEST_EXISTS))
2591+ {
2592+ result = TRUE;
2593+ }
2594+ g_free (filename);
2595+
2596+ return result;
2597+}
2598+
2599+static void
2600+device_generate_kernel_change_event (Device *device)
2601+{
2602+ FILE *f;
2603+ char *filename;
2604+
2605+ filename = g_build_filename (device->priv->native_path, "uevent", NULL);
2606+ f = fopen (filename, "w");
2607+ if (f == NULL)
2608+ {
2609+ g_warning ("error opening %s for writing: %m", filename);
2610+ }
2611+ else
2612+ {
2613+ if (fputs ("change", f) == EOF)
2614+ {
2615+ g_warning ("error writing 'change' to %s: %m", filename);
2616+ }
2617+ fclose (f);
2618+ }
2619+ g_free (filename);
2620+}
2621+
2622+static char *
2623+_dupv8 (const char *s)
2624+{
2625+ const char *end_valid;
2626+
2627+ if (!g_utf8_validate (s, -1, &end_valid))
2628+ {
2629+ g_print ("**** NOTE: The string '%s' is not valid UTF-8. Invalid characters begins at '%s'\n", s, end_valid);
2630+ return g_strndup (s, end_valid - s);
2631+ }
2632+ else
2633+ {
2634+ return g_strdup (s);
2635+ }
2636+}
2637+
2638+static char *
2639+sysfs_resolve_link (const char *sysfs_path,
2640+ const char *name)
2641+{
2642+ char *full_path;
2643+ char link_path[PATH_MAX];
2644+ char resolved_path[PATH_MAX];
2645+ ssize_t num;
2646+ gboolean found_it;
2647+
2648+ found_it = FALSE;
2649+
2650+ full_path = g_build_filename (sysfs_path, name, NULL);
2651+
2652+ //g_debug ("name='%s'", name);
2653+ //g_debug ("full_path='%s'", full_path);
2654+ num = readlink (full_path, link_path, sizeof(link_path) - 1);
2655+ if (num != -1)
2656+ {
2657+ char *absolute_path;
2658+
2659+ link_path[num] = '\0';
2660+
2661+ //g_debug ("link_path='%s'", link_path);
2662+ absolute_path = g_build_filename (sysfs_path, link_path, NULL);
2663+ //g_debug ("absolute_path='%s'", absolute_path);
2664+ if (realpath (absolute_path, resolved_path) != NULL)
2665+ {
2666+ //g_debug ("resolved_path='%s'", resolved_path);
2667+ found_it = TRUE;
2668+ }
2669+ g_free (absolute_path);
2670+ }
2671+ g_free (full_path);
2672+
2673+ if (found_it)
2674+ return g_strdup (resolved_path);
2675+ else
2676+ return NULL;
2677+}
2678+
2679+/* unescapes things like \x20 to " " and ensures the returned string is valid UTF-8.
2680+ *
2681+ * see volume_id_encode_string() in extras/volume_id/lib/volume_id.c in the
2682+ * udev tree for the encoder
2683+ */
2684+static gchar *
2685+decode_udev_encoded_string (const gchar *str)
2686+{
2687+ GString *s;
2688+ gchar *ret;
2689+ const gchar *end_valid;
2690+ guint n;
2691+
2692+ s = g_string_new (NULL);
2693+ for (n = 0; str[n] != '\0'; n++)
2694+ {
2695+ if (str[n] == '\\')
2696+ {
2697+ gint val;
2698+
2699+ if (str[n + 1] != 'x' || str[n + 2] == '\0' || str[n + 3] == '\0')
2700+ {
2701+ g_print ("**** NOTE: malformed encoded string '%s'\n", str);
2702+ break;
2703+ }
2704+
2705+ val = (g_ascii_xdigit_value (str[n + 2]) << 4) | g_ascii_xdigit_value (str[n + 3]);
2706+
2707+ g_string_append_c (s, val);
2708+
2709+ n += 3;
2710+ }
2711+ else
2712+ {
2713+ g_string_append_c (s, str[n]);
2714+ }
2715+ }
2716+
2717+ if (!g_utf8_validate (s->str, -1, &end_valid))
2718+ {
2719+ g_print ("**** NOTE: The string '%s' is not valid UTF-8. Invalid characters begins at '%s'\n", s->str, end_valid);
2720+ ret = g_strndup (s->str, end_valid - s->str);
2721+ g_string_free (s, TRUE);
2722+ }
2723+ else
2724+ {
2725+ ret = g_string_free (s, FALSE);
2726+ }
2727+
2728+ return ret;
2729+}
2730+
2731+static gboolean
2732+poll_syncing_md_device (gpointer user_data)
2733+{
2734+ Device *device = DEVICE (user_data);
2735+
2736+ g_print ("**** POLL SYNCING MD %s\n", device->priv->native_path);
2737+
2738+ device->priv->linux_md_poll_timeout_id = 0;
2739+ daemon_local_synthesize_changed (device->priv->daemon, device);
2740+ return FALSE;
2741+}
2742+
2743+static GList *
2744+dup_list_from_ptrarray (GPtrArray *p)
2745+{
2746+ GList *ret;
2747+ guint n;
2748+
2749+ ret = NULL;
2750+
2751+ for (n = 0; n < p->len; n++)
2752+ ret = g_list_prepend (ret, g_strdup (((gchar **) p->pdata)[n]));
2753+
2754+ return ret;
2755+}
2756+
2757+static gint
2758+ptr_str_array_compare (const gchar **a,
2759+ const gchar **b)
2760+{
2761+ return g_strcmp0 (*a, *b);
2762+}
2763+
2764+static void
2765+diff_sorted_lists (GList *list1,
2766+ GList *list2,
2767+ GCompareFunc compare,
2768+ GList **added,
2769+ GList **removed)
2770+{
2771+ int order;
2772+
2773+ *added = *removed = NULL;
2774+
2775+ while (list1 != NULL && list2 != NULL)
2776+ {
2777+ order = (*compare) (list1->data, list2->data);
2778+ if (order < 0)
2779+ {
2780+ *removed = g_list_prepend (*removed, list1->data);
2781+ list1 = list1->next;
2782+ }
2783+ else if (order > 0)
2784+ {
2785+ *added = g_list_prepend (*added, list2->data);
2786+ list2 = list2->next;
2787+ }
2788+ else
2789+ { /* same item */
2790+ list1 = list1->next;
2791+ list2 = list2->next;
2792+ }
2793+ }
2794+
2795+ while (list1 != NULL)
2796+ {
2797+ *removed = g_list_prepend (*removed, list1->data);
2798+ list1 = list1->next;
2799+ }
2800+ while (list2 != NULL)
2801+ {
2802+ *added = g_list_prepend (*added, list2->data);
2803+ list2 = list2->next;
2804+ }
2805+}
2806+
2807+/* ---------------------------------------------------------------------------------------------------- */
2808+
2809+/* update id_* properties */
2810+static gboolean
2811+update_info_presentation (Device *device)
2812+{
2813+ gboolean hide;
2814+ gboolean nopolicy;
2815+
2816+ hide = FALSE;
2817+ if (g_udev_device_has_property (device->priv->d, "UDISKS_PRESENTATION_HIDE"))
2818+ hide = g_udev_device_get_property_as_boolean (device->priv->d, "UDISKS_PRESENTATION_HIDE");
2819+ device_set_device_presentation_hide (device, hide);
2820+
2821+ nopolicy = FALSE;
2822+ if (g_udev_device_has_property (device->priv->d, "UDISKS_PRESENTATION_NOPOLICY"))
2823+ nopolicy = g_udev_device_get_property_as_boolean (device->priv->d, "UDISKS_PRESENTATION_NOPOLICY");
2824+ device_set_device_presentation_nopolicy (device, nopolicy);
2825+
2826+ device_set_device_presentation_name (device, g_udev_device_get_property (device->priv->d, "UDISKS_PRESENTATION_NAME"));
2827+
2828+ device_set_device_presentation_icon_name (device, g_udev_device_get_property (device->priv->d,
2829+ "UDISKS_PRESENTATION_ICON_NAME"));
2830+
2831+ return TRUE;
2832+}
2833+
2834+/* ---------------------------------------------------------------------------------------------------- */
2835+
2836+/* update id_* properties */
2837+static gboolean
2838+update_info_id (Device *device)
2839+{
2840+ gchar *decoded_string;
2841+ const gchar *partition_scheme;
2842+ gint partition_type;
2843+
2844+ partition_scheme = g_udev_device_get_property (device->priv->d, "UDISKS_PARTITION_SCHEME");
2845+ partition_type = g_udev_device_get_property_as_int (device->priv->d, "UDISKS_PARTITION_TYPE");
2846+ if (g_strcmp0 (partition_scheme, "mbr") == 0 && (partition_type == 0x05 || partition_type == 0x0f || partition_type
2847+ == 0x85))
2848+ {
2849+ device_set_id_usage (device, "");
2850+ device_set_id_type (device, "");
2851+ device_set_id_version (device, "");
2852+ device_set_id_label (device, "");
2853+ device_set_id_uuid (device, "");
2854+ goto out;
2855+ }
2856+
2857+ device_set_id_usage (device, g_udev_device_get_property (device->priv->d, "ID_FS_USAGE"));
2858+ device_set_id_type (device, g_udev_device_get_property (device->priv->d, "ID_FS_TYPE"));
2859+ device_set_id_version (device, g_udev_device_get_property (device->priv->d, "ID_FS_VERSION"));
2860+ if (g_udev_device_has_property (device->priv->d, "ID_FS_LABEL_ENC"))
2861+ {
2862+ decoded_string = decode_udev_encoded_string (g_udev_device_get_property (device->priv->d, "ID_FS_LABEL_ENC"));
2863+ device_set_id_label (device, decoded_string);
2864+ g_free (decoded_string);
2865+ }
2866+ else
2867+ {
2868+ device_set_id_label (device, g_udev_device_get_property (device->priv->d, "ID_FS_LABEL"));
2869+ }
2870+ device_set_id_uuid (device, g_udev_device_get_property (device->priv->d, "ID_FS_UUID"));
2871+
2872+ out:
2873+ return TRUE;
2874+}
2875+
2876+/* ---------------------------------------------------------------------------------------------------- */
2877+
2878+/* update partition_table_* properties */
2879+static gboolean
2880+update_info_partition_table (Device *device)
2881+{
2882+ gboolean is_partition_table;
2883+
2884+ is_partition_table = FALSE;
2885+
2886+ /* Check if udisks-part-id identified the device as a partition table.. this includes
2887+ * identifying partition tables set up by kpartx for multipath etc.
2888+ */
2889+ if (g_udev_device_get_property_as_boolean (device->priv->d, "UDISKS_PARTITION_TABLE"))
2890+ {
2891+ device_set_partition_table_scheme (device,
2892+ g_udev_device_get_property (device->priv->d,
2893+ "UDISKS_PARTITION_TABLE_SCHEME"));
2894+ device_set_partition_table_count (device,
2895+ g_udev_device_get_property_as_int (device->priv->d,
2896+ "UDISKS_PARTITION_TABLE_COUNT"));
2897+ is_partition_table = TRUE;
2898+ }
2899+
2900+ /* Note that udisks-part-id might not detect all partition table
2901+ * formats.. so in the negative case, also double check with
2902+ * information in sysfs.
2903+ *
2904+ * The kernel guarantees that all childs are created before the
2905+ * uevent for the parent is created. So if we have childs, we must
2906+ * be a partition table.
2907+ *
2908+ * To detect a child we check for the existance of a subdir that has
2909+ * the parents name as a prefix (e.g. for parent sda then sda1,
2910+ * sda2, sda3 ditto md0, md0p1 etc. etc. will work).
2911+ */
2912+ if (!is_partition_table)
2913+ {
2914+ gchar *s;
2915+ GDir *dir;
2916+
2917+ s = g_path_get_basename (device->priv->native_path);
2918+ if ((dir = g_dir_open (device->priv->native_path, 0, NULL)) != NULL)
2919+ {
2920+ guint partition_count;
2921+ const gchar *name;
2922+
2923+ partition_count = 0;
2924+ while ((name = g_dir_read_name (dir)) != NULL)
2925+ {
2926+ if (g_str_has_prefix (name, s))
2927+ {
2928+ partition_count++;
2929+ }
2930+ }
2931+ g_dir_close (dir);
2932+
2933+ if (partition_count > 0)
2934+ {
2935+ device_set_partition_table_scheme (device, "");
2936+ device_set_partition_table_count (device, partition_count);
2937+ is_partition_table = TRUE;
2938+ }
2939+ }
2940+ g_free (s);
2941+ }
2942+
2943+ device_set_device_is_partition_table (device, is_partition_table);
2944+ if (!is_partition_table)
2945+ {
2946+ /* otherwise, clear all the data */
2947+ device_set_partition_table_scheme (device, NULL);
2948+ device_set_partition_table_count (device, 0);
2949+ }
2950+
2951+ return TRUE;
2952+}
2953+
2954+/* ---------------------------------------------------------------------------------------------------- */
2955+
2956+/* update partition_* properties */
2957+static gboolean
2958+update_info_partition (Device *device)
2959+{
2960+ gboolean is_partition;
2961+
2962+ is_partition = FALSE;
2963+
2964+ /* Check if udisks-part-id identified the device as a partition.. this includes
2965+ * identifying partitions set up by kpartx for multipath
2966+ */
2967+ if (g_udev_device_has_property (device->priv->d, "UDISKS_PARTITION"))
2968+ {
2969+ guint64 size;
2970+ const gchar *scheme;
2971+ const gchar *type;
2972+ const gchar *label;
2973+ const gchar *uuid;
2974+ const gchar* const *flags;
2975+ guint64 offset;
2976+ guint64 alignment_offset;
2977+ const gchar *slave_sysfs_path;
2978+ gint number;
2979+
2980+ scheme = g_udev_device_get_property (device->priv->d, "UDISKS_PARTITION_SCHEME");
2981+ size = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_PARTITION_SIZE");
2982+ type = g_udev_device_get_property (device->priv->d, "UDISKS_PARTITION_TYPE");
2983+ label = g_udev_device_get_property (device->priv->d, "UDISKS_PARTITION_LABEL");
2984+ uuid = g_udev_device_get_property (device->priv->d, "UDISKS_PARTITION_UUID");
2985+ flags = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_PARTITION_FLAGS");
2986+ offset = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_PARTITION_OFFSET");
2987+ alignment_offset = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_PARTITION_ALIGNMENT_OFFSET");
2988+ number = g_udev_device_get_property_as_int (device->priv->d, "UDISKS_PARTITION_NUMBER");
2989+ slave_sysfs_path = g_udev_device_get_property (device->priv->d, "UDISKS_PARTITION_SLAVE");
2990+
2991+ if (slave_sysfs_path != NULL && scheme != NULL && number > 0)
2992+ {
2993+ gchar *s;
2994+
2995+ device_set_partition_scheme (device, scheme);
2996+ device_set_partition_size (device, size);
2997+ device_set_partition_type (device, type);
2998+ device_set_partition_label (device, label);
2999+ device_set_partition_uuid (device, uuid);
3000+ device_set_partition_flags (device, (gchar **) flags);
3001+ device_set_partition_offset (device, offset);
3002+ device_set_partition_alignment_offset (device, alignment_offset);
3003+ device_set_partition_number (device, number);
3004+
3005+ s = compute_object_path (slave_sysfs_path);
3006+ device_set_partition_slave (device, s);
3007+ g_free (s);
3008+
3009+ is_partition = TRUE;
3010+ }
3011+ }
3012+
3013+ /* Also handle the case where we are partitioned by the kernel and don't have
3014+ * any UDISKS_PARTITION_* properties.
3015+ *
3016+ * This works without any udev UDISKS_PARTITION_* properties and is
3017+ * there for maximum compatibility since udisks-part-id only knows a
3018+ * limited set of partition table formats.
3019+ */
3020+ if (!is_partition && sysfs_file_exists (device->priv->native_path, "start"))
3021+ {
3022+ guint64 start;
3023+ guint64 size;
3024+ guint64 offset;
3025+ guint64 alignment_offset;
3026+ gchar *s;
3027+ guint n;
3028+
3029+ device_set_device_is_partition (device, TRUE);
3030+ start = sysfs_get_uint64 (device->priv->native_path, "start");
3031+ size = sysfs_get_uint64 (device->priv->native_path, "size");
3032+ alignment_offset = sysfs_get_uint64 (device->priv->native_path, "alignment_offset");
3033+
3034+ device_set_partition_size (device, size * 512); /* device->priv->device_block_size; */
3035+ device_set_partition_alignment_offset (device, alignment_offset);
3036+
3037+ offset = sysfs_get_uint64 (device->priv->native_path, "start") * device->priv->device_block_size;
3038+ device_set_partition_offset (device, offset);
3039+
3040+ s = device->priv->native_path;
3041+ for (n = strlen (s) - 1; n >= 0 && g_ascii_isdigit (s[n]); n--)
3042+ ;
3043+ device_set_partition_number (device, strtol (s + n + 1, NULL, 0));
3044+
3045+ s = g_strdup (device->priv->native_path);
3046+ for (n = strlen (s) - 1; n >= 0 && s[n] != '/'; n--)
3047+ s[n] = '\0';
3048+ s[n] = '\0';
3049+ device_set_partition_slave (device, compute_object_path (s));
3050+ g_free (s);
3051+
3052+ is_partition = TRUE;
3053+ }
3054+
3055+ device_set_device_is_partition (device, is_partition);
3056+ if (!is_partition)
3057+ {
3058+ /* otherwise, clear all the data */
3059+ device_set_partition_scheme (device, NULL);
3060+ device_set_partition_size (device, device->priv->device_size);
3061+ device_set_partition_type (device, NULL);
3062+ device_set_partition_label (device, NULL);
3063+ device_set_partition_uuid (device, NULL);
3064+ device_set_partition_flags (device, NULL);
3065+ }
3066+ else
3067+ {
3068+ device_set_device_is_drive (device, FALSE);
3069+ }
3070+
3071+ return TRUE;
3072+}
3073+
3074+/* ---------------------------------------------------------------------------------------------------- */
3075+
3076+/* this function sets
3077+ *
3078+ * - drive_vendor (unless set already)
3079+ * - drive_model (unless set already)
3080+ * - connection_interface (if we can figure that out)
3081+ * - connection_speed (if we can figure that out)
3082+ *
3083+ * All this should really come from udev properties but right now it isn't.
3084+ */
3085+static void
3086+update_drive_properties_from_sysfs (Device *device)
3087+{
3088+ char *s;
3089+ char *p;
3090+ char *q;
3091+ char *model;
3092+ char *vendor;
3093+ char *subsystem;
3094+ char *serial;
3095+ char *revision;
3096+ const char *connection_interface;
3097+ guint64 connection_speed;
3098+
3099+ connection_interface = NULL;
3100+ connection_speed = 0;
3101+
3102+ /* walk up the device tree to figure out the subsystem */
3103+ s = g_strdup (device->priv->native_path);
3104+ do
3105+ {
3106+ p = sysfs_resolve_link (s, "subsystem");
3107+ if (p != NULL)
3108+ {
3109+ subsystem = g_path_get_basename (p);
3110+ g_free (p);
3111+
3112+ if (strcmp (subsystem, "scsi") == 0)
3113+ {
3114+ connection_interface = "scsi";
3115+ connection_speed = 0;
3116+
3117+ /* continue walking up the chain; we just use scsi as a fallback */
3118+
3119+ /* grab the names from SCSI since the names from udev currently
3120+ * - replaces whitespace with _
3121+ * - is missing for e.g. Firewire
3122+ */
3123+ vendor = sysfs_get_string (s, "vendor");
3124+ if (vendor != NULL)
3125+ {
3126+ g_strstrip (vendor);
3127+ /* Don't overwrite what we set earlier from ID_VENDOR */
3128+ if (device->priv->drive_vendor == NULL)
3129+ {
3130+ q = _dupv8 (vendor);
3131+ device_set_drive_vendor (device, q);
3132+ g_free (q);
3133+ }
3134+ g_free (vendor);
3135+ }
3136+
3137+ model = sysfs_get_string (s, "model");
3138+ if (model != NULL)
3139+ {
3140+ g_strstrip (model);
3141+ /* Don't overwrite what we set earlier from ID_MODEL */
3142+ if (device->priv->drive_model == NULL)
3143+ {
3144+ q = _dupv8 (model);
3145+ device_set_drive_model (device, q);
3146+ g_free (q);
3147+ }
3148+ g_free (model);
3149+ }
3150+
3151+ /* TODO: need to improve this code; we probably need the kernel to export more
3152+ * information before we can properly get the type and speed.
3153+ */
3154+
3155+ if (device->priv->drive_vendor != NULL && strcmp (device->priv->drive_vendor, "ATA") == 0)
3156+ {
3157+ connection_interface = "ata";
3158+ break;
3159+ }
3160+
3161+ }
3162+ else if (strcmp (subsystem, "usb") == 0)
3163+ {
3164+ double usb_speed;
3165+
3166+ /* both the interface and the device will be 'usb'. However only
3167+ * the device will have the 'speed' property.
3168+ */
3169+ usb_speed = sysfs_get_double (s, "speed");
3170+ if (usb_speed > 0)
3171+ {
3172+ connection_interface = "usb";
3173+ connection_speed = usb_speed * (1000 * 1000);
3174+ break;
3175+
3176+ }
3177+ }
3178+ else if (strcmp (subsystem, "firewire") == 0 || strcmp (subsystem, "ieee1394") == 0)
3179+ {
3180+
3181+ /* TODO: krh has promised a speed file in sysfs; theoretically, the speed can
3182+ * be anything from 100, 200, 400, 800 and 3200. Till then we just hardcode
3183+ * a resonable default of 400 Mbit/s.
3184+ */
3185+
3186+ connection_interface = "firewire";
3187+ connection_speed = 400 * (1000 * 1000);
3188+ break;
3189+
3190+ }
3191+ else if (strcmp (subsystem, "mmc") == 0)
3192+ {
3193+
3194+ /* TODO: what about non-SD, e.g. MMC? Is that another bus? */
3195+ connection_interface = "sdio";
3196+
3197+ /* Set vendor name. According to this MMC document
3198+ *
3199+ * http://www.mmca.org/membership/IAA_Agreement_10_12_06.pdf
3200+ *
3201+ * - manfid: the manufacturer id
3202+ * - oemid: the customer of the manufacturer
3203+ *
3204+ * Apparently these numbers are kept secret. It would be nice
3205+ * to map these into names for setting the manufacturer of the drive,
3206+ * e.g. Panasonic, Sandisk etc.
3207+ */
3208+
3209+ model = sysfs_get_string (s, "name");
3210+ if (model != NULL)
3211+ {
3212+ g_strstrip (model);
3213+ /* Don't overwrite what we set earlier from ID_MODEL */
3214+ if (device->priv->drive_model == NULL)
3215+ {
3216+ q = _dupv8 (model);
3217+ device_set_drive_model (device, q);
3218+ g_free (q);
3219+ }
3220+ g_free (model);
3221+ }
3222+
3223+ serial = sysfs_get_string (s, "serial");
3224+ if (serial != NULL)
3225+ {
3226+ g_strstrip (serial);
3227+ /* Don't overwrite what we set earlier from ID_SERIAL */
3228+ if (device->priv->drive_serial == NULL)
3229+ {
3230+ /* this is formatted as a hexnumber; drop the leading 0x */
3231+ q = _dupv8 (serial + 2);
3232+ device_set_drive_serial (device, q);
3233+ g_free (q);
3234+ }
3235+ g_free (serial);
3236+ }
3237+
3238+ /* TODO: use hwrev and fwrev files? */
3239+ revision = sysfs_get_string (s, "date");
3240+ if (revision != NULL)
3241+ {
3242+ g_strstrip (revision);
3243+ /* Don't overwrite what we set earlier from ID_REVISION */
3244+ if (device->priv->drive_revision == NULL)
3245+ {
3246+ q = _dupv8 (revision);
3247+ device_set_drive_revision (device, q);
3248+ g_free (q);
3249+ }
3250+ g_free (revision);
3251+ }
3252+
3253+ /* TODO: interface speed; the kernel driver knows; would be nice
3254+ * if it could export it */
3255+
3256+ }
3257+ else if (strcmp (subsystem, "platform") == 0)
3258+ {
3259+ const gchar *sysfs_name;
3260+
3261+ sysfs_name = g_strrstr (s, "/");
3262+ if (g_str_has_prefix (sysfs_name + 1, "floppy."))
3263+ {
3264+ device_set_drive_vendor (device, "Floppy Drive");
3265+ connection_interface = "platform";
3266+ }
3267+ }
3268+
3269+ g_free (subsystem);
3270+ }
3271+
3272+ /* advance up the chain */
3273+ p = g_strrstr (s, "/");
3274+ if (p == NULL)
3275+ break;
3276+ *p = '\0';
3277+
3278+ /* but stop at the root */
3279+ if (strcmp (s, "/sys/devices") == 0)
3280+ break;
3281+
3282+ }
3283+ while (TRUE);
3284+
3285+ if (connection_interface != NULL)
3286+ {
3287+ device_set_drive_connection_interface (device, connection_interface);
3288+ device_set_drive_connection_speed (device, connection_speed);
3289+ }
3290+
3291+ g_free (s);
3292+}
3293+
3294+static const struct
3295+{
3296+ const gchar *udev_property;
3297+ const gchar *media_name;
3298+} drive_media_mapping[] =
3299+ {
3300+ { "ID_DRIVE_FLASH", "flash" },
3301+ { "ID_DRIVE_FLASH_CF", "flash_cf" },
3302+ { "ID_DRIVE_FLASH_MS", "flash_ms" },
3303+ { "ID_DRIVE_FLASH_SM", "flash_sm" },
3304+ { "ID_DRIVE_FLASH_SD", "flash_sd" },
3305+ { "ID_DRIVE_FLASH_SDHC", "flash_sdhc" },
3306+ { "ID_DRIVE_FLASH_MMC", "flash_mmc" },
3307+ { "ID_DRIVE_FLOPPY", "floppy" },
3308+ { "ID_DRIVE_FLOPPY_ZIP", "floppy_zip" },
3309+ { "ID_DRIVE_FLOPPY_JAZ", "floppy_jaz" },
3310+ { "ID_CDROM", "optical_cd" },
3311+ { "ID_CDROM_CD_R", "optical_cd_r" },
3312+ { "ID_CDROM_CD_RW", "optical_cd_rw" },
3313+ { "ID_CDROM_DVD", "optical_dvd" },
3314+ { "ID_CDROM_DVD_R", "optical_dvd_r" },
3315+ { "ID_CDROM_DVD_RW", "optical_dvd_rw" },
3316+ { "ID_CDROM_DVD_RAM", "optical_dvd_ram" },
3317+ { "ID_CDROM_DVD_PLUS_R", "optical_dvd_plus_r" },
3318+ { "ID_CDROM_DVD_PLUS_RW", "optical_dvd_plus_rw" },
3319+ { "ID_CDROM_DVD_PLUS_R_DL", "optical_dvd_plus_r_dl" },
3320+ { "ID_CDROM_DVD_PLUS_RW_DL", "optical_dvd_plus_rw_dl" },
3321+ { "ID_CDROM_BD", "optical_bd" },
3322+ { "ID_CDROM_BD_R", "optical_bd_r" },
3323+ { "ID_CDROM_BD_RE", "optical_bd_re" },
3324+ { "ID_CDROM_HDDVD", "optical_hddvd" },
3325+ { "ID_CDROM_HDDVD_R", "optical_hddvd_r" },
3326+ { "ID_CDROM_HDDVD_RW", "optical_hddvd_rw" },
3327+ { "ID_CDROM_MO", "optical_mo" },
3328+ { "ID_CDROM_MRW", "optical_mrw" },
3329+ { "ID_CDROM_MRW_W", "optical_mrw_w" },
3330+ { NULL, NULL }, };
3331+
3332+static const struct
3333+{
3334+ const gchar *udev_property;
3335+ const gchar *media_name;
3336+} media_mapping[] =
3337+ {
3338+ { "ID_DRIVE_MEDIA_FLASH", "flash" },
3339+ { "ID_DRIVE_MEDIA_FLASH_CF", "flash_cf" },
3340+ { "ID_DRIVE_MEDIA_FLASH_MS", "flash_ms" },
3341+ { "ID_DRIVE_MEDIA_FLASH_SM", "flash_sm" },
3342+ { "ID_DRIVE_MEDIA_FLASH_SD", "flash_sd" },
3343+ { "ID_DRIVE_MEDIA_FLASH_SDHC", "flash_sdhc" },
3344+ { "ID_DRIVE_MEDIA_FLASH_MMC", "flash_mmc" },
3345+ { "ID_DRIVE_MEDIA_FLOPPY", "floppy" },
3346+ { "ID_DRIVE_MEDIA_FLOPPY_ZIP", "floppy_zip" },
3347+ { "ID_DRIVE_MEDIA_FLOPPY_JAZ", "floppy_jaz" },
3348+ { "ID_CDROM_MEDIA_CD", "optical_cd" },
3349+ { "ID_CDROM_MEDIA_CD_R", "optical_cd_r" },
3350+ { "ID_CDROM_MEDIA_CD_RW", "optical_cd_rw" },
3351+ { "ID_CDROM_MEDIA_DVD", "optical_dvd" },
3352+ { "ID_CDROM_MEDIA_DVD_R", "optical_dvd_r" },
3353+ { "ID_CDROM_MEDIA_DVD_RW", "optical_dvd_rw" },
3354+ { "ID_CDROM_MEDIA_DVD_RAM", "optical_dvd_ram" },
3355+ { "ID_CDROM_MEDIA_DVD_PLUS_R", "optical_dvd_plus_r" },
3356+ { "ID_CDROM_MEDIA_DVD_PLUS_RW", "optical_dvd_plus_rw" },
3357+ { "ID_CDROM_MEDIA_DVD_PLUS_R_DL", "optical_dvd_plus_r_dl" },
3358+ { "ID_CDROM_MEDIA_DVD_PLUS_RW_DL", "optical_dvd_plus_rw_dl" },
3359+ { "ID_CDROM_MEDIA_BD", "optical_bd" },
3360+ { "ID_CDROM_MEDIA_BD_R", "optical_bd_r" },
3361+ { "ID_CDROM_MEDIA_BD_RE", "optical_bd_re" },
3362+ { "ID_CDROM_MEDIA_HDDVD", "optical_hddvd" },
3363+ { "ID_CDROM_MEDIA_HDDVD_R", "optical_hddvd_r" },
3364+ { "ID_CDROM_MEDIA_HDDVD_RW", "optical_hddvd_rw" },
3365+ { "ID_CDROM_MEDIA_MO", "optical_mo" },
3366+ { "ID_CDROM_MEDIA_MRW", "optical_mrw" },
3367+ { "ID_CDROM_MEDIA_MRW_W", "optical_mrw_w" },
3368+ { NULL, NULL }, };
3369+
3370+/* update drive_* properties */
3371+static gboolean
3372+update_info_drive (Device *device)
3373+{
3374+ GPtrArray *media_compat_array;
3375+ const gchar *media_in_drive;
3376+ gboolean drive_is_ejectable;
3377+ gboolean drive_can_detach;
3378+ gchar *decoded_string;
3379+ guint n;
3380+
3381+ if (g_udev_device_has_property (device->priv->d, "ID_VENDOR_ENC"))
3382+ {
3383+ decoded_string = decode_udev_encoded_string (g_udev_device_get_property (device->priv->d, "ID_VENDOR_ENC"));
3384+ g_strstrip (decoded_string);
3385+ device_set_drive_vendor (device, decoded_string);
3386+ g_free (decoded_string);
3387+ }
3388+ else if (g_udev_device_has_property (device->priv->d, "ID_VENDOR"))
3389+ {
3390+ device_set_drive_vendor (device, g_udev_device_get_property (device->priv->d, "ID_VENDOR"));
3391+ }
3392+
3393+ if (g_udev_device_has_property (device->priv->d, "ID_MODEL_ENC"))
3394+ {
3395+ decoded_string = decode_udev_encoded_string (g_udev_device_get_property (device->priv->d, "ID_MODEL_ENC"));
3396+ g_strstrip (decoded_string);
3397+ device_set_drive_model (device, decoded_string);
3398+ g_free (decoded_string);
3399+ }
3400+ else if (g_udev_device_has_property (device->priv->d, "ID_MODEL"))
3401+ {
3402+ device_set_drive_model (device, g_udev_device_get_property (device->priv->d, "ID_MODEL"));
3403+ }
3404+
3405+ if (g_udev_device_has_property (device->priv->d, "ID_REVISION"))
3406+ device_set_drive_revision (device, g_udev_device_get_property (device->priv->d, "ID_REVISION"));
3407+ if (g_udev_device_has_property (device->priv->d, "ID_SCSI_SERIAL"))
3408+ {
3409+ /* scsi_id sometimes use the WWN as the serial - annoying - see
3410+ * http://git.kernel.org/?p=linux/hotplug/udev.git;a=commit;h=4e9fdfccbdd16f0cfdb5c8fa8484a8ba0f2e69d3
3411+ * for details
3412+ */
3413+ device_set_drive_serial (device, g_udev_device_get_property (device->priv->d, "ID_SCSI_SERIAL"));
3414+ }
3415+ else if (g_udev_device_has_property (device->priv->d, "ID_SERIAL_SHORT"))
3416+ {
3417+ device_set_drive_serial (device, g_udev_device_get_property (device->priv->d, "ID_SERIAL_SHORT"));
3418+ }
3419+
3420+ if (g_udev_device_has_property (device->priv->d, "ID_WWN_WITH_EXTENSION"))
3421+ device_set_drive_wwn (device, g_udev_device_get_property (device->priv->d, "ID_WWN_WITH_EXTENSION") + 2);
3422+ else if (g_udev_device_has_property (device->priv->d, "ID_WWN"))
3423+ device_set_drive_wwn (device, g_udev_device_get_property (device->priv->d, "ID_WWN") + 2);
3424+
3425+ /* pick up some things (vendor, model, connection_interface, connection_speed)
3426+ * not (yet) exported by udev helpers
3427+ */
3428+ update_drive_properties_from_sysfs (device);
3429+
3430+ if (g_udev_device_has_property (device->priv->d, "ID_DRIVE_EJECTABLE"))
3431+ {
3432+ drive_is_ejectable = g_udev_device_get_property_as_boolean (device->priv->d, "ID_DRIVE_EJECTABLE");
3433+ }
3434+ else
3435+ {
3436+ drive_is_ejectable = FALSE;
3437+ drive_is_ejectable |= g_udev_device_has_property (device->priv->d, "ID_CDROM");
3438+ drive_is_ejectable |= g_udev_device_has_property (device->priv->d, "ID_DRIVE_FLOPPY_ZIP");
3439+ drive_is_ejectable |= g_udev_device_has_property (device->priv->d, "ID_DRIVE_FLOPPY_JAZ");
3440+ }
3441+ device_set_drive_is_media_ejectable (device, drive_is_ejectable);
3442+
3443+ media_compat_array = g_ptr_array_new ();
3444+ for (n = 0; drive_media_mapping[n].udev_property != NULL; n++)
3445+ {
3446+ if (!g_udev_device_has_property (device->priv->d, drive_media_mapping[n].udev_property))
3447+ continue;
3448+
3449+ g_ptr_array_add (media_compat_array, (gpointer) drive_media_mapping[n].media_name);
3450+ }
3451+ /* special handling for SDIO since we don't yet have a sdio_id helper in udev to set properties */
3452+ if (g_strcmp0 (device->priv->drive_connection_interface, "sdio") == 0)
3453+ {
3454+ gchar *type;
3455+
3456+ type = sysfs_get_string (device->priv->native_path, "../../type");
3457+ g_strstrip (type);
3458+ if (g_strcmp0 (type, "MMC") == 0)
3459+ {
3460+ g_ptr_array_add (media_compat_array, "flash_mmc");
3461+ }
3462+ else if (g_strcmp0 (type, "SD") == 0)
3463+ {
3464+ g_ptr_array_add (media_compat_array, "flash_sd");
3465+ }
3466+ else if (g_strcmp0 (type, "SDHC") == 0)
3467+ {
3468+ g_ptr_array_add (media_compat_array, "flash_sdhc");
3469+ }
3470+ g_free (type);
3471+ }
3472+ g_ptr_array_sort (media_compat_array, (GCompareFunc) ptr_str_array_compare);
3473+ g_ptr_array_add (media_compat_array, NULL);
3474+ device_set_drive_media_compatibility (device, (GStrv) media_compat_array->pdata);
3475+
3476+ media_in_drive = NULL;
3477+
3478+ if (device->priv->device_is_media_available)
3479+ {
3480+ for (n = 0; media_mapping[n].udev_property != NULL; n++)
3481+ {
3482+ if (!g_udev_device_has_property (device->priv->d, media_mapping[n].udev_property))
3483+ continue;
3484+
3485+ media_in_drive = drive_media_mapping[n].media_name;
3486+ break;
3487+ }
3488+ /* If the media isn't set (from e.g. udev rules), just pick the first one in media_compat - note
3489+ * that this may be NULL (if we don't know what media is compatible with the drive) which is OK.
3490+ */
3491+ if (media_in_drive == NULL)
3492+ media_in_drive = ((const gchar **) media_compat_array->pdata)[0];
3493+ }
3494+ device_set_drive_media (device, media_in_drive);
3495+
3496+ g_ptr_array_free (media_compat_array, TRUE);
3497+
3498+ /* right now, we only offer to detach USB devices */
3499+ drive_can_detach = FALSE;
3500+ if (g_strcmp0 (device->priv->drive_connection_interface, "usb") == 0)
3501+ {
3502+ drive_can_detach = TRUE;
3503+ }
3504+ if (g_udev_device_has_property (device->priv->d, "ID_DRIVE_DETACHABLE"))
3505+ {
3506+ drive_can_detach = g_udev_device_get_property_as_boolean (device->priv->d, "ID_DRIVE_DETACHABLE");
3507+ }
3508+ device_set_drive_can_detach (device, drive_can_detach);
3509+
3510+ /* rotational is in sysfs */
3511+ device_set_drive_is_rotational (device, g_udev_device_get_sysfs_attr_as_boolean (device->priv->d, "queue/rotational"));
3512+
3513+ if (g_udev_device_has_property (device->priv->d, "ID_ATA_ROTATION_RATE_RPM"))
3514+ {
3515+ device_set_drive_rotation_rate (device, g_udev_device_get_property_as_int (device->priv->d,
3516+ "ID_ATA_ROTATION_RATE_RPM"));
3517+ }
3518+
3519+ if (g_udev_device_get_property_as_boolean (device->priv->d, "ID_ATA_WRITE_CACHE"))
3520+ {
3521+ if (g_udev_device_get_property_as_boolean (device->priv->d, "ID_ATA_WRITE_CACHE_ENABLED"))
3522+ {
3523+ device_set_drive_write_cache (device, "enabled");
3524+ }
3525+ else
3526+ {
3527+ device_set_drive_write_cache (device, "disabled");
3528+ }
3529+ }
3530+
3531+ return TRUE;
3532+}
3533+
3534+/* ---------------------------------------------------------------------------------------------------- */
3535+
3536+/* update drive_can_spindown property */
3537+static gboolean
3538+update_info_drive_can_spindown (Device *device)
3539+{
3540+ gboolean drive_can_spindown;
3541+
3542+ /* Right now we only know how to spin down ATA devices (including those USB devices
3543+ * that can do ATA SMART)
3544+ *
3545+ * This would probably also work for SCSI devices (since the helper is doing SCSI
3546+ * STOP (which translated in libata to ATA's STANDBY IMMEDIATE) - but that needs
3547+ * testing...
3548+ */
3549+ drive_can_spindown = FALSE;
3550+ if (g_strcmp0 (device->priv->drive_connection_interface, "ata") == 0 || device->priv->drive_ata_smart_is_available)
3551+ {
3552+ drive_can_spindown = TRUE;
3553+ }
3554+ if (g_udev_device_has_property (device->priv->d, "ID_DRIVE_CAN_SPINDOWN"))
3555+ {
3556+ drive_can_spindown = g_udev_device_get_property_as_boolean (device->priv->d, "ID_DRIVE_CAN_SPINDOWN");
3557+ }
3558+ device_set_drive_can_spindown (device, drive_can_spindown);
3559+
3560+ return TRUE;
3561+}
3562+
3563+/* ---------------------------------------------------------------------------------------------------- */
3564+
3565+/* update device_is_optical_disc and optical_disc_* properties */
3566+static gboolean
3567+update_info_optical_disc (Device *device)
3568+{
3569+ const gchar *cdrom_disc_state;
3570+ gint cdrom_track_count;
3571+ gint cdrom_track_count_audio;
3572+ gint cdrom_session_count;
3573+
3574+ /* device_is_optical_disc and optical_disc_* */
3575+ if (g_udev_device_has_property (device->priv->d, "ID_CDROM_MEDIA"))
3576+ {
3577+ device_set_device_is_optical_disc (device, TRUE);
3578+
3579+ cdrom_track_count = 0;
3580+ cdrom_track_count_audio = 0;
3581+ cdrom_session_count = 0;
3582+
3583+ if (g_udev_device_has_property (device->priv->d, "ID_CDROM_MEDIA_TRACK_COUNT"))
3584+ cdrom_track_count = g_udev_device_get_property_as_int (device->priv->d, "ID_CDROM_MEDIA_TRACK_COUNT");
3585+ if (g_udev_device_has_property (device->priv->d, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"))
3586+ cdrom_track_count_audio = g_udev_device_get_property_as_int (device->priv->d,
3587+ "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO");
3588+ if (g_udev_device_has_property (device->priv->d, "ID_CDROM_MEDIA_SESSION_COUNT"))
3589+ cdrom_session_count = g_udev_device_get_property_as_int (device->priv->d, "ID_CDROM_MEDIA_SESSION_COUNT");
3590+ device_set_optical_disc_num_tracks (device, cdrom_track_count);
3591+ device_set_optical_disc_num_audio_tracks (device, cdrom_track_count_audio);
3592+ device_set_optical_disc_num_sessions (device, cdrom_session_count);
3593+ cdrom_disc_state = g_udev_device_get_property (device->priv->d, "ID_CDROM_MEDIA_STATE");
3594+ device_set_optical_disc_is_blank (device, g_strcmp0 (cdrom_disc_state, "blank") == 0);
3595+ device_set_optical_disc_is_appendable (device, g_strcmp0 (cdrom_disc_state, "appendable") == 0);
3596+ device_set_optical_disc_is_closed (device, g_strcmp0 (cdrom_disc_state, "complete") == 0);
3597+ }
3598+ else
3599+ {
3600+ device_set_device_is_optical_disc (device, FALSE);
3601+
3602+ device_set_optical_disc_num_tracks (device, 0);
3603+ device_set_optical_disc_num_audio_tracks (device, 0);
3604+ device_set_optical_disc_num_sessions (device, 0);
3605+ device_set_optical_disc_is_blank (device, FALSE);
3606+ device_set_optical_disc_is_appendable (device, FALSE);
3607+ device_set_optical_disc_is_closed (device, FALSE);
3608+ }
3609+
3610+ return TRUE;
3611+}
3612+
3613+/* ---------------------------------------------------------------------------------------------------- */
3614+
3615+/* update device_is_luks and luks_holder properties */
3616+static gboolean
3617+update_info_luks (Device *device)
3618+{
3619+ if (g_strcmp0 (device->priv->id_type, "crypto_LUKS") == 0 && device->priv->holders_objpath->len == 1)
3620+ {
3621+ device_set_device_is_luks (device, TRUE);
3622+ device_set_luks_holder (device, device->priv->holders_objpath->pdata[0]);
3623+ }
3624+ else
3625+ {
3626+ device_set_device_is_luks (device, FALSE);
3627+ device_set_luks_holder (device, NULL);
3628+ }
3629+
3630+ return TRUE;
3631+}
3632+
3633+/* ---------------------------------------------------------------------------------------------------- */
3634+
3635+/* update device_is_luks_cleartext and luks_cleartext_* properties */
3636+static gboolean
3637+update_info_luks_cleartext (Device *device)
3638+{
3639+ uid_t unlocked_by_uid;
3640+ const gchar *dkd_dm_name;
3641+ const gchar *dkd_dm_target_types;
3642+ gboolean ret;
3643+
3644+ ret = FALSE;
3645+
3646+ dkd_dm_name = g_udev_device_get_property (device->priv->d, "DM_NAME");
3647+ dkd_dm_target_types = g_udev_device_get_property (device->priv->d, "UDISKS_DM_TARGETS_TYPE");
3648+ if (dkd_dm_name != NULL && g_strcmp0 (dkd_dm_target_types, "crypt") == 0 && device->priv->slaves_objpath->len == 1)
3649+ {
3650+
3651+ /* TODO: might be racing with setting is_drive earlier */
3652+ device_set_device_is_drive (device, FALSE);
3653+
3654+ if (g_str_has_prefix (dkd_dm_name, "temporary-cryptsetup-"))
3655+ {
3656+ /* ignore temporary devices created by /sbin/cryptsetup */
3657+ goto out;
3658+ }
3659+
3660+ device_set_device_is_luks_cleartext (device, TRUE);
3661+
3662+ device_set_luks_cleartext_slave (device, ((gchar **) device->priv->slaves_objpath->pdata)[0]);
3663+
3664+ if (luks_get_uid_from_dm_name (dkd_dm_name, &unlocked_by_uid))
3665+ {
3666+ device_set_luks_cleartext_unlocked_by_uid (device, unlocked_by_uid);
3667+ }
3668+
3669+ /* TODO: export this at some point */
3670+ device_set_dm_name (device, dkd_dm_name);
3671+ }
3672+ else
3673+ {
3674+ device_set_device_is_luks_cleartext (device, FALSE);
3675+ device_set_luks_cleartext_slave (device, NULL);
3676+ }
3677+
3678+ ret = TRUE;
3679+
3680+ out:
3681+ return ret;
3682+}
3683+
3684+/* ---------------------------------------------------------------------------------------------------- */
3685+
3686+#ifdef HAVE_LVM2
3687+static gchar *
3688+extract_lvm_uuid (const gchar *s)
3689+{
3690+ GString *str;
3691+
3692+ if (s == NULL || strlen (s) < 32)
3693+ return NULL;
3694+
3695+ str = g_string_new_len (s, 6); g_string_append_c (str, '-'); s += 6;
3696+ g_string_append_len (str, s, 4); g_string_append_c (str, '-'); s += 4;
3697+ g_string_append_len (str, s, 4); g_string_append_c (str, '-'); s += 4;
3698+ g_string_append_len (str, s, 4); g_string_append_c (str, '-'); s += 4;
3699+ g_string_append_len (str, s, 4); g_string_append_c (str, '-'); s += 4;
3700+ g_string_append_len (str, s, 4); g_string_append_c (str, '-'); s += 4;
3701+ g_string_append_len (str, s, 6);
3702+
3703+ return g_string_free (str, FALSE);
3704+}
3705+
3706+/* update device_is_linux_lvm2_lv and linux_lvm2_lv_* properties */
3707+static gboolean
3708+update_info_linux_lvm2_lv (Device *device)
3709+{
3710+ const gchar *lv_name;
3711+ const gchar *vg_name;
3712+ const gchar *uuid;
3713+ gchar *lv_uuid;
3714+ gchar *vg_uuid;
3715+ gboolean is_lv;
3716+
3717+ is_lv = FALSE;
3718+ lv_uuid = NULL;
3719+ vg_uuid = NULL;
3720+
3721+ lv_name = g_udev_device_get_property (device->priv->d, "DM_LV_NAME");
3722+ vg_name = g_udev_device_get_property (device->priv->d, "DM_VG_NAME");
3723+
3724+ if (lv_name == NULL || vg_name == NULL)
3725+ goto out;
3726+
3727+ uuid = g_udev_device_get_sysfs_attr (device->priv->d, "dm/uuid");
3728+ if (uuid == NULL || !g_str_has_prefix (uuid, "LVM-"))
3729+ goto out;
3730+
3731+ vg_uuid = extract_lvm_uuid (uuid + 4);
3732+ if (vg_uuid == NULL)
3733+ goto out;
3734+
3735+ lv_uuid = extract_lvm_uuid (uuid + 4 + 32);
3736+ if (lv_uuid == NULL)
3737+ goto out;
3738+
3739+ is_lv = TRUE;
3740+ device_set_linux_lvm2_lv_name (device, lv_name);
3741+ device_set_linux_lvm2_lv_uuid (device, lv_uuid);
3742+ device_set_linux_lvm2_lv_group_name (device, vg_name);
3743+ device_set_linux_lvm2_lv_group_uuid (device, vg_uuid);
3744+
3745+ device_set_device_is_drive (device, FALSE);
3746+ device_set_device_is_partition (device, FALSE);
3747+
3748+ out:
3749+ device_set_device_is_linux_lvm2_lv (device, is_lv);
3750+ g_free (vg_uuid);
3751+ g_free (lv_uuid);
3752+ return TRUE;
3753+}
3754+#endif
3755+
3756+/* ---------------------------------------------------------------------------------------------------- */
3757+
3758+#ifdef HAVE_DMMP
3759+/* update device_is_linux_dmmp and linux_dmmp_* properties */
3760+static gboolean
3761+update_info_linux_dmmp (Device *device)
3762+{
3763+ const gchar *dm_name;
3764+ const gchar* const *target_types;
3765+ const gchar* const *target_parameters;
3766+ gchar *decoded_params;
3767+ gboolean is_dmmp;
3768+ guint n;
3769+ GPtrArray *p;
3770+ Device *component;
3771+ gchar *s;
3772+
3773+ is_dmmp = FALSE;
3774+ p = NULL;
3775+ decoded_params = NULL;
3776+
3777+ dm_name = g_udev_device_get_property (device->priv->d, "DM_NAME");
3778+ if (dm_name == NULL)
3779+ goto out;
3780+
3781+ target_types = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_DM_TARGETS_TYPE");
3782+ if (target_types == NULL || g_strcmp0 (target_types[0], "multipath") != 0)
3783+ goto out;
3784+
3785+ if (device->priv->slaves_objpath->len == 0)
3786+ goto out;
3787+
3788+ target_parameters = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_DM_TARGETS_PARAMS");
3789+ if (target_parameters == NULL || g_strv_length ((gchar **) target_parameters) != 1)
3790+ goto out;
3791+ decoded_params = decode_udev_encoded_string (target_parameters[0]);
3792+
3793+ device_set_linux_dmmp_name (device, dm_name);
3794+
3795+ device_set_linux_dmmp_parameters (device, decoded_params);
3796+
3797+ p = g_ptr_array_new ();
3798+ component = NULL;
3799+ for (n = 0; n < device->priv->slaves_objpath->len; n++)
3800+ {
3801+ const gchar *component_objpath = device->priv->slaves_objpath->pdata[n];
3802+ if (component == NULL)
3803+ {
3804+ component = daemon_local_find_by_object_path (device->priv->daemon, component_objpath);
3805+ }
3806+ g_ptr_array_add (p, (gpointer) component_objpath);
3807+ }
3808+ g_ptr_array_add (p, NULL);
3809+ device_set_linux_dmmp_slaves (device, (GStrv) p->pdata);
3810+
3811+ if (component == NULL)
3812+ goto out;
3813+
3814+ /* Copy only drive properties used for identification to the multipath device. Yes,
3815+ * this means, we'll get serial/wwn clashes but this is already so for each path.
3816+ *
3817+ * Also, clients *should* be smart about things and special-handle linux_dmmp and
3818+ * linux_dmmp_component devices.
3819+ */
3820+ device_set_drive_vendor (device, component->priv->drive_vendor);
3821+ device_set_drive_model (device, component->priv->drive_model);
3822+ device_set_drive_revision (device, component->priv->drive_revision);
3823+ device_set_drive_serial (device, component->priv->drive_serial);
3824+ device_set_drive_wwn (device, component->priv->drive_wwn);
3825+
3826+ /* connection interface */
3827+ device_set_drive_connection_interface (device, "virtual_multipath");
3828+ device_set_drive_connection_speed (device, 0);
3829+
3830+ s = g_strdup_printf ("/dev/mapper/%s", dm_name);
3831+ device_set_device_file_presentation (device, s);
3832+ g_free (s);
3833+
3834+ is_dmmp = TRUE;
3835+
3836+ out:
3837+ g_free (decoded_params);
3838+ if (p != NULL)
3839+ g_ptr_array_free (p, TRUE);
3840+ device_set_device_is_linux_dmmp (device, is_dmmp);
3841+ return TRUE;
3842+}
3843+#endif
3844+
3845+/* ---------------------------------------------------------------------------------------------------- */
3846+
3847+#ifdef HAVE_DMMP
3848+/* updates device_is_partition and partition_* properties for dm-0 "partitions" on a multi-path device */
3849+static gboolean
3850+update_info_partition_on_linux_dmmp (Device *device)
3851+{
3852+ const gchar *dm_name;
3853+ const gchar* const *targets_type;
3854+ const gchar* const *targets_params;
3855+ gchar *params;
3856+ gint linear_slave_major;
3857+ gint linear_slave_minor;
3858+ guint64 offset_sectors;
3859+ Device *linear_slave;
3860+ gchar *s;
3861+
3862+ params = NULL;
3863+
3864+ dm_name = g_udev_device_get_property (device->priv->d, "DM_NAME");
3865+ if (dm_name == NULL)
3866+ goto out;
3867+
3868+ targets_type = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_DM_TARGETS_TYPE");
3869+ /* If we ever need this for other types than "linear", remember to update
3870+ udisks-dm-export.c as well. */
3871+ if (targets_type == NULL || g_strcmp0 (targets_type[0], "linear") != 0)
3872+ goto out;
3873+
3874+ targets_params = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_DM_TARGETS_PARAMS");
3875+ if (targets_params == NULL)
3876+ goto out;
3877+ params = decode_udev_encoded_string (targets_params[0]);
3878+
3879+ if (sscanf (params,
3880+ "%d:%d %" G_GUINT64_FORMAT,
3881+ &linear_slave_major,
3882+ &linear_slave_minor,
3883+ &offset_sectors) != 3)
3884+ goto out;
3885+
3886+ linear_slave = daemon_local_find_by_dev (device->priv->daemon,
3887+ makedev (linear_slave_major, linear_slave_minor));
3888+ if (linear_slave == NULL)
3889+ goto out;
3890+ if (!linear_slave->priv->device_is_linux_dmmp)
3891+ goto out;
3892+
3893+ /* The Partition* properties has been set as part of
3894+ * update_info_partition() by reading UDISKS_PARTITION_*
3895+ * properties.. so here we bascially just update the presentation
3896+ * device file name and and whether the device is a drive.
3897+ */
3898+
3899+ s = g_strdup_printf ("/dev/mapper/%s", dm_name);
3900+ device_set_device_file_presentation (device, s);
3901+ g_free (s);
3902+
3903+ device_set_device_is_drive (device, FALSE);
3904+
3905+ out:
3906+ g_free (params);
3907+ return TRUE;
3908+}
3909+#endif
3910+
3911+/* ---------------------------------------------------------------------------------------------------- */
3912+
3913+#ifdef HAVE_DMMP
3914+/* update device_is_linux_dmmp_component and linux_dmmp_component_* properties */
3915+static gboolean
3916+update_info_linux_dmmp_component (Device *device)
3917+{
3918+ gboolean is_dmmp_component;
3919+
3920+ is_dmmp_component = FALSE;
3921+
3922+ if (device->priv->holders_objpath->len == 1)
3923+ {
3924+ Device *holder;
3925+
3926+ holder = daemon_local_find_by_object_path (device->priv->daemon, device->priv->holders_objpath->pdata[0]);
3927+ if (holder != NULL && holder->priv->device_is_linux_dmmp)
3928+ {
3929+ is_dmmp_component = TRUE;
3930+ device_set_linux_dmmp_component_holder (device, holder->priv->object_path);
3931+ }
3932+ }
3933+
3934+ device_set_device_is_linux_dmmp_component (device, is_dmmp_component);
3935+ return TRUE;
3936+}
3937+#endif
3938+
3939+/* ---------------------------------------------------------------------------------------------------- */
3940+
3941+#ifdef HAVE_LVM2
3942+/* update device_is_linux_lvm2_pv and linux_lvm2_pv_* properties */
3943+static gboolean
3944+update_info_linux_lvm2_pv (Device *device)
3945+{
3946+ const gchar *pv_uuid;
3947+ guint64 pv_num_mda;
3948+ const gchar *vg_name;
3949+ const gchar *vg_uuid;
3950+ gboolean is_pv;
3951+ guint64 vg_size;
3952+ guint64 vg_unallocated_size;
3953+ guint64 vg_extent_size;
3954+ guint64 vg_seqnum;
3955+ const gchar* const *vg_pvs;
3956+ const gchar* const *vg_lvs;
3957+
3958+ pv_uuid = g_udev_device_get_property (device->priv->d, "UDISKS_LVM2_PV_UUID");
3959+ pv_num_mda = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_LVM2_PV_NUM_MDA");
3960+ vg_name = g_udev_device_get_property (device->priv->d, "UDISKS_LVM2_PV_VG_NAME");
3961+ vg_uuid = g_udev_device_get_property (device->priv->d, "UDISKS_LVM2_PV_VG_UUID");
3962+ vg_size = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_LVM2_PV_VG_SIZE");
3963+ vg_unallocated_size = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_LVM2_PV_VG_FREE_SIZE");
3964+ vg_extent_size = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_LVM2_PV_VG_EXTENT_SIZE");
3965+ vg_seqnum = g_udev_device_get_property_as_uint64 (device->priv->d, "UDISKS_LVM2_PV_VG_SEQNUM");
3966+ vg_pvs = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_LVM2_PV_VG_PV_LIST");
3967+ vg_lvs = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_LVM2_PV_VG_LV_LIST");
3968+
3969+ is_pv = FALSE;
3970+
3971+ if (pv_uuid == NULL)
3972+ goto out;
3973+
3974+ is_pv = TRUE;
3975+ device_set_linux_lvm2_pv_uuid (device, pv_uuid);
3976+ device_set_linux_lvm2_pv_num_metadata_areas (device, pv_num_mda);
3977+ device_set_linux_lvm2_pv_group_name (device, vg_name);
3978+ device_set_linux_lvm2_pv_group_uuid (device, vg_uuid);
3979+ device_set_linux_lvm2_pv_group_size (device, vg_size);
3980+ device_set_linux_lvm2_pv_group_unallocated_size (device, vg_unallocated_size);
3981+ device_set_linux_lvm2_pv_group_extent_size (device, vg_extent_size);
3982+ device_set_linux_lvm2_pv_group_sequence_number (device, vg_seqnum);
3983+ device_set_linux_lvm2_pv_group_physical_volumes (device, (GStrv) vg_pvs);
3984+ device_set_linux_lvm2_pv_group_logical_volumes (device, (GStrv) vg_lvs);
3985+
3986+ out:
3987+ device_set_device_is_linux_lvm2_pv (device, is_pv);
3988+ return TRUE;
3989+}
3990+#endif
3991+
3992+/* ---------------------------------------------------------------------------------------------------- */
3993+
3994+/* update device_is_linux_md_component and linux_md_component_* properties */
3995+static gboolean
3996+update_info_linux_md_component (Device *device)
3997+{
3998+ if (g_strcmp0 (device->priv->id_type, "linux_raid_member") == 0)
3999+ {
4000+ const gchar *md_comp_level;
4001+ gint md_comp_num_raid_devices;
4002+ const gchar *md_comp_uuid;
4003+ const gchar *md_comp_home_host;
4004+ const gchar *md_comp_name;
4005+ const gchar *md_comp_version;
4006+ gchar *md_name;
4007+ gchar *s;
4008+ int md_comp_position;
4009+
4010+ md_comp_position = -1;
4011+
4012+ device_set_device_is_linux_md_component (device, TRUE);
4013+
4014+ /* linux_md_component_holder and linux_md_component_state */
4015+ if (device->priv->holders_objpath->len == 1)
4016+ {
4017+ Device *holder;
4018+ gchar **state_tokens;
4019+
4020+ device_set_linux_md_component_holder (device, device->priv->holders_objpath->pdata[0]);
4021+ state_tokens = NULL;
4022+ holder = daemon_local_find_by_object_path (device->priv->daemon, device->priv->holders_objpath->pdata[0]);
4023+ if (holder != NULL && holder->priv->device_is_linux_md)
4024+ {
4025+ gchar *dev_name;
4026+ gchar *md_dev_path;
4027+ gchar *state_contents;
4028+ gchar *slot_contents;
4029+ gint slot_number;
4030+ gchar *endp;
4031+
4032+ dev_name = g_path_get_basename (device->priv->native_path);
4033+ md_dev_path = g_strdup_printf ("%s/md/dev-%s", holder->priv->native_path, dev_name);
4034+ state_contents = sysfs_get_string (md_dev_path, "state");
4035+ g_strstrip (state_contents);
4036+ state_tokens = g_strsplit (state_contents, ",", 0);
4037+
4038+ slot_contents = sysfs_get_string (md_dev_path, "slot");
4039+ g_strstrip (slot_contents);
4040+ slot_number = strtol (slot_contents, &endp, 0);
4041+ if (endp != NULL && *endp == '\0')
4042+ {
4043+ md_comp_position = slot_number;
4044+ }
4045+
4046+ g_free (slot_contents);
4047+ g_free (state_contents);
4048+ g_free (md_dev_path);
4049+ g_free (dev_name);
4050+ }
4051+
4052+ device_set_linux_md_component_state (device, state_tokens);
4053+ g_strfreev (state_tokens);
4054+
4055+ }
4056+ else
4057+ {
4058+ /* no holder, nullify properties */
4059+ device_set_linux_md_component_holder (device, NULL);
4060+ device_set_linux_md_component_state (device, NULL);
4061+ }
4062+
4063+ md_comp_level = g_udev_device_get_property (device->priv->d, "MD_LEVEL");
4064+ md_comp_num_raid_devices = g_udev_device_get_property_as_int (device->priv->d, "MD_DEVICES");
4065+ md_comp_uuid = g_udev_device_get_property (device->priv->d, "MD_UUID");
4066+ md_name = g_strdup (g_udev_device_get_property (device->priv->d, "MD_NAME"));
4067+ s = NULL;
4068+ if (md_name != NULL)
4069+ s = strstr (md_name, ":");
4070+ if (s != NULL)
4071+ {
4072+ *s = '\0';
4073+ md_comp_home_host = md_name;
4074+ md_comp_name = s + 1;
4075+ }
4076+ else
4077+ {
4078+ md_comp_home_host = "";
4079+ md_comp_name = md_name;
4080+ }
4081+ md_comp_version = device->priv->id_version;
4082+
4083+ device_set_linux_md_component_level (device, md_comp_level);
4084+ device_set_linux_md_component_position (device, md_comp_position);
4085+ device_set_linux_md_component_num_raid_devices (device, md_comp_num_raid_devices);
4086+ device_set_linux_md_component_uuid (device, md_comp_uuid);
4087+ device_set_linux_md_component_home_host (device, md_comp_home_host);
4088+ device_set_linux_md_component_name (device, md_comp_name);
4089+ device_set_linux_md_component_version (device, md_comp_version);
4090+
4091+ g_free (md_name);
4092+ }
4093+ else
4094+ {
4095+ device_set_device_is_linux_md_component (device, FALSE);
4096+ device_set_linux_md_component_level (device, NULL);
4097+ device_set_linux_md_component_position (device, -1);
4098+ device_set_linux_md_component_num_raid_devices (device, 0);
4099+ device_set_linux_md_component_uuid (device, NULL);
4100+ device_set_linux_md_component_home_host (device, NULL);
4101+ device_set_linux_md_component_name (device, NULL);
4102+ device_set_linux_md_component_version (device, NULL);
4103+ device_set_linux_md_component_holder (device, NULL);
4104+ device_set_linux_md_component_state (device, NULL);
4105+ }
4106+
4107+ return TRUE;
4108+}
4109+
4110+/* ---------------------------------------------------------------------------------------------------- */
4111+
4112+/* update device_is_linux_md and linux_md_* properties */
4113+static gboolean
4114+update_info_linux_md (Device *device)
4115+{
4116+ gboolean ret;
4117+ guint n;
4118+ gchar *s;
4119+ gchar *p;
4120+
4121+ ret = FALSE;
4122+
4123+ if (sysfs_file_exists (device->priv->native_path, "md"))
4124+ {
4125+ gchar *uuid;
4126+ gint num_raid_devices;
4127+ gchar *raid_level;
4128+ gchar *array_state;
4129+ Device *slave;
4130+ GPtrArray *md_slaves;
4131+ const gchar *md_name;
4132+ const gchar *md_home_host;
4133+
4134+ device_set_device_is_linux_md (device, TRUE);
4135+
4136+ /* figure out if the array is active */
4137+ array_state = sysfs_get_string (device->priv->native_path, "md/array_state");
4138+ if (array_state == NULL)
4139+ {
4140+ g_print ("**** NOTE: Linux MD array %s has no array_state file'; removing\n", device->priv->native_path);
4141+ goto out;
4142+ }
4143+ g_strstrip (array_state);
4144+
4145+ /* ignore clear arrays since these have no devices, no size, no level */
4146+ if (strcmp (array_state, "clear") == 0)
4147+ {
4148+ g_print ("**** NOTE: Linux MD array %s is 'clear'; removing\n", device->priv->native_path);
4149+ g_free (array_state);
4150+ goto out;
4151+ }
4152+
4153+ device_set_linux_md_state (device, array_state);
4154+ g_free (array_state);
4155+
4156+ /* find a slave from the array */
4157+ slave = NULL;
4158+ for (n = 0; n < device->priv->slaves_objpath->len; n++)
4159+ {
4160+ const gchar *slave_objpath;
4161+
4162+ slave_objpath = device->priv->slaves_objpath->pdata[n];
4163+ slave = daemon_local_find_by_object_path (device->priv->daemon, slave_objpath);
4164+ if (slave != NULL)
4165+ break;
4166+ }
4167+
4168+ uuid = g_strdup (g_udev_device_get_property (device->priv->d, "MD_UUID"));
4169+ num_raid_devices = sysfs_get_int (device->priv->native_path, "md/raid_disks");
4170+ raid_level = g_strstrip (sysfs_get_string (device->priv->native_path, "md/level"));
4171+
4172+ if (slave != NULL)
4173+ {
4174+ /* if the UUID isn't set by the udev rules (array may be inactive) get it from a slave */
4175+ if (uuid == NULL || strlen (uuid) == 0)
4176+ {
4177+ g_free (uuid);
4178+ uuid = g_strdup (slave->priv->linux_md_component_uuid);
4179+ }
4180+
4181+ /* ditto for raid level */
4182+ if (raid_level == NULL || strlen (raid_level) == 0)
4183+ {
4184+ g_free (raid_level);
4185+ raid_level = g_strdup (slave->priv->linux_md_component_level);
4186+ }
4187+
4188+ /* and num_raid_devices too */
4189+ if (device->priv->linux_md_num_raid_devices == 0)
4190+ {
4191+ num_raid_devices = slave->priv->linux_md_component_num_raid_devices;
4192+ }
4193+ }
4194+
4195+ device_set_linux_md_uuid (device, uuid);
4196+ device_set_linux_md_num_raid_devices (device, num_raid_devices);
4197+ device_set_linux_md_level (device, raid_level);
4198+ g_free (raid_level);
4199+ g_free (uuid);
4200+
4201+ /* infer the array name and homehost */
4202+ p = g_strdup (g_udev_device_get_property (device->priv->d, "MD_NAME"));
4203+ s = NULL;
4204+ if (p != NULL)
4205+ s = strstr (p, ":");
4206+ if (s != NULL)
4207+ {
4208+ *s = '\0';
4209+ md_home_host = p;
4210+ md_name = s + 1;
4211+ }
4212+ else
4213+ {
4214+ md_home_host = "";
4215+ md_name = p;
4216+ }
4217+ device_set_linux_md_home_host (device, md_home_host);
4218+ device_set_linux_md_name (device, md_name);
4219+ g_free (p);
4220+
4221+ s = g_strstrip (sysfs_get_string (device->priv->native_path, "md/metadata_version"));
4222+ device_set_linux_md_version (device, s);
4223+ g_free (s);
4224+
4225+ /* Go through all block slaves and build up the linux_md_slaves property
4226+ *
4227+ * Also update the slaves since the slave state may have changed.
4228+ */
4229+ md_slaves = g_ptr_array_new ();
4230+ for (n = 0; n < device->priv->slaves_objpath->len; n++)
4231+ {
4232+ Device *slave_device;
4233+ const gchar *slave_objpath;
4234+
4235+ slave_objpath = device->priv->slaves_objpath->pdata[n];
4236+ g_ptr_array_add (md_slaves, (gpointer) slave_objpath);
4237+ slave_device = daemon_local_find_by_object_path (device->priv->daemon, slave_objpath);
4238+ if (slave_device != NULL)
4239+ {
4240+ update_info (slave_device);
4241+ }
4242+ }
4243+ g_ptr_array_sort (md_slaves, (GCompareFunc) ptr_str_array_compare);
4244+ g_ptr_array_add (md_slaves, NULL);
4245+ device_set_linux_md_slaves (device, (GStrv) md_slaves->pdata);
4246+ g_ptr_array_free (md_slaves, TRUE);
4247+
4248+ /* TODO: may race */
4249+ device_set_drive_vendor (device, "Linux");
4250+ if (device->priv->linux_md_level != NULL)
4251+ s = g_strdup_printf ("Software RAID %s", device->priv->linux_md_level);
4252+ else
4253+ s = g_strdup_printf ("Software RAID");
4254+ device_set_drive_model (device, s);
4255+ g_free (s);
4256+ device_set_drive_revision (device, device->priv->linux_md_version);
4257+ device_set_drive_connection_interface (device, "virtual");
4258+ device_set_drive_serial (device, device->priv->linux_md_uuid);
4259+
4260+ /* RAID-0 can never resync or run degraded */
4261+ if (g_strcmp0 (device->priv->linux_md_level, "raid0") == 0 || g_strcmp0 (device->priv->linux_md_level, "linear")
4262+ == 0)
4263+ {
4264+ device_set_linux_md_sync_action (device, "idle");
4265+ device_set_linux_md_is_degraded (device, FALSE);
4266+ }
4267+ else
4268+ {
4269+ gchar *degraded_file;
4270+ gint num_degraded_devices;
4271+
4272+ degraded_file = sysfs_get_string (device->priv->native_path, "md/degraded");
4273+ if (degraded_file == NULL)
4274+ {
4275+ num_degraded_devices = 0;
4276+ }
4277+ else
4278+ {
4279+ num_degraded_devices = strtol (degraded_file, NULL, 0);
4280+ }
4281+ g_free (degraded_file);
4282+
4283+ device_set_linux_md_is_degraded (device, (num_degraded_devices > 0));
4284+
4285+ s = g_strstrip (sysfs_get_string (device->priv->native_path, "md/sync_action"));
4286+ device_set_linux_md_sync_action (device, s);
4287+ g_free (s);
4288+
4289+ if (device->priv->linux_md_sync_action == NULL || strlen (device->priv->linux_md_sync_action) == 0)
4290+ {
4291+ device_set_linux_md_sync_action (device, "idle");
4292+ }
4293+
4294+ /* if not idle; update percentage and speed */
4295+ if (g_strcmp0 (device->priv->linux_md_sync_action, "idle") != 0)
4296+ {
4297+ char *s;
4298+ guint64 done;
4299+ guint64 remaining;
4300+
4301+ s = g_strstrip (sysfs_get_string (device->priv->native_path, "md/sync_completed"));
4302+ if (sscanf (s, "%" G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT "", &done, &remaining) == 2)
4303+ {
4304+ device_set_linux_md_sync_percentage (device, 100.0 * ((double) done) / ((double) remaining));
4305+ }
4306+ else
4307+ {
4308+ g_warning ("cannot parse md/sync_completed for %s: '%s'", device->priv->native_path, s);
4309+ }
4310+ g_free (s);
4311+
4312+ device_set_linux_md_sync_speed (device, 1000L * sysfs_get_uint64 (device->priv->native_path,
4313+ "md/sync_speed"));
4314+
4315+ /* Since the kernel doesn't emit uevents while the job is pending, set up
4316+ * a timeout for every two seconds to synthesize the change event so we can
4317+ * refresh the completed/speed properties.
4318+ */
4319+ if (device->priv->linux_md_poll_timeout_id == 0)
4320+ {
4321+ device->priv->linux_md_poll_timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
4322+ 2,
4323+ poll_syncing_md_device,
4324+ g_object_ref (device),
4325+ g_object_unref);
4326+ }
4327+ }
4328+ else
4329+ {
4330+ device_set_linux_md_sync_percentage (device, 0.0);
4331+ device_set_linux_md_sync_speed (device, 0);
4332+ }
4333+ }
4334+
4335+ }
4336+ else
4337+ {
4338+ device_set_device_is_linux_md (device, FALSE);
4339+ device_set_linux_md_state (device, NULL);
4340+ device_set_linux_md_level (device, NULL);
4341+ device_set_linux_md_num_raid_devices (device, 0);
4342+ device_set_linux_md_uuid (device, NULL);
4343+ device_set_linux_md_home_host (device, NULL);
4344+ device_set_linux_md_name (device, NULL);
4345+ device_set_linux_md_version (device, NULL);
4346+ device_set_linux_md_slaves (device, NULL);
4347+ device_set_linux_md_is_degraded (device, FALSE);
4348+ device_set_linux_md_sync_action (device, NULL);
4349+ device_set_linux_md_sync_percentage (device, 0.0);
4350+ device_set_linux_md_sync_speed (device, 0);
4351+ }
4352+
4353+ ret = TRUE;
4354+
4355+ out:
4356+ return ret;
4357+}
4358+
4359+/* ---------------------------------------------------------------------------------------------------- */
4360+
4361+/* update drive_ata_smart_* properties */
4362+static gboolean
4363+update_info_drive_ata_smart (Device *device)
4364+{
4365+ gboolean ata_smart_is_available;
4366+
4367+ ata_smart_is_available = FALSE;
4368+ if (device->priv->device_is_drive && g_udev_device_has_property (device->priv->d, "UDISKS_ATA_SMART_IS_AVAILABLE"))
4369+ ata_smart_is_available = g_udev_device_get_property_as_boolean (device->priv->d, "UDISKS_ATA_SMART_IS_AVAILABLE");
4370+
4371+ device_set_drive_ata_smart_is_available (device, ata_smart_is_available);
4372+
4373+ /* NOTE: we don't collect ATA SMART data here, we only set whether the device is ATA SMART capable;
4374+ * collecting data is done in separate routines, see the
4375+ * device_drive_ata_smart_refresh_data() function for details.
4376+ */
4377+
4378+ return TRUE;
4379+}
4380+
4381+/* ---------------------------------------------------------------------------------------------------- */
4382+
4383+/* device_is_system_internal */
4384+static gboolean
4385+update_info_is_system_internal (Device *device)
4386+{
4387+ gboolean is_system_internal;
4388+
4389+ /* TODO: make it possible to override this property from a udev property.
4390+ */
4391+
4392+ /* start out by assuming the device is system internal, then adjust depending on what kind of
4393+ * device we are dealing with
4394+ */
4395+ is_system_internal = TRUE;
4396+
4397+ /* A Linux MD device is system internal if, and only if
4398+ *
4399+ * - a single component is system internal
4400+ * - there are no components
4401+ */
4402+ if (device->priv->device_is_linux_md)
4403+ {
4404+ is_system_internal = FALSE;
4405+
4406+ if (device->priv->slaves_objpath->len == 0)
4407+ {
4408+ is_system_internal = TRUE;
4409+ }
4410+ else
4411+ {
4412+ guint n;
4413+
4414+ for (n = 0; n < device->priv->slaves_objpath->len; n++)
4415+ {
4416+ const gchar *slave_objpath;
4417+ Device *slave;
4418+
4419+ slave_objpath = device->priv->slaves_objpath->pdata[n];
4420+ slave = daemon_local_find_by_object_path (device->priv->daemon, slave_objpath);
4421+ if (slave == NULL)
4422+ continue;
4423+
4424+ if (slave->priv->device_is_system_internal)
4425+ {
4426+ is_system_internal = TRUE;
4427+ break;
4428+ }
4429+ }
4430+ }
4431+
4432+ goto determined;
4433+ }
4434+
4435+ /* a partition is system internal only if the drive it belongs to is system internal */
4436+ if (device->priv->device_is_partition)
4437+ {
4438+ Device *enclosing_device;
4439+
4440+ enclosing_device = daemon_local_find_by_object_path (device->priv->daemon, device->priv->partition_slave);
4441+ if (enclosing_device != NULL)
4442+ {
4443+ is_system_internal = enclosing_device->priv->device_is_system_internal;
4444+ }
4445+ else
4446+ {
4447+ is_system_internal = TRUE;
4448+ }
4449+
4450+ goto determined;
4451+ }
4452+
4453+ /* a LUKS cleartext device is system internal only if the underlying crypto-text
4454+ * device is system internal
4455+ */
4456+ if (device->priv->device_is_luks_cleartext)
4457+ {
4458+ Device *enclosing_device;
4459+ enclosing_device = daemon_local_find_by_object_path (device->priv->daemon, device->priv->luks_cleartext_slave);
4460+ if (enclosing_device != NULL)
4461+ {
4462+ is_system_internal = enclosing_device->priv->device_is_system_internal;
4463+ }
4464+ else
4465+ {
4466+ is_system_internal = TRUE;
4467+ }
4468+
4469+ goto determined;
4470+ }
4471+
4472+ /* devices with removable media are never system internal */
4473+ if (device->priv->device_is_removable)
4474+ {
4475+ is_system_internal = FALSE;
4476+ goto determined;
4477+ }
4478+
4479+ /* devices on certain buses are never system internal */
4480+ if (device->priv->device_is_drive && device->priv->drive_connection_interface != NULL)
4481+ {
4482+
4483+ if (strcmp (device->priv->drive_connection_interface, "ata_serial_esata") == 0
4484+ || strcmp (device->priv->drive_connection_interface, "sdio") == 0
4485+ || strcmp (device->priv->drive_connection_interface, "usb") == 0
4486+ || strcmp (device->priv->drive_connection_interface, "firewire") == 0)
4487+ {
4488+ is_system_internal = FALSE;
4489+ }
4490+ else
4491+ {
4492+ is_system_internal = TRUE;
4493+ }
4494+ goto determined;
4495+ }
4496+
4497+ determined:
4498+ device_set_device_is_system_internal (device, is_system_internal);
4499+
4500+ return TRUE;
4501+}
4502+
4503+/* ---------------------------------------------------------------------------------------------------- */
4504+
4505+/* device_is_mounted, device_mount, device_mounted_by_uid */
4506+static gboolean
4507+update_info_mount_state (Device *device)
4508+{
4509+ MountMonitor *monitor;
4510+ GList *mounts;
4511+ gboolean was_mounted;
4512+
4513+ mounts = NULL;
4514+
4515+ /* defer setting the mount point until FilesystemMount returns and
4516+ * the mounts file is written
4517+ */
4518+ if (device->priv->job_in_progress && g_strcmp0 (device->priv->job_id, "FilesystemMount") == 0)
4519+ goto out;
4520+
4521+ monitor = daemon_local_get_mount_monitor (device->priv->daemon);
4522+
4523+ mounts = mount_monitor_get_mounts_for_dev (monitor, device->priv->dev);
4524+
4525+ was_mounted = device->priv->device_is_mounted;
4526+
4527+ if (mounts != NULL)
4528+ {
4529+ GList *l;
4530+ guint n;
4531+ gchar **mount_paths;
4532+
4533+ mount_paths = g_new0 (gchar *, g_list_length (mounts) + 1);
4534+ for (l = mounts, n = 0; l != NULL; l = l->next, n++)
4535+ {
4536+ mount_paths[n] = g_strdup (mount_get_mount_path (MOUNT (l->data)));
4537+ }
4538+
4539+ device_set_device_is_mounted (device, TRUE);
4540+ device_set_device_mount_paths (device, mount_paths);
4541+ if (!was_mounted)
4542+ {
4543+ uid_t mounted_by_uid;
4544+
4545+ if (!mount_file_has_device (device->priv->device_file, &mounted_by_uid, NULL))
4546+ mounted_by_uid = 0;
4547+ device_set_device_mounted_by_uid (device, mounted_by_uid);
4548+ }
4549+
4550+ g_strfreev (mount_paths);
4551+
4552+ }
4553+ else
4554+ {
4555+ gboolean remove_dir_on_unmount;
4556+ gchar *old_mount_path;
4557+
4558+ old_mount_path = NULL;
4559+ if (device->priv->device_mount_paths->len > 0)
4560+ old_mount_path = g_strdup (((gchar **) device->priv->device_mount_paths->pdata)[0]);
4561+
4562+ device_set_device_is_mounted (device, FALSE);
4563+ device_set_device_mount_paths (device, NULL);
4564+ device_set_device_mounted_by_uid (device, 0);
4565+
4566+ /* clean up stale mount directory */
4567+ remove_dir_on_unmount = FALSE;
4568+ if (was_mounted && mount_file_has_device (device->priv->device_file, NULL, &remove_dir_on_unmount))
4569+ {
4570+ mount_file_remove (device->priv->device_file, old_mount_path);
4571+ if (remove_dir_on_unmount)
4572+ {
4573+ if (g_rmdir (old_mount_path) != 0)
4574+ {
4575+ g_warning ("Error removing dir '%s' on unmount: %m", old_mount_path);
4576+ }
4577+ }
4578+ }
4579+
4580+ g_free (old_mount_path);
4581+
4582+ }
4583+
4584+ out:
4585+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
4586+ g_list_free (mounts);
4587+
4588+ return TRUE;
4589+}
4590+
4591+/* ---------------------------------------------------------------------------------------------------- */
4592+
4593+/* device_is_media_change_detected, device_is_media_change_detection_* properties */
4594+static gboolean
4595+update_info_media_detection (Device *device)
4596+{
4597+ gboolean detected;
4598+ gboolean polling;
4599+ gboolean inhibitable;
4600+ gboolean inhibited;
4601+
4602+ detected = FALSE;
4603+ polling = FALSE;
4604+ inhibitable = FALSE;
4605+ inhibited = FALSE;
4606+
4607+ if (device->priv->device_is_removable)
4608+ {
4609+ guint64 evt_media_change;
4610+ GUdevDevice *parent;
4611+
4612+ evt_media_change = sysfs_get_uint64 (device->priv->native_path, "../../evt_media_change");
4613+ if (evt_media_change & 1)
4614+ {
4615+ /* SATA AN capabable drive */
4616+
4617+ polling = FALSE;
4618+ detected = TRUE;
4619+ goto determined;
4620+ }
4621+
4622+ parent = g_udev_device_get_parent_with_subsystem (device->priv->d, "platform", NULL);
4623+ if (parent != NULL)
4624+ {
4625+ /* never poll PC floppy drives, they are noisy (fdo #22149) */
4626+ if (g_str_has_prefix (g_udev_device_get_name (parent), "floppy."))
4627+ {
4628+ g_object_unref (parent);
4629+ goto determined;
4630+ }
4631+ g_object_unref (parent);
4632+ }
4633+
4634+ /* assume the device needs polling */
4635+ polling = TRUE;
4636+ inhibitable = TRUE;
4637+
4638+ /* custom udev rules might want to disable polling for known-broken
4639+ * devices (fdo #26508) */
4640+ if (g_udev_device_has_property (device->priv->d, "UDISKS_DISABLE_POLLING") &&
4641+ g_udev_device_get_property_as_boolean (device->priv->d, "UDISKS_DISABLE_POLLING"))
4642+ polling = FALSE;
4643+
4644+ if (device->priv->polling_inhibitors != NULL || daemon_local_has_polling_inhibitors (device->priv->daemon))
4645+ {
4646+
4647+ detected = FALSE;
4648+ inhibited = TRUE;
4649+ }
4650+ else
4651+ {
4652+ detected = TRUE;
4653+ inhibited = FALSE;
4654+ }
4655+ }
4656+
4657+ determined:
4658+ device_set_device_is_media_change_detected (device, detected);
4659+ device_set_device_is_media_change_detection_polling (device, polling);
4660+ device_set_device_is_media_change_detection_inhibitable (device, inhibitable);
4661+ device_set_device_is_media_change_detection_inhibited (device, inhibited);
4662+
4663+ return TRUE;
4664+}
4665+
4666+/* ---------------------------------------------------------------------------------------------------- */
4667+
4668+/* drive_adapter property */
4669+static gboolean
4670+update_info_drive_adapter (Device *device)
4671+{
4672+ Adapter *adapter;
4673+ const gchar *adapter_object_path;
4674+
4675+ adapter_object_path = NULL;
4676+
4677+ adapter = daemon_local_find_enclosing_adapter (device->priv->daemon, device->priv->native_path);
4678+ if (adapter != NULL)
4679+ {
4680+ adapter_object_path = adapter_local_get_object_path (adapter);
4681+ }
4682+
4683+ device_set_drive_adapter (device, adapter_object_path);
4684+
4685+ return TRUE;
4686+}
4687+
4688+/* drive_ports property */
4689+static gboolean
4690+update_info_drive_ports (Device *device)
4691+{
4692+ GList *ports;
4693+ GList *l;
4694+ GPtrArray *p;
4695+
4696+ ports = daemon_local_find_enclosing_ports (device->priv->daemon, device->priv->native_path);
4697+
4698+ p = g_ptr_array_new ();
4699+ for (l = ports; l != NULL; l = l->next)
4700+ {
4701+ Port *port = PORT (l->data);
4702+
4703+ g_ptr_array_add (p, (gpointer) port_local_get_object_path (port));
4704+ }
4705+ g_ptr_array_add (p, NULL);
4706+ device_set_drive_ports (device, (GStrv) p->pdata);
4707+ g_ptr_array_unref (p);
4708+
4709+ g_list_free (ports);
4710+
4711+ return TRUE;
4712+}
4713+
4714+/* drive_similar_devices property */
4715+static gboolean
4716+update_info_drive_similar_devices (Device *device)
4717+{
4718+ GList *devices;
4719+ GList *l;
4720+ GPtrArray *p;
4721+
4722+ p = g_ptr_array_new ();
4723+
4724+ if (!device->priv->device_is_drive)
4725+ goto out;
4726+
4727+ /* We need non-empty SERIAL and WWN for this to work */
4728+ if ((device->priv->drive_serial == NULL || strlen (device->priv->drive_serial) == 0) ||
4729+ (device->priv->drive_wwn == NULL || strlen (device->priv->drive_wwn) == 0))
4730+ goto out;
4731+
4732+ /* TODO: this might be slow - if so, use a hash on the Daemon class */
4733+ devices = daemon_local_get_all_devices (device->priv->daemon);
4734+ for (l = devices; l != NULL; l = l->next)
4735+ {
4736+ Device *d = DEVICE (l->data);
4737+
4738+ if (!d->priv->device_is_drive)
4739+ continue;
4740+
4741+ if (d == device)
4742+ continue;
4743+
4744+#if 0
4745+ g_debug ("looking at %s:\n"
4746+ " %s\n"
4747+ " %s\n"
4748+ " %s\n"
4749+ " %s\n",
4750+ d->priv->device_file,
4751+ d->priv->drive_serial,
4752+ device->priv->drive_serial,
4753+ d->priv->drive_wwn,
4754+ device->priv->drive_wwn);
4755+#endif
4756+
4757+ /* current policy is that *both* SERIAL and WWN must match */
4758+ if (g_strcmp0 (d->priv->drive_serial, device->priv->drive_serial) == 0 &&
4759+ g_strcmp0 (d->priv->drive_wwn, device->priv->drive_wwn) == 0)
4760+ {
4761+ g_ptr_array_add (p, d->priv->object_path);
4762+
4763+ /* ensure that the device we added also exists in its own drive_similar_devices property */
4764+ if (!ptr_array_has_string (d->priv->drive_similar_devices, device->priv->object_path))
4765+ {
4766+ //g_debug ("\n************************************************************\nforcing update in idle");
4767+ update_info_in_idle (d);
4768+ }
4769+ else
4770+ {
4771+ //g_debug ("\n************************************************************\nNOT forcing update in idle");
4772+ }
4773+ }
4774+ }
4775+
4776+ out:
4777+ g_ptr_array_add (p, NULL);
4778+ device_set_drive_similar_devices (device, (GStrv) p->pdata);
4779+ g_ptr_array_free (p, TRUE);
4780+ return TRUE;
4781+}
4782+
4783+/* ---------------------------------------------------------------------------------------------------- */
4784+
4785+/* update device_is_linux_loop and linux_loop_* properties */
4786+static gboolean
4787+update_info_linux_loop (Device *device)
4788+{
4789+ gboolean ret;
4790+ gint fd;
4791+ struct loop_info64 loop_info_buf;
4792+ gboolean is_loop;
4793+ gchar *s;
4794+ gchar *s2;
4795+
4796+ is_loop = FALSE;
4797+ ret = FALSE;
4798+ fd = -1;
4799+
4800+ if (!g_str_has_prefix (device->priv->native_path, "/sys/devices/virtual/block/loop"))
4801+ {
4802+ ret = TRUE;
4803+ goto out;
4804+ }
4805+
4806+ fd = open (device->priv->device_file, O_RDONLY);
4807+ if (fd < 0)
4808+ goto out;
4809+
4810+ if (ioctl (fd, LOOP_GET_STATUS64, &loop_info_buf) != 0)
4811+ goto out;
4812+
4813+ /* TODO: is lo_file_name really NUL-terminated? */
4814+ device_set_linux_loop_filename (device, (const gchar *) loop_info_buf.lo_file_name);
4815+
4816+ ret = TRUE;
4817+ is_loop = TRUE;
4818+
4819+ device_set_drive_vendor (device, "Linux");
4820+ s2 = g_path_get_basename ((gchar *) loop_info_buf.lo_file_name);
4821+ s = g_strdup_printf ("Loop: %s", s2);
4822+ g_free (s2);
4823+ device_set_drive_model (device, s);
4824+ g_free (s);
4825+
4826+ out:
4827+ if (fd > 0)
4828+ close (fd);
4829+ device_set_device_is_linux_loop (device, is_loop);
4830+ return ret;
4831+}
4832+
4833+/* ---------------------------------------------------------------------------------------------------- */
4834+
4835+typedef struct
4836+{
4837+ guint idle_id;
4838+ Device *device;
4839+} UpdateInfoInIdleData;
4840+
4841+static void
4842+update_info_in_idle_device_unreffed (gpointer user_data,
4843+ GObject *where_the_object_was)
4844+{
4845+ UpdateInfoInIdleData *data = user_data;
4846+ g_source_remove (data->idle_id);
4847+}
4848+
4849+static void
4850+update_info_in_idle_data_free (UpdateInfoInIdleData *data)
4851+{
4852+ g_object_weak_unref (G_OBJECT (data->device), update_info_in_idle_device_unreffed, data);
4853+ g_free (data);
4854+}
4855+
4856+static gboolean
4857+update_info_in_idle_cb (gpointer user_data)
4858+{
4859+ UpdateInfoInIdleData *data = user_data;
4860+
4861+ /* this indirectly calls update_info and also removes the device
4862+ * if it wants to be removed (e.g. if update_info() returns FALSE)
4863+ */
4864+ daemon_local_synthesize_changed (data->device->priv->daemon, data->device);
4865+
4866+ return FALSE; /* remove source */
4867+}
4868+
4869+/**
4870+ * update_info_in_idle:
4871+ * @device: A #Device.
4872+ *
4873+ * Like update_info() but does the update in idle. Takes a weak ref to
4874+ * @device and cancels the update if @device is unreffed.
4875+ */
4876+static void
4877+update_info_in_idle (Device *device)
4878+{
4879+ UpdateInfoInIdleData *data;
4880+
4881+ data = g_new0 (UpdateInfoInIdleData, 1);
4882+ data->device = device;
4883+ data->idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
4884+ update_info_in_idle_cb,
4885+ data,
4886+ (GDestroyNotify) update_info_in_idle_data_free);
4887+
4888+ g_object_weak_ref (G_OBJECT (device), update_info_in_idle_device_unreffed, data);
4889+}
4890+
4891+/**
4892+ * update_info:
4893+ * @device: the device
4894+ *
4895+ * Update information about the device.
4896+ *
4897+ * If one or more properties changed, the changes are scheduled to be emitted. Use
4898+ * drain_pending_changes() to force emitting the pending changes (which is useful
4899+ * before returning the result of an operation).
4900+ *
4901+ * Returns: #TRUE to keep (or add) the device; #FALSE to ignore (or remove) the device
4902+ **/
4903+static gboolean
4904+update_info (Device *device)
4905+{
4906+ char *s;
4907+ guint n;
4908+ gboolean ret;
4909+ char *path;
4910+ GDir *dir;
4911+ const char *name;
4912+ GList *l;
4913+ GList *old_slaves_objpath;
4914+ GList *old_holders_objpath;
4915+ GList *cur_slaves_objpath;
4916+ GList *cur_holders_objpath;
4917+ GList *added_objpath;
4918+ GList *removed_objpath;
4919+ GPtrArray *symlinks_by_id;
4920+ GPtrArray *symlinks_by_path;
4921+ GPtrArray *slaves;
4922+ GPtrArray *holders;
4923+ gint major;
4924+ gint minor;
4925+ gboolean media_available;
4926+
4927+ ret = FALSE;
4928+
4929+ PROFILE ("update_info(device=%s) start", device->priv->native_path);
4930+
4931+ g_print ("**** UPDATING %s\n", device->priv->native_path);
4932+
4933+ /* need the slaves/holders to synthesize 'change' events if a device goes away (since the kernel
4934+ * doesn't do generate these)
4935+ */
4936+ old_slaves_objpath = dup_list_from_ptrarray (device->priv->slaves_objpath);
4937+ old_holders_objpath = dup_list_from_ptrarray (device->priv->holders_objpath);
4938+
4939+ /* drive identification */
4940+ if (sysfs_file_exists (device->priv->native_path, "range"))
4941+ {
4942+ device_set_device_is_drive (device, TRUE);
4943+ }
4944+ else
4945+ {
4946+ device_set_device_is_drive (device, FALSE);
4947+ }
4948+
4949+ if (!g_udev_device_has_property (device->priv->d, "MAJOR") || !g_udev_device_has_property (device->priv->d, "MINOR"))
4950+ {
4951+ g_warning ("No major/minor for %s", device->priv->native_path);
4952+ goto out;
4953+ }
4954+
4955+ /* ignore dm devices that are suspended */
4956+ if (g_str_has_prefix (g_udev_device_get_name (device->priv->d), "dm-"))
4957+ {
4958+ if (g_strcmp0 (g_udev_device_get_property (device->priv->d, "DM_SUSPENDED"), "1") == 0)
4959+ goto out;
4960+ }
4961+
4962+ major = g_udev_device_get_property_as_int (device->priv->d, "MAJOR");
4963+ minor = g_udev_device_get_property_as_int (device->priv->d, "MINOR");
4964+ device->priv->dev = makedev (major, minor);
4965+
4966+ device_set_device_file (device, g_udev_device_get_device_file (device->priv->d));
4967+ if (device->priv->device_file == NULL)
4968+ {
4969+ g_warning ("No device file for %s", device->priv->native_path);
4970+ goto out;
4971+ }
4972+
4973+ const char * const * symlinks;
4974+ symlinks = g_udev_device_get_device_file_symlinks (device->priv->d);
4975+ symlinks_by_id = g_ptr_array_new ();
4976+ symlinks_by_path = g_ptr_array_new ();
4977+ for (n = 0; symlinks[n] != NULL; n++)
4978+ {
4979+ if (g_str_has_prefix (symlinks[n], "/dev/disk/by-id/") || g_str_has_prefix (symlinks[n], "/dev/disk/by-uuid/"))
4980+ {
4981+ g_ptr_array_add (symlinks_by_id, (gpointer) symlinks[n]);
4982+ }
4983+ else if (g_str_has_prefix (symlinks[n], "/dev/disk/by-path/"))
4984+ {
4985+ g_ptr_array_add (symlinks_by_path, (gpointer) symlinks[n]);
4986+ }
4987+ }
4988+ g_ptr_array_sort (symlinks_by_id, (GCompareFunc) ptr_str_array_compare);
4989+ g_ptr_array_sort (symlinks_by_path, (GCompareFunc) ptr_str_array_compare);
4990+ g_ptr_array_add (symlinks_by_id, NULL);
4991+ g_ptr_array_add (symlinks_by_path, NULL);
4992+ device_set_device_file_by_id (device, (GStrv) symlinks_by_id->pdata);
4993+ device_set_device_file_by_path (device, (GStrv) symlinks_by_path->pdata);
4994+ g_ptr_array_free (symlinks_by_id, TRUE);
4995+ g_ptr_array_free (symlinks_by_path, TRUE);
4996+
4997+ device_set_device_is_removable (device, (sysfs_get_int (device->priv->native_path, "removable") != 0));
4998+
4999+ /* device_is_media_available and device_media_detection_time property */
5000+ if (device->priv->device_is_removable)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: