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

Subscribers

People subscribed via source and target branches

to all changes: