libhal-storage.c revision 2912:85ea316d9c18
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
60typedef struct IconMappingEntry_s {
61	LibHalStoragePolicyIcon icon;
62	char *path;
63	struct IconMappingEntry_s *next;
64} IconMappingEntry;
65
66struct LibHalStoragePolicy_s {
67	IconMappingEntry *icon_mappings;
68};
69
70LibHalStoragePolicy *
71libhal_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;
80out:
81	return p;
82}
83
84void
85libhal_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
100void
101libhal_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
122out:
123	return;
124}
125
126void
127libhal_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
136const char *
137libhal_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	}
149out:
150	return path;
151}
152
153
154#define MAX_STRING_SZ 256
155
156char *
157libhal_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
190out:
191	return result;
192}
193
194static void
195fixup_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) */
204char *
205libhal_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
350char *
351libhal_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
512out:
513	free (size_str);
514	return name;
515}
516
517char *
518libhal_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
547char *
548libhal_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	}
582out:
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 */
605dbus_bool_t
606libhal_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
670out:
671	return is_visible;
672}
673
674/*************************************************************************/
675
676#define MOUNT_OPTIONS_SIZE 256
677
678struct 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
723struct 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
780const char *
781libhal_drive_get_dedicated_icon_drive (LibHalDrive *drive)
782{
783	return drive->dedicated_icon_drive;
784}
785
786const char *
787libhal_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 */
796void
797libhal_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 */
825void
826libhal_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
853static char **
854my_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
871out:
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 */
894LibHalDrive *
895libhal_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
1055error:
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
1063const char *
1064libhal_volume_get_storage_device_udi (LibHalVolume *volume)
1065{
1066	return volume->storage_device;
1067}
1068
1069const char *libhal_drive_get_physical_device_udi (LibHalDrive *drive)
1070{
1071	return drive->physical_device;
1072}
1073
1074dbus_bool_t
1075libhal_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 */
1088LibHalVolume *
1089libhal_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;
1239error:
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 */
1259int
1260libhal_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 */
1273dbus_uint64_t
1274libhal_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 */
1287dbus_uint64_t
1288libhal_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 */
1302LibHalDrive *
1303libhal_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);
1354out:
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 */
1365LibHalVolume *
1366libhal_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);
1400out:
1401	LIBHAL_FREE_DBUS_ERROR(&error);
1402	return result;
1403}
1404
1405dbus_uint64_t
1406libhal_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
1414dbus_uint64_t
1415libhal_volume_get_disc_capacity (LibHalVolume *volume)
1416{
1417	return volume->disc_capacity;
1418}
1419
1420
1421dbus_bool_t
1422libhal_drive_is_hotpluggable (LibHalDrive *drive)
1423{
1424	return drive->is_hotpluggable;
1425}
1426
1427dbus_bool_t
1428libhal_drive_uses_removable_media (LibHalDrive *drive)
1429{
1430	return drive->is_removable;
1431}
1432
1433dbus_bool_t
1434libhal_drive_is_media_detected (LibHalDrive *drive)
1435{
1436	return drive->is_media_detected;
1437}
1438
1439dbus_uint64_t
1440libhal_drive_get_size (LibHalDrive *drive)
1441{
1442	return drive->drive_size;
1443}
1444
1445dbus_uint64_t
1446libhal_drive_get_media_size (LibHalDrive *drive)
1447{
1448	return drive->drive_media_size;
1449}
1450
1451const char *
1452libhal_drive_get_partition_scheme (LibHalDrive *drive)
1453{
1454	return drive->partition_scheme;
1455}
1456
1457
1458LibHalDriveType
1459libhal_drive_get_type (LibHalDrive *drive)
1460{
1461	return drive->type;
1462}
1463
1464LibHalDriveBus
1465libhal_drive_get_bus (LibHalDrive *drive)
1466{
1467	return drive->bus;
1468}
1469
1470LibHalDriveCdromCaps
1471libhal_drive_get_cdrom_caps (LibHalDrive *drive)
1472{
1473	return drive->cdrom_caps;
1474}
1475
1476unsigned int
1477libhal_drive_get_device_major (LibHalDrive *drive)
1478{
1479	return drive->device_major;
1480}
1481
1482unsigned int
1483libhal_drive_get_device_minor (LibHalDrive *drive)
1484{
1485	return drive->device_minor;
1486}
1487
1488const char *
1489libhal_drive_get_type_textual (LibHalDrive *drive)
1490{
1491	return drive->type_textual;
1492}
1493
1494const char *
1495libhal_drive_get_device_file (LibHalDrive *drive)
1496{
1497	return drive->device_file;
1498}
1499
1500const char *
1501libhal_drive_get_udi (LibHalDrive *drive)
1502{
1503	return drive->udi;
1504}
1505
1506const char *
1507libhal_drive_get_serial (LibHalDrive *drive)
1508{
1509	return drive->serial;
1510}
1511
1512const char *
1513libhal_drive_get_firmware_version (LibHalDrive *drive)
1514{
1515	return drive->firmware_version;
1516}
1517
1518const char *
1519libhal_drive_get_model (LibHalDrive *drive)
1520{
1521	return drive->model;
1522}
1523
1524const char *
1525libhal_drive_get_vendor (LibHalDrive *drive)
1526{
1527	return drive->vendor;
1528}
1529
1530/*****************************************************************************/
1531
1532const char *
1533libhal_volume_get_udi (LibHalVolume *volume)
1534{
1535	return volume->udi;
1536}
1537
1538const char *
1539libhal_volume_get_device_file (LibHalVolume *volume)
1540{
1541	return volume->device_file;
1542}
1543
1544unsigned int libhal_volume_get_device_major (LibHalVolume *volume)
1545{
1546	return volume->device_major;
1547}
1548
1549unsigned int libhal_volume_get_device_minor (LibHalVolume *volume)
1550{
1551	return volume->device_minor;
1552}
1553
1554const char *
1555libhal_volume_get_fstype (LibHalVolume *volume)
1556{
1557	return volume->fstype;
1558}
1559
1560const char *
1561libhal_volume_get_fsversion (LibHalVolume *volume)
1562{
1563	return volume->fsversion;
1564}
1565
1566LibHalVolumeUsage
1567libhal_volume_get_fsusage (LibHalVolume *volume)
1568{
1569	return volume->fsusage;
1570}
1571
1572dbus_bool_t
1573libhal_volume_is_mounted (LibHalVolume *volume)
1574{
1575	return volume->is_mounted;
1576}
1577
1578dbus_bool_t
1579libhal_volume_is_mounted_read_only (LibHalVolume *volume)
1580{
1581	return volume->is_mounted_read_only;
1582}
1583
1584dbus_bool_t
1585libhal_volume_is_partition (LibHalVolume *volume)
1586{
1587	return volume->is_partition;
1588}
1589
1590dbus_bool_t
1591libhal_volume_is_disc (LibHalVolume *volume)
1592{
1593	return volume->is_disc;
1594}
1595
1596unsigned int
1597libhal_volume_get_partition_number (LibHalVolume *volume)
1598{
1599	return volume->partition_number;
1600}
1601
1602const char *
1603libhal_volume_get_partition_scheme (LibHalVolume *volume)
1604{
1605	return volume->partition_scheme;
1606}
1607
1608const char *
1609libhal_volume_get_partition_type (LibHalVolume *volume)
1610{
1611	return volume->partition_type;
1612}
1613
1614const char *
1615libhal_volume_get_partition_label (LibHalVolume *volume)
1616{
1617	return volume->partition_label;
1618}
1619
1620const char *
1621libhal_volume_get_partition_uuid (LibHalVolume *volume)
1622{
1623	return volume->partition_uuid;
1624}
1625
1626const char **
1627libhal_volume_get_partition_flags (LibHalVolume *volume)
1628{
1629	return (const char **) volume->partition_flags;
1630}
1631
1632
1633dbus_uint64_t
1634libhal_volume_get_partition_start_offset (LibHalVolume *volume)
1635{
1636	return volume->partition_start_offset;
1637}
1638
1639dbus_uint64_t
1640libhal_volume_get_partition_media_size (LibHalVolume *volume)
1641{
1642	return volume->partition_media_size;
1643}
1644
1645const char *
1646libhal_volume_get_label (LibHalVolume *volume)
1647{
1648	return volume->volume_label;
1649}
1650
1651const char *
1652libhal_volume_get_mount_point (LibHalVolume *volume)
1653{
1654	return volume->mount_point;
1655}
1656
1657const char *
1658libhal_volume_get_uuid (LibHalVolume *volume)
1659{
1660	return volume->uuid;
1661}
1662
1663dbus_bool_t
1664libhal_volume_disc_has_audio (LibHalVolume *volume)
1665{
1666	return volume->disc_has_audio;
1667}
1668
1669dbus_bool_t
1670libhal_volume_disc_has_data (LibHalVolume *volume)
1671{
1672	return volume->disc_has_data;
1673}
1674
1675dbus_bool_t
1676libhal_volume_disc_is_blank (LibHalVolume *volume)
1677{
1678	return volume->disc_is_blank;
1679}
1680
1681dbus_bool_t
1682libhal_volume_disc_is_rewritable (LibHalVolume *volume)
1683{
1684	return volume->disc_is_rewritable;
1685}
1686
1687dbus_bool_t
1688libhal_volume_disc_is_appendable (LibHalVolume *volume)
1689{
1690	return volume->disc_is_appendable;
1691}
1692
1693LibHalVolumeDiscType
1694libhal_volume_get_disc_type (LibHalVolume *volume)
1695{
1696	return volume->disc_type;
1697}
1698
1699dbus_bool_t
1700libhal_volume_should_ignore (LibHalVolume     *volume)
1701{
1702	return volume->ignore_volume;
1703}
1704
1705char **
1706libhal_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);
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
1747out:
1748	libhal_free_string_array (udis);
1749	return result;
1750}
1751
1752const char *
1753libhal_volume_crypto_get_backing_volume_udi (LibHalVolume *volume)
1754{
1755	return volume->crypto_backing_volume;
1756}
1757
1758char *
1759libhal_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
1790char *
1791libhal_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
1806dbus_bool_t
1807libhal_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
1822char *
1823libhal_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
1838char *
1839libhal_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
1856dbus_bool_t
1857libhal_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
1864const char *
1865libhal_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
1877static void
1878mopts_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
1957const char *
1958libhal_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
1983const char *
1984libhal_drive_policy_get_mount_fs (LibHalDrive *drive, LibHalStoragePolicy *policy)
1985{
1986	return drive->mount_filesystem;
1987}
1988
1989
1990dbus_bool_t
1991libhal_volume_policy_is_mountable (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
1992{
1993	return drive->should_mount && volume->should_mount;
1994}
1995
1996const char *libhal_volume_policy_get_desired_mount_point (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
1997{
1998	return volume->desired_mount_point;
1999}
2000
2001const 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
2026const char *libhal_volume_policy_get_mount_fs (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
2027{
2028	return volume->mount_filesystem;
2029}
2030
2031dbus_bool_t
2032libhal_drive_no_partitions_hint (LibHalDrive *drive)
2033{
2034	return drive->no_partitions_hint;
2035}
2036
2037/** @} */
2038