device_info.c revision 18c2aff776a775d34a4c9893a4c72e0434d68e36
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/***************************************************************************
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * CVSID: $Id$
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * device_store.c : Search for .fdi files and merge on match
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Licensed under the Academic Free License version 2.1
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * This program is free software; you can redistribute it and/or modify
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * it under the terms of the GNU General Public License as published by
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * the Free Software Foundation; either version 2 of the License, or
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * (at your option) any later version.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * This program is distributed in the hope that it will be useful,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * but WITHOUT ANY WARRANTY; without even the implied warranty of
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * GNU General Public License for more details.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * You should have received a copy of the GNU General Public License
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * along with this program; if not, write to the Free Software
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c2aff776a775d34a4c9893a4c72e0434d68e36artem **************************************************************************/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @defgroup DeviceInfo Device Info File Parsing
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @ingroup HalDaemon
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @brief Parsing of device info files
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Maximum nesting depth */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Maximum amount of CDATA */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Max length of property key */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Possible elements the parser can process */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Not processing a known tag */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a deviceinfo element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a device element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a match element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a merge element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing an append element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a prepend element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a remove element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a clear element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Processing a spawn element */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** What and how to merge */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Parsing Context
18c2aff776a775d34a4c9893a4c72e0434d68e36artemtypedef struct {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Name of file being parsed */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Parser object */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Device we are trying to match*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Buffer to put CDATA in */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Current length of CDATA buffer */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Current depth we are parsing at */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Element currently being processed */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Stack of elements being processed */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** #TRUE if parsing of document have been aborted */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Depth of match-fail */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** #TRUE if all matches on prior depths have been OK */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** When merging, the key to store the value in */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Type to merge*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** Set to #TRUE if a device is matched */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Resolve a udi-property path as used in .fdi files.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Examples of udi-property paths:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * /org/freedesktop/Hal/devices/computer:kernel.name
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @block.storage_device:storage.bus
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @block.storage_device:@storage.physical_device:ide.channel
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param source_udi UDI of source device
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param path The given path
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param udi_result Where to store the resulting UDI
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param udi_result_size Size of UDI string
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param prop_result Where to store the resulting property name
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param prop_result_size Size of property string
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @return TRUE if and only if the path resolved.
18c2aff776a775d34a4c9893a4c72e0434d68e36artemresolve_udiprop_path (const char *path, const char *source_udi,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("Looking at '%s' for udi='%s'", path, source_udi));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Split up path into ':' tokens */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Detect trivial property access, e.g. path='foo.bar' */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (tokens == NULL || tokens[0] == NULL || tokens[1] == NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Start with the source udi */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("tokens[%d] = '%s'", i, tokens[i]));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem d = hal_device_store_find (hald_get_gdl (), udi_result);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem d = hal_device_store_find (hald_get_tdl (), udi_result);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* process all but the last tokens as UDI paths */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Check for indirection */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *udiprop;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *newudi;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("new_udi = '%s' (from indirection)", newudi));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("new_udi = '%s'", curtoken));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_INFO (("success = '%s'", rc ? "yes" : "no"));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_INFO (("udi_result = '%s'", udi_result));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_INFO (("prop_result = '%s'", prop_result));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Compare the value of a property on a hal device object against a string value
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * and return the result. Note that this works for several types, e.g. both strings
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * and integers - in the latter case the given right side string will be interpreted
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * as a number.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * The comparison might not make sense if you are comparing a property which is an integer
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * against a string in which case this function returns FALSE. Also, if the property doesn't
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * exist this function will also return FALSE.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param d hal device object
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param key Key of the property to compare
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param right_side Value to compare against
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param result Pointer to where to store result
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @return TRUE if, and only if, the comparison could take place
18c2aff776a775d34a4c9893a4c72e0434d68e36artemmatch_compare_property (HalDevice *d, const char *key, const char *right_side, dbus_int64_t *result)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *result = (dbus_int64_t) strcmp (hal_device_property_get_string (d, key), right_side);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *result = ((dbus_int64_t) hal_device_property_get_int (d, key)) - strtoll (right_side, NULL, 0);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *result = ((dbus_int64_t) hal_device_property_get_uint64 (d, key)) - ((dbus_int64_t) strtoll (right_side, NULL, 0));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *result = (dbus_int64_t) ceil (hal_device_property_get_double (d, key) - atof (right_side));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* explicit fallthrough */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* explicit blank since this doesn't make sense */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called when the match element begins.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param attr Attribute key/value pairs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @return #FALSE if the device in question didn't
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * match the data in the attributes
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *key;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Resolve key paths like 'someudi/foo/bar/baz:prop.name' '@prop.here.is.an.udi:with.prop.name' */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", key, pc->device->udi));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem d = hal_device_store_find (hald_get_gdl (), udi_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (d == NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem d = hal_device_store_find (hald_get_tdl (), udi_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (d == NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Could not find device with udi '%s'", udi_to_check));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *value;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("Checking that key='%s' is a string that "
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "equals '%s'", key, value)); */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (strcmp (hal_device_property_get_string (d, prop_to_check),
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("*** string match for key %s", key));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match integer property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** @todo Check error condition */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("Checking that key='%s' is a int that equals %d",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem key, value));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_INT32)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_int (d, prop_to_check) != value) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match integer property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** @todo Check error condition */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("Checking that key='%s' is a int that equals %d",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem key, value));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_UINT64)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_uint64 (d, prop_to_check) != value) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("Checking that key='%s' is a bool that equals %s",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem key, value ? "TRUE" : "FALSE"));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) !=
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_bool (d, prop_to_check) != value)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("*** bool match for key %s", key));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem type = hal_device_property_get_type (d, prop_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (strlen (hal_device_property_get_string (d, prop_to_check)) > 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!hal_device_property_strlist_is_empty(d, prop_to_check))
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* explicit fallthrough */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem unsigned int i;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *str;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem str = hal_device_property_get_string (d, prop_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (strcmp (attr[2], "is_absolute_path") == 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("d->udi='%s', prop_to_check='%s'", d->udi, prop_to_check));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem path = hal_device_property_get_string (d, prop_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("is_absolute=%d, should_be=%d, path='%s'", is_absolute_path, should_be_absolute_path, path));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *needle;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRING) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *haystack;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem haystack = hal_device_property_get_string (d, prop_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (needle != NULL && haystack != NULL && strstr (haystack, needle)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST &&
18c2aff776a775d34a4c9893a4c72e0434d68e36artem value = hal_device_property_get_strlist (d, prop_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem const char *needle;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRING) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem haystack_lowercase = g_utf8_strdown (hal_device_property_get_string (d, prop_to_check), -1);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (needle_lowercase != NULL && haystack_lowercase != NULL && strstr (haystack_lowercase, needle_lowercase)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST &&
18c2aff776a775d34a4c9893a4c72e0434d68e36artem value = hal_device_property_get_strlist (d, prop_to_check);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!match_compare_property (d, prop_to_check, attr[3], &result)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return result < 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!match_compare_property (d, prop_to_check, attr[3], &result))
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return result <= 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!match_compare_property (d, prop_to_check, attr[3], &result))
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return result > 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!match_compare_property (d, prop_to_check, attr[3], &result))
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return result >= 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called when the merge element begins.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param attr Attribute key/value pairs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match string property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* copy another property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called when the append or prepend element begins.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param attr Attribute key/value pairs
18c2aff776a775d34a4c9893a4c72e0434d68e36artemhandle_append_prepend (ParsingContext * pc, const char **attr)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* append to a string */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* append to a string list*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* copy another property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called when the spawn element begins.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param attr Attribute key/value pairs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called when the remove element begins.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param attr Attribute key/value pairs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* remove from strlist */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called when the clear element begins.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param attr Attribute key/value pairs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Abort parsing of document
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Grr, expat can't abort parsing */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called by expat when an element begins.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param el Element name
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param attr Attribute key/value pairs
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstart (ParsingContext * pc, const char *el, const char **attr)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (i = 0; i < pc->depth; i++)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem printf(" ");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem printf("%s", el);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (i = 0; attr[i]; i += 2) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem printf(" %s='%s'", attr[i], attr[i + 1]);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem printf(" curelem=%d\n", pc->curelem);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <device> and <match>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* don't bother checking if matching at lower depths failed */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* No match */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <device> and <match>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("No merge!")); */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <device> and <match>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("No merge!")); */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("%s:%d:%d: Element <prepend> can only be "
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <device> and <match>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("No merge!")); */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <device> and <match>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("No merge!")); */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <device> and <match>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("No merge!")); */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <deviceinfo>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "a top-level element",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "inside <match>",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Nasty hack */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* store depth */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemspawned_device_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Move from temporary to global device store */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called by expat when an element ends.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param el Element name
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* printf(" curelem=%d\n", pc->curelem);*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* As soon as we are merging, we have matched the device... */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_string (pc->device, pc->merge_key, pc->cdata_buf);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem int type = hal_device_property_get_type (pc->device, pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (type == HAL_PROPERTY_TYPE_STRLIST || type == HAL_PROPERTY_TYPE_INVALID) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_remove (pc->device, pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_strlist_append (pc->device, pc->merge_key, pc->cdata_buf);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match integer property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** @todo FIXME: Check error condition */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* match integer property */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /** @todo FIXME: Check error condition */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_bool (pc->device, pc->merge_key,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "true") == 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_double (pc->device, pc->merge_key,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Resolve key paths like 'someudi/foo/bar/baz:prop.name'
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * '@prop.here.is.an.udi:with.prop.name'
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", pc->cdata_buf, pc->device->udi));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem d = hal_device_store_find (hald_get_gdl (), udi_to_merge_from);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (d == NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem d = hal_device_store_find (hald_get_tdl (), udi_to_merge_from);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (d == NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Could not find device with udi '%s'", udi_to_merge_from));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_copy_property (d, prop_to_merge, pc->device, pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (pc->curelem == CURELEM_APPEND && pc->match_ok &&
18c2aff776a775d34a4c9893a4c72e0434d68e36artem (hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRING ||
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRLIST ||
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_INVALID)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* As soon as we are appending, we have matched the device... */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_strlist_append (pc->device, pc->merge_key, pc->cdata_buf);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_get_as_string (pc->device, pc->cdata_buf, buf, sizeof (buf));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Unknown merge_type=%d='%c'", pc->merge_type, pc->merge_type));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem existing_string = hal_device_property_get_string (pc->device, pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_string (pc->device, pc->merge_key, buf2);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (pc->curelem == CURELEM_PREPEND && pc->match_ok &&
18c2aff776a775d34a4c9893a4c72e0434d68e36artem (hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRING ||
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRLIST ||
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_INVALID)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* As soon as we are prepending, we have matched the device... */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_strlist_prepend (pc->device, pc->merge_key, pc->cdata_buf);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_get_as_string (pc->device, pc->cdata_buf, buf, sizeof (buf));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Unknown merge_type=%d='%c'", pc->merge_type, pc->merge_type));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem existing_string = hal_device_property_get_string (pc->device, pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem strncat (buf2, existing_string, sizeof (buf2) - strlen(buf2));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_string (pc->device, pc->merge_key, buf2);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (pc->curelem == CURELEM_REMOVE && pc->match_ok) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* covers <remove key="foobar" type="strlist">blah</remove> */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_strlist_remove (pc->device, pc->merge_key, pc->cdata_buf);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* only allow <remove key="foobar"/>, not <remove key="foobar">blah</remove> */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_remove (pc->device, pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem spawned = hal_device_store_find (hald_get_gdl (), pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem spawned = hal_device_store_find (hald_get_tdl (), pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_INFO (("Spawning new device object '%s' caused by <spawn> on udi '%s'",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_string (spawned, "info.bus", "unknown");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_string (spawned, "info.udi", pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_set_string (spawned, "info.parent", pc->device->udi);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem di_search_and_merge (spawned, DEVICE_INFO_TYPE_INFORMATION);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem di_search_and_merge (spawned, DEVICE_INFO_TYPE_POLICY);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_util_callout_device_add (spawned, spawned_device_callouts_add_done, NULL, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (pc->curelem == CURELEM_CLEAR && pc->match_ok) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_device_property_strlist_clear (pc->device, pc->merge_key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* maintain curelem */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* maintain pc->match_ok */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Called when there is CDATA
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param pc Parsing context
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param s Pointer to data
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param len Length of data
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Process a device information info file.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param dir Directory file resides in
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param filename File name
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param device Device to match on
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @return #TRUE if file matched device and information
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * was merged
18c2aff776a775d34a4c9893a4c72e0434d68e36artemprocess_fdi_file (const char *dir, const char *filename,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("analyzing file %s", buf));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* open file and read it into a buffer; it's a small file... */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Could not allocate %d bytes for file %s", filesize, buf));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem read = fread (filebuf, sizeof (char), filesize, file);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* initialize parsing context */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* TODO: reuse parser
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*printf("XML_Parse rc=%d\r\n", rc); */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rc == 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* error parsing document */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Error parsing XML document %s at line %d, "
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "column %d : %s",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* document parsed ok */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemmy_alphasort(const void *a, const void *b)
18c2aff776a775d34a4c9893a4c72e0434d68e36artemmy_alphasort(const struct dirent **a, const struct dirent **b)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return -alphasort (a, b);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Scan all directories and subdirectories in the given directory and
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * process each *.fdi file
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param d Device to merge information into
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @return #TRUE if information was merged
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO(("scan_fdi_files: Processing dir '%s'", dir));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem num_entries = scandir (dir, &name_list, 0, my_alphasort);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("Full path = %s", full_path));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Mmm, d_type can be DT_UNKNOWN, use glib to determine
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (g_file_test (full_path, (G_FILE_TEST_IS_REGULAR))) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* regular file */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /*HAL_INFO (("scan_fdi_files: Processing file '%s'", filename));*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if (g_file_test (full_path, (G_FILE_TEST_IS_DIR))
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Directory; do the recursion thingy but not
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * for . and ..
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (found_fdi_file)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (; i >= 0; i--) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Search the device info file repository for a .fdi file to merge
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * more information into the device object.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param d Device to merge information into
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @return #TRUE if information was merged
18c2aff776a775d34a4c9893a4c72e0434d68e36artemdi_search_and_merge (HalDevice *d, DeviceInfoType type)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_fdi_source_preprobe = getenv ("HAL_FDI_SOURCE_PREPROBE");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_fdi_source_information = getenv ("HAL_FDI_SOURCE_INFORMATION");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem hal_fdi_source_policy = getenv ("HAL_FDI_SOURCE_POLICY");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_ERROR (("Bogus device information type %d", type));