hal/hald Makefile.am, 1.36, 1.37 device.c, 1.10, 1.11 device.h, 1.8, 1.9 device_info.c, 1.12, 1.13 hald.c, 1.19, 1.20

David Zeuthen david at freedesktop.org
Tue Oct 12 13:17:10 PDT 2004


Update of /cvs/hal/hal/hald
In directory gabe:/tmp/cvs-serv22195/hald

Modified Files:
	Makefile.am device.c device.h device_info.c hald.c 
Log Message:
2004-10-12  David Zeuthen  <davidz at redhat.com>

	First part of big patch to use .fdi files for policy properties.

	* configure.in: Add a bunch of new configure.in variables

	* doc/Makefile.am: Add conf directory

	* doc/conf/Makefile.am: New file

	* doc/conf/storage-policy-examples.fdi: New file

	* fdi/30osvendor/Makefile.am: New file

	* fdi/40oem/Makefile.am: New file

	* fdi/50user/Makefile.am: New file

	* fdi/90defaultpolicy/Makefile.am: New File

	* fdi/90defaultpolicy/storage-policy.fdi: New file

	* fdi/95userpolicy/Makefile.am: New file

	* fdi/Makefile.am: Added new subdirs

	* hald/Makefile.am: Link with libselinux if selinux is enabled

	* hald/device.c: 
	(hal_device_property_get_as_string): New function
	(hal_device_copy_property): New function

	* hald/device.h: Add prototypes for two new functions

	* hald/device_info.c:
	(resolve_udiprop_path): New function 
	(match_compare_property): New function
	(handle_match): Allow property names to contain UDI dirct and indirect
	references. Add support for 'exists', 'empty', 'is_absolute_path', 
	'compare_lt', 'compare_le', 'compare_gt', 'compare_ge'
	(handle_merge): Add support for 'copy_property'
	(handle_append): New function
	(start): Support new 'append' operation (like merge)
	(end): Also support MERGE_TYPE_COPY_PROPERTY. Fixup compare bug in 
	match_depth_first_fail that made several matches on the same level
	impossible.
	(process_fdi_file): Init match_depth_first_fail to -1

	* hald/linux/osspec.c (osspec_probe): Add selinux support to
	root computer device object.



Index: Makefile.am
===================================================================
RCS file: /cvs/hal/hal/hald/Makefile.am,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- Makefile.am	20 Sep 2004 18:31:15 -0000	1.36
+++ Makefile.am	12 Oct 2004 20:17:08 -0000	1.37
@@ -80,6 +80,10 @@
 
 hald_LDADD = @PACKAGE_LIBS@ -lcap @EXPAT_LIB@
 
+if HAVE_SELINUX
+hald_LDADD += -lselinux
+endif
+
 #### Init scripts fun
 SCRIPT_IN_FILES=haldaemon.in
 

Index: device.c
===================================================================
RCS file: /cvs/hal/hal/hald/device.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- device.c	2 Sep 2004 21:45:49 -0000	1.10
+++ device.c	12 Oct 2004 20:17:08 -0000	1.11
@@ -564,6 +564,42 @@
 		return NULL;
 }
 
+const char *
+hal_device_property_get_as_string (HalDevice *device, const char *key, char *buf, size_t bufsize)
+{
+	HalProperty *prop;
+
+	g_return_val_if_fail (device != NULL, NULL);
+	g_return_val_if_fail (key != NULL, NULL);
+	g_return_val_if_fail (buf != NULL, NULL);
+
+	prop = hal_device_property_find (device, key);
+
+	if (prop != NULL) {
+		switch (hal_property_get_type (prop)) {
+		case DBUS_TYPE_STRING:
+			strncpy (buf, hal_property_get_string (prop), bufsize);
+			break;
+		case DBUS_TYPE_INT32:
+			snprintf (buf, bufsize, "%d", hal_property_get_int (prop));
+			break;
+		case DBUS_TYPE_UINT64:
+			snprintf (buf, bufsize, "%lld", hal_property_get_uint64 (prop));
+			break;
+		case DBUS_TYPE_DOUBLE:
+			snprintf (buf, bufsize, "%f", hal_property_get_double (prop));
+			break;
+		case DBUS_TYPE_BOOLEAN:
+			strncpy (buf, hal_property_get_bool (prop) ? "true" : "false", bufsize);
+			break;
+		}
+		return buf;
+	} else {
+		buf[0] = '\0';
+		return NULL;
+	}
+}
+
 dbus_int32_t
 hal_device_property_get_int (HalDevice *device, const char *key)
 {
@@ -831,6 +867,41 @@
 }
 
 gboolean
+hal_device_copy_property (HalDevice *from_device, const char *from, HalDevice *to_device, const char *to)
+{
+	gboolean rc;
+
+	rc = FALSE;
+
+	if (hal_device_has_property (from_device, from)) {
+		switch (hal_device_property_get_type (from_device, from)) {
+		case DBUS_TYPE_STRING:
+			rc = hal_device_property_set_string (
+				to_device, to, hal_device_property_get_string (from_device, from));
+			break;
+		case DBUS_TYPE_INT32:
+			rc = hal_device_property_set_int (
+				to_device, to, hal_device_property_get_int (from_device, from));
+			break;
+		case DBUS_TYPE_UINT64:
+			rc = hal_device_property_set_uint64 (
+				to_device, to, hal_device_property_get_uint64 (from_device, from));
+			break;
+		case DBUS_TYPE_BOOLEAN:
+			rc = hal_device_property_set_bool (
+				to_device, to, hal_device_property_get_bool (from_device, from));
+			break;
+		case DBUS_TYPE_DOUBLE:
+			rc = hal_device_property_set_double (
+				to_device, to, hal_device_property_get_double (from_device, from));
+			break;
+		}
+	}
+
+	return rc;
+}
+
+gboolean
 hal_device_property_remove (HalDevice *device, const char *key)
 {
 	HalProperty *prop;

Index: device.h
===================================================================
RCS file: /cvs/hal/hal/hald/device.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- device.h	1 Sep 2004 17:38:58 -0000	1.8
+++ device.h	12 Oct 2004 20:17:08 -0000	1.9
@@ -117,6 +117,10 @@
 
 int           hal_device_property_get_type   (HalDevice    *device,
 					      const char   *key);
+const char   *hal_device_property_get_as_string (HalDevice    *device,
+						 const char   *key,
+						 char *buf,
+						 size_t bufsize);
 const char   *hal_device_property_get_string (HalDevice    *device,
 					      const char   *key);
 dbus_int32_t  hal_device_property_get_int    (HalDevice    *device,
@@ -147,6 +151,12 @@
 gboolean      hal_device_property_remove     (HalDevice    *device,
 					      const char   *key);
 
+gboolean      hal_device_copy_property       (HalDevice *from_device, 
+					      const char *from,
+					      HalDevice *to_device,
+					      const char *to);
+
+
 void          hal_device_print               (HalDevice    *device);
 
 void          hal_device_async_wait_property (HalDevice    *device,

Index: device_info.c
===================================================================
RCS file: /cvs/hal/hal/hald/device_info.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- device_info.c	1 Sep 2004 17:38:58 -0000	1.12
+++ device_info.c	12 Oct 2004 20:17:08 -0000	1.13
@@ -35,9 +35,12 @@
 #include <assert.h>
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
+#include <math.h>
 
+#include "hald.h"
 #include "logger.h"
 #include "device_info.h"
+#include "device_store.h"
 
 /**
  * @defgroup DeviceInfo Device Info File Parsing
@@ -72,6 +75,20 @@
 
 	/** Processing a merge element */
 	CURELEM_MERGE = 3,
+
+	/** Processing an append element */
+	CURELEM_APPEND = 4,
+};
+
+/** What and how to merge */
+enum {
+	MERGE_TYPE_UNKNOWN,
+	MERGE_TYPE_STRING,
+	MERGE_TYPE_BOOLEAN,
+	MERGE_TYPE_INT32,
+	MERGE_TYPE_UINT64,
+	MERGE_TYPE_DOUBLE,
+	MERGE_TYPE_COPY_PROPERTY
 };
 
 /** Parsing Context
@@ -124,6 +141,166 @@
 
 } ParsingContext;
 
+/** Resolve a udi-property path as used in .fdi files. 
+ *
+ *  Examples of udi-property paths:
+ *
+ *   info.udi
+ *   /org/freedesktop/Hal/devices/computer:kernel.name
+ *   @block.storage_device:storage.bus
+ *   @block.storage_device:@storage.physical_device:ide.channel
+ *
+ *  @param  source_udi          UDI of source device
+ *  @param  path                The given path
+ *  @param  udi_result          Where to store the resulting UDI
+ *  @param  udi_result_size     Size of UDI string
+ *  @param  prop_result         Where to store the resulting property name
+ *  @param  prop_result_size    Size of property string
+ *  @return                     TRUE if and only if the path resolved.
+ */
+gboolean
+resolve_udiprop_path (const char *path, const char *source_udi,
+		      char *udi_result, size_t udi_result_size, 
+		      char *prop_result, size_t prop_result_size)
+{
+	int i;
+	gchar **tokens = NULL;
+	gboolean rc;
+
+	rc = FALSE;
+
+	/*HAL_INFO (("Looking at '%s' for udi='%s'", path, source_udi));*/
+
+	/* Split up path into ':' tokens */
+	tokens = g_strsplit (path, ":", 64);
+
+	/* Detect trivial property access, e.g. path='foo.bar'   */
+	if (tokens == NULL || tokens[0] == NULL || tokens[1] == NULL) {
+		strncpy (udi_result, source_udi, udi_result_size);
+		strncpy (prop_result, path, prop_result_size);
+		rc = TRUE;
+		goto out;
+	}
+
+	
+	/* Start with the source udi */
+	strncpy (udi_result, source_udi, udi_result_size);
+
+	for (i = 0; tokens[i] != NULL; i++) {
+		HalDevice *d;
+		gchar *curtoken;
+
+		/*HAL_INFO (("tokens[%d] = '%s'", i, tokens[i]));*/
+
+		d = hal_device_store_find (hald_get_gdl (), udi_result);
+		if (d == NULL)
+			d = hal_device_store_find (hald_get_tdl (), udi_result);
+		if (d == NULL)
+			goto out;
+
+		curtoken = tokens[i];
+
+		/* process all but the last tokens as UDI paths */
+		if (tokens[i+1] == NULL) {
+			strncpy (prop_result, curtoken, prop_result_size);
+			rc = TRUE;
+			goto out;
+		}
+
+
+		/* Check for indirection */
+		if (curtoken[0] == '@') {
+			const char *udiprop;
+			const char *newudi;
+
+			udiprop = curtoken + 1;
+
+			newudi = hal_device_property_get_string (d, udiprop);
+			if (newudi == NULL)
+				goto out;
+
+			/*HAL_INFO (("new_udi = '%s' (from indirection)", newudi));*/
+
+			strncpy (udi_result, newudi, udi_result_size);
+		} else {
+			/*HAL_INFO (("new_udi = '%s'", curtoken));*/
+			strncpy (udi_result, curtoken, udi_result_size);			
+		}
+
+	}
+
+out:
+
+/*
+	HAL_INFO (("success     = '%s'", rc ? "yes" : "no"));
+	HAL_INFO (("udi_result  = '%s'", udi_result));
+	HAL_INFO (("prop_result = '%s'", prop_result));
+*/
+
+	g_strfreev (tokens);
+
+	return rc;
+}
+
+/* Compare the value of a property on a hal device object against a string value
+ * and return the result. Note that this works for several types, e.g. both strings
+ * and integers - in the latter case the given right side string will be interpreted
+ * as a number.
+ *
+ * The comparison might not make sense if you are comparing a property which is an integer
+ * against a string in which case this function returns FALSE. Also, if the property doesn't
+ * exist this function will also return FALSE.
+ *
+ * @param  d                    hal device object
+ * @param  key                  Key of the property to compare
+ * @param  right_side           Value to compare against
+ * @param  result               Pointer to where to store result
+ * @return                      TRUE if, and only if, the comparison could take place
+ */
+static gboolean
+match_compare_property (HalDevice *d, const char *key, const char *right_side, dbus_int64_t *result)
+{
+	gboolean rc;
+	int proptype;
+
+	rc = FALSE;
+
+	if (!hal_device_has_property (d, key))
+		goto out;
+
+	proptype = hal_device_property_get_type (d, key);
+	switch (proptype) {
+	case DBUS_TYPE_STRING:
+		*result = (dbus_int64_t) strcmp (hal_device_property_get_string (d, key), right_side);
+		rc = TRUE;
+		break;
+
+	case DBUS_TYPE_INT32:
+		*result = ((dbus_int64_t) hal_device_property_get_int (d, key)) - strtoll (right_side, NULL, 0);
+		rc = TRUE;
+		break;
+
+	case DBUS_TYPE_UINT64:
+		*result = ((dbus_int64_t) hal_device_property_get_uint64 (d, key)) - ((dbus_int64_t) strtoll (right_side, NULL, 0));
+		rc = TRUE;
+		break;
+
+	case DBUS_TYPE_DOUBLE:
+		*result = (dbus_int64_t) ceil (hal_device_property_get_double (d, key) - atof (right_side));
+		rc = TRUE;
+		break;
+
+	default:
+		/* explicit fallthrough */
+	case DBUS_TYPE_BOOLEAN:
+		/* explicit blank since this doesn't make sense */
+		break;
+	}
+
+out:
+	return rc;
+}
+
 /** Called when the match element begins.
  *
  *  @param  pc                  Parsing context
@@ -134,8 +311,11 @@
 static dbus_bool_t
 handle_match (ParsingContext * pc, const char **attr)
 {
+	char udi_to_check[256];
+	char prop_to_check[256];
 	const char *key;
 	int num_attrib;
+	HalDevice *d;
 
 	for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++);
 
@@ -146,6 +326,25 @@
 		return FALSE;
 	key = attr[1];
 
+	/* Resolve key paths like 'someudi/foo/bar/baz:prop.name' '@prop.here.is.an.udi:with.prop.name' */
+	if (!resolve_udiprop_path (key,
+				   pc->device->udi,
+				   udi_to_check, sizeof (udi_to_check),
+				   prop_to_check, sizeof (prop_to_check))) {
+		HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", key, pc->device->udi));
+		return FALSE;
+	}
+
+	d = hal_device_store_find (hald_get_gdl (), udi_to_check);
+	if (d == NULL) {
+		d = hal_device_store_find (hald_get_tdl (), udi_to_check);
+	}
+	if (d == NULL) {
+		HAL_ERROR (("Could not find device with udi '%s'", udi_to_check));
+		return FALSE;
+	}
+	
+
 	if (strcmp (attr[2], "string") == 0) {
 		const char *value;
 
@@ -156,10 +355,10 @@
 		/*HAL_INFO(("Checking that key='%s' is a string that "
 		  "equals '%s'", key, value)); */
 
-		if (hal_device_property_get_type (pc->device, key) != DBUS_TYPE_STRING)
+		if (hal_device_property_get_type (d, prop_to_check) != DBUS_TYPE_STRING)
 			return FALSE;
 
-		if (strcmp (hal_device_property_get_string (pc->device, key),
+		if (strcmp (hal_device_property_get_string (d, prop_to_check),
 			    value) != 0)
 			return FALSE;
 
@@ -176,10 +375,10 @@
 		/*HAL_INFO (("Checking that key='%s' is a int that equals %d", 
 		  key, value));*/
 
-		if (hal_device_property_get_type (pc->device, key) != DBUS_TYPE_INT32)
+		if (hal_device_property_get_type (d, prop_to_check) != DBUS_TYPE_INT32)
 			return FALSE;
 
-		if (hal_device_property_get_int (pc->device, key) != value) {
+		if (hal_device_property_get_int (d, prop_to_check) != value) {
 			return FALSE;
 		}
 
@@ -195,10 +394,10 @@
 		/*HAL_INFO (("Checking that key='%s' is a int that equals %d", 
 		  key, value));*/
 
-		if (hal_device_property_get_type (pc->device, key) != DBUS_TYPE_UINT64)
+		if (hal_device_property_get_type (d, prop_to_check) != DBUS_TYPE_UINT64)
 			return FALSE;
 
-		if (hal_device_property_get_uint64 (pc->device, key) != value) {
+		if (hal_device_property_get_uint64 (d, prop_to_check) != value) {
 			return FALSE;
 		}
 
@@ -218,17 +417,120 @@
 		/*HAL_INFO (("Checking that key='%s' is a bool that equals %s", 
 		  key, value ? "TRUE" : "FALSE"));*/
 
-		if (hal_device_property_get_type (pc->device, key) != 
+		if (hal_device_property_get_type (d, prop_to_check) != 
 		    DBUS_TYPE_BOOLEAN)
 			return FALSE;
 
-		if (hal_device_property_get_bool (pc->device, key) != value)
+		if (hal_device_property_get_bool (d, prop_to_check) != value)
 			return FALSE;
 
 		/*HAL_INFO (("*** bool match for key %s", key));*/
 		return TRUE;
-	}
+	} else if (strcmp (attr[2], "exists") == 0) {
+		dbus_bool_t should_exist = TRUE;
+
+		if (strcmp (attr[3], "false") == 0)
+			should_exist = FALSE;
+
+		if (should_exist) {
+			if (hal_device_has_property (d, prop_to_check))
+				return TRUE;
+			else
+				return FALSE;
+		} else {
+			if (hal_device_has_property (d, prop_to_check))
+				return FALSE;
+			else
+				return TRUE;
+		}
+	} else if (strcmp (attr[2], "empty") == 0) {
+		dbus_bool_t is_empty = TRUE;
+		dbus_bool_t should_be_empty = TRUE;
+
+		if (strcmp (attr[3], "false") == 0)
+			should_be_empty = FALSE;
+
+		if (hal_device_property_get_type (d, prop_to_check) != DBUS_TYPE_STRING)
+			return FALSE;
+
+		if (hal_device_has_property (d, prop_to_check))
+			if (strlen (hal_device_property_get_string (d, prop_to_check)) > 0)
+				is_empty = FALSE;
+
+		if (should_be_empty) {
+			if (is_empty)
+				return TRUE;
+			else
+				return FALSE;
+		} else {
+			if (is_empty)
+				return FALSE;
+			else
+				return TRUE;
+		}
+	} else if (strcmp (attr[2], "is_absolute_path") == 0) {
+		const char *path = NULL;
+		dbus_bool_t is_absolute_path = FALSE;
+		dbus_bool_t should_be_absolute_path = TRUE;
+
+		if (strcmp (attr[3], "false") == 0)
+			should_be_absolute_path = FALSE;
+
+		/*HAL_INFO (("d->udi='%s', prop_to_check='%s'", d->udi, prop_to_check));*/
+
+		if (hal_device_property_get_type (d, prop_to_check) != DBUS_TYPE_STRING)
+			return FALSE;
+
+		if (hal_device_has_property (d, prop_to_check)) {
+			path = hal_device_property_get_string (d, prop_to_check);
+			if (g_path_is_absolute (path))
+				is_absolute_path = TRUE;
+		}
 
+		/*HAL_INFO (("is_absolute=%d, should_be=%d, path='%s'", is_absolute_path, should_be_absolute_path, path));*/
+
+
+		if (should_be_absolute_path) {
+			if (is_absolute_path)
+				return TRUE;
+			else
+				return FALSE;
+		} else {
+			if (is_absolute_path)
+				return FALSE;
+			else
+				return TRUE;
+		}
+	} else if (strcmp (attr[2], "compare_lt") == 0) {
+		dbus_int64_t result;
+		if (!match_compare_property (d, prop_to_check, attr[3], &result)) {
+			HAL_INFO (("foob failed"));
+			return FALSE;
+		} else {
+			HAL_INFO (("foob result = %lld", result));
+			HAL_INFO (("foob %d", result < 0));
+			return result < 0;
+		}
+	} else if (strcmp (attr[2], "compare_le") == 0) {
+		dbus_int64_t result;
+		if (!match_compare_property (d, prop_to_check, attr[3], &result))
+			return FALSE;
+		else
+			return result <= 0;
+	} else if (strcmp (attr[2], "compare_gt") == 0) {
+		dbus_int64_t result;
+		if (!match_compare_property (d, prop_to_check, attr[3], &result))
+			return FALSE;
+		else
+			return result > 0;
+	} else if (strcmp (attr[2], "compare_ge") == 0) {
+		dbus_int64_t result;
+		if (!match_compare_property (d, prop_to_check, attr[3], &result))
+			return FALSE;
+		else
+			return result >= 0;
+	}
+	
 	return FALSE;
 }
 
@@ -243,6 +545,9 @@
 {
 	int num_attrib;
 
+	pc->merge_type = MERGE_TYPE_UNKNOWN;
+
+
 	for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
 		;
 	}
@@ -259,23 +564,66 @@
 
 	if (strcmp (attr[3], "string") == 0) {
 		/* match string property */
-		pc->merge_type = DBUS_TYPE_STRING;
+		pc->merge_type = MERGE_TYPE_STRING;
 		return;
 	} else if (strcmp (attr[3], "bool") == 0) {
 		/* match string property */
-		pc->merge_type = DBUS_TYPE_BOOLEAN;
+		pc->merge_type = MERGE_TYPE_BOOLEAN;
 		return;
 	} else if (strcmp (attr[3], "int") == 0) {
 		/* match string property */
-		pc->merge_type = DBUS_TYPE_INT32;
+		pc->merge_type = MERGE_TYPE_INT32;
 		return;
 	} else if (strcmp (attr[3], "uint64") == 0) {
 		/* match string property */
-		pc->merge_type = DBUS_TYPE_UINT64;
+		pc->merge_type = MERGE_TYPE_UINT64;
 		return;
 	} else if (strcmp (attr[3], "double") == 0) {
 		/* match string property */
-		pc->merge_type = DBUS_TYPE_DOUBLE;
+		pc->merge_type = MERGE_TYPE_DOUBLE;
+		return;
+	} else if (strcmp (attr[3], "copy_property") == 0) {
+		/* copy another property */
+		pc->merge_type = MERGE_TYPE_COPY_PROPERTY;
+		return;
+	}
+
+	return;
+}
+
+/** Called when the append element begins.
+ *
+ *  @param  pc                  Parsing context
+ *  @param  attr                Attribute key/value pairs
+ */
+static void
+handle_append (ParsingContext * pc, const char **attr)
+{
+	int num_attrib;
+
+	pc->merge_type = MERGE_TYPE_UNKNOWN;
+
+	for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
+		;
+	}
+
+	if (num_attrib != 4)
+		return;
+
+	if (strcmp (attr[0], "key") != 0)
+		return;
+	strncpy (pc->merge_key, attr[1], MAX_KEY_SIZE);
+
+	if (strcmp (attr[2], "type") != 0)
+		return;
+
+	if (strcmp (attr[3], "string") == 0) {
+		/* match string property */
+		pc->merge_type = MERGE_TYPE_STRING;
+		return;
+	} else if (strcmp (attr[3], "copy_property") == 0) {
+		/* copy another property */
+		pc->merge_type = MERGE_TYPE_COPY_PROPERTY;
 		return;
 	}
 
@@ -333,6 +681,7 @@
 		}
 
 		pc->curelem = CURELEM_MATCH;
+
 		/* don't bother checking if matching at lower depths failed */
 		if (pc->match_ok) {
 			if (!handle_match (pc, attr)) {
@@ -358,6 +707,23 @@
 		} else {
 			/*HAL_INFO(("No merge!")); */
 		}
+	} else if (strcmp (el, "append") == 0) {
+		if (pc->curelem != CURELEM_DEVICE
+		    && pc->curelem != CURELEM_MATCH) {
+			HAL_ERROR (("%s:%d:%d: Element <append> can only be "
+				    "inside <device> and <match>", 
+				    pc->file, 
+				    XML_GetCurrentLineNumber (pc->parser), 
+				    XML_GetCurrentColumnNumber (pc->parser)));
+			parsing_abort (pc);
+		}
+
+		pc->curelem = CURELEM_APPEND;
+		if (pc->match_ok) {
+			handle_append (pc, attr);
+		} else {
+			/*HAL_INFO(("No merge!")); */
+		}
 	} else if (strcmp (el, "device") == 0) {
 		if (pc->curelem != CURELEM_DEVICE_INFO) {
 			HAL_ERROR (("%s:%d:%d: Element <device> can only be "
@@ -416,13 +782,13 @@
 		pc->device_matched = TRUE;
 
 		switch (pc->merge_type) {
-		case DBUS_TYPE_STRING:
+		case MERGE_TYPE_STRING:
 			hal_device_property_set_string (pc->device, pc->merge_key,
 						pc->cdata_buf);
 			break;
 
 
-		case DBUS_TYPE_INT32:
+		case MERGE_TYPE_INT32:
 			{
 				dbus_int32_t value;
 
@@ -436,7 +802,7 @@
 				break;
 			}
 
-		case DBUS_TYPE_UINT64:
+		case MERGE_TYPE_UINT64:
 			{
 				dbus_uint64_t value;
 
@@ -450,23 +816,78 @@
 				break;
 			}
 
-		case DBUS_TYPE_BOOLEAN:
+		case MERGE_TYPE_BOOLEAN:
 			hal_device_property_set_bool (pc->device, pc->merge_key,
 					      (strcmp (pc->cdata_buf,
 						       "true") == 0) 
 					      ? TRUE : FALSE);
 			break;
 
-		case DBUS_TYPE_DOUBLE:
+		case MERGE_TYPE_DOUBLE:
 			hal_device_property_set_double (pc->device, pc->merge_key,
 						atof (pc->cdata_buf));
 			break;
 
+		case MERGE_TYPE_COPY_PROPERTY:
+		{
+			char udi_to_merge_from[256];
+			char prop_to_merge[256];
+
+			/* Resolve key paths like 'someudi/foo/bar/baz:prop.name' 
+			 * '@prop.here.is.an.udi:with.prop.name'
+			 */
+			if (!resolve_udiprop_path (pc->cdata_buf,
+						   pc->device->udi,
+						   udi_to_merge_from, sizeof (udi_to_merge_from),
+						   prop_to_merge, sizeof (prop_to_merge))) {
+				HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", pc->cdata_buf, pc->device->udi));
+			} else {
+				HalDevice *d;
+
+				d = hal_device_store_find (hald_get_gdl (), udi_to_merge_from);
+				if (d == NULL) {
+					d = hal_device_store_find (hald_get_tdl (), udi_to_merge_from);
+				}
+				if (d == NULL) {
+					HAL_ERROR (("Could not find device with udi '%s'", udi_to_merge_from));
+				} else {
+					hal_device_copy_property (d, prop_to_merge, pc->device, pc->merge_key);
+				}
+			}
+			break;
+		}
+
+		default:
+			HAL_ERROR (("Unknown merge_type=%d='%c'",
+				    pc->merge_type, pc->merge_type));
+			break;
+		}
+	} else if (pc->curelem == CURELEM_APPEND && pc->match_ok && 
+		   hal_device_property_get_type (pc->device, pc->merge_key) == DBUS_TYPE_STRING) {
+		char buf[256];
+		char buf2[256];
+
+		/* As soon as we are appending, we have matched the device... */
+		pc->device_matched = TRUE;
+
+		switch (pc->merge_type) {
+		case MERGE_TYPE_STRING:
+			strncpy (buf, pc->cdata_buf, sizeof (buf));
+			break;
+
+		case MERGE_TYPE_COPY_PROPERTY:
+			hal_device_property_get_as_string (pc->device, pc->cdata_buf, buf, sizeof (buf));
+			break;
+
 		default:
 			HAL_ERROR (("Unknown merge_type=%d='%c'",
 				    pc->merge_type, pc->merge_type));
 			break;
 		}
+
+		strncpy (buf2, hal_device_property_get_string (pc->device, pc->merge_key), sizeof (buf2));
+		strncat (buf2, buf, sizeof (buf2) - strlen(buf2));
+		hal_device_property_set_string (pc->device, pc->merge_key, buf2);
 	}
 
 
@@ -477,7 +898,7 @@
 	pc->curelem = pc->curelem_stack[pc->depth];
 
 	/* maintain pc->match_ok */
-	if (pc->depth < pc->match_depth_first_fail)
+	if (pc->depth <= pc->match_depth_first_fail)
 		pc->match_ok = TRUE;
 }
 
@@ -578,7 +999,7 @@
 	parsing_context->file = buf;
 	parsing_context->parser = parser;
 	parsing_context->device = device;
-
+	parsing_context->match_depth_first_fail = -1;
 
 	XML_SetElementHandler (parser,
 			       (XML_StartElementHandler) start,
@@ -720,6 +1141,7 @@
 dbus_bool_t
 di_search_and_merge (HalDevice *d)
 {
+
 	return scan_fdi_files (PACKAGE_DATA_DIR "/hal/fdi", d);
 }
 

Index: hald.c
===================================================================
RCS file: /cvs/hal/hal/hald/hald.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- hald.c	6 Oct 2004 20:23:44 -0000	1.19
+++ hald.c	12 Oct 2004 20:17:08 -0000	1.20
@@ -512,6 +512,11 @@
 	return 0;
 }
 
+gboolean
+resolve_udiprop_path (const char *path, const char *source_udi,
+		      char *udi_result, size_t udi_result_size, 
+		      char *prop_result, size_t prop_result_size);
+
 void 
 osspec_probe_done (void)
 {
@@ -519,6 +524,28 @@
 
 	HAL_INFO (("Device probing completed"));
 
+/*
+	{
+		char udi[256];
+		char prop[256];
+
+		resolve_udiprop_path ("info.udi", 
+				      "/org/freedesktop/Hal/devices/computer", 
+				      udi, sizeof (udi), 
+				      prop, sizeof (prop));
+		HAL_INFO (("----------------------------------------"));
+		resolve_udiprop_path ("/org/freedesktop/Hal/devices/computer:kernel.name", 
+				      "/org/freedesktop/Hal/devices/pci_8086_3341", 
+				      udi, sizeof (udi), 
+				      prop, sizeof (prop));
+		HAL_INFO (("----------------------------------------"));
+		resolve_udiprop_path ("@block.storage_device:@storage.physical_device:ide.channel", 
+				      "/org/freedesktop/Hal/devices/block_3_3", 
+				      udi, sizeof (udi), 
+				      prop, sizeof (prop));
+	}
+*/
+
 	/* tell parent to exit */
 	write (startup_daemonize_pipe[1], buf, sizeof (buf));
 	close (startup_daemonize_pipe[0]);




More information about the hal-commit mailing list