1 /***************************************************************************
2  * CVSID: $Id$
3  *
4  * libhal-storage.c : HAL convenience library for storage devices and volumes
5  *
6  * Copyright (C) 2004 Red Hat, Inc.
7  *
8  * Author: David Zeuthen <davidz@redhat.com>
9  *
10  * Licensed under the Academic Free License version 2.1
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
25  *
26  **************************************************************************/
27 
28 #ifdef HAVE_CONFIG_H
29 #  include <config.h>
30 #endif
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <dbus/dbus.h>
36 
37 #include <libhal.h>
38 #include "libhal-storage.h"
39 
40 
41 #ifdef ENABLE_NLS
42 # include <libintl.h>
43 # define _(String) dgettext (GETTEXT_PACKAGE, String)
44 # ifdef gettext_noop
45 #   define N_(String) gettext_noop (String)
46 # else
47 #   define N_(String) (String)
48 # endif
49 #else
50 /* Stubs that do something close enough.  */
51 # define textdomain(String) (String)
52 # define gettext(String) (String)
53 # define dgettext(Domain,Message) (Message)
54 # define dcgettext(Domain,Message,Type) (Message)
55 # define bindtextdomain(Domain,Directory) (Domain)
56 # define _(String) (String)
57 # define N_(String) (String)
58 #endif
59 
60 typedef struct IconMappingEntry_s {
61 	LibHalStoragePolicyIcon icon;
62 	char *path;
63 	struct IconMappingEntry_s *next;
64 } IconMappingEntry;
65 
66 struct LibHalStoragePolicy_s {
67 	IconMappingEntry *icon_mappings;
68 };
69 
70 LibHalStoragePolicy *
71 libhal_storage_policy_new ()
72 {
73 	LibHalStoragePolicy *p;
74 
75 	p = malloc (sizeof (LibHalStoragePolicy));
76 	if (p == NULL)
77 		goto out;
78 
79 	p->icon_mappings = NULL;
80 out:
81 	return p;
82 }
83 
84 void
85 libhal_storage_policy_free (LibHalStoragePolicy *policy)
86 {
87 	IconMappingEntry *i;
88 	IconMappingEntry *j;
89 
90 	/* free all icon mappings */
91 	for (i = policy->icon_mappings; i != NULL; i = j) {
92 		j = i->next;
93 		free (i->path);
94 		free (i);
95 	}
96 
97 	free (policy);
98 }
99 
100 void
101 libhal_storage_policy_set_icon_path (LibHalStoragePolicy *policy, LibHalStoragePolicyIcon icon, const char *path)
102 {
103 	IconMappingEntry *i;
104 
105 	/* see if it already exist */
106 	for (i = policy->icon_mappings; i != NULL; i = i->next) {
107 		if (i->icon == icon) {
108 			free (i->path);
109 			i->path = strdup (path);
110 			goto out;
111 		}
112 	}
113 
114 	i = malloc (sizeof (IconMappingEntry));
115 	if (i == NULL)
116 		goto out;
117 	i->icon = icon;
118 	i->path = strdup (path);
119 	i->next = policy->icon_mappings;
120 	policy->icon_mappings = i;
121 
122 out:
123 	return;
124 }
125 
126 void
127 libhal_storage_policy_set_icon_mapping (LibHalStoragePolicy *policy, LibHalStoragePolicyIconPair *pairs)
128 {
129 	LibHalStoragePolicyIconPair *i;
130 
131 	for (i = pairs; i->icon != 0x00; i++) {
132 		libhal_storage_policy_set_icon_path (policy, i->icon, i->icon_path);
133 	}
134 }
135 
136 const char *
137 libhal_storage_policy_lookup_icon (LibHalStoragePolicy *policy, LibHalStoragePolicyIcon icon)
138 {
139 	IconMappingEntry *i;
140 	const char *path;
141 
142 	path = NULL;
143 	for (i = policy->icon_mappings; i != NULL; i = i->next) {
144 		if (i->icon == icon) {
145 			path = i->path;
146 			goto out;
147 		}
148 	}
149 out:
150 	return path;
151 }
152 
153 
154 #define MAX_STRING_SZ 256
155 
156 char *
157 libhal_volume_policy_compute_size_as_string (LibHalVolume *volume)
158 {
159 	dbus_uint64_t size;
160 	char *result;
161 	char* sizes_str[] = {"K", "M", "G", "T", NULL};
162 	dbus_uint64_t cur = 1000L;
163 	dbus_uint64_t base = 10L;
164 	dbus_uint64_t step = 10L*10L*10L;
165 	int cur_str = 0;
166 	char buf[MAX_STRING_SZ];
167 
168 	result = NULL;
169 
170 	size = libhal_volume_get_size (volume);
171 
172 	do {
173 		if (sizes_str[cur_str+1] == NULL || size < cur*step) {
174 			/* found the unit, display a comma number if result is a single digit */
175 			if (size < cur*base) {
176 				snprintf (buf, MAX_STRING_SZ, "%.01f%s",
177 					  ((double)size)/((double)cur), sizes_str[cur_str]);
178 				result = strdup (buf);
179 			} else {
180 				snprintf (buf, MAX_STRING_SZ, "%llu%s", (long long unsigned int) size / cur, sizes_str[cur_str]);
181 				result = strdup (buf);
182 				}
183 			goto out;
184 		}
185 
186 		cur *= step;
187 		cur_str++;
188 	} while (1);
189 
190 out:
191 	return result;
192 }
193 
194 static void
195 fixup_string (char *s)
196 {
197 	/* TODO: first strip leading and trailing whitespace */
198 	/*g_strstrip (s);*/
199 
200 	/* TODO: could do nice things on all-upper case strings */
201 }
202 
203 /* volume may be NULL (e.g. if drive supports removable media) */
204 char *
205 libhal_drive_policy_compute_display_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
206 {
207 	char *name;
208 	char *size_str;
209 	char *vendormodel_str;
210 	const char *model;
211 	const char *vendor;
212 	LibHalDriveType drive_type;
213 	dbus_bool_t drive_is_hotpluggable;
214 	dbus_bool_t drive_is_removable;
215 	LibHalDriveCdromCaps drive_cdrom_caps;
216 	char buf[MAX_STRING_SZ];
217 
218 	model = libhal_drive_get_model (drive);
219 	vendor = libhal_drive_get_vendor (drive);
220 	drive_type = libhal_drive_get_type (drive);
221 	drive_is_hotpluggable = libhal_drive_is_hotpluggable (drive);
222 	drive_is_removable = libhal_drive_uses_removable_media (drive);
223 	drive_cdrom_caps = libhal_drive_get_cdrom_caps (drive);
224 
225 	if (volume != NULL)
226 		size_str = libhal_volume_policy_compute_size_as_string (volume);
227 	else
228 		size_str = NULL;
229 
230 	if (vendor == NULL || strlen (vendor) == 0) {
231 		if (model == NULL || strlen (model) == 0)
232 			vendormodel_str = strdup ("");
233 		else
234 			vendormodel_str = strdup (model);
235 	} else {
236 		if (model == NULL || strlen (model) == 0)
237 			vendormodel_str = strdup (vendor);
238 		else {
239 			snprintf (buf, MAX_STRING_SZ, "%s %s", vendor, model);
240 			vendormodel_str = strdup (buf);
241 		}
242 	}
243 
244 	fixup_string (vendormodel_str);
245 
246 	if (drive_type==LIBHAL_DRIVE_TYPE_CDROM) {
247 
248 		/* Optical drive handling */
249 		char *first;
250 		char *second;
251 
252 
253 		first = "CD-ROM";
254 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_CDR)
255 			first = "CD-R";
256 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_CDRW)
257 			first = "CD-RW";
258 
259 		second = "";
260 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDROM)
261 			second = "/DVD-ROM";
262 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSR)
263 			second = "/DVD+R";
264 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRW)
265 			second = "/DVD+RW";
266 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDR)
267 			second = "/DVD-R";
268 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDRW)
269 			second = "/DVD-RW";
270 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDRAM)
271 			second = "/DVD-RAM";
272 		if ((drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDR) &&
273 		    (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSR)) {
274 			if(drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRDL)
275 				second = "/DVD±R DL";
276 			else
277 				second = "/DVD±R";
278 		}
279 		if ((drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDRW) &&
280 		    (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRW)) {
281                         if(drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRDL ||
282 			   drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRWDL)
283                                 second = "/DVD±RW DL";
284                         else
285                                 second = "/DVD±RW";
286                 }
287 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_BDROM)
288 			second = "/BD-ROM";
289 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_BDR)
290 			second = "/BD-R";
291 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_BDRE)
292 			second = "/BD-RE";
293 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_HDDVDROM)
294 			second = "/HD DVD-ROM";
295 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_HDDVDR)
296 			second = "/HD DVD-R";
297 		if (drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_HDDVDRW)
298 			second = "/HD DVD-RW";
299 
300 		if (drive_is_hotpluggable) {
301 			snprintf (buf, MAX_STRING_SZ, _("External %s%s Drive"), first, second);
302 			name = strdup (buf);
303 		} else {
304 			snprintf (buf, MAX_STRING_SZ, _("%s%s Drive"), first, second);
305 			name = strdup (buf);
306 		}
307 
308 	} else if (drive_type==LIBHAL_DRIVE_TYPE_FLOPPY) {
309 
310 		/* Floppy Drive handling */
311 
312 		if (drive_is_hotpluggable)
313 			name = strdup (_("External Floppy Drive"));
314 		else
315 			name = strdup (_("Floppy Drive"));
316 	} else if (drive_type==LIBHAL_DRIVE_TYPE_DISK && !drive_is_removable) {
317 
318 		/* Harddisks */
319 
320 		if (size_str != NULL) {
321 			if (drive_is_hotpluggable) {
322 				snprintf (buf, MAX_STRING_SZ, _("%s External Hard Drive"), size_str);
323 				name = strdup (buf);
324 			} else {
325 				snprintf (buf, MAX_STRING_SZ, _("%s Hard Drive"), size_str);
326 				name = strdup (buf);
327 			}
328 		} else {
329 			if (drive_is_hotpluggable)
330 				name = strdup (_("External Hard Drive"));
331 			else
332 				name = strdup (_("Hard Drive"));
333 		}
334 	} else {
335 
336 		/* The rest - includes drives with removable Media */
337 
338 		if (strlen (vendormodel_str) > 0)
339 			name = strdup (vendormodel_str);
340 		else
341 			name = strdup (_("Drive"));
342 	}
343 
344 	free (vendormodel_str);
345 	free (size_str);
346 
347 	return name;
348 }
349 
350 char *
351 libhal_volume_policy_compute_display_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
352 {
353 	char *name;
354 	char *size_str;
355 	const char *volume_label;
356 	const char *model;
357 	const char *vendor;
358 	LibHalDriveType drive_type;
359 	dbus_bool_t drive_is_hotpluggable;
360 	dbus_bool_t drive_is_removable;
361 	LibHalDriveCdromCaps drive_cdrom_caps;
362 	char buf[MAX_STRING_SZ];
363 
364 	volume_label = libhal_volume_get_label (volume);
365 	model = libhal_drive_get_model (drive);
366 	vendor = libhal_drive_get_vendor (drive);
367 	drive_type = libhal_drive_get_type (drive);
368 	drive_is_hotpluggable = libhal_drive_is_hotpluggable (drive);
369 	drive_is_removable = libhal_drive_uses_removable_media (drive);
370 	drive_cdrom_caps = libhal_drive_get_cdrom_caps (drive);
371 
372 	size_str = libhal_volume_policy_compute_size_as_string (volume);
373 
374 	/* If the volume label is available use that
375 	 *
376 	 * TODO: If label is a fully-qualified UNIX path don't use that
377 	 */
378 	if (volume_label != NULL) {
379 		name = strdup (volume_label);
380 		goto out;
381 	}
382 
383 	/* Handle media in optical drives */
384 	if (drive_type==LIBHAL_DRIVE_TYPE_CDROM) {
385 		switch (libhal_volume_get_disc_type (volume)) {
386 
387 		default:
388 			/* explict fallthrough */
389 		case LIBHAL_VOLUME_DISC_TYPE_CDROM:
390 			name = strdup (_("CD-ROM "));
391 			break;
392 
393 		case LIBHAL_VOLUME_DISC_TYPE_CDR:
394 			if (libhal_volume_disc_is_blank (volume))
395 				name = strdup (_("Blank CD-R"));
396 			else
397 				name = strdup (_("CD-R"));
398 			break;
399 
400 		case LIBHAL_VOLUME_DISC_TYPE_CDRW:
401 			if (libhal_volume_disc_is_blank (volume))
402 				name = strdup (_("Blank CD-RW"));
403 			else
404 				name = strdup (_("CD-RW"));
405 			break;
406 
407 		case LIBHAL_VOLUME_DISC_TYPE_DVDROM:
408 			name = strdup (_("DVD-ROM"));
409 			break;
410 
411 		case LIBHAL_VOLUME_DISC_TYPE_DVDRAM:
412 			if (libhal_volume_disc_is_blank (volume))
413 				name = strdup (_("Blank DVD-RAM"));
414 			else
415 				name = strdup (_("DVD-RAM"));
416 			break;
417 
418 		case LIBHAL_VOLUME_DISC_TYPE_DVDR:
419 			if (libhal_volume_disc_is_blank (volume))
420 				name = strdup (_("Blank DVD-R"));
421 			else
422 				name = strdup (_("DVD-R"));
423 			break;
424 
425 		case LIBHAL_VOLUME_DISC_TYPE_DVDRW:
426 			if (libhal_volume_disc_is_blank (volume))
427 				name = strdup (_("Blank DVD-RW"));
428 			else
429 				name = strdup (_("DVD-RW"));
430 			break;
431 
432 		case LIBHAL_VOLUME_DISC_TYPE_DVDPLUSR:
433 			if (libhal_volume_disc_is_blank (volume))
434 				name = strdup (_("Blank DVD+R"));
435 			else
436 				name = strdup (_("DVD+R"));
437 			break;
438 
439 		case LIBHAL_VOLUME_DISC_TYPE_DVDPLUSRW:
440 			if (libhal_volume_disc_is_blank (volume))
441 				name = strdup (_("Blank DVD+RW"));
442 			else
443 				name = strdup (_("DVD+RW"));
444 			break;
445 
446 		case LIBHAL_VOLUME_DISC_TYPE_DVDPLUSR_DL:
447 			if (libhal_volume_disc_is_blank (volume))
448 				name = strdup (_("Blank DVD+R Dual-Layer"));
449 			else
450 				name = strdup (_("DVD+R Dual-Layer"));
451 			break;
452 
453 		case LIBHAL_VOLUME_DISC_TYPE_BDROM:
454 			name = strdup (_("BD-ROM"));
455 			break;
456 
457 		case LIBHAL_VOLUME_DISC_TYPE_BDR:
458 			if (libhal_volume_disc_is_blank (volume))
459 				name = strdup (_("Blank BD-R"));
460 			else
461 				name = strdup (_("BD-R"));
462 			break;
463 
464 		case LIBHAL_VOLUME_DISC_TYPE_BDRE:
465 			if (libhal_volume_disc_is_blank (volume))
466 				name = strdup (_("Blank BD-RE"));
467 			else
468 				name = strdup (_("BD-RE"));
469 			break;
470 
471 		case LIBHAL_VOLUME_DISC_TYPE_HDDVDROM:
472 			name = strdup (_("HD DVD-ROM"));
473 			break;
474 
475 		case LIBHAL_VOLUME_DISC_TYPE_HDDVDR:
476 			if (libhal_volume_disc_is_blank (volume))
477 				name = strdup (_("Blank HD DVD-R"));
478 			else
479 				name = strdup (_("HD DVD-R"));
480 			break;
481 
482 		case LIBHAL_VOLUME_DISC_TYPE_HDDVDRW:
483 			if (libhal_volume_disc_is_blank (volume))
484 				name = strdup (_("Blank HD DVD-RW"));
485 			else
486 				name = strdup (_("HD DVD-RW"));
487 			break;
488 
489 		}
490 
491 		/* Special case for pure audio disc */
492 		if (libhal_volume_disc_has_audio (volume) && !libhal_volume_disc_has_data (volume)) {
493 			free (name);
494 			name = strdup (_("Audio CD"));
495 		}
496 
497 		goto out;
498 	}
499 
500 	/* Fallback: size of media */
501 	if (drive_is_removable) {
502 		snprintf (buf, MAX_STRING_SZ, _("%s Removable Media"), size_str);
503 		name = strdup (buf);
504 	} else {
505 		snprintf (buf, MAX_STRING_SZ, _("%s Media"), size_str);
506 		name = strdup (buf);
507 	}
508 
509 	/* Fallback: Use drive name */
510 	/*name = libhal_drive_policy_compute_display_name (drive, volume);*/
511 
512 out:
513 	free (size_str);
514 	return name;
515 }
516 
517 char *
518 libhal_drive_policy_compute_icon_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
519 {
520 	const char *name;
521 	LibHalDriveBus bus;
522 	LibHalDriveType drive_type;
523 
524 	bus        = libhal_drive_get_bus (drive);
525 	drive_type = libhal_drive_get_type (drive);
526 
527 	/* by design, the enums are laid out so we can do easy computations */
528 
529 	switch (drive_type) {
530 	case LIBHAL_DRIVE_TYPE_REMOVABLE_DISK:
531 	case LIBHAL_DRIVE_TYPE_DISK:
532 	case LIBHAL_DRIVE_TYPE_CDROM:
533 	case LIBHAL_DRIVE_TYPE_FLOPPY:
534 		name = libhal_storage_policy_lookup_icon (policy, 0x10000 + drive_type*0x100 + bus);
535 		break;
536 
537 	default:
538 		name = libhal_storage_policy_lookup_icon (policy, 0x10000 + drive_type*0x100);
539 	}
540 
541 	if (name != NULL)
542 		return strdup (name);
543 	else
544 		return NULL;
545 }
546 
547 char *
548 libhal_volume_policy_compute_icon_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
549 {
550 	const char *name;
551 	LibHalDriveBus bus;
552 	LibHalDriveType drive_type;
553 	LibHalVolumeDiscType disc_type;
554 
555 	/* by design, the enums are laid out so we can do easy computations */
556 
557 	if (libhal_volume_is_disc (volume)) {
558 		disc_type = libhal_volume_get_disc_type (volume);
559 		name = libhal_storage_policy_lookup_icon (policy, 0x30000 + disc_type);
560 		goto out;
561 	}
562 
563 	if (drive == NULL) {
564 		name = libhal_storage_policy_lookup_icon (policy, LIBHAL_STORAGE_ICON_VOLUME_REMOVABLE_DISK);
565 		goto out;
566 	}
567 
568 	bus        = libhal_drive_get_bus (drive);
569 	drive_type = libhal_drive_get_type (drive);
570 
571 	switch (drive_type) {
572 	case LIBHAL_DRIVE_TYPE_REMOVABLE_DISK:
573 	case LIBHAL_DRIVE_TYPE_DISK:
574 	case LIBHAL_DRIVE_TYPE_CDROM:
575 	case LIBHAL_DRIVE_TYPE_FLOPPY:
576 		name = libhal_storage_policy_lookup_icon (policy, 0x20000 + drive_type*0x100 + bus);
577 		break;
578 
579 	default:
580 		name = libhal_storage_policy_lookup_icon (policy, 0x20000 + drive_type*0x100);
581 	}
582 out:
583 	if (name != NULL)
584 		return strdup (name);
585 	else
586 		return NULL;
587 }
588 
589 /** Policy function to determine if a volume should be visible in a desktop
590  *  environment. This is useful to hide certain system volumes as bootstrap
591  *  partitions, the /usr partition, swap partitions and other volumes that
592  *  a unprivileged desktop user shouldn't know even exists.
593  *
594  *  @param  drive               Drive that the volume is stemming from
595  *  @param  volume              Volume
596  *  @param  policy              Policy object
597  *  @param  target_mount_point  The mount point that the volume is expected to
598  *                              be mounted at if not already mounted. This may
599  *                              e.g. stem from /etc/fstab. If this is NULL the
600  *                              then mount point isn't taking into account when
601  *                              evaluating whether the volume should be visible
602  *  @return                     Whether the volume should be shown in a desktop
603  *                              environment.
604  */
605 dbus_bool_t
606 libhal_volume_policy_should_be_visible (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy,
607 				     const char *target_mount_point)
608 {
609 	unsigned int i;
610 	dbus_bool_t is_visible;
611 	const char *label;
612 	const char *mount_point;
613 	const char *fstype;
614 	const char *fhs23_toplevel_mount_points[] = {
615 		"/",
616 		"/bin",
617 		"/boot",
618 		"/dev",
619 		"/etc",
620 		"/home",
621 		"/lib",
622 		"/lib64",
623 		"/media",
624 		"/mnt",
625 		"/opt",
626 		"/root",
627 		"/sbin",
628 		"/srv",
629 		"/tmp",
630 		"/usr",
631 		"/var",
632 		"/proc",
633 		"/sbin",
634 		NULL
635 	};
636 
637 	is_visible = FALSE;
638 
639 	/* skip if hal says it's not used as a filesystem */
640 	if (libhal_volume_get_fsusage (volume) != LIBHAL_VOLUME_USAGE_MOUNTABLE_FILESYSTEM)
641 		goto out;
642 
643 	label = libhal_volume_get_label (volume);
644 	mount_point = libhal_volume_get_mount_point (volume);
645 	fstype = libhal_volume_get_fstype (volume);
646 
647 	/* use target mount point if we're not mounted yet */
648 	if (mount_point == NULL)
649 		mount_point = target_mount_point;
650 
651 	/* bail out if we don't know the filesystem */
652 	if (fstype == NULL)
653 		goto out;
654 
655 	/* blacklist fhs2.3 top level mount points */
656 	if (mount_point != NULL) {
657 		for (i = 0; fhs23_toplevel_mount_points[i] != NULL; i++) {
658 			if (strcmp (mount_point, fhs23_toplevel_mount_points[i]) == 0)
659 				goto out;
660 		}
661 	}
662 
663 	/* blacklist partitions with name 'bootstrap' of type HFS (Apple uses that) */
664 	if (label != NULL && strcmp (label, "bootstrap") == 0 && strcmp (fstype, "hfs") == 0)
665 		goto out;
666 
667 	/* only the real lucky mount points will make it this far :-) */
668 	is_visible = TRUE;
669 
670 out:
671 	return is_visible;
672 }
673 
674 /*************************************************************************/
675 
676 #define MOUNT_OPTIONS_SIZE 256
677 
678 struct LibHalDrive_s {
679 	char *udi;
680 
681 	int device_major;
682 	int device_minor;
683 	char *device_file;
684 
685 	LibHalDriveBus bus;
686 	char *vendor;             /* may be "", is never NULL */
687 	char *model;              /* may be "", is never NULL */
688 	dbus_bool_t is_hotpluggable;
689 	dbus_bool_t is_removable;
690 	dbus_bool_t is_media_detected;
691 	dbus_bool_t requires_eject;
692 
693 	LibHalDriveType type;
694 	char *type_textual;
695 
696 	char *physical_device;  /* UDI of physical device, e.g. the
697 				 * IDE, USB, IEEE1394 device */
698 
699 	char *dedicated_icon_drive;
700 	char *dedicated_icon_volume;
701 
702 	char *serial;
703 	char *firmware_version;
704 	LibHalDriveCdromCaps cdrom_caps;
705 
706 	char *desired_mount_point;
707 	char *mount_filesystem;
708 	dbus_bool_t should_mount;
709 
710 	dbus_bool_t no_partitions_hint;
711 
712 	dbus_uint64_t drive_size;
713 	dbus_uint64_t drive_media_size;
714 	char *partition_scheme;
715 
716 	LibHalContext *hal_ctx;
717 
718 	char **capabilities;
719 
720 	char mount_options[MOUNT_OPTIONS_SIZE];
721 };
722 
723 struct LibHalVolume_s {
724 	char *udi;
725 
726 	int device_major;
727 	int device_minor;
728 	char *device_file;
729 	char *volume_label; /* may be NULL, is never "" */
730 	dbus_bool_t is_mounted;
731 	dbus_bool_t is_mounted_read_only; /* TRUE iff is_mounted and r/o fs */
732 	char *mount_point;  /* NULL iff !is_mounted */
733 	char *fstype;       /* NULL iff !is_mounted or unknown */
734 	char *fsversion;
735 	char *uuid;
736 	char *storage_device;
737 
738 	LibHalVolumeUsage fsusage;
739 
740 	dbus_bool_t is_partition;
741 	unsigned int partition_number;
742 	char *partition_scheme;
743 	char *partition_type;
744 	char *partition_label;
745 	char *partition_uuid;
746 	char **partition_flags;
747 
748 	int msdos_part_table_type;
749 	dbus_uint64_t msdos_part_table_start;
750 	dbus_uint64_t msdos_part_table_size;
751 
752 	dbus_bool_t is_disc;
753 	LibHalVolumeDiscType disc_type;
754 	dbus_bool_t disc_has_audio;
755 	dbus_bool_t disc_has_data;
756 	dbus_bool_t disc_is_appendable;
757 	dbus_bool_t disc_is_blank;
758 	dbus_bool_t disc_is_rewritable;
759 
760 	unsigned int block_size;
761 	unsigned int num_blocks;
762 
763 	char *desired_mount_point;
764 	char *mount_filesystem;
765 	dbus_bool_t should_mount;
766 
767 	dbus_bool_t ignore_volume;
768 
769 	char *crypto_backing_volume;
770 
771 	char mount_options[MOUNT_OPTIONS_SIZE];
772 
773 	dbus_uint64_t volume_size;
774 	dbus_uint64_t disc_capacity;
775 
776 	dbus_uint64_t partition_start_offset;
777 	dbus_uint64_t partition_media_size;
778 };
779 
780 const char *
781 libhal_drive_get_dedicated_icon_drive (LibHalDrive *drive)
782 {
783 	return drive->dedicated_icon_drive;
784 }
785 
786 const char *
787 libhal_drive_get_dedicated_icon_volume (LibHalDrive *drive)
788 {
789 	return drive->dedicated_icon_volume;
790 }
791 
792 /** Free all resources used by a LibHalDrive object.
793  *
794  *  @param  drive               Object to free
795  */
796 void
797 libhal_drive_free (LibHalDrive *drive)
798 {
799 	if (drive == NULL )
800 		return;
801 
802 	free (drive->udi);
803 	libhal_free_string (drive->device_file);
804 	libhal_free_string (drive->vendor);
805 	libhal_free_string (drive->model);
806 	libhal_free_string (drive->type_textual);
807 	libhal_free_string (drive->physical_device);
808 	libhal_free_string (drive->dedicated_icon_drive);
809 	libhal_free_string (drive->dedicated_icon_volume);
810 	libhal_free_string (drive->serial);
811 	libhal_free_string (drive->firmware_version);
812 	libhal_free_string (drive->desired_mount_point);
813 	libhal_free_string (drive->mount_filesystem);
814 	libhal_free_string_array (drive->capabilities);
815 	libhal_free_string (drive->partition_scheme);
816 
817 	free (drive);
818 }
819 
820 
821 /** Free all resources used by a LibHalVolume object.
822  *
823  *  @param  vol              Object to free
824  */
825 void
826 libhal_volume_free (LibHalVolume *vol)
827 {
828 	if (vol == NULL )
829 		return;
830 
831 	free (vol->udi);
832 	libhal_free_string (vol->device_file);
833 	libhal_free_string (vol->volume_label);
834 	libhal_free_string (vol->fstype);
835 	libhal_free_string (vol->mount_point);
836 	libhal_free_string (vol->fsversion);
837 	libhal_free_string (vol->uuid);
838 	libhal_free_string (vol->desired_mount_point);
839 	libhal_free_string (vol->mount_filesystem);
840 	libhal_free_string (vol->crypto_backing_volume);
841 	libhal_free_string (vol->storage_device);
842 
843 	libhal_free_string (vol->partition_scheme);
844 	libhal_free_string (vol->partition_type);
845 	libhal_free_string (vol->partition_label);
846 	libhal_free_string (vol->partition_uuid);
847 	libhal_free_string_array (vol->partition_flags);
848 
849 	free (vol);
850 }
851 
852 
853 static char **
854 my_strvdup (char **strv)
855 {
856 	unsigned int num_elems;
857 	unsigned int i;
858 	char **res;
859 
860 	for (num_elems = 0; strv[num_elems] != NULL; num_elems++)
861 		;
862 
863 	res = calloc (num_elems + 1, sizeof (char*));
864 	if (res == NULL)
865 		goto out;
866 
867 	for (i = 0; i < num_elems; i++)
868 		res[i] = strdup (strv[i]);
869 	res[i] = NULL;
870 
871 out:
872 	return res;
873 }
874 
875 /* ok, hey, so this is a bit ugly */
876 
877 #define LIBHAL_PROP_EXTRACT_BEGIN if (FALSE)
878 #define LIBHAL_PROP_EXTRACT_END ;
879 #define LIBHAL_PROP_EXTRACT_INT(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_INT32) _where_ = libhal_psi_get_int (&it)
880 #define LIBHAL_PROP_EXTRACT_UINT64(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_UINT64) _where_ = libhal_psi_get_uint64 (&it)
881 #define LIBHAL_PROP_EXTRACT_STRING(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_STRING) _where_ = (libhal_psi_get_string (&it) != NULL && strlen (libhal_psi_get_string (&it)) > 0) ? strdup (libhal_psi_get_string (&it)) : NULL
882 #define LIBHAL_PROP_EXTRACT_BOOL(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_BOOLEAN) _where_ = libhal_psi_get_bool (&it)
883 #define LIBHAL_PROP_EXTRACT_BOOL_BITFIELD(_property_, _where_, _field_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_BOOLEAN) _where_ |= libhal_psi_get_bool (&it) ? _field_ : 0
884 #define LIBHAL_PROP_EXTRACT_STRLIST(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_STRLIST) _where_ = my_strvdup (libhal_psi_get_strlist (&it))
885 
886 /** Given a UDI for a HAL device of capability 'storage', this
887  *  function retrieves all the relevant properties into convenient
888  *  in-process data structures.
889  *
890  *  @param  hal_ctx             libhal context
891  *  @param  udi                 HAL UDI
892  *  @return                     LibHalDrive object or NULL if UDI is invalid
893  */
894 LibHalDrive *
895 libhal_drive_from_udi (LibHalContext *hal_ctx, const char *udi)
896 {
897 	char *bus_textual;
898 	LibHalDrive *drive;
899 	LibHalPropertySet *properties;
900 	LibHalPropertySetIterator it;
901 	DBusError error;
902 	unsigned int i;
903 
904 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
905 
906 	drive = NULL;
907 	properties = NULL;
908 	bus_textual = NULL;
909 
910 	dbus_error_init (&error);
911 	if (!libhal_device_query_capability (hal_ctx, udi, "storage", &error))
912 		goto error;
913 
914 	drive = malloc (sizeof (LibHalDrive));
915 	if (drive == NULL)
916 		goto error;
917 	memset (drive, 0x00, sizeof (LibHalDrive));
918 
919 	drive->hal_ctx = hal_ctx;
920 
921 	drive->udi = strdup (udi);
922 	if (drive->udi == NULL)
923 		goto error;
924 
925 	properties = libhal_device_get_all_properties (hal_ctx, udi, &error);
926 	if (properties == NULL)
927 		goto error;
928 
929 	/* we can count on hal to give us all these properties */
930 	for (libhal_psi_init (&it, properties); libhal_psi_has_more (&it); libhal_psi_next (&it)) {
931 		int type;
932 		char *key;
933 
934 		type = libhal_psi_get_type (&it);
935 		key = libhal_psi_get_key (&it);
936 
937 		LIBHAL_PROP_EXTRACT_BEGIN;
938 
939 		LIBHAL_PROP_EXTRACT_INT    ("block.minor",               drive->device_minor);
940 		LIBHAL_PROP_EXTRACT_INT    ("block.major",               drive->device_major);
941 		LIBHAL_PROP_EXTRACT_STRING ("block.device",              drive->device_file);
942 		LIBHAL_PROP_EXTRACT_STRING ("storage.bus",               bus_textual);
943 		LIBHAL_PROP_EXTRACT_STRING ("storage.vendor",            drive->vendor);
944 		LIBHAL_PROP_EXTRACT_STRING ("storage.model",             drive->model);
945 		LIBHAL_PROP_EXTRACT_STRING ("storage.drive_type",        drive->type_textual);
946 		LIBHAL_PROP_EXTRACT_UINT64 ("storage.size", 		 drive->drive_size);
947 
948 		LIBHAL_PROP_EXTRACT_STRING ("storage.icon.drive",        drive->dedicated_icon_drive);
949 		LIBHAL_PROP_EXTRACT_STRING ("storage.icon.volume",       drive->dedicated_icon_volume);
950 
951 		LIBHAL_PROP_EXTRACT_BOOL   ("storage.hotpluggable",      drive->is_hotpluggable);
952 		LIBHAL_PROP_EXTRACT_BOOL   ("storage.removable",         drive->is_removable);
953 		LIBHAL_PROP_EXTRACT_BOOL   ("storage.removable.media_available", drive->is_media_detected);
954 		LIBHAL_PROP_EXTRACT_UINT64 ("storage.removable.media_size", drive->drive_media_size);
955 		LIBHAL_PROP_EXTRACT_BOOL   ("storage.requires_eject",    drive->requires_eject);
956 
957 		LIBHAL_PROP_EXTRACT_STRING ("storage.partitioning_scheme", drive->partition_scheme);
958 
959 		LIBHAL_PROP_EXTRACT_STRING ("storage.physical_device",   drive->physical_device);
960 		LIBHAL_PROP_EXTRACT_STRING ("storage.firmware_version",  drive->firmware_version);
961 		LIBHAL_PROP_EXTRACT_STRING ("storage.serial",            drive->serial);
962 
963 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.cdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_CDR);
964 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.cdrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_CDRW);
965 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvd", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDROM);
966 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSR);
967 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRW);
968 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusrwdl", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRWDL);
969 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusrdl", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRDL);
970 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDR);
971 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDRW);
972 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdram", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDRAM);
973 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.bd", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_BDROM);
974 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.bdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_BDR);
975 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.bdre", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_BDRE);
976 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.hddvd", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_HDDVDROM);
977 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.hddvdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_HDDVDR);
978 		LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.hddvdrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_HDDVDRW);
979 
980 		LIBHAL_PROP_EXTRACT_BOOL   ("storage.policy.should_mount",        drive->should_mount);
981 		LIBHAL_PROP_EXTRACT_STRING ("storage.policy.desired_mount_point", drive->desired_mount_point);
982 		LIBHAL_PROP_EXTRACT_STRING ("storage.policy.mount_filesystem",    drive->mount_filesystem);
983 
984 		LIBHAL_PROP_EXTRACT_BOOL   ("storage.no_partitions_hint",        drive->no_partitions_hint);
985 
986 		LIBHAL_PROP_EXTRACT_STRLIST ("info.capabilities",                drive->capabilities);
987 
988 		LIBHAL_PROP_EXTRACT_END;
989 	}
990 
991 	if (drive->type_textual != NULL) {
992 		if (strcmp (drive->type_textual, "cdrom") == 0) {
993 			drive->cdrom_caps |= LIBHAL_DRIVE_CDROM_CAPS_CDROM;
994 			drive->type = LIBHAL_DRIVE_TYPE_CDROM;
995 		} else if (strcmp (drive->type_textual, "floppy") == 0) {
996 			drive->type = LIBHAL_DRIVE_TYPE_FLOPPY;
997 		} else if (strcmp (drive->type_textual, "disk") == 0) {
998 			if (drive->is_removable)
999 				drive->type = LIBHAL_DRIVE_TYPE_REMOVABLE_DISK;
1000 			else
1001 				drive->type = LIBHAL_DRIVE_TYPE_DISK;
1002 		} else if (strcmp (drive->type_textual, "tape") == 0) {
1003 			drive->type = LIBHAL_DRIVE_TYPE_TAPE;
1004 		} else if (strcmp (drive->type_textual, "compact_flash") == 0) {
1005 			drive->type = LIBHAL_DRIVE_TYPE_COMPACT_FLASH;
1006 		} else if (strcmp (drive->type_textual, "memory_stick") == 0) {
1007 			drive->type = LIBHAL_DRIVE_TYPE_MEMORY_STICK;
1008 		} else if (strcmp (drive->type_textual, "smart_media") == 0) {
1009 			drive->type = LIBHAL_DRIVE_TYPE_SMART_MEDIA;
1010 		} else if (strcmp (drive->type_textual, "sd_mmc") == 0) {
1011 			drive->type = LIBHAL_DRIVE_TYPE_SD_MMC;
1012 		} else if (strcmp (drive->type_textual, "zip") == 0) {
1013 			drive->type = LIBHAL_DRIVE_TYPE_ZIP;
1014 		} else if (strcmp (drive->type_textual, "jaz") == 0) {
1015 			drive->type = LIBHAL_DRIVE_TYPE_JAZ;
1016 		} else if (strcmp (drive->type_textual, "flashkey") == 0) {
1017 			drive->type = LIBHAL_DRIVE_TYPE_FLASHKEY;
1018 		} else {
1019 		        drive->type = LIBHAL_DRIVE_TYPE_DISK;
1020 		}
1021 
1022 	}
1023 
1024 	if (drive->capabilities != NULL) {
1025 		for (i = 0; drive->capabilities[i] != NULL; i++) {
1026 			if (strcmp (drive->capabilities[i], "portable_audio_player") == 0) {
1027 				drive->type = LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER;
1028 				break;
1029 			} else if (strcmp (drive->capabilities[i], "camera") == 0) {
1030 				drive->type = LIBHAL_DRIVE_TYPE_CAMERA;
1031 				break;
1032 			}
1033 		}
1034 	}
1035 
1036 	if (bus_textual != NULL) {
1037 		if (strcmp (bus_textual, "usb") == 0) {
1038 			drive->bus = LIBHAL_DRIVE_BUS_USB;
1039 		} else if (strcmp (bus_textual, "ieee1394") == 0) {
1040 			drive->bus = LIBHAL_DRIVE_BUS_IEEE1394;
1041 		} else if (strcmp (bus_textual, "ide") == 0) {
1042 			drive->bus = LIBHAL_DRIVE_BUS_IDE;
1043 		} else if (strcmp (bus_textual, "scsi") == 0) {
1044 			drive->bus = LIBHAL_DRIVE_BUS_SCSI;
1045 		} else if (strcmp (bus_textual, "ccw") == 0) {
1046 			drive->bus = LIBHAL_DRIVE_BUS_CCW;
1047 		}
1048 	}
1049 
1050 	libhal_free_string (bus_textual);
1051 	libhal_free_property_set (properties);
1052 
1053 	return drive;
1054 
1055 error:
1056 	LIBHAL_FREE_DBUS_ERROR(&error);
1057 	libhal_free_string (bus_textual);
1058 	libhal_free_property_set (properties);
1059 	libhal_drive_free (drive);
1060 	return NULL;
1061 }
1062 
1063 const char *
1064 libhal_volume_get_storage_device_udi (LibHalVolume *volume)
1065 {
1066 	return volume->storage_device;
1067 }
1068 
1069 const char *libhal_drive_get_physical_device_udi (LibHalDrive *drive)
1070 {
1071 	return drive->physical_device;
1072 }
1073 
1074 dbus_bool_t
1075 libhal_drive_requires_eject (LibHalDrive *drive)
1076 {
1077 	return drive->requires_eject;
1078 }
1079 
1080 /** Given a UDI for a LIBHAL device of capability 'volume', this
1081  *  function retrieves all the relevant properties into convenient
1082  *  in-process data structures.
1083  *
1084  *  @param  hal_ctx             libhal context
1085  *  @param  udi                 HAL UDI
1086  *  @return                     LibHalVolume object or NULL if UDI is invalid
1087  */
1088 LibHalVolume *
1089 libhal_volume_from_udi (LibHalContext *hal_ctx, const char *udi)
1090 {
1091 	char *disc_type_textual;
1092 	char *vol_fsusage_textual;
1093 	LibHalVolume *vol;
1094 	LibHalPropertySet *properties;
1095 	LibHalPropertySetIterator it;
1096 	DBusError error;
1097 
1098 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
1099 
1100 	vol = NULL;
1101 	properties = NULL;
1102 	disc_type_textual = NULL;
1103 	vol_fsusage_textual = NULL;
1104 
1105 	dbus_error_init (&error);
1106 	if (!libhal_device_query_capability (hal_ctx, udi, "volume", &error))
1107 		goto error;
1108 
1109 	vol = malloc (sizeof (LibHalVolume));
1110 	if (vol == NULL)
1111 		goto error;
1112 	memset (vol, 0x00, sizeof (LibHalVolume));
1113 
1114 	vol->udi = strdup (udi);
1115 
1116 	properties = libhal_device_get_all_properties (hal_ctx, udi, &error);
1117 	if (properties == NULL)
1118 		goto error;
1119 
1120 	/* we can count on hal to give us all these properties */
1121 	for (libhal_psi_init (&it, properties); libhal_psi_has_more (&it); libhal_psi_next (&it)) {
1122 		int type;
1123 		char *key;
1124 
1125 		type = libhal_psi_get_type (&it);
1126 		key = libhal_psi_get_key (&it);
1127 
1128 		LIBHAL_PROP_EXTRACT_BEGIN;
1129 
1130 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.is_partition",                    vol->is_partition);
1131 		LIBHAL_PROP_EXTRACT_INT    ("volume.partition.number",                vol->partition_number);
1132 		LIBHAL_PROP_EXTRACT_STRING ("volume.partition.scheme",                vol->partition_scheme);
1133 		LIBHAL_PROP_EXTRACT_STRING ("volume.partition.type",                  vol->partition_type);
1134 		LIBHAL_PROP_EXTRACT_STRING ("volume.partition.label",                 vol->partition_label);
1135 		LIBHAL_PROP_EXTRACT_STRING ("volume.partition.uuid",                  vol->partition_uuid);
1136 		LIBHAL_PROP_EXTRACT_STRLIST ("volume.partition.flags",                vol->partition_flags);
1137 
1138 		LIBHAL_PROP_EXTRACT_UINT64 ("volume.partition.start", 		      vol->partition_start_offset);
1139 		LIBHAL_PROP_EXTRACT_UINT64 ("volume.partition.media_size",            vol->partition_media_size);
1140 		LIBHAL_PROP_EXTRACT_INT    ("volume.partition.msdos_part_table_type", vol->msdos_part_table_type);
1141 		LIBHAL_PROP_EXTRACT_UINT64 ("volume.partition.msdos_part_table_start", vol->msdos_part_table_start);
1142 		LIBHAL_PROP_EXTRACT_UINT64 ("volume.partition.msdos_part_table_size", vol->msdos_part_table_size);
1143 
1144 		LIBHAL_PROP_EXTRACT_INT    ("block.minor",               vol->device_minor);
1145 		LIBHAL_PROP_EXTRACT_INT    ("block.major",               vol->device_major);
1146 		LIBHAL_PROP_EXTRACT_STRING ("block.device",              vol->device_file);
1147 
1148 		LIBHAL_PROP_EXTRACT_STRING ("block.storage_device",      vol->storage_device);
1149 
1150 		LIBHAL_PROP_EXTRACT_STRING ("volume.crypto_luks.clear.backing_volume", vol->crypto_backing_volume);
1151 
1152 		LIBHAL_PROP_EXTRACT_INT    ("volume.block_size",         vol->block_size);
1153 		LIBHAL_PROP_EXTRACT_INT    ("volume.num_blocks",         vol->num_blocks);
1154 		LIBHAL_PROP_EXTRACT_UINT64 ("volume.size", 		 vol->volume_size);
1155 		LIBHAL_PROP_EXTRACT_STRING ("volume.label",              vol->volume_label);
1156 		LIBHAL_PROP_EXTRACT_STRING ("volume.mount_point",        vol->mount_point);
1157 		LIBHAL_PROP_EXTRACT_STRING ("volume.fstype",             vol->fstype);
1158 		LIBHAL_PROP_EXTRACT_STRING ("volume.fsversion",             vol->fsversion);
1159 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.is_mounted",         vol->is_mounted);
1160 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.is_mounted_read_only", vol->is_mounted_read_only);
1161 		LIBHAL_PROP_EXTRACT_STRING ("volume.fsusage",            vol_fsusage_textual);
1162 		LIBHAL_PROP_EXTRACT_STRING ("volume.uuid",               vol->uuid);
1163 
1164 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.ignore",             vol->ignore_volume);
1165 
1166 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.is_disc",            vol->is_disc);
1167 		LIBHAL_PROP_EXTRACT_STRING ("volume.disc.type",          disc_type_textual);
1168 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.disc.has_audio",     vol->disc_has_audio);
1169 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.disc.has_data",      vol->disc_has_data);
1170 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.disc.is_appendable", vol->disc_is_appendable);
1171 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.disc.is_blank",      vol->disc_is_blank);
1172 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.disc.is_rewritable", vol->disc_is_rewritable);
1173 		LIBHAL_PROP_EXTRACT_UINT64 ("volume.disc.capacity",      vol->disc_capacity);
1174 
1175 		LIBHAL_PROP_EXTRACT_BOOL   ("volume.policy.should_mount",        vol->should_mount);
1176 		LIBHAL_PROP_EXTRACT_STRING ("volume.policy.desired_mount_point", vol->desired_mount_point);
1177 		LIBHAL_PROP_EXTRACT_STRING ("volume.policy.mount_filesystem",    vol->mount_filesystem);
1178 
1179 		LIBHAL_PROP_EXTRACT_END;
1180 	}
1181 
1182 	if (disc_type_textual != NULL) {
1183 		if (strcmp (disc_type_textual, "cd_rom") == 0) {
1184 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_CDROM;
1185 		} else if (strcmp (disc_type_textual, "cd_r") == 0) {
1186 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_CDR;
1187 		} else if (strcmp (disc_type_textual, "cd_rw") == 0) {
1188 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_CDRW;
1189 		} else if (strcmp (disc_type_textual, "dvd_rom") == 0) {
1190 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_DVDROM;
1191 		} else if (strcmp (disc_type_textual, "dvd_ram") == 0) {
1192 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_DVDRAM;
1193 		} else if (strcmp (disc_type_textual, "dvd_r") == 0) {
1194 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_DVDR;
1195 		} else if (strcmp (disc_type_textual, "dvd_rw") == 0) {
1196 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_DVDRW;
1197 		} else if (strcmp (disc_type_textual, "dvd_plus_r") == 0) {
1198 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_DVDPLUSR;
1199 		} else if (strcmp (disc_type_textual, "dvd_plus_rw") == 0) {
1200 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_DVDPLUSRW;
1201 		} else if (strcmp (disc_type_textual, "dvd_plus_r_dl") == 0) {
1202 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_DVDPLUSR_DL;
1203 		} else if (strcmp (disc_type_textual, "bd_rom") == 0) {
1204 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_BDROM;
1205 		} else if (strcmp (disc_type_textual, "bd_r") == 0) {
1206 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_BDR;
1207 		} else if (strcmp (disc_type_textual, "bd_re") == 0) {
1208 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_BDRE;
1209 		} else if (strcmp (disc_type_textual, "hddvd_rom") == 0) {
1210 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_HDDVDROM;
1211 		} else if (strcmp (disc_type_textual, "hddvd_r") == 0) {
1212 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_HDDVDR;
1213 		} else if (strcmp (disc_type_textual, "hddvd_rw") == 0) {
1214 			vol->disc_type = LIBHAL_VOLUME_DISC_TYPE_HDDVDRW;
1215 		}
1216 	}
1217 
1218 	vol->fsusage = LIBHAL_VOLUME_USAGE_UNKNOWN;
1219 	if (vol_fsusage_textual != NULL) {
1220 		if (strcmp (vol_fsusage_textual, "filesystem") == 0) {
1221 			vol->fsusage = LIBHAL_VOLUME_USAGE_MOUNTABLE_FILESYSTEM;
1222 		} else if (strcmp (vol_fsusage_textual, "partitiontable") == 0) {
1223 			vol->fsusage = LIBHAL_VOLUME_USAGE_PARTITION_TABLE;
1224 		} else if (strcmp (vol_fsusage_textual, "raid") == 0) {
1225 			vol->fsusage = LIBHAL_VOLUME_USAGE_RAID_MEMBER;
1226 		} else if (strcmp (vol_fsusage_textual, "crypto") == 0) {
1227 			vol->fsusage = LIBHAL_VOLUME_USAGE_CRYPTO;
1228 		} else if (strcmp (vol_fsusage_textual, "other") == 0) {
1229 			vol->fsusage = LIBHAL_VOLUME_USAGE_OTHER;
1230 		} else {
1231 			vol->fsusage = LIBHAL_VOLUME_USAGE_UNKNOWN;
1232 		}
1233 	}
1234 
1235 	libhal_free_string (vol_fsusage_textual);
1236 	libhal_free_string (disc_type_textual);
1237 	libhal_free_property_set (properties);
1238 	return vol;
1239 error:
1240 	if (dbus_error_is_set (&error)) {
1241 		dbus_error_free (&error);
1242 	}
1243 	libhal_free_string (vol_fsusage_textual);
1244 	libhal_free_string (disc_type_textual);
1245 	libhal_free_property_set (properties);
1246 	libhal_volume_free (vol);
1247 	return NULL;
1248 }
1249 
1250 
1251 /** If the volume is on a drive with a MSDOS style partition table, return
1252  *  the partition table id.
1253  *
1254  *  @param  volume              Volume object
1255  *  @return                     The partition type or -1 if volume is not
1256  *                              a partition or the media the volume stems from
1257  *                              isn't partition with a MS DOS style table
1258  */
1259 int
1260 libhal_volume_get_msdos_part_table_type (LibHalVolume *volume)
1261 {
1262 	return volume->msdos_part_table_type;
1263 }
1264 
1265 /** If the volume is on a drive with a MSDOS style partition table, return
1266  *  the partition start offset according to the partition table.
1267  *
1268  *  @param  volume              Volume object
1269  *  @return                     The partition start offset or -1 if volume isnt
1270  *                              a partition or the media the volume stems from
1271  *                              isn't partition with a MS DOS style table
1272  */
1273 dbus_uint64_t
1274 libhal_volume_get_msdos_part_table_start (LibHalVolume *volume)
1275 {
1276 	return volume->msdos_part_table_start;
1277 }
1278 
1279 /** If the volume is on a drive with a MSDOS style partition table, return
1280  *  the partition size according to the partition table.
1281  *
1282  *  @param  volume              Volume object
1283  *  @return                     The partition size or -1 if volume is not
1284  *                              a partition or the media the volume stems from
1285  *                              isn't partition with a MS DOS style table
1286  */
1287 dbus_uint64_t
1288 libhal_volume_get_msdos_part_table_size (LibHalVolume *volume)
1289 {
1290 	return volume->msdos_part_table_size;
1291 }
1292 
1293 /***********************************************************************/
1294 
1295 /** Get the drive object that either is (when given e.g. /dev/sdb) or contains
1296  *  (when given e.g. /dev/sdb1) the given device file.
1297  *
1298  *  @param  hal_ctx             libhal context to use
1299  *  @param  device_file         Name of special device file, e.g. '/dev/hdc'
1300  *  @return                     LibHalDrive object or NULL if it doesn't exist
1301  */
1302 LibHalDrive *
1303 libhal_drive_from_device_file (LibHalContext *hal_ctx, const char *device_file)
1304 {
1305 	int i;
1306 	char **hal_udis;
1307 	int num_hal_udis;
1308 	LibHalDrive *result;
1309 	char *found_udi;
1310 	DBusError error;
1311 
1312 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
1313 
1314 	result = NULL;
1315 	found_udi = NULL;
1316 
1317 	dbus_error_init (&error);
1318 	if ((hal_udis = libhal_manager_find_device_string_match (hal_ctx, "block.device",
1319 								 device_file, &num_hal_udis, &error)) == NULL) {
1320 		LIBHAL_FREE_DBUS_ERROR(&error);
1321 		goto out;
1322 	}
1323 
1324 	for (i = 0; i < num_hal_udis; i++) {
1325 		char *udi;
1326 		char *storage_udi;
1327 		DBusError err1;
1328 		DBusError err2;
1329 		udi = hal_udis[i];
1330 
1331 		dbus_error_init (&err1);
1332 		dbus_error_init (&err2);
1333 		if (libhal_device_query_capability (hal_ctx, udi, "volume", &err1)) {
1334 
1335 			storage_udi = libhal_device_get_property_string (hal_ctx, udi, "block.storage_device", &err1);
1336 			if (storage_udi == NULL)
1337 				continue;
1338 			found_udi = strdup (storage_udi);
1339 			libhal_free_string (storage_udi);
1340 			break;
1341 		} else if (libhal_device_query_capability (hal_ctx, udi, "storage", &err2)) {
1342 			found_udi = strdup (udi);
1343 		}
1344 		LIBHAL_FREE_DBUS_ERROR(&err1);
1345 		LIBHAL_FREE_DBUS_ERROR(&err2);
1346 	}
1347 
1348 	libhal_free_string_array (hal_udis);
1349 
1350 	if (found_udi != NULL)
1351 		result = libhal_drive_from_udi (hal_ctx, found_udi);
1352 
1353 	free (found_udi);
1354 out:
1355 	return result;
1356 }
1357 
1358 
1359 /** Get the volume object for a given device file.
1360  *
1361  *  @param  hal_ctx             libhal context to use
1362  *  @param  device_file         Name of special device file, e.g. '/dev/hda5'
1363  *  @return                     LibHalVolume object or NULL if it doesn't exist
1364  */
1365 LibHalVolume *
1366 libhal_volume_from_device_file (LibHalContext *hal_ctx, const char *device_file)
1367 {
1368 	int i;
1369 	char **hal_udis;
1370 	int num_hal_udis;
1371 	LibHalVolume *result;
1372 	char *found_udi;
1373 	DBusError error;
1374 
1375 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
1376 
1377 	result = NULL;
1378 	found_udi = NULL;
1379 
1380 	dbus_error_init (&error);
1381 	if ((hal_udis = libhal_manager_find_device_string_match (hal_ctx, "block.device",
1382 								 device_file, &num_hal_udis, &error)) == NULL)
1383 		goto out;
1384 
1385 	for (i = 0; i < num_hal_udis; i++) {
1386 		char *udi;
1387 		udi = hal_udis[i];
1388 		if (libhal_device_query_capability (hal_ctx, udi, "volume", &error)) {
1389 			found_udi = strdup (udi);
1390 			break;
1391 		}
1392 	}
1393 
1394 	libhal_free_string_array (hal_udis);
1395 
1396 	if (found_udi != NULL)
1397 		result = libhal_volume_from_udi (hal_ctx, found_udi);
1398 
1399 	free (found_udi);
1400 out:
1401 	LIBHAL_FREE_DBUS_ERROR(&error);
1402 	return result;
1403 }
1404 
1405 dbus_uint64_t
1406 libhal_volume_get_size (LibHalVolume *volume)
1407 {
1408 	if (volume->volume_size > 0)
1409 		return volume->volume_size;
1410 	else
1411 		return ((dbus_uint64_t)volume->block_size) * ((dbus_uint64_t)volume->num_blocks);
1412 }
1413 
1414 dbus_uint64_t
1415 libhal_volume_get_disc_capacity (LibHalVolume *volume)
1416 {
1417 	return volume->disc_capacity;
1418 }
1419 
1420 
1421 dbus_bool_t
1422 libhal_drive_is_hotpluggable (LibHalDrive *drive)
1423 {
1424 	return drive->is_hotpluggable;
1425 }
1426 
1427 dbus_bool_t
1428 libhal_drive_uses_removable_media (LibHalDrive *drive)
1429 {
1430 	return drive->is_removable;
1431 }
1432 
1433 dbus_bool_t
1434 libhal_drive_is_media_detected (LibHalDrive *drive)
1435 {
1436 	return drive->is_media_detected;
1437 }
1438 
1439 dbus_uint64_t
1440 libhal_drive_get_size (LibHalDrive *drive)
1441 {
1442 	return drive->drive_size;
1443 }
1444 
1445 dbus_uint64_t
1446 libhal_drive_get_media_size (LibHalDrive *drive)
1447 {
1448 	return drive->drive_media_size;
1449 }
1450 
1451 const char *
1452 libhal_drive_get_partition_scheme (LibHalDrive *drive)
1453 {
1454 	return drive->partition_scheme;
1455 }
1456 
1457 
1458 LibHalDriveType
1459 libhal_drive_get_type (LibHalDrive *drive)
1460 {
1461 	return drive->type;
1462 }
1463 
1464 LibHalDriveBus
1465 libhal_drive_get_bus (LibHalDrive *drive)
1466 {
1467 	return drive->bus;
1468 }
1469 
1470 LibHalDriveCdromCaps
1471 libhal_drive_get_cdrom_caps (LibHalDrive *drive)
1472 {
1473 	return drive->cdrom_caps;
1474 }
1475 
1476 unsigned int
1477 libhal_drive_get_device_major (LibHalDrive *drive)
1478 {
1479 	return drive->device_major;
1480 }
1481 
1482 unsigned int
1483 libhal_drive_get_device_minor (LibHalDrive *drive)
1484 {
1485 	return drive->device_minor;
1486 }
1487 
1488 const char *
1489 libhal_drive_get_type_textual (LibHalDrive *drive)
1490 {
1491 	return drive->type_textual;
1492 }
1493 
1494 const char *
1495 libhal_drive_get_device_file (LibHalDrive *drive)
1496 {
1497 	return drive->device_file;
1498 }
1499 
1500 const char *
1501 libhal_drive_get_udi (LibHalDrive *drive)
1502 {
1503 	return drive->udi;
1504 }
1505 
1506 const char *
1507 libhal_drive_get_serial (LibHalDrive *drive)
1508 {
1509 	return drive->serial;
1510 }
1511 
1512 const char *
1513 libhal_drive_get_firmware_version (LibHalDrive *drive)
1514 {
1515 	return drive->firmware_version;
1516 }
1517 
1518 const char *
1519 libhal_drive_get_model (LibHalDrive *drive)
1520 {
1521 	return drive->model;
1522 }
1523 
1524 const char *
1525 libhal_drive_get_vendor (LibHalDrive *drive)
1526 {
1527 	return drive->vendor;
1528 }
1529 
1530 /*****************************************************************************/
1531 
1532 const char *
1533 libhal_volume_get_udi (LibHalVolume *volume)
1534 {
1535 	return volume->udi;
1536 }
1537 
1538 const char *
1539 libhal_volume_get_device_file (LibHalVolume *volume)
1540 {
1541 	return volume->device_file;
1542 }
1543 
1544 unsigned int libhal_volume_get_device_major (LibHalVolume *volume)
1545 {
1546 	return volume->device_major;
1547 }
1548 
1549 unsigned int libhal_volume_get_device_minor (LibHalVolume *volume)
1550 {
1551 	return volume->device_minor;
1552 }
1553 
1554 const char *
1555 libhal_volume_get_fstype (LibHalVolume *volume)
1556 {
1557 	return volume->fstype;
1558 }
1559 
1560 const char *
1561 libhal_volume_get_fsversion (LibHalVolume *volume)
1562 {
1563 	return volume->fsversion;
1564 }
1565 
1566 LibHalVolumeUsage
1567 libhal_volume_get_fsusage (LibHalVolume *volume)
1568 {
1569 	return volume->fsusage;
1570 }
1571 
1572 dbus_bool_t
1573 libhal_volume_is_mounted (LibHalVolume *volume)
1574 {
1575 	return volume->is_mounted;
1576 }
1577 
1578 dbus_bool_t
1579 libhal_volume_is_mounted_read_only (LibHalVolume *volume)
1580 {
1581 	return volume->is_mounted_read_only;
1582 }
1583 
1584 dbus_bool_t
1585 libhal_volume_is_partition (LibHalVolume *volume)
1586 {
1587 	return volume->is_partition;
1588 }
1589 
1590 dbus_bool_t
1591 libhal_volume_is_disc (LibHalVolume *volume)
1592 {
1593 	return volume->is_disc;
1594 }
1595 
1596 unsigned int
1597 libhal_volume_get_partition_number (LibHalVolume *volume)
1598 {
1599 	return volume->partition_number;
1600 }
1601 
1602 const char *
1603 libhal_volume_get_partition_scheme (LibHalVolume *volume)
1604 {
1605 	return volume->partition_scheme;
1606 }
1607 
1608 const char *
1609 libhal_volume_get_partition_type (LibHalVolume *volume)
1610 {
1611 	return volume->partition_type;
1612 }
1613 
1614 const char *
1615 libhal_volume_get_partition_label (LibHalVolume *volume)
1616 {
1617 	return volume->partition_label;
1618 }
1619 
1620 const char *
1621 libhal_volume_get_partition_uuid (LibHalVolume *volume)
1622 {
1623 	return volume->partition_uuid;
1624 }
1625 
1626 const char **
1627 libhal_volume_get_partition_flags (LibHalVolume *volume)
1628 {
1629 	return (const char **) volume->partition_flags;
1630 }
1631 
1632 
1633 dbus_uint64_t
1634 libhal_volume_get_partition_start_offset (LibHalVolume *volume)
1635 {
1636 	return volume->partition_start_offset;
1637 }
1638 
1639 dbus_uint64_t
1640 libhal_volume_get_partition_media_size (LibHalVolume *volume)
1641 {
1642 	return volume->partition_media_size;
1643 }
1644 
1645 const char *
1646 libhal_volume_get_label (LibHalVolume *volume)
1647 {
1648 	return volume->volume_label;
1649 }
1650 
1651 const char *
1652 libhal_volume_get_mount_point (LibHalVolume *volume)
1653 {
1654 	return volume->mount_point;
1655 }
1656 
1657 const char *
1658 libhal_volume_get_uuid (LibHalVolume *volume)
1659 {
1660 	return volume->uuid;
1661 }
1662 
1663 dbus_bool_t
1664 libhal_volume_disc_has_audio (LibHalVolume *volume)
1665 {
1666 	return volume->disc_has_audio;
1667 }
1668 
1669 dbus_bool_t
1670 libhal_volume_disc_has_data (LibHalVolume *volume)
1671 {
1672 	return volume->disc_has_data;
1673 }
1674 
1675 dbus_bool_t
1676 libhal_volume_disc_is_blank (LibHalVolume *volume)
1677 {
1678 	return volume->disc_is_blank;
1679 }
1680 
1681 dbus_bool_t
1682 libhal_volume_disc_is_rewritable (LibHalVolume *volume)
1683 {
1684 	return volume->disc_is_rewritable;
1685 }
1686 
1687 dbus_bool_t
1688 libhal_volume_disc_is_appendable (LibHalVolume *volume)
1689 {
1690 	return volume->disc_is_appendable;
1691 }
1692 
1693 LibHalVolumeDiscType
1694 libhal_volume_get_disc_type (LibHalVolume *volume)
1695 {
1696 	return volume->disc_type;
1697 }
1698 
1699 dbus_bool_t
1700 libhal_volume_should_ignore (LibHalVolume     *volume)
1701 {
1702 	return volume->ignore_volume;
1703 }
1704 
1705 char **
1706 libhal_drive_find_all_volumes (LibHalContext *hal_ctx, LibHalDrive *drive, int *num_volumes)
1707 {
1708 	int i;
1709 	char **udis;
1710 	int num_udis;
1711 	const char *drive_udi;
1712 	char **result;
1713 	DBusError error;
1714 
1715 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
1716 
1717 	udis = NULL;
1718 	result = NULL;
1719 	*num_volumes = 0;
1720 
1721 	drive_udi = libhal_drive_get_udi (drive);
1722 	if (drive_udi == NULL)
1723 		goto out;
1724 
1725 	/* get initial list... */
1726 	dbus_error_init (&error);
1727 	if ((udis = libhal_manager_find_device_string_match (hal_ctx, "block.storage_device",
1728 							     drive_udi, &num_udis, &error)) == NULL) {
1729 		LIBHAL_FREE_DBUS_ERROR(&error);
1730 		goto out;
1731 	}
1732 
1733 	result = malloc (sizeof (char *) * (num_udis + 1));
1734 	if (result == NULL)
1735 		goto out;
1736 
1737 	/* ...and filter out the single UDI that is the drive itself */
1738 	for (i = 0; i < num_udis; i++) {
1739 		if (strcmp (udis[i], drive_udi) == 0)
1740 			continue;
1741 		result[*num_volumes] = strdup (udis[i]);
1742 		*num_volumes = (*num_volumes) + 1;
1743 	}
1744 	/* set last element (above removed UDI) to NULL for libhal_free_string_array()*/
1745 	result[*num_volumes] = NULL;
1746 
1747 out:
1748 	libhal_free_string_array (udis);
1749 	return result;
1750 }
1751 
1752 const char *
1753 libhal_volume_crypto_get_backing_volume_udi (LibHalVolume *volume)
1754 {
1755 	return volume->crypto_backing_volume;
1756 }
1757 
1758 char *
1759 libhal_volume_crypto_get_clear_volume_udi (LibHalContext *hal_ctx, LibHalVolume *volume)
1760 {
1761 	DBusError error;
1762 	char **clear_devices;
1763 	int num_clear_devices;
1764 	char *result;
1765 
1766 	result = NULL;
1767 
1768 	LIBHAL_CHECK_LIBHALCONTEXT (hal_ctx, NULL);
1769 
1770 	dbus_error_init (&error);
1771 	clear_devices = libhal_manager_find_device_string_match (hal_ctx,
1772 								 "volume.crypto_luks.clear.backing_volume",
1773 								 volume->udi,
1774 								 &num_clear_devices,
1775 								 &error);
1776 	if (clear_devices != NULL) {
1777 
1778 		if (num_clear_devices >= 1) {
1779 			result = strdup (clear_devices[0]);
1780 		}
1781 		libhal_free_string_array (clear_devices);
1782 	}
1783 
1784 	return result;
1785 }
1786 
1787 
1788 /*************************************************************************/
1789 
1790 char *
1791 libhal_drive_policy_default_get_mount_root (LibHalContext *hal_ctx)
1792 {
1793 	char *result;
1794 	DBusError error;
1795 
1796 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
1797 
1798 	dbus_error_init (&error);
1799 	if ((result = libhal_device_get_property_string (hal_ctx, "/org/freedesktop/Hal/devices/computer",
1800 						    "storage.policy.default.mount_root", &error)) == NULL)
1801 		LIBHAL_FREE_DBUS_ERROR(&error);
1802 
1803 	return result;
1804 }
1805 
1806 dbus_bool_t
1807 libhal_drive_policy_default_use_managed_keyword (LibHalContext *hal_ctx)
1808 {
1809 	dbus_bool_t result;
1810 	DBusError error;
1811 
1812 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, FALSE);
1813 
1814 	dbus_error_init (&error);
1815 	if ((result = libhal_device_get_property_bool (hal_ctx, "/org/freedesktop/Hal/devices/computer",
1816 						  "storage.policy.default.use_managed_keyword", &error)) == FALSE)
1817 		LIBHAL_FREE_DBUS_ERROR(&error);
1818 
1819 	return result;
1820 }
1821 
1822 char *
1823 libhal_drive_policy_default_get_managed_keyword_primary (LibHalContext *hal_ctx)
1824 {
1825 	char *result;
1826 	DBusError error;
1827 
1828 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
1829 
1830 	dbus_error_init (&error);
1831 	if ((result = libhal_device_get_property_string (hal_ctx, "/org/freedesktop/Hal/devices/computer",
1832 						    "storage.policy.default.managed_keyword.primary", &error)) == NULL)
1833 		LIBHAL_FREE_DBUS_ERROR(&error);
1834 
1835 	return result;
1836 }
1837 
1838 char *
1839 libhal_drive_policy_default_get_managed_keyword_secondary (LibHalContext *hal_ctx)
1840 {
1841 	char *result;
1842 	DBusError error;
1843 
1844 	LIBHAL_CHECK_LIBHALCONTEXT(hal_ctx, NULL);
1845 
1846 	dbus_error_init (&error);
1847 	if ((result = libhal_device_get_property_string (hal_ctx, "/org/freedesktop/Hal/devices/computer",
1848 						    "storage.policy.default.managed_keyword.secondary", &error)) == NULL)
1849 		LIBHAL_FREE_DBUS_ERROR(&error);
1850 
1851 	return result;
1852 }
1853 
1854 /*************************************************************************/
1855 
1856 dbus_bool_t
1857 libhal_drive_policy_is_mountable (LibHalDrive *drive, LibHalStoragePolicy *policy)
1858 {
1859 	printf ("should_mount=%d, no_partitions_hint=%d\n", drive->should_mount, drive->no_partitions_hint);
1860 
1861 	return drive->should_mount && drive->no_partitions_hint;
1862 }
1863 
1864 const char *
1865 libhal_drive_policy_get_desired_mount_point (LibHalDrive *drive, LibHalStoragePolicy *policy)
1866 {
1867 	return drive->desired_mount_point;
1868 }
1869 
1870 /* safely strcat() at most the remaining space in 'dst' */
1871 #define strcat_len(dst, src, dstmaxlen) do {    \
1872 	dst[dstmaxlen - 1] = '\0'; \
1873 	strncat (dst, src, dstmaxlen - strlen (dst) - 1); \
1874 } while(0)
1875 
1876 
1877 static void
1878 mopts_collect (LibHalContext *hal_ctx, const char *namespace, int namespace_len,
1879 	       const char *udi, char *options_string, size_t options_max_len, dbus_bool_t only_collect_imply_opts)
1880 {
1881 	LibHalPropertySet *properties;
1882 	LibHalPropertySetIterator it;
1883 	DBusError error;
1884 
1885 	if(hal_ctx == 0) {
1886 		fprintf (stderr,"%s %d : LibHalContext *ctx is NULL\n",__FILE__, __LINE__);
1887 		return;
1888 	}
1889 
1890 	dbus_error_init (&error);
1891 
1892 	/* first collect from root computer device */
1893 	properties = libhal_device_get_all_properties (hal_ctx, udi, &error);
1894 	if (properties == NULL ) {
1895 		LIBHAL_FREE_DBUS_ERROR(&error);
1896 		return;
1897 	}
1898 
1899 	for (libhal_psi_init (&it, properties); libhal_psi_has_more (&it); libhal_psi_next (&it)) {
1900 		int type;
1901 		char *key;
1902 
1903 		type = libhal_psi_get_type (&it);
1904 		key = libhal_psi_get_key (&it);
1905 		if (libhal_psi_get_type (&it) == LIBHAL_PROPERTY_TYPE_BOOLEAN &&
1906 		    strncmp (key, namespace, namespace_len - 1) == 0) {
1907 			const char *option = key + namespace_len - 1;
1908 			char *location;
1909 			dbus_bool_t is_imply_opt;
1910 
1911 			is_imply_opt = FALSE;
1912 			if (strcmp (option, "user") == 0 ||
1913 			    strcmp (option, "users") == 0 ||
1914 			    strcmp (option, "defaults") == 0 ||
1915 			    strcmp (option, "pamconsole") == 0)
1916 				is_imply_opt = TRUE;
1917 
1918 
1919 			if (only_collect_imply_opts) {
1920 				if (!is_imply_opt)
1921 					continue;
1922 			} else {
1923 				if (is_imply_opt)
1924 					continue;
1925 			}
1926 
1927 			if (libhal_psi_get_bool (&it)) {
1928 				/* see if option is already there */
1929 				location = strstr (options_string, option);
1930 				if (location == NULL) {
1931 					if (strlen (options_string) > 0)
1932 						strcat_len (options_string, ",", options_max_len);
1933 					strcat_len (options_string, option, options_max_len);
1934 				}
1935 			} else {
1936 				/* remove option if already there */
1937 				location = strstr (options_string, option);
1938 				if (location != NULL) {
1939 					char *end;
1940 
1941 					end = strchr (location, ',');
1942 					if (end == NULL) {
1943 						location[0] = '\0';
1944 					} else {
1945 						strcpy (location, end + 1); /* skip the extra comma */
1946 					}
1947 				}
1948 
1949 			}
1950 		}
1951 	}
1952 
1953 	libhal_free_property_set (properties);
1954 }
1955 
1956 
1957 const char *
1958 libhal_drive_policy_get_mount_options (LibHalDrive *drive, LibHalStoragePolicy *policy)
1959 {
1960 	const char *result;
1961 	char stor_mount_option_default_begin[] = "storage.policy.default.mount_option.";
1962 	char stor_mount_option_begin[] = "storage.policy.mount_option.";
1963 
1964 	result = NULL;
1965 	drive->mount_options[0] = '\0';
1966 
1967 	/* collect options != ('pamconsole', 'user', 'users', 'defaults' options that imply other options)  */
1968 	mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
1969 		       "/org/freedesktop/Hal/devices/computer", drive->mount_options, MOUNT_OPTIONS_SIZE, TRUE);
1970 	mopts_collect (drive->hal_ctx, stor_mount_option_begin, sizeof (stor_mount_option_begin),
1971 		       drive->udi, drive->mount_options, MOUNT_OPTIONS_SIZE, TRUE);
1972 	/* ensure ('pamconsole', 'user', 'users', 'defaults' options that imply other options), are first */
1973 	mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
1974 		       "/org/freedesktop/Hal/devices/computer", drive->mount_options, MOUNT_OPTIONS_SIZE, FALSE);
1975 	mopts_collect (drive->hal_ctx, stor_mount_option_begin, sizeof (stor_mount_option_begin),
1976 		       drive->udi, drive->mount_options, MOUNT_OPTIONS_SIZE, FALSE);
1977 
1978 	result = drive->mount_options;
1979 
1980 	return result;
1981 }
1982 
1983 const char *
1984 libhal_drive_policy_get_mount_fs (LibHalDrive *drive, LibHalStoragePolicy *policy)
1985 {
1986 	return drive->mount_filesystem;
1987 }
1988 
1989 
1990 dbus_bool_t
1991 libhal_volume_policy_is_mountable (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
1992 {
1993 	return drive->should_mount && volume->should_mount;
1994 }
1995 
1996 const char *libhal_volume_policy_get_desired_mount_point (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
1997 {
1998 	return volume->desired_mount_point;
1999 }
2000 
2001 const char *libhal_volume_policy_get_mount_options (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
2002 {
2003 	const char *result;
2004 	char stor_mount_option_default_begin[] = "storage.policy.default.mount_option.";
2005 	char vol_mount_option_begin[] = "volume.policy.mount_option.";
2006 
2007 	result = NULL;
2008 	volume->mount_options[0] = '\0';
2009 
2010 	/* ensure ('pamconsole', 'user', 'users', 'defaults' options that imply other options), are first */
2011 	mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
2012 		       "/org/freedesktop/Hal/devices/computer", volume->mount_options, MOUNT_OPTIONS_SIZE, TRUE);
2013 	mopts_collect (drive->hal_ctx, vol_mount_option_begin, sizeof (vol_mount_option_begin),
2014 		       volume->udi, volume->mount_options, MOUNT_OPTIONS_SIZE, TRUE);
2015 	/* collect options != ('pamconsole', 'user', 'users', 'defaults' options that imply other options)  */
2016 	mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
2017 		       "/org/freedesktop/Hal/devices/computer", volume->mount_options, MOUNT_OPTIONS_SIZE, FALSE);
2018 	mopts_collect (drive->hal_ctx, vol_mount_option_begin, sizeof (vol_mount_option_begin),
2019 		       volume->udi, volume->mount_options, MOUNT_OPTIONS_SIZE, FALSE);
2020 
2021 	result = volume->mount_options;
2022 
2023 	return result;
2024 }
2025 
2026 const char *libhal_volume_policy_get_mount_fs (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
2027 {
2028 	return volume->mount_filesystem;
2029 }
2030 
2031 dbus_bool_t
2032 libhal_drive_no_partitions_hint (LibHalDrive *drive)
2033 {
2034 	return drive->no_partitions_hint;
2035 }
2036 
2037 /** @} */
2038