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