hal: Branch 'origin' - 12 commits
Kay Sievers
kay at kemper.freedesktop.org
Wed Oct 11 02:05:11 PDT 2006
hald/device.c | 5
hald/device_info.c | 1869 +++++++++++++++++++++-----------------------------
hald/device_info.h | 4
hald/hald.c | 8
hald/hald_runner.c | 68 -
hald/ids.c | 151 +---
hald/util.c | 6
hald/valgrind-hald.sh | 3
8 files changed, 899 insertions(+), 1215 deletions(-)
New commits:
diff-tree b105ec345ad12fc4eff158c9aeaab78caebe9a71 (from 5e33459557cf9d4680f894392a834b7752acd60a)
Author: David Zeuthen <davidz at redhat.com>
Date: Wed Oct 11 00:43:32 2006 -0400
make pnp.ids static to save writable memory
Goodbye another 8KB!
diff --git a/hald/ids.c b/hald/ids.c
index aa23e1c..223c8d4 100644
--- a/hald/ids.c
+++ b/hald/ids.c
@@ -527,9 +527,9 @@ ids_init (void)
* Keep this sorted!
*/
struct pnp_id {
- char *id;
- char *desc;
-} static pnp_ids_list[] = {
+ const char *id;
+ const char *desc;
+} static const pnp_ids_list[] = {
/* Crystal Semiconductor devices */
{"CSC0000", "Crystal Semiconductor CS423x sound -- SB/WSS/OPL3 emulation"},
{"CSC0001", "Crystal Semiconductor CS423x sound -- joystick"},
@@ -948,22 +948,14 @@ ids_comp_pnp(const void *id1, const void
void
ids_find_pnp (const char *pnp_id, char **pnp_description)
{
- static gboolean sorted = FALSE;
struct pnp_id search, *res;
-
- if (!sorted) {
- /* sort the list, to be sure that all is in correc order */
- qsort(pnp_ids_list, sizeof(pnp_ids_list)/sizeof(pnp_ids_list[0]),
- sizeof(struct pnp_id), ids_comp_pnp);
- sorted = TRUE;
- }
search.id = (char *) pnp_id;
res = bsearch(&search, pnp_ids_list, sizeof(pnp_ids_list)/sizeof(pnp_ids_list[0]),
sizeof(struct pnp_id), ids_comp_pnp);
if (res != NULL)
- *pnp_description = res->desc;
+ *pnp_description = (char *) res->desc;
else
*pnp_description = NULL;
return;
diff-tree 5e33459557cf9d4680f894392a834b7752acd60a (from e6b0bd21ae250d6d589e2584fd624b7bd2fa6835)
Author: David Zeuthen <davidz at redhat.com>
Date: Wed Oct 11 00:17:34 2006 -0400
use mmap to access pci.ids and usb.ids
Goodbye 580KB of writable memory! :-)
diff --git a/hald/ids.c b/hald/ids.c
index 5d2fe62..aa23e1c 100644
--- a/hald/ids.c
+++ b/hald/ids.c
@@ -31,6 +31,11 @@
#include <stdint.h>
#include <string.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
@@ -43,10 +48,10 @@
static char *pci_ids = NULL;
/** Length of data store at at pci_ids */
-static unsigned int pci_ids_len;
+static size_t pci_ids_len;
/** Iterator position into pci_ids */
-static unsigned int pci_ids_iter_pos;
+static size_t pci_ids_iter_pos;
/** Initialize the pci.ids line iterator to the beginning of the file */
static void
@@ -258,20 +263,6 @@ ids_find_pci (int vendor_id, int product
}
}
-/** Free resources used by to store the PCI database
- *
- * @param #FALSE if the PCI database wasn't loaded
- */
-static dbus_bool_t
-pci_ids_free ()
-{
- if (pci_ids != NULL) {
- free (pci_ids);
- pci_ids = NULL;
- return TRUE;
- }
- return FALSE;
-}
/** Load the PCI database used for mapping vendor, product, subsys_vendor
* and subsys_product numbers into names.
@@ -283,35 +274,36 @@ pci_ids_free ()
static dbus_bool_t
pci_ids_load (const char *path)
{
- FILE *fp;
- unsigned int num_read;
+ int fd;
+ struct stat statbuf;
+ gboolean ret;
- fp = fopen (path, "r");
- if (fp == NULL) {
- HAL_ERROR (("couldn't open PCI database at %s,", path));
- return FALSE;
- }
+ ret = FALSE;
- fseek (fp, 0, SEEK_END);
- pci_ids_len = ftell (fp);
- fseek (fp, 0, SEEK_SET);
+ if (stat (path, &statbuf) != 0) {
+ HAL_WARNING (("Couldn't stat pci.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
+ goto out;
+ }
+ pci_ids_len = statbuf.st_size;
- pci_ids = malloc (pci_ids_len);
- if (pci_ids == NULL) {
- DIE (("Couldn't allocate %d bytes for PCI database file\n",
- pci_ids_len));
+ fd = open (path, O_RDONLY);
+ if (fd < 0) {
+ HAL_WARNING (("Couldn't open pci.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
+ goto out;
}
- num_read = fread (pci_ids, sizeof (char), pci_ids_len, fp);
- if (pci_ids_len != num_read) {
- HAL_ERROR (("Error loading PCI database file"));
- pci_ids_free();
- fclose(fp);
- return FALSE;
+ pci_ids = mmap (NULL, pci_ids_len, PROT_READ, MAP_SHARED, fd, 0);
+ if (pci_ids == MAP_FAILED) {
+ HAL_WARNING (("Couldn't mmap pci.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
+ close (fd);
+ goto out;
}
- fclose(fp);
- return TRUE;
+ ret = TRUE;
+
+ close (fd);
+out:
+ return ret;
}
/*==========================================================================*/
@@ -320,10 +312,10 @@ pci_ids_load (const char *path)
static char *usb_ids = NULL;
/** Length of data store at at usb_ids */
-static unsigned int usb_ids_len;
+static size_t usb_ids_len;
/** Iterator position into usb_ids */
-static unsigned int usb_ids_iter_pos;
+static size_t usb_ids_iter_pos;
/** Initialize the usb.ids line iterator to the beginning of the file */
static void
@@ -475,21 +467,6 @@ ids_find_usb (int vendor_id, int product
}
}
-/** Free resources used by to store the USB database
- *
- * @param #FALSE if the USB database wasn't loaded
- */
-static dbus_bool_t
-usb_ids_free ()
-{
- if (usb_ids != NULL) {
- free (usb_ids);
- usb_ids = NULL;
- return TRUE;
- }
- return FALSE;
-}
-
/** Load the USB database used for mapping vendor, product, subsys_vendor
* and subsys_product numbers into names.
*
@@ -500,38 +477,36 @@ usb_ids_free ()
static dbus_bool_t
usb_ids_load (const char *path)
{
- FILE *fp;
- unsigned int num_read;
+ int fd;
+ struct stat statbuf;
+ gboolean ret;
+
+ ret = FALSE;
- fp = fopen (path, "r");
- if (fp == NULL) {
- printf ("couldn't open USB database at %s,", path);
- return FALSE;
- }
-
- fseek (fp, 0, SEEK_END);
- usb_ids_len = ftell (fp);
- fseek (fp, 0, SEEK_SET);
-
- usb_ids = malloc (usb_ids_len);
- if (usb_ids == NULL) {
- printf
- ("Couldn't allocate %d bytes for USB database file\n",
- usb_ids_len);
- fclose(fp);
- return FALSE;
- }
-
- num_read = fread (usb_ids, sizeof (char), usb_ids_len, fp);
- if (usb_ids_len != num_read) {
- printf ("Error loading USB database file\n");
- usb_ids_free ();
- fclose(fp);
- return FALSE;
+ if (stat (path, &statbuf) != 0) {
+ HAL_WARNING (("Couldn't stat usb.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
+ goto out;
}
+ usb_ids_len = statbuf.st_size;
+
+ fd = open (path, O_RDONLY);
+ if (fd < 0) {
+ HAL_WARNING (("Couldn't open usb.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
+ goto out;
+ }
+
+ usb_ids = mmap (NULL, usb_ids_len, PROT_READ, MAP_SHARED, fd, 0);
+ if (usb_ids == MAP_FAILED) {
+ HAL_WARNING (("Couldn't mmap usb.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
+ close (fd);
+ goto out;
+ }
+
+ ret = TRUE;
- fclose(fp);
- return TRUE;
+ close (fd);
+out:
+ return ret;
}
diff-tree e6b0bd21ae250d6d589e2584fd624b7bd2fa6835 (from 9aa082592ee8fa3c33539bda2e0226c12880d30a)
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 21:11:39 2006 -0400
comment out some debugging spew from fdi matching
We really need a modularized logging system Real Soon Now(tm).
diff --git a/hald/device_info.c b/hald/device_info.c
index fe5ac98..9ff8ba8 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -153,6 +153,7 @@ rule_type get_rule_type (const char *str
return RULE_UNKNOWN;
}
+/*
static char *
get_rule_type_str (enum rule_type type)
{
@@ -178,6 +179,7 @@ get_rule_type_str (enum rule_type type)
}
return "invalid rule type";
}
+*/
static enum
merge_type get_merge_type (const char *str)
@@ -201,6 +203,7 @@ merge_type get_merge_type (const char *s
return MERGE_UNKNOWN;
}
+/*
static char *
get_merge_type_str (enum merge_type type)
{
@@ -226,6 +229,7 @@ get_merge_type_str (enum merge_type type
}
return "invalid merge type";
}
+*/
static enum
match_type get_match_type(const char *str)
@@ -261,6 +265,7 @@ match_type get_match_type(const char *st
return MATCH_UNKNOWN;
}
+/*
static char *
get_match_type_str (enum match_type type)
{
@@ -298,6 +303,7 @@ get_match_type_str (enum match_type type
}
return "invalid match type";
}
+*/
/** Resolve a udi-property path as used in .fdi files.
*
@@ -1296,9 +1302,9 @@ rules_match_and_merge_device (GSList *fd
switch (rule->rtype) {
case RULE_MATCH:
/* skip non-matching rules block */
- HAL_INFO(("%p match '%s' at %s", rule, rule->key, hal_device_get_udi (d)));
+ /*HAL_INFO(("%p match '%s' at %s", rule, rule->key, hal_device_get_udi (d)));*/
if (!handle_match (rule, d)) {
- HAL_INFO(("no match, skip to rule %s (%p)", get_rule_type_str (rule->next_rule->rtype), rule->next_rule));
+ /*HAL_INFO(("no match, skip to rule %s (%p)", get_rule_type_str (rule->next_rule->rtype), rule->next_rule));*/
elem = g_slist_find (elem, rule->next_rule);
continue;
}
@@ -1310,12 +1316,12 @@ rules_match_and_merge_device (GSList *fd
case RULE_CLEAR:
case RULE_SPAWN:
case RULE_MERGE:
- HAL_INFO(("%p merge '%s' at %s", rule, rule->key, hal_device_get_udi (d)));
+ /*HAL_INFO(("%p merge '%s' at %s", rule, rule->key, hal_device_get_udi (d)));*/
handle_merge (rule, d);
break;
case RULE_EOF:
- HAL_INFO(("%p fdi file '%s' finished", rule, rule->key));
+ /*HAL_INFO(("%p fdi file '%s' finished", rule, rule->key));*/
break;
default:
@@ -1332,17 +1338,17 @@ di_search_and_merge (HalDevice *d, Devic
{
switch (type) {
case DEVICE_INFO_TYPE_PREPROBE:
- HAL_INFO(("apply fdi preprobe to device %p", d));
+ /*HAL_INFO(("apply fdi preprobe to device %p", d));*/
rules_match_and_merge_device (fdi_rules_preprobe, d);
break;
case DEVICE_INFO_TYPE_INFORMATION:
- HAL_INFO(("apply fdi info to device %p", d));
+ /*HAL_INFO(("apply fdi info to device %p", d));*/
rules_match_and_merge_device (fdi_rules_information, d);
break;
case DEVICE_INFO_TYPE_POLICY:
- HAL_INFO(("apply fdi policy to device %p", d));
+ /*HAL_INFO(("apply fdi policy to device %p", d));*/
rules_match_and_merge_device (fdi_rules_policy, d);
break;
diff-tree 9aa082592ee8fa3c33539bda2e0226c12880d30a (from 8ee20db66713838d7b4bede2ba2162082b66165b)
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 20:47:55 2006 -0400
report how much memory the rules use
diff --git a/hald/device_info.c b/hald/device_info.c
index fd54e7a..fe5ac98 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -127,6 +127,8 @@ struct fdi_context {
/* current rule */
struct rule *rule;
+ int fdi_rule_size;
+
/* all rules */
GSList* rules;
};
@@ -1058,6 +1060,13 @@ end (void *data, const char *el)
if (fdi_ctx->rule->value == NULL)
fdi_ctx->rule->value = g_strdup ("");
+ if (fdi_ctx->fdi_rule_size >= 0) {
+ fdi_ctx->fdi_rule_size +=
+ sizeof (struct rule) +
+ strlen (fdi_ctx->rule->key) +
+ fdi_ctx->rule->value_len;
+ }
+
/* insert merge rule into list and get new rule */
fdi_ctx->rules = g_slist_append (fdi_ctx->rules, fdi_ctx->rule);
fdi_ctx->rule = g_new0 (struct rule, 1);
@@ -1065,12 +1074,13 @@ end (void *data, const char *el)
/* decompile an fdi file into a list of rules as this is quicker than opening then each time we want to search */
static int
-rules_add_fdi_file (GSList **fdi_rules, const char *filename)
+rules_add_fdi_file (GSList **fdi_rules, const char *filename, gboolean compute_rule_size)
{
struct fdi_context *fdi_ctx;
char *buf;
gsize buflen;
int rc;
+ int fdi_rule_size;
if (!g_file_get_contents (filename, &buf, &buflen, NULL))
return -1;
@@ -1078,6 +1088,7 @@ rules_add_fdi_file (GSList **fdi_rules,
/* get context and first rule */
fdi_ctx = g_new0 (struct fdi_context ,1);
fdi_ctx->rule = g_new0 (struct rule ,1);
+ fdi_ctx->fdi_rule_size = compute_rule_size ? 0 : -1;
XML_Parser parser = XML_ParserCreate (NULL);
if (parser == NULL) {
@@ -1106,35 +1117,14 @@ rules_add_fdi_file (GSList **fdi_rules,
else
*fdi_rules = g_slist_concat (*fdi_rules, fdi_ctx->rules);
+ fdi_rule_size = (gint64) fdi_ctx->fdi_rule_size;
+
g_free (fdi_ctx);
if (rc == 0)
return -1;
- return 0;
-}
-
-/* print the rules to screen, mainly useful for debugging */
-static void
-rules_dump (GSList *fdi_rules)
-{
- GSList *elem;
-
- for (elem = fdi_rules; elem != NULL; elem = g_slist_next (elem)) {
- struct rule *rule = elem->data;
- if (rule->rtype == RULE_EOF) {
- printf ("%p: eof %s\n", rule, rule->key);
- } else if (rule->rtype == RULE_MATCH) {
- printf ("\n");
- printf ("%p: match '%s' (%s) '%s' (skip to %p)\n",
- rule, rule->key, get_match_type_str (rule->type_match),
- rule->value, rule->next_rule);
- } else {
- printf ("%p: %s '%s' (%s) '%s'\n",
- rule, get_rule_type_str (rule->rtype), rule->key,
- get_merge_type_str (rule->type_merge), rule->value);
- }
- }
+ return compute_rule_size ? fdi_rule_size : 0;
}
/* modified alphasort to count downwards */
@@ -1150,7 +1140,7 @@ _alphasort(const struct dirent **a, cons
/* recurse a directory tree, searching and adding fdi files */
static int
-rules_search_and_add_fdi_files (GSList **fdi_rules, const char *dir)
+rules_search_and_add_fdi_files (GSList **fdi_rules, const char *dir, int *rules_size)
{
int i;
int num_entries;
@@ -1169,8 +1159,19 @@ rules_search_and_add_fdi_files (GSList *
len = strlen (filename);
full_path = g_strdup_printf ("%s/%s", dir, filename);
if (g_file_test (full_path, (G_FILE_TEST_IS_REGULAR))) {
- if (len >= 5 && strcmp(&filename[len - 4], ".fdi") == 0)
- rules_add_fdi_file (fdi_rules, full_path);
+ if (len >= 5 && strcmp(&filename[len - 4], ".fdi") == 0) {
+ int fdi_rules_size;
+ fdi_rules_size = rules_add_fdi_file (fdi_rules, full_path, rules_size != NULL);
+ if (fdi_rules_size >= 0) {
+ if (rules_size != NULL) {
+ *rules_size += fdi_rules_size;
+ HAL_INFO (("fdi file '%s' -> %d bytes of rules",
+ full_path, fdi_rules_size));
+ }
+ } else {
+ HAL_WARNING (("error processing fdi file '%s'", full_path));
+ }
+ }
} else if (g_file_test (full_path, (G_FILE_TEST_IS_DIR)) && filename[0] != '.') {
int num_bytes;
char *dirname;
@@ -1181,7 +1182,7 @@ rules_search_and_add_fdi_files (GSList *
break;
snprintf (dirname, num_bytes, "%s/%s", dir, filename);
- rules_search_and_add_fdi_files (fdi_rules, dirname);
+ rules_search_and_add_fdi_files (fdi_rules, dirname, rules_size);
free (dirname);
}
g_free (full_path);
@@ -1196,45 +1197,73 @@ rules_search_and_add_fdi_files (GSList *
return 0;
}
+/* print the rules to screen, mainly useful for debugging */
+#if 0
+static void
+rules_dump (GSList *fdi_rules)
+{
+ GSList *elem;
+
+ for (elem = fdi_rules; elem != NULL; elem = g_slist_next (elem)) {
+ struct rule *rule = elem->data;
+
+ if (rule->rtype == RULE_EOF) {
+ printf ("%p: eof %s\n", rule, rule->key);
+ } else if (rule->rtype == RULE_MATCH) {
+ printf ("\n");
+ printf ("%p: match '%s' (%s) '%s' (skip to %p)\n",
+ rule, rule->key, get_match_type_str (rule->type_match),
+ rule->value, rule->next_rule);
+ } else {
+ printf ("%p: %s '%s' (%s) '%s'\n",
+ rule, get_rule_type_str (rule->rtype), rule->key,
+ get_merge_type_str (rule->type_merge), rule->value);
+ }
+ }
+}
+#endif
+
/* setup the location of the rules */
void
di_rules_init (void)
{
+ int size;
char *hal_fdi_source_preprobe = getenv ("HAL_FDI_SOURCE_PREPROBE");
char *hal_fdi_source_information = getenv ("HAL_FDI_SOURCE_INFORMATION");
char *hal_fdi_source_policy = getenv ("HAL_FDI_SOURCE_POLICY");
HAL_INFO (("Loading rules"));
+ size = 0;
+
if (hal_fdi_source_preprobe != NULL)
- rules_search_and_add_fdi_files (&fdi_rules_preprobe, hal_fdi_source_preprobe);
+ rules_search_and_add_fdi_files (&fdi_rules_preprobe, hal_fdi_source_preprobe, &size);
else {
- rules_search_and_add_fdi_files (&fdi_rules_preprobe, PACKAGE_DATA_DIR "/hal/fdi/preprobe");
- rules_search_and_add_fdi_files (&fdi_rules_preprobe, PACKAGE_SYSCONF_DIR "/hal/fdi/preprobe");
+ rules_search_and_add_fdi_files (&fdi_rules_preprobe, PACKAGE_DATA_DIR "/hal/fdi/preprobe", &size);
+ rules_search_and_add_fdi_files (&fdi_rules_preprobe, PACKAGE_SYSCONF_DIR "/hal/fdi/preprobe", &size);
}
if (hal_fdi_source_information != NULL)
- rules_search_and_add_fdi_files (&fdi_rules_information, hal_fdi_source_information);
+ rules_search_and_add_fdi_files (&fdi_rules_information, hal_fdi_source_information, &size);
else {
- rules_search_and_add_fdi_files (&fdi_rules_information, PACKAGE_DATA_DIR "/hal/fdi/information");
- rules_search_and_add_fdi_files (&fdi_rules_information, PACKAGE_SYSCONF_DIR "/hal/fdi/information");
+ rules_search_and_add_fdi_files (&fdi_rules_information, PACKAGE_DATA_DIR "/hal/fdi/information", &size);
+ rules_search_and_add_fdi_files (&fdi_rules_information, PACKAGE_SYSCONF_DIR "/hal/fdi/information", &size);
}
if (hal_fdi_source_policy != NULL)
- rules_search_and_add_fdi_files (&fdi_rules_policy, hal_fdi_source_policy);
+ rules_search_and_add_fdi_files (&fdi_rules_policy, hal_fdi_source_policy, &size);
else {
- rules_search_and_add_fdi_files (&fdi_rules_policy, PACKAGE_DATA_DIR "/hal/fdi/policy");
- rules_search_and_add_fdi_files (&fdi_rules_policy, PACKAGE_SYSCONF_DIR "/hal/fdi/policy");
+ rules_search_and_add_fdi_files (&fdi_rules_policy, PACKAGE_DATA_DIR "/hal/fdi/policy", &size);
+ rules_search_and_add_fdi_files (&fdi_rules_policy, PACKAGE_SYSCONF_DIR "/hal/fdi/policy", &size);
}
- /* only dump the rules if we are being verbose as this is expensive */
- if (getenv ("HALD_VERBOSE") != NULL) {
- rules_dump (fdi_rules_preprobe);
- rules_dump (fdi_rules_information);
- rules_dump (fdi_rules_policy);
- }
+ /* dump the rules (commented out as this is expensive) */
+ /*rules_dump (fdi_rules_preprobe);
+ rules_dump (fdi_rules_information);
+ rules_dump (fdi_rules_policy);
+ */
- HAL_INFO (("Loading rules done"));
+ HAL_INFO (("Loading rules done (occupying %d bytes)", size));
}
/* cleanup the rules */
diff-tree 8ee20db66713838d7b4bede2ba2162082b66165b (from 9cdc896239875e778682a5fc8f25a823c015761d)
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 19:57:48 2006 -0400
fix segfault on cleaning up rules
diff --git a/hald/device_info.c b/hald/device_info.c
index e96ee15..fd54e7a 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -1056,7 +1056,7 @@ end (void *data, const char *el)
/* set empty value to empty string */
if (fdi_ctx->rule->value == NULL)
- fdi_ctx->rule->value = "";
+ fdi_ctx->rule->value = g_strdup ("");
/* insert merge rule into list and get new rule */
fdi_ctx->rules = g_slist_append (fdi_ctx->rules, fdi_ctx->rule);
@@ -1204,6 +1204,8 @@ di_rules_init (void)
char *hal_fdi_source_information = getenv ("HAL_FDI_SOURCE_INFORMATION");
char *hal_fdi_source_policy = getenv ("HAL_FDI_SOURCE_POLICY");
+ HAL_INFO (("Loading rules"));
+
if (hal_fdi_source_preprobe != NULL)
rules_search_and_add_fdi_files (&fdi_rules_preprobe, hal_fdi_source_preprobe);
else {
@@ -1231,6 +1233,8 @@ di_rules_init (void)
rules_dump (fdi_rules_information);
rules_dump (fdi_rules_policy);
}
+
+ HAL_INFO (("Loading rules done"));
}
/* cleanup the rules */
diff-tree 9cdc896239875e778682a5fc8f25a823c015761d (from 1ffd76385cebb2be97a3c474f9a92e0a64602c1b)
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 19:44:05 2006 -0400
forward port changes made to hald/device_info.c since June 2006
diff --git a/hald/device_info.c b/hald/device_info.c
index f1b1061..e96ee15 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -640,12 +640,11 @@ handle_match (struct rule *rule, HalDevi
contains = TRUE;
}
} else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST && value != NULL) {
- GSList *list;
- GSList *i;
-
- list = hal_device_property_get_strlist (d, prop_to_check);
- for (i = list; i != NULL; i = g_slist_next (i)) {
- const char *str = i->data;
+ HalDeviceStrListIter iter;
+ for (hal_device_property_strlist_iter_init (d, prop_to_check, &iter);
+ hal_device_property_strlist_iter_is_valid (&iter);
+ hal_device_property_strlist_iter_next (&iter)) {
+ const char *str = hal_device_property_strlist_iter_get_value (&iter);
if (strcmp (str, value) == 0) {
contains = TRUE;
break;
@@ -677,12 +676,11 @@ handle_match (struct rule *rule, HalDevi
g_free (haystack_lowercase);
}
} else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST && value != NULL) {
- GSList *list;
- GSList *i;
-
- list = hal_device_property_get_strlist (d, prop_to_check);
- for (i = list; i != NULL; i = g_slist_next (i)) {
- const char *str = i->data;
+ HalDeviceStrListIter iter;
+ for (hal_device_property_strlist_iter_init (d, prop_to_check, &iter);
+ hal_device_property_strlist_iter_is_valid (&iter);
+ hal_device_property_strlist_iter_next (&iter)) {
+ const char *str = hal_device_property_strlist_iter_get_value (&iter);
if (g_ascii_strcasecmp (str, value) == 0) {
contains_ncase = TRUE;
break;
@@ -745,7 +743,7 @@ handle_match (struct rule *rule, HalDevi
static void
spawned_device_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
{
- HAL_INFO (("Add callouts completed udi=%s", d->udi));
+ HAL_INFO (("Add callouts completed udi=%s", hal_device_get_udi (d)));
/* Move from temporary to global device store */
hal_device_store_remove (hald_get_tdl (), d);
@@ -909,11 +907,11 @@ handle_merge (struct rule *rule, HalDevi
if (spawned == NULL) {
HAL_INFO (("Spawning new device object '%s' caused by <spawn> on udi '%s'",
- key, d->udi));
+ key, hal_device_get_udi (d)));
spawned = hal_device_new ();
hal_device_property_set_string (spawned, "info.bus", "unknown");
hal_device_property_set_string (spawned, "info.udi", key);
- hal_device_property_set_string (spawned, "info.parent", d->udi);
+ hal_device_property_set_string (spawned, "info.parent", hal_device_get_udi (d));
hal_device_set_udi (spawned, key);
hal_device_store_add (hald_get_tdl (), spawned);
@@ -1141,7 +1139,11 @@ rules_dump (GSList *fdi_rules)
/* modified alphasort to count downwards */
static int
+#ifdef __GLIBC__
_alphasort(const void *a, const void *b)
+#else
+_alphasort(const struct dirent **a, const struct dirent **b)
+#endif
{
return -alphasort (a, b);
}
diff-tree 1ffd76385cebb2be97a3c474f9a92e0a64602c1b (from 195222c1b1115e62a55b3a21898176c8d01c8da8)
Author: Kay Sievers <kay.sievers at vrfy.org>
Date: Tue Oct 10 19:32:40 2006 -0400
store fdi files as rules object
Some work by Richard Hughes <richard at hughsie.com> to implement
the <spawn> rules.
diff --git a/hald/device_info.c b/hald/device_info.c
index 17751d3..f1b1061 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -1,9 +1,11 @@
/***************************************************************************
* CVSID: $Id$
*
- * device_store.c : Search for .fdi files and merge on match
+ * device_store.c : Parse .fdi files and match/merge device properties.
*
* Copyright (C) 2003 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2006 Kay Sievers, <kay.sievers at vrfy.org>
+ * Copyright (C) 2006 Richard Hughes <richard at hughsie.com>
*
* Licensed under the Academic Free License version 2.1
*
@@ -31,10 +33,12 @@
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
+#include <unistd.h>
#include <expat.h>
#include <assert.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
+#include <sys/stat.h>
#include <math.h>
#include "hald.h"
@@ -43,122 +47,257 @@
#include "device_store.h"
#include "util.h"
-/**
- * @defgroup DeviceInfo Device Info File Parsing
- * @ingroup HalDaemon
- * @brief Parsing of device info files
- * @{
- */
-
-
-/** Maximum nesting depth */
-#define MAX_DEPTH 32
-
-/** Maximum amount of CDATA */
-#define CDATA_BUF_SIZE 1024
-
-/** Max length of property key */
-#define MAX_KEY_SIZE 128
-
-/** Possible elements the parser can process */
-enum {
- /** Not processing a known tag */
- CURELEM_UNKNOWN = -1,
-
- /** Processing a deviceinfo element */
- CURELEM_DEVICE_INFO = 0,
-
- /** Processing a device element */
- CURELEM_DEVICE = 1,
-
- /** Processing a match element */
- CURELEM_MATCH = 2,
-
- /** Processing a merge element */
- CURELEM_MERGE = 3,
-
- /** Processing an append element */
- CURELEM_APPEND = 4,
-
- /** Processing a prepend element */
- CURELEM_PREPEND = 5,
-
- /** Processing a remove element */
- CURELEM_REMOVE = 6,
-
- /** Processing a clear element */
- CURELEM_CLEAR = 7,
+#define MAX_INDENT_DEPTH 64
- /** Processing a spawn element */
- CURELEM_SPAWN = 8
+/* pre-parsed rules to keep in memory */
+static GSList *fdi_rules_preprobe;
+static GSList *fdi_rules_information;
+static GSList *fdi_rules_policy;
+
+/* rule type to process */
+enum rule_type {
+ RULE_UNKNOWN,
+ RULE_MATCH,
+ RULE_MERGE,
+ RULE_APPEND,
+ RULE_PREPEND,
+ RULE_REMOVE,
+ RULE_CLEAR,
+ RULE_SPAWN,
+ RULE_EOF,
};
-/** What and how to merge */
-enum {
- MERGE_TYPE_UNKNOWN = 0,
- MERGE_TYPE_STRING = 1,
- MERGE_TYPE_BOOLEAN = 2,
- MERGE_TYPE_INT32 = 3,
- MERGE_TYPE_UINT64 = 4,
- MERGE_TYPE_DOUBLE = 5,
- MERGE_TYPE_COPY_PROPERTY = 6,
- MERGE_TYPE_STRLIST = 7,
- MERGE_TYPE_REMOVE = 8,
- MERGE_TYPE_CLEAR = 9,
- MERGE_TYPE_SPAWN = 10
+/* type of merge command */
+enum merge_type {
+ MERGE_UNKNOWN,
+ MERGE_STRING,
+ MERGE_BOOLEAN,
+ MERGE_INT32,
+ MERGE_UINT64,
+ MERGE_DOUBLE,
+ MERGE_COPY_PROPERTY,
+ MERGE_STRLIST,
+ MERGE_REMOVE,
};
-/** Parsing Context
- */
-typedef struct {
- /** Name of file being parsed */
- char *file;
-
- /** Parser object */
- XML_Parser parser;
-
- /** Device we are trying to match*/
- HalDevice *device;
-
- /** Buffer to put CDATA in */
- char cdata_buf[CDATA_BUF_SIZE];
-
- /** Current length of CDATA buffer */
- int cdata_buf_len;
-
- /** Current depth we are parsing at */
- int depth;
+/* type of match command */
+enum
+match_type {
+ MATCH_UNKNOWN,
+ MATCH_STRING,
+ MATCH_INT,
+ MATCH_UINT64,
+ MATCH_BOOL,
+ MATCH_EXISTS,
+ MATCH_EMPTY,
+ MATCH_ISASCII,
+ MATCH_IS_ABS_PATH,
+ MATCH_CONTAINS,
+ MATCH_CONTAINS_NCASE,
+ MATCH_COMPARE_LT,
+ MATCH_COMPARE_LE,
+ MATCH_COMPARE_GT,
+ MATCH_COMPARE_GE,
+};
- /** Element currently being processed */
- int curelem;
+/* a "rule" structure that is a generic node of the fdi file */
+struct rule {
+ /* typ of tule in the list */
+ enum rule_type rtype;
+
+ /* all rules have a key */
+ char *key;
+
+ /* "match" or "merge" rule */
+ enum match_type type_match;
+ enum merge_type type_merge;
- /** Stack of elements being processed */
- int curelem_stack[MAX_DEPTH];
+ char *value;
+ int value_len;
- /** #TRUE if parsing of document have been aborted */
- dbus_bool_t aborted;
+ /* if rule does not match, skip to this rule */
+ struct rule *next_rule;
+};
+/* ctx of the current fdi file used for parsing */
+struct fdi_context {
+ int depth;
+ struct rule *match_at_depth[MAX_INDENT_DEPTH];
- /** Depth of match-fail */
- int match_depth_first_fail;
+ /* current rule */
+ struct rule *rule;
- /** #TRUE if all matches on prior depths have been OK */
- dbus_bool_t match_ok;
+ /* all rules */
+ GSList* rules;
+};
+static enum
+rule_type get_rule_type (const char *str)
+{
+ if (strcmp (str, "match") == 0)
+ return RULE_MATCH;
+ if (strcmp (str, "merge") == 0)
+ return RULE_MERGE;
+ if (strcmp (str, "append") == 0)
+ return RULE_APPEND;
+ if (strcmp (str, "prepend") == 0)
+ return RULE_PREPEND;
+ if (strcmp (str, "remove") == 0)
+ return RULE_REMOVE;
+ if (strcmp (str, "clear") == 0)
+ return RULE_CLEAR;
+ if (strcmp (str, "spawn") == 0)
+ return RULE_SPAWN;
+ return RULE_UNKNOWN;
+}
+static char *
+get_rule_type_str (enum rule_type type)
+{
+ switch (type) {
+ case RULE_MATCH:
+ return "match";
+ case RULE_MERGE:
+ return "merge";
+ case RULE_APPEND:
+ return "append";
+ case RULE_PREPEND:
+ return "prepend";
+ case RULE_REMOVE:
+ return "remove";
+ case RULE_CLEAR:
+ return "clear";
+ case RULE_SPAWN:
+ return "spawn";
+ case RULE_EOF:
+ return "eof";
+ case RULE_UNKNOWN:
+ return "unknown rule type";
+ }
+ return "invalid rule type";
+}
- /** When merging, the key to store the value in */
- char merge_key[MAX_KEY_SIZE];
+static enum
+merge_type get_merge_type (const char *str)
+{
+ if (strcmp (str, "string") == 0)
+ return MERGE_STRING;
+ if (strcmp (str, "bool") == 0)
+ return MERGE_BOOLEAN;
+ if (strcmp (str, "int") == 0)
+ return MERGE_INT32;
+ if (strcmp (str, "unint64") == 0)
+ return MERGE_UINT64;
+ if (strcmp (str, "double") == 0)
+ return MERGE_DOUBLE;
+ if (strcmp (str, "strlist") == 0)
+ return MERGE_STRLIST;
+ if (strcmp (str, "copy_property") == 0)
+ return MERGE_COPY_PROPERTY;
+ if (strcmp (str, "remove") == 0)
+ return MERGE_REMOVE;
+ return MERGE_UNKNOWN;
+}
- /** Type to merge*/
- int merge_type;
+static char *
+get_merge_type_str (enum merge_type type)
+{
+ switch (type) {
+ case MERGE_STRING:
+ return "string";
+ case MERGE_BOOLEAN:
+ return "bool";
+ case MERGE_INT32:
+ return "int";
+ case MERGE_UINT64:
+ return "unint64";
+ case MERGE_DOUBLE:
+ return "double";
+ case MERGE_STRLIST:
+ return "strlist";
+ case MERGE_COPY_PROPERTY:
+ return "copy_property";
+ case MERGE_REMOVE:
+ return "remove";
+ case MERGE_UNKNOWN:
+ return "unknown merge type";
+ }
+ return "invalid merge type";
+}
- /** Set to #TRUE if a device is matched */
- dbus_bool_t device_matched;
+static enum
+match_type get_match_type(const char *str)
+{
+ if (strcmp (str, "string") == 0)
+ return MATCH_STRING;
+ if (strcmp (str, "int") == 0)
+ return MATCH_INT;
+ if (strcmp (str, "uint64") == 0)
+ return MATCH_UINT64;
+ if (strcmp (str, "bool") == 0)
+ return MATCH_BOOL;
+ if (strcmp (str, "exists") == 0)
+ return MATCH_EXISTS;
+ if (strcmp (str, "empty") == 0)
+ return MATCH_EMPTY;
+ if (strcmp (str, "is_ascii") == 0)
+ return MATCH_ISASCII;
+ if (strcmp (str, "is_absolute_path") == 0)
+ return MATCH_IS_ABS_PATH;
+ if (strcmp (str, "contains") == 0)
+ return MATCH_CONTAINS;
+ if (strcmp (str, "contains_ncase") == 0)
+ return MATCH_CONTAINS_NCASE;
+ if (strcmp (str, "compare_lt") == 0)
+ return MATCH_COMPARE_LT;
+ if (strcmp (str, "compare_le") == 0)
+ return MATCH_COMPARE_LE;
+ if (strcmp (str, "compare_gt") == 0)
+ return MATCH_COMPARE_GT;
+ if (strcmp (str, "compare_ge") == 0)
+ return MATCH_COMPARE_GE;
+ return MATCH_UNKNOWN;
+}
-} ParsingContext;
+static char *
+get_match_type_str (enum match_type type)
+{
+ switch (type) {
+ case MATCH_STRING:
+ return "string";
+ case MATCH_INT:
+ return "int";
+ case MATCH_UINT64:
+ return "uint64";
+ case MATCH_BOOL:
+ return "bool";
+ case MATCH_EXISTS:
+ return "exists";
+ case MATCH_EMPTY:
+ return "empty";
+ case MATCH_ISASCII:
+ return "is_ascii";
+ case MATCH_IS_ABS_PATH:
+ return "is_absolute_path";
+ case MATCH_CONTAINS:
+ return "contains";
+ case MATCH_CONTAINS_NCASE:
+ return "contains_ncase";
+ case MATCH_COMPARE_LT:
+ return "compare_lt";
+ case MATCH_COMPARE_LE:
+ return "compare_le";
+ case MATCH_COMPARE_GT:
+ return "compare_gt";
+ case MATCH_COMPARE_GE:
+ return "compare_ge";
+ case MATCH_UNKNOWN:
+ return "unknown match type";
+ }
+ return "invalid match type";
+}
-/** Resolve a udi-property path as used in .fdi files.
+/** Resolve a udi-property path as used in .fdi files.
*
* Examples of udi-property paths:
*
@@ -177,16 +316,12 @@ typedef struct {
*/
static gboolean
resolve_udiprop_path (const char *path, const char *source_udi,
- char *udi_result, size_t udi_result_size,
+ 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));*/
+ gboolean rc = FALSE;
/* Split up path into ':' tokens */
tokens = g_strsplit (path, ":", 64);
@@ -235,26 +370,15 @@ resolve_udiprop_path (const char *path,
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;
}
@@ -317,135 +441,86 @@ out:
return rc;
}
-/** Called when the match element begins.
- *
- * @param pc Parsing context
- * @param attr Attribute key/value pairs
- * @return #FALSE if the device in question didn't
- * match the data in the attributes
- */
-static dbus_bool_t
-handle_match (ParsingContext * pc, const char **attr)
+static gboolean
+handle_match (struct rule *rule, HalDevice *d)
{
- 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++);
-
- if (num_attrib != 4)
- return FALSE;
-
- if (strcmp (attr[0], "key") != 0)
- return FALSE;
- key = attr[1];
+ char udi_to_check[HAL_PATH_MAX];
+ char prop_to_check[HAL_PATH_MAX];
+ const char *key = rule->key;
+ const char *value = rule->value;
/* 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,
+ hal_device_get_udi (d),
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));
+ HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", key, value));
return FALSE;
}
d = hal_device_store_find (hald_get_gdl (), udi_to_check);
- if (d == NULL) {
+ 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;
-
- /* match string property */
-
- value = attr[3];
-
- /*HAL_INFO(("Checking that key='%s' is a string that "
- "equals '%s'", key, value)); */
+ switch (rule->type_match) {
+ case MATCH_STRING:
+ {
if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
return FALSE;
-
- if (strcmp (hal_device_property_get_string (d, prop_to_check),
- value) != 0)
+ if (strcmp (hal_device_property_get_string (d, prop_to_check), value) != 0)
return FALSE;
-
- /*HAL_INFO (("*** string match for key %s", key));*/
return TRUE;
- } else if (strcmp (attr[2], "int") == 0) {
- dbus_int32_t value;
-
- /* match integer property */
- value = strtol (attr[3], NULL, 0);
-
- /** @todo Check error condition */
+ }
- /*HAL_INFO (("Checking that key='%s' is a int that equals %d",
- key, value));*/
+ case MATCH_INT:
+ {
+ int val = strtol (value, NULL, 0);
if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_INT32)
return FALSE;
-
- if (hal_device_property_get_int (d, prop_to_check) != value) {
+ if (hal_device_property_get_int (d, prop_to_check) != val)
return FALSE;
- }
-
return TRUE;
- } else if (strcmp (attr[2], "uint64") == 0) {
- dbus_uint64_t value;
-
- /* match integer property */
- value = strtoull (attr[3], NULL, 0);
-
- /** @todo Check error condition */
+ }
- /*HAL_INFO (("Checking that key='%s' is a int that equals %d",
- key, value));*/
+ case MATCH_UINT64:
+ {
+ dbus_uint64_t val = strtol (value, NULL, 0);
if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_UINT64)
return FALSE;
-
- if (hal_device_property_get_uint64 (d, prop_to_check) != value) {
+ if (hal_device_property_get_uint64 (d, prop_to_check) != val)
return FALSE;
- }
-
return TRUE;
- } else if (strcmp (attr[2], "bool") == 0) {
- dbus_bool_t value;
-
- /* match string property */
+ }
- if (strcmp (attr[3], "false") == 0)
- value = FALSE;
- else if (strcmp (attr[3], "true") == 0)
- value = TRUE;
+ case MATCH_BOOL:
+ {
+ dbus_bool_t val;
+
+ if (strcmp (value, "false") == 0)
+ val = FALSE;
+ else if (strcmp (value, "true") == 0)
+ val = TRUE;
else
return FALSE;
- /*HAL_INFO (("Checking that key='%s' is a bool that equals %s",
- key, value ? "TRUE" : "FALSE"));*/
-
- if (hal_device_property_get_type (d, prop_to_check) !=
- HAL_PROPERTY_TYPE_BOOLEAN)
+ if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_BOOLEAN)
return FALSE;
-
- if (hal_device_property_get_bool (d, prop_to_check) != value)
+ if (hal_device_property_get_bool (d, prop_to_check) != val)
return FALSE;
-
- /*HAL_INFO (("*** bool match for key %s", key));*/
return TRUE;
- } else if (strcmp (attr[2], "exists") == 0) {
+ }
+
+ case MATCH_EXISTS:
+ {
dbus_bool_t should_exist = TRUE;
- if (strcmp (attr[3], "false") == 0)
+ if (strcmp (value, "false") == 0)
should_exist = FALSE;
if (should_exist) {
@@ -459,16 +534,17 @@ handle_match (ParsingContext * pc, const
else
return TRUE;
}
- } else if (strcmp (attr[2], "empty") == 0) {
+ }
+
+ case MATCH_EMPTY:
+ {
dbus_bool_t is_empty = TRUE;
dbus_bool_t should_be_empty = TRUE;
- if (strcmp (attr[3], "false") == 0)
+ if (strcmp (value, "false") == 0)
should_be_empty = FALSE;
-
if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_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;
@@ -484,13 +560,16 @@ handle_match (ParsingContext * pc, const
else
return TRUE;
}
- } else if (strcmp (attr[2], "is_ascii") == 0) {
+ }
+
+ case MATCH_ISASCII:
+ {
dbus_bool_t is_ascii = TRUE;
dbus_bool_t should_be_ascii = TRUE;
unsigned int i;
const char *str;
- if (strcmp (attr[3], "false") == 0)
+ if (strcmp (value, "false") == 0)
should_be_ascii = FALSE;
if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
@@ -515,16 +594,17 @@ handle_match (ParsingContext * pc, const
else
return TRUE;
}
- } else if (strcmp (attr[2], "is_absolute_path") == 0) {
+ }
+
+ case MATCH_IS_ABS_PATH:
+ {
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)
+ if (strcmp (value, "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) != HAL_PROPERTY_TYPE_STRING)
return FALSE;
@@ -534,8 +614,6 @@ handle_match (ParsingContext * pc, const
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;
@@ -547,31 +625,28 @@ handle_match (ParsingContext * pc, const
else
return TRUE;
}
- } else if (strcmp (attr[2], "contains") == 0) {
- const char *needle;
- dbus_bool_t contains = FALSE;
+ }
- needle = attr[3];
+ case MATCH_CONTAINS:
+ {
+ dbus_bool_t contains = FALSE;
if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRING) {
if (hal_device_has_property (d, prop_to_check)) {
const char *haystack;
-
+
haystack = hal_device_property_get_string (d, prop_to_check);
- if (needle != NULL && haystack != NULL && strstr (haystack, needle)) {
+ if (value != NULL && haystack != NULL && strstr (haystack, value))
contains = TRUE;
- }
-
}
- } else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST &&
- needle != NULL) {
+ } else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST && value != NULL) {
+ GSList *list;
GSList *i;
- GSList *value;
- value = hal_device_property_get_strlist (d, prop_to_check);
- for (i = value; i != NULL; i = g_slist_next (i)) {
+ list = hal_device_property_get_strlist (d, prop_to_check);
+ for (i = list; i != NULL; i = g_slist_next (i)) {
const char *str = i->data;
- if (strcmp (str, needle) == 0) {
+ if (strcmp (str, value) == 0) {
contains = TRUE;
break;
}
@@ -581,482 +656,93 @@ handle_match (ParsingContext * pc, const
}
return contains;
- } else if (strcmp (attr[2], "contains_ncase") == 0) {
- const char *needle;
- dbus_bool_t contains_ncase = FALSE;
+ }
- needle = attr[3];
+ case MATCH_CONTAINS_NCASE:
+ {
+ dbus_bool_t contains_ncase = FALSE;
if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRING) {
if (hal_device_has_property (d, prop_to_check)) {
- char *needle_lowercase;
+ char *value_lowercase;
char *haystack_lowercase;
-
- needle_lowercase = g_utf8_strdown (needle, -1);
+
+ value_lowercase = g_utf8_strdown (value, -1);
haystack_lowercase = g_utf8_strdown (hal_device_property_get_string (d, prop_to_check), -1);
- if (needle_lowercase != NULL && haystack_lowercase != NULL && strstr (haystack_lowercase, needle_lowercase)) {
+ if (value_lowercase != NULL && haystack_lowercase != NULL &&
+ strstr (haystack_lowercase, value_lowercase))
contains_ncase = TRUE;
- }
-
- g_free (needle_lowercase);
+
+ g_free (value_lowercase);
g_free (haystack_lowercase);
}
- } else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST &&
- needle != NULL) {
+ } else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST && value != NULL) {
+ GSList *list;
GSList *i;
- GSList *value;
- value = hal_device_property_get_strlist (d, prop_to_check);
- for (i = value; i != NULL; i = g_slist_next (i)) {
+ list = hal_device_property_get_strlist (d, prop_to_check);
+ for (i = list; i != NULL; i = g_slist_next (i)) {
const char *str = i->data;
- if (g_ascii_strcasecmp (str, needle) == 0) {
+ if (g_ascii_strcasecmp (str, value) == 0) {
contains_ncase = TRUE;
break;
}
}
- } else {
+ } else
return FALSE;
- }
-
return contains_ncase;
- } else if (strcmp (attr[2], "compare_lt") == 0) {
+ }
+
+ case MATCH_COMPARE_LT:
+ {
dbus_int64_t result;
- if (!match_compare_property (d, prop_to_check, attr[3], &result)) {
+
+ if (!match_compare_property (d, prop_to_check, value, &result))
return FALSE;
- } else {
+ else
return result < 0;
- }
- } else if (strcmp (attr[2], "compare_le") == 0) {
+ }
+
+ case MATCH_COMPARE_LE:
+ {
dbus_int64_t result;
- if (!match_compare_property (d, prop_to_check, attr[3], &result))
+
+ if (!match_compare_property (d, prop_to_check, value, &result))
return FALSE;
else
return result <= 0;
- } else if (strcmp (attr[2], "compare_gt") == 0) {
+ }
+
+ case MATCH_COMPARE_GT:
+ {
dbus_int64_t result;
- if (!match_compare_property (d, prop_to_check, attr[3], &result))
+
+ if (!match_compare_property (d, prop_to_check, value, &result))
return FALSE;
else
return result > 0;
- } else if (strcmp (attr[2], "compare_ge") == 0) {
+ }
+
+ case MATCH_COMPARE_GE:
+ {
dbus_int64_t result;
- if (!match_compare_property (d, prop_to_check, attr[3], &result))
+
+ if (!match_compare_property (d, prop_to_check, value, &result))
return FALSE;
else
return result >= 0;
}
-
- return FALSE;
-}
-
-
-/** Called when the merge element begins.
- *
- * @param pc Parsing context
- * @param attr Attribute key/value pairs
- */
-static void
-handle_merge (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], "bool") == 0) {
- /* match string property */
- pc->merge_type = MERGE_TYPE_BOOLEAN;
- return;
- } else if (strcmp (attr[3], "int") == 0) {
- /* match string property */
- pc->merge_type = MERGE_TYPE_INT32;
- return;
- } else if (strcmp (attr[3], "uint64") == 0) {
- /* match string property */
- pc->merge_type = MERGE_TYPE_UINT64;
- return;
- } else if (strcmp (attr[3], "double") == 0) {
- /* match string property */
- pc->merge_type = MERGE_TYPE_DOUBLE;
- return;
- } else if (strcmp (attr[3], "strlist") == 0) {
- /* match string property */
- pc->merge_type = MERGE_TYPE_STRLIST;
- 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 or prepend element begins.
- *
- * @param pc Parsing context
- * @param attr Attribute key/value pairs
- */
-static void
-handle_append_prepend (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) {
- /* append to a string */
- pc->merge_type = MERGE_TYPE_STRING;
- return;
- } else if (strcmp (attr[3], "strlist") == 0) {
- /* append to a string list*/
- pc->merge_type = MERGE_TYPE_STRLIST;
- return;
- } else if (strcmp (attr[3], "copy_property") == 0) {
- /* copy another property */
- pc->merge_type = MERGE_TYPE_COPY_PROPERTY;
- return;
- }
-
- return;
-}
-
-
-/** Called when the spawn element begins.
- *
- * @param pc Parsing context
- * @param attr Attribute key/value pairs
- */
-static void
-handle_spawn (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 != 2)
- return;
-
- if (strcmp (attr[0], "udi") != 0)
- return;
-
- strncpy (pc->merge_key, attr[1], MAX_KEY_SIZE);
-
- pc->merge_type = MERGE_TYPE_SPAWN;
-
- return;
-}
-
-/** Called when the remove element begins.
- *
- * @param pc Parsing context
- * @param attr Attribute key/value pairs
- */
-static void
-handle_remove (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 != 2 && num_attrib != 4)
- return;
-
- if (strcmp (attr[0], "key") != 0)
- return;
- strncpy (pc->merge_key, attr[1], MAX_KEY_SIZE);
-
- if (num_attrib == 4) {
- if (strcmp (attr[2], "type") != 0)
- return;
-
- if (strcmp (attr[3], "strlist") == 0) {
- /* remove from strlist */
- pc->merge_type = MERGE_TYPE_STRLIST;
- return;
- } else {
- pc->merge_type = MERGE_TYPE_UNKNOWN;
- return;
- }
- } else {
- pc->merge_type = MERGE_TYPE_REMOVE;
- }
-
- return;
-}
-
-/** Called when the clear element begins.
- *
- * @param pc Parsing context
- * @param attr Attribute key/value pairs
- */
-static void
-handle_clear (ParsingContext * pc, const char **attr)
-{
- int num_attrib;
-
- pc->merge_type = MERGE_TYPE_UNKNOWN;
- for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
- ;
+ default:
+ HAL_INFO(("match ERROR"));
+ return FALSE;
}
- if (num_attrib != 4)
- return;
-
- if (strcmp (attr[0], "key") != 0)
- return;
-
-
- if (strcmp (attr[3], "strlist") != 0)
- return;
-
- strncpy (pc->merge_key, attr[1], MAX_KEY_SIZE);
-
- pc->merge_type = MERGE_TYPE_CLEAR;
-
- return;
-}
-
-/** Abort parsing of document
- *
- * @param pc Parsing context
- */
-static void
-parsing_abort (ParsingContext * pc)
-{
- /* Grr, expat can't abort parsing */
- HAL_ERROR (("Aborting parsing of document"));
- pc->aborted = TRUE;
+ return FALSE;
}
-/** Called by expat when an element begins.
- *
- * @param pc Parsing context
- * @param el Element name
- * @param attr Attribute key/value pairs
- */
+/* we have finished the callouts for a device, now add it to the gdl */
static void
-start (ParsingContext * pc, const char *el, const char **attr)
-{
- if (pc->aborted)
- return;
-
- pc->cdata_buf_len = 0;
-
-/*
- for (i = 0; i < pc->depth; i++)
- printf(" ");
-
- printf("%s", el);
-
- for (i = 0; attr[i]; i += 2) {
- printf(" %s='%s'", attr[i], attr[i + 1]);
- }
-
- printf(" curelem=%d\n", pc->curelem);
-*/
-
- if (strcmp (el, "match") == 0) {
- if (pc->curelem != CURELEM_DEVICE
- && pc->curelem != CURELEM_MATCH) {
- HAL_ERROR (("%s:%d:%d: Element <match> can only be "
- "inside <device> and <match>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
-
- pc->curelem = CURELEM_MATCH;
-
- /* don't bother checking if matching at lower depths failed */
- if (pc->match_ok) {
- if (!handle_match (pc, attr)) {
- /* No match */
- pc->match_depth_first_fail = pc->depth;
- pc->match_ok = FALSE;
- }
- }
- } else if (strcmp (el, "merge") == 0) {
- if (pc->curelem != CURELEM_DEVICE
- && pc->curelem != CURELEM_MATCH) {
- HAL_ERROR (("%s:%d:%d: Element <merge> can only be "
- "inside <device> and <match>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
-
- pc->curelem = CURELEM_MERGE;
- if (pc->match_ok) {
- handle_merge (pc, attr);
- } 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_prepend (pc, attr);
- } else {
- /*HAL_INFO(("No merge!")); */
- }
- } else if (strcmp (el, "prepend") == 0) {
- if (pc->curelem != CURELEM_DEVICE
- && pc->curelem != CURELEM_MATCH) {
- HAL_ERROR (("%s:%d:%d: Element <prepend> can only be "
- "inside <device> and <match>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
-
- pc->curelem = CURELEM_PREPEND;
- if (pc->match_ok) {
- handle_append_prepend (pc, attr);
- } else {
- /*HAL_INFO(("No merge!")); */
- }
- } else if (strcmp (el, "remove") == 0) {
- if (pc->curelem != CURELEM_DEVICE
- && pc->curelem != CURELEM_MATCH) {
- HAL_ERROR (("%s:%d:%d: Element <remove> can only be "
- "inside <device> and <match>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
-
- pc->curelem = CURELEM_REMOVE;
- if (pc->match_ok) {
- handle_remove (pc, attr);
- } else {
- /*HAL_INFO(("No merge!")); */
- }
- } else if (strcmp (el, "clear") == 0) {
- if (pc->curelem != CURELEM_DEVICE
- && pc->curelem != CURELEM_MATCH) {
- HAL_ERROR (("%s:%d:%d: Element <remove> can only be "
- "inside <device> and <match>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
-
- pc->curelem = CURELEM_CLEAR;
- if (pc->match_ok) {
- handle_clear (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 "
- "inside <deviceinfo>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
- pc->curelem = CURELEM_DEVICE;
- } else if (strcmp (el, "deviceinfo") == 0) {
- if (pc->curelem != CURELEM_UNKNOWN) {
- HAL_ERROR (("%s:%d:%d: Element <deviceinfo> must be "
- "a top-level element",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
- pc->curelem = CURELEM_DEVICE_INFO;
- } else if (strcmp (el, "spawn") == 0) {
- if (pc->curelem != CURELEM_MATCH) {
- HAL_ERROR (("%s:%d:%d: Element <spawn> can only be "
- "inside <match>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser)));
- parsing_abort (pc);
- }
-
- pc->curelem = CURELEM_SPAWN;
- if (pc->match_ok) {
- handle_spawn (pc, attr);
- }
-
- } else {
- HAL_ERROR (("%s:%d:%d: Unknown element <%s>",
- pc->file,
- XML_GetCurrentLineNumber (pc->parser),
- XML_GetCurrentColumnNumber (pc->parser), el));
- parsing_abort (pc);
- }
-
- /* Nasty hack */
- assert (pc->depth < MAX_DEPTH);
-
- pc->depth++;
-
- /* store depth */
- pc->curelem_stack[pc->depth] = pc->curelem;
-
-}
-
-static void
spawned_device_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
{
HAL_INFO (("Add callouts completed udi=%s", d->udi));
@@ -1064,96 +750,55 @@ spawned_device_callouts_add_done (HalDev
/* Move from temporary to global device store */
hal_device_store_remove (hald_get_tdl (), d);
hal_device_store_add (hald_get_gdl (), d);
-
}
-/** Called by expat when an element ends.
- *
- * @param pc Parsing context
- * @param el Element name
- */
-static void
-end (ParsingContext * pc, const char *el)
+/* for this device, process the rule */
+static gboolean
+handle_merge (struct rule *rule, HalDevice *d)
{
- if (pc->aborted)
- return;
-
- pc->cdata_buf[pc->cdata_buf_len] = '\0';
+ const char *key = rule->key;
+ const char *value = rule->value;
-/* printf(" curelem=%d\n", pc->curelem);*/
+ if (rule->rtype == RULE_MERGE) {
- if (pc->curelem == CURELEM_MERGE && pc->match_ok) {
- /* As soon as we are merging, we have matched the device... */
- pc->device_matched = TRUE;
+ if (rule->type_merge == MERGE_STRING) {
+ hal_device_property_set_string (d, key, value);
- switch (pc->merge_type) {
- case MERGE_TYPE_STRING:
- hal_device_property_set_string (pc->device, pc->merge_key, pc->cdata_buf);
- break;
+ } else if (rule->type_merge == MERGE_STRLIST) {
+ int type = hal_device_property_get_type (d, key);
- case MERGE_TYPE_STRLIST:
- {
- int type = hal_device_property_get_type (pc->device, pc->merge_key);
if (type == HAL_PROPERTY_TYPE_STRLIST || type == HAL_PROPERTY_TYPE_INVALID) {
- hal_device_property_remove (pc->device, pc->merge_key);
- hal_device_property_strlist_append (pc->device, pc->merge_key, pc->cdata_buf);
+ hal_device_property_remove (d, key);
+ hal_device_property_strlist_append (d, key, value);
}
- break;
- }
- case MERGE_TYPE_INT32:
- {
- dbus_int32_t value;
+ } else if (rule->type_merge == MERGE_INT32) {
+ dbus_int32_t val = strtol (value, NULL, 0);
+ hal_device_property_set_int (d, key, val);
- /* match integer property */
- value = strtol (pc->cdata_buf, NULL, 0);
+ } else if (rule->type_merge == MERGE_UINT64) {
+ dbus_uint64_t val = strtoull (value, NULL, 0);
+ hal_device_property_set_uint64 (d, key, val);
- /** @todo FIXME: Check error condition */
+ } else if (rule->type_merge == MERGE_BOOLEAN) {
+ hal_device_property_set_bool (d, key, (strcmp (value, "true") == 0) ? TRUE : FALSE);
- hal_device_property_set_int (pc->device,
- pc->merge_key, value);
- break;
- }
-
- case MERGE_TYPE_UINT64:
- {
- dbus_uint64_t value;
-
- /* match integer property */
- value = strtoull (pc->cdata_buf, NULL, 0);
-
- /** @todo FIXME: Check error condition */
-
- hal_device_property_set_uint64 (pc->device,
- pc->merge_key, value);
- break;
- }
-
- case MERGE_TYPE_BOOLEAN:
- hal_device_property_set_bool (pc->device, pc->merge_key,
- (strcmp (pc->cdata_buf,
- "true") == 0)
- ? TRUE : FALSE);
- break;
+ } else if (rule->type_merge == MERGE_DOUBLE) {
+ hal_device_property_set_double (d, key, atof (value));
- case MERGE_TYPE_DOUBLE:
- hal_device_property_set_double (pc->device, pc->merge_key,
- atof (pc->cdata_buf));
- break;
+ } else if (rule->type_merge == MERGE_COPY_PROPERTY) {
- case MERGE_TYPE_COPY_PROPERTY:
- {
- char udi_to_merge_from[256];
- char prop_to_merge[256];
+ char udi_to_merge_from[HAL_PATH_MAX];
+ char prop_to_merge[HAL_PATH_MAX];
- /* Resolve key paths like 'someudi/foo/bar/baz:prop.name'
+ /* 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,
+ if (!resolve_udiprop_path (value,
+ hal_device_get_udi (d),
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));
+ HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", value, hal_device_get_udi (d)));
} else {
HalDevice *d;
@@ -1164,386 +809,380 @@ end (ParsingContext * pc, const char *el
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);
+ hal_device_copy_property (d, prop_to_merge, d, key);
}
}
- break;
- }
- default:
- HAL_ERROR (("Unknown merge_type=%d='%c'",
- pc->merge_type, pc->merge_type));
- break;
+ } else {
+ HAL_ERROR (("unknown merge type (%u)", rule->type_merge));
}
- } else if (pc->curelem == CURELEM_APPEND && pc->match_ok &&
- (hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRING ||
- hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRLIST ||
- hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_INVALID)) {
- char buf[256];
- char buf2[256];
- /* As soon as we are appending, we have matched the device... */
- pc->device_matched = TRUE;
+ } else if (rule->rtype == RULE_APPEND) {
+ char buf[HAL_PATH_MAX];
+ char buf2[HAL_PATH_MAX];
- if (pc->merge_type == MERGE_TYPE_STRLIST) {
- hal_device_property_strlist_append (pc->device, pc->merge_key, pc->cdata_buf);
+ if (hal_device_property_get_type (d, key) != HAL_PROPERTY_TYPE_STRING &&
+ hal_device_property_get_type (d, key) != HAL_PROPERTY_TYPE_STRLIST &&
+ hal_device_property_get_type (d, key) != HAL_PROPERTY_TYPE_INVALID) {
+ HAL_ERROR (("invalid key type"));
+ return FALSE;
+ }
+
+ if (rule->type_merge == MERGE_STRLIST) {
+ hal_device_property_strlist_append (d, key, value);
} else {
const char *existing_string;
-
- switch (pc->merge_type) {
- case MERGE_TYPE_STRING:
- strncpy (buf, pc->cdata_buf, sizeof (buf));
+
+ switch (rule->type_merge) {
+ case MERGE_STRING:
+ strncpy (buf, value, sizeof (buf));
break;
-
- case MERGE_TYPE_COPY_PROPERTY:
- hal_device_property_get_as_string (pc->device, pc->cdata_buf, buf, sizeof (buf));
+
+ case MERGE_COPY_PROPERTY:
+ hal_device_property_get_as_string (d, value, buf, sizeof (buf));
break;
-
+
default:
- HAL_ERROR (("Unknown merge_type=%d='%c'", pc->merge_type, pc->merge_type));
break;
}
-
- existing_string = hal_device_property_get_string (pc->device, pc->merge_key);
+
+ existing_string = hal_device_property_get_string (d, key);
if (existing_string != NULL) {
strncpy (buf2, existing_string, sizeof (buf2));
strncat (buf2, buf, sizeof (buf2) - strlen(buf2));
- } else {
+ } else
strncpy (buf2, buf, sizeof (buf2));
- }
- hal_device_property_set_string (pc->device, pc->merge_key, buf2);
+ hal_device_property_set_string (d, key, buf2);
}
- } else if (pc->curelem == CURELEM_PREPEND && pc->match_ok &&
- (hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRING ||
- hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRLIST ||
- hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_INVALID)) {
- char buf[256];
- char buf2[256];
- /* As soon as we are prepending, we have matched the device... */
- pc->device_matched = TRUE;
+ } else if (rule->rtype == RULE_PREPEND) {
+ char buf[HAL_PATH_MAX];
+ char buf2[HAL_PATH_MAX];
- if (pc->merge_type == MERGE_TYPE_STRLIST) {
- hal_device_property_strlist_prepend (pc->device, pc->merge_key, pc->cdata_buf);
+ if (hal_device_property_get_type (d, key) != HAL_PROPERTY_TYPE_STRING &&
+ hal_device_property_get_type (d, key) != HAL_PROPERTY_TYPE_STRLIST &&
+ hal_device_property_get_type (d, key) != HAL_PROPERTY_TYPE_INVALID) {
+ HAL_ERROR (("invalid key type"));
+ return FALSE;
+ }
+
+ if (rule->type_merge == MERGE_STRLIST) {
+ hal_device_property_strlist_prepend (d, key, value);
} else {
const char *existing_string;
-
- 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;
+
+ if (rule->type_merge == MERGE_STRING) {
+ strncpy (buf, value, sizeof (buf));
+
+ } else if (rule->type_merge == MERGE_COPY_PROPERTY) {
+ hal_device_property_get_as_string (d, value, buf, sizeof (buf));
+
}
-
- existing_string = hal_device_property_get_string (pc->device, pc->merge_key);
+
+ existing_string = hal_device_property_get_string (d, key);
if (existing_string != NULL) {
strncpy (buf2, buf, sizeof (buf2));
strncat (buf2, existing_string, sizeof (buf2) - strlen(buf2));
} else {
strncpy (buf2, buf, sizeof (buf2));
}
- hal_device_property_set_string (pc->device, pc->merge_key, buf2);
+ hal_device_property_set_string (d, key, buf2);
}
- } else if (pc->curelem == CURELEM_REMOVE && pc->match_ok) {
- if (pc->merge_type == MERGE_TYPE_STRLIST) {
+ } else if (rule->rtype == RULE_REMOVE) {
+
+ if (rule->type_merge == MERGE_STRLIST) {
/* covers <remove key="foobar" type="strlist">blah</remove> */
- hal_device_property_strlist_remove (pc->device, pc->merge_key, pc->cdata_buf);
+ hal_device_property_strlist_remove (d, key, value);
+
} else {
/* only allow <remove key="foobar"/>, not <remove key="foobar">blah</remove> */
- if (strlen (pc->cdata_buf) == 0) {
- hal_device_property_remove (pc->device, pc->merge_key);
- }
+ if (strlen (value) == 0)
+ hal_device_property_remove (d, key);
}
- } else if (pc->merge_type == MERGE_TYPE_SPAWN) {
- HalDevice *spawned;
- spawned = hal_device_store_find (hald_get_gdl (), pc->merge_key);
+ } else if (rule->rtype == RULE_SPAWN) {
+ HalDevice *spawned;
+ spawned = hal_device_store_find (hald_get_gdl (), key);
if (spawned == NULL)
- spawned = hal_device_store_find (hald_get_tdl (), pc->merge_key);
+ spawned = hal_device_store_find (hald_get_tdl (), key);
if (spawned == NULL) {
- HAL_INFO (("Spawning new device object '%s' caused by <spawn> on udi '%s'",
- pc->merge_key, pc->device->udi));
-
+ HAL_INFO (("Spawning new device object '%s' caused by <spawn> on udi '%s'",
+ key, d->udi));
spawned = hal_device_new ();
hal_device_property_set_string (spawned, "info.bus", "unknown");
- hal_device_property_set_string (spawned, "info.udi", pc->merge_key);
- hal_device_property_set_string (spawned, "info.parent", pc->device->udi);
- hal_device_set_udi (spawned, pc->merge_key);
-
+ hal_device_property_set_string (spawned, "info.udi", key);
+ hal_device_property_set_string (spawned, "info.parent", d->udi);
+ hal_device_set_udi (spawned, key);
+
hal_device_store_add (hald_get_tdl (), spawned);
-
+
di_search_and_merge (spawned, DEVICE_INFO_TYPE_INFORMATION);
di_search_and_merge (spawned, DEVICE_INFO_TYPE_POLICY);
-
+
hal_util_callout_device_add (spawned, spawned_device_callouts_add_done, NULL, NULL);
}
- } else if (pc->curelem == CURELEM_CLEAR && pc->match_ok) {
- if (pc->merge_type == MERGE_TYPE_CLEAR) {
- hal_device_property_strlist_clear (pc->device, pc->merge_key);
+ } else {
+ HAL_ERROR (("Unknown rule type (%u)", rule->rtype));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* for each node, free memory and it's own list of nodes */
+static void
+rules_cleanup_list (GSList *fdi_rules)
+{
+ GSList *elem;
+
+ for (elem = fdi_rules; elem != NULL; elem = g_slist_next (elem)) {
+ struct rule *rule = elem->data;
+
+ g_free (rule->key);
+ g_free (rule->value);
+ g_free (rule);
+ }
+ g_slist_free (fdi_rules);
+ fdi_rules = NULL;
+}
+
+/* expat cb for start, e.g. <match foo=bar */
+static void
+start (void *data, const char *el, const char **attr)
+{
+ struct fdi_context *fdi_ctx = data;
+ enum rule_type rtype = get_rule_type (el);
+ int i;
+
+ if (rtype == RULE_UNKNOWN)
+ return;
+
+ if (fdi_ctx->rule == NULL)
+ return;
+
+ /* get key and attribute for current rule */
+ for (i = 0; attr[i] != NULL; i+=2) {
+ if (strcmp (attr[i], "key") == 0) {
+ fdi_ctx->rule->key = g_strdup (attr[1]);
+ continue;
+ }
+ if (rtype == RULE_SPAWN) {
+ if (strcmp (attr[i], "udi") == 0) {
+ fdi_ctx->rule->key = g_strdup (attr[1]);
+ continue;
+ }
+ } else if (rtype == RULE_MATCH) {
+ fdi_ctx->rule->type_match = get_match_type (attr[i]);
+ if (fdi_ctx->rule->type_match == MATCH_UNKNOWN)
+ continue;
+ fdi_ctx->rule->value = g_strdup (attr[i+1]);
+ } else {
+ if (strcmp (attr[i], "type") != 0)
+ continue;
+ fdi_ctx->rule->type_merge = get_merge_type (attr[i+1]);
+ if (fdi_ctx->rule->type_merge == MERGE_UNKNOWN)
+ return;
}
}
+ if (fdi_ctx->rule->key[0] == '\0')
+ return;
+
+ fdi_ctx->rule->rtype = rtype;
- pc->cdata_buf_len = 0;
- pc->depth--;
+ /* match rules remember the current nesting and the label to jump to if not matching */
+ if (rtype == RULE_MATCH) {
+ /* remember current nesting */
+ fdi_ctx->depth++;
- /* maintain curelem */
- pc->curelem = pc->curelem_stack[pc->depth];
+ /* remember rule at nesting level nesting */
+ fdi_ctx->match_at_depth[fdi_ctx->depth] = fdi_ctx->rule;
- /* maintain pc->match_ok */
- if (pc->depth <= pc->match_depth_first_fail)
- pc->match_ok = TRUE;
+ /* insert match rule into list and get new rule */
+ fdi_ctx->rules = g_slist_append (fdi_ctx->rules, fdi_ctx->rule);
+ fdi_ctx->rule = g_new0 (struct rule ,1);
+ }
}
-/** Called when there is CDATA
- *
- * @param pc Parsing context
- * @param s Pointer to data
- * @param len Length of data
- */
+/* expat cb for character data, i.e. the text data in between tags */
+static void
+cdata (void *data, const char *s, int len)
+{
+ struct fdi_context *fdi_ctx = data;
+
+ if (fdi_ctx->rule == NULL)
+ return;
+
+ if (fdi_ctx->rule->rtype != RULE_MERGE &&
+ fdi_ctx->rule->rtype != RULE_PREPEND &&
+ fdi_ctx->rule->rtype != RULE_APPEND &&
+ fdi_ctx->rule->rtype != RULE_REMOVE &&
+ fdi_ctx->rule->rtype != RULE_SPAWN)
+ return;
+
+ if (len < 1)
+ return;
+
+ /* copy cdata in current context */
+ fdi_ctx->rule->value = g_realloc (fdi_ctx->rule->value, fdi_ctx->rule->value_len + len+1);
+ memcpy (&fdi_ctx->rule->value[fdi_ctx->rule->value_len], s, len);
+ fdi_ctx->rule->value_len += len;
+ fdi_ctx->rule->value[fdi_ctx->rule->value_len] = '\0';
+}
+
+/* expat cb for end, e.g. </device> */
static void
-cdata (ParsingContext * pc, const char *s, int len)
+end (void *data, const char *el)
{
- int bytes_left;
- int bytes_to_copy;
+ struct fdi_context *fdi_ctx = data;
+ enum rule_type rtype = get_rule_type (el);
- if (pc->aborted)
+ if (rtype == RULE_UNKNOWN)
return;
- bytes_left = CDATA_BUF_SIZE - pc->cdata_buf_len;
- if (len > bytes_left) {
- HAL_ERROR (("CDATA in element larger than %d",
- CDATA_BUF_SIZE));
+ if (rtype == RULE_MATCH) {
+ if (fdi_ctx->depth <= 0)
+ return;
+
+ /* get corresponding match rule and set the rule to skip to */
+ fdi_ctx->match_at_depth[fdi_ctx->depth]->next_rule = fdi_ctx->rule;
+ fdi_ctx->depth--;
+ return;
}
- bytes_to_copy = len;
- if (bytes_to_copy > bytes_left)
- bytes_to_copy = bytes_left;
+ /* only valid if element is in the current context */
+ if (fdi_ctx->rule->rtype != rtype)
+ return;
- if (bytes_to_copy > 0)
- memcpy (pc->cdata_buf + pc->cdata_buf_len, s,
- bytes_to_copy);
+ /* set empty value to empty string */
+ if (fdi_ctx->rule->value == NULL)
+ fdi_ctx->rule->value = "";
- pc->cdata_buf_len += bytes_to_copy;
+ /* insert merge rule into list and get new rule */
+ fdi_ctx->rules = g_slist_append (fdi_ctx->rules, fdi_ctx->rule);
+ fdi_ctx->rule = g_new0 (struct rule, 1);
}
-
-/** Process a device information info file.
- *
- * @param dir Directory file resides in
- * @param filename File name
- * @param device Device to match on
- * @return #TRUE if file matched device and information
- * was merged
- */
-static dbus_bool_t
-process_fdi_file (const char *dir, const char *filename,
- HalDevice * device)
+/* decompile an fdi file into a list of rules as this is quicker than opening then each time we want to search */
+static int
+rules_add_fdi_file (GSList **fdi_rules, const char *filename)
{
+ struct fdi_context *fdi_ctx;
+ char *buf;
+ gsize buflen;
int rc;
- char buf[512];
- FILE *file;
- int filesize;
- size_t read;
- char *filebuf;
- dbus_bool_t device_matched;
- XML_Parser parser;
- ParsingContext *parsing_context;
-
- file = NULL;
- filebuf = NULL;
- parser = NULL;
- parsing_context = NULL;
-
- device_matched = FALSE;
-
- snprintf (buf, sizeof (buf), "%s/%s", dir, filename);
-
- /*HAL_INFO(("analyzing file %s", buf));*/
-
- /* open file and read it into a buffer; it's a small file... */
- file = fopen (buf, "r");
- if (file == NULL) {
- HAL_ERROR (("Could not open file %s", buf));
- goto out;
- }
- fseek (file, 0L, SEEK_END);
- filesize = (int) ftell (file);
- rewind (file);
- filebuf = (char *) malloc (filesize);
- if (filebuf == NULL) {
- HAL_ERROR (("Could not allocate %d bytes for file %s", filesize, buf));
- goto out;
- }
- read = fread (filebuf, sizeof (char), filesize, file);
+ if (!g_file_get_contents (filename, &buf, &buflen, NULL))
+ return -1;
- /* initialize parsing context */
- parsing_context =
- (ParsingContext *) malloc (sizeof (ParsingContext));
- if (parsing_context == NULL) {
- HAL_ERROR (("Could not allocate parsing context"));
- goto out;
- }
+ /* get context and first rule */
+ fdi_ctx = g_new0 (struct fdi_context ,1);
+ fdi_ctx->rule = g_new0 (struct rule ,1);
- /* TODO: reuse parser
- */
- parser = XML_ParserCreate (NULL);
+ XML_Parser parser = XML_ParserCreate (NULL);
if (parser == NULL) {
- HAL_ERROR (("Could not allocate XML parser"));
- goto out;
+ fprintf (stderr, "Couldn't allocate memory for parser\n");
+ return -1;
}
+ XML_SetUserData (parser, fdi_ctx);
+ XML_SetElementHandler (parser, start, end);
+ XML_SetCharacterDataHandler (parser, cdata);
+ rc = XML_Parse (parser, buf, buflen, 1);
+ if (rc == 0)
+ fprintf (stderr, "Parse error at line %i:\n%s\n",
+ (int) XML_GetCurrentLineNumber (parser),
+ XML_ErrorString (XML_GetErrorCode (parser)));
+ XML_ParserFree (parser);
+ g_free (buf);
+
+ /* insert last dummy rule into list */
+ fdi_ctx->rule->rtype = RULE_EOF;
+ fdi_ctx->rule->key = g_strdup (filename);
+ fdi_ctx->rules = g_slist_append (fdi_ctx->rules, fdi_ctx->rule);
+
+ /* add rules to external list */
+ if (rc == 0)
+ rules_cleanup_list (fdi_ctx->rules);
+ else
+ *fdi_rules = g_slist_concat (*fdi_rules, fdi_ctx->rules);
+
+ g_free (fdi_ctx);
+
+ if (rc == 0)
+ return -1;
+ return 0;
+}
- parsing_context->depth = 0;
- parsing_context->device_matched = FALSE;
- parsing_context->match_ok = TRUE;
- parsing_context->curelem = CURELEM_UNKNOWN;
- parsing_context->aborted = FALSE;
- 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,
- (XML_EndElementHandler) end);
- XML_SetCharacterDataHandler (parser,
- (XML_CharacterDataHandler) cdata);
- XML_SetUserData (parser, parsing_context);
-
- rc = XML_Parse (parser, filebuf, filesize, 1);
- /*printf("XML_Parse rc=%d\r\n", rc); */
-
- if (rc == 0) {
- /* error parsing document */
- HAL_ERROR (("Error parsing XML document %s at line %d, "
- "column %d : %s",
- buf,
- XML_GetCurrentLineNumber (parser),
- XML_GetCurrentColumnNumber (parser),
- XML_ErrorString (XML_GetErrorCode (parser))));
- device_matched = FALSE;
- } else {
- /* document parsed ok */
- device_matched = parsing_context->device_matched;
- }
+/* print the rules to screen, mainly useful for debugging */
+static void
+rules_dump (GSList *fdi_rules)
+{
+ GSList *elem;
-out:
- if (filebuf != NULL)
- free (filebuf);
- if (file != NULL)
- fclose (file);
- if (parser != NULL)
- XML_ParserFree (parser);
- if (parsing_context != NULL)
- free (parsing_context);
+ for (elem = fdi_rules; elem != NULL; elem = g_slist_next (elem)) {
+ struct rule *rule = elem->data;
- return device_matched;
+ if (rule->rtype == RULE_EOF) {
+ printf ("%p: eof %s\n", rule, rule->key);
+ } else if (rule->rtype == RULE_MATCH) {
+ printf ("\n");
+ printf ("%p: match '%s' (%s) '%s' (skip to %p)\n",
+ rule, rule->key, get_match_type_str (rule->type_match),
+ rule->value, rule->next_rule);
+ } else {
+ printf ("%p: %s '%s' (%s) '%s'\n",
+ rule, get_rule_type_str (rule->rtype), rule->key,
+ get_merge_type_str (rule->type_merge), rule->value);
+ }
+ }
}
-
-
-static int
-my_alphasort(const void *a, const void *b)
+/* modified alphasort to count downwards */
+static int
+_alphasort(const void *a, const void *b)
{
return -alphasort (a, b);
}
-
-/** Scan all directories and subdirectories in the given directory and
- * process each *.fdi file
- *
- * @param d Device to merge information into
- * @return #TRUE if information was merged
- */
-static dbus_bool_t
-scan_fdi_files (const char *dir, HalDevice * d)
+/* recurse a directory tree, searching and adding fdi files */
+static int
+rules_search_and_add_fdi_files (GSList **fdi_rules, const char *dir)
{
int i;
int num_entries;
- dbus_bool_t found_fdi_file;
struct dirent **name_list;
- found_fdi_file = 0;
-
- /*HAL_INFO(("scan_fdi_files: Processing dir '%s'", dir));*/
-
- num_entries = scandir (dir, &name_list, 0, my_alphasort);
- if (num_entries == -1) {
- perror ("scandir");
- return FALSE;
- }
+ num_entries = scandir (dir, &name_list, 0, _alphasort);
+ if (num_entries == -1)
+ return -1;
for (i = num_entries - 1; i >= 0; i--) {
int len;
char *filename;
- gchar *full_path;
+ gchar *full_path;
filename = name_list[i]->d_name;
len = strlen (filename);
-
full_path = g_strdup_printf ("%s/%s", dir, filename);
- /*HAL_INFO (("Full path = %s", full_path));*/
-
- /* Mmm, d_type can be DT_UNKNOWN, use glib to determine
- * the type
- */
if (g_file_test (full_path, (G_FILE_TEST_IS_REGULAR))) {
- /* regular file */
-
- if (len >= 5 &&
- filename[len - 4] == '.' &&
- filename[len - 3] == 'f' &&
- filename[len - 2] == 'd' &&
- filename[len - 1] == 'i') {
- /*HAL_INFO (("scan_fdi_files: Processing file '%s'", filename));*/
- found_fdi_file = process_fdi_file (dir, filename, d);
- if (found_fdi_file) {
- HAL_INFO (("*** Matched file %s/%s", dir, filename));
- /*break;*/
- }
- }
-
- } else if (g_file_test (full_path, (G_FILE_TEST_IS_DIR))
- && strcmp (filename, ".") != 0
- && strcmp (filename, "..") != 0) {
+ if (len >= 5 && strcmp(&filename[len - 4], ".fdi") == 0)
+ rules_add_fdi_file (fdi_rules, full_path);
+ } else if (g_file_test (full_path, (G_FILE_TEST_IS_DIR)) && filename[0] != '.') {
int num_bytes;
char *dirname;
- /* Directory; do the recursion thingy but not
- * for . and ..
- */
-
num_bytes = len + strlen (dir) + 1 + 1;
dirname = (char *) malloc (num_bytes);
- if (dirname == NULL) {
- HAL_ERROR (("couldn't allocated %d bytes",
- num_bytes));
+ if (dirname == NULL)
break;
- }
- snprintf (dirname, num_bytes, "%s/%s", dir,
- filename);
- found_fdi_file = scan_fdi_files (dirname, d);
+ snprintf (dirname, num_bytes, "%s/%s", dir, filename);
+ rules_search_and_add_fdi_files (fdi_rules, dirname);
free (dirname);
- /*
- if (found_fdi_file)
- break;
- */
}
-
g_free (full_path);
-
free (name_list[i]);
}
@@ -1552,80 +1191,129 @@ scan_fdi_files (const char *dir, HalDevi
}
free (name_list);
+ return 0;
+}
- return found_fdi_file;
+/* setup the location of the rules */
+void
+di_rules_init (void)
+{
+ char *hal_fdi_source_preprobe = getenv ("HAL_FDI_SOURCE_PREPROBE");
+ char *hal_fdi_source_information = getenv ("HAL_FDI_SOURCE_INFORMATION");
+ char *hal_fdi_source_policy = getenv ("HAL_FDI_SOURCE_POLICY");
+
+ if (hal_fdi_source_preprobe != NULL)
+ rules_search_and_add_fdi_files (&fdi_rules_preprobe, hal_fdi_source_preprobe);
+ else {
+ rules_search_and_add_fdi_files (&fdi_rules_preprobe, PACKAGE_DATA_DIR "/hal/fdi/preprobe");
+ rules_search_and_add_fdi_files (&fdi_rules_preprobe, PACKAGE_SYSCONF_DIR "/hal/fdi/preprobe");
+ }
+
+ if (hal_fdi_source_information != NULL)
+ rules_search_and_add_fdi_files (&fdi_rules_information, hal_fdi_source_information);
+ else {
+ rules_search_and_add_fdi_files (&fdi_rules_information, PACKAGE_DATA_DIR "/hal/fdi/information");
+ rules_search_and_add_fdi_files (&fdi_rules_information, PACKAGE_SYSCONF_DIR "/hal/fdi/information");
+ }
+
+ if (hal_fdi_source_policy != NULL)
+ rules_search_and_add_fdi_files (&fdi_rules_policy, hal_fdi_source_policy);
+ else {
+ rules_search_and_add_fdi_files (&fdi_rules_policy, PACKAGE_DATA_DIR "/hal/fdi/policy");
+ rules_search_and_add_fdi_files (&fdi_rules_policy, PACKAGE_SYSCONF_DIR "/hal/fdi/policy");
+ }
+
+ /* only dump the rules if we are being verbose as this is expensive */
+ if (getenv ("HALD_VERBOSE") != NULL) {
+ rules_dump (fdi_rules_preprobe);
+ rules_dump (fdi_rules_information);
+ rules_dump (fdi_rules_policy);
+ }
}
-/** Search the device info file repository for a .fdi file to merge
- * more information into the device object.
- *
- * @param d Device to merge information into
- * @return #TRUE if information was merged
- */
-dbus_bool_t
-di_search_and_merge (HalDevice *d, DeviceInfoType type)
+/* cleanup the rules */
+void
+di_rules_cleanup (void)
{
- static gboolean have_checked_hal_fdi_source = FALSE;
- static char *hal_fdi_source_preprobe = NULL;
- static char *hal_fdi_source_information = NULL;
- static char *hal_fdi_source_policy = NULL;
- dbus_bool_t ret;
- char *s1;
- char *s2;
-
- ret = FALSE;
-
- if (!have_checked_hal_fdi_source) {
- hal_fdi_source_preprobe = getenv ("HAL_FDI_SOURCE_PREPROBE");
- hal_fdi_source_information = getenv ("HAL_FDI_SOURCE_INFORMATION");
- hal_fdi_source_policy = getenv ("HAL_FDI_SOURCE_POLICY");
- have_checked_hal_fdi_source = TRUE;
+ rules_cleanup_list (fdi_rules_preprobe);
+ rules_cleanup_list (fdi_rules_information);
+ rules_cleanup_list (fdi_rules_policy);
+ fdi_rules_preprobe = NULL;
+ fdi_rules_information = NULL;
+ fdi_rules_policy = NULL;
+}
+
+/* process a match and merge comand for a device */
+static void
+rules_match_and_merge_device (GSList *fdi_rules, HalDevice *d)
+{
+ GSList *elem;
+
+ if (fdi_rules == NULL) {
+ di_rules_cleanup ();
+ di_rules_init ();
+ }
+
+ elem = fdi_rules;
+ while (elem != NULL) {
+ struct rule *rule = elem->data;
+
+ switch (rule->rtype) {
+ case RULE_MATCH:
+ /* skip non-matching rules block */
+ HAL_INFO(("%p match '%s' at %s", rule, rule->key, hal_device_get_udi (d)));
+ if (!handle_match (rule, d)) {
+ HAL_INFO(("no match, skip to rule %s (%p)", get_rule_type_str (rule->next_rule->rtype), rule->next_rule));
+ elem = g_slist_find (elem, rule->next_rule);
+ continue;
+ }
+ break;
+
+ case RULE_APPEND:
+ case RULE_PREPEND:
+ case RULE_REMOVE:
+ case RULE_CLEAR:
+ case RULE_SPAWN:
+ case RULE_MERGE:
+ HAL_INFO(("%p merge '%s' at %s", rule, rule->key, hal_device_get_udi (d)));
+ handle_merge (rule, d);
+ break;
+
+ case RULE_EOF:
+ HAL_INFO(("%p fdi file '%s' finished", rule, rule->key));
+ break;
+
+ default:
+ HAL_WARNING(("Unhandled rule (%i)!", rule->rtype));
+ break;
+ }
+ elem = g_slist_next (elem);
}
+}
+/* merge the device info type, either preprobe, info or policy */
+gboolean
+di_search_and_merge (HalDevice *d, DeviceInfoType type)
+{
switch (type) {
case DEVICE_INFO_TYPE_PREPROBE:
- if (hal_fdi_source_preprobe != NULL) {
- s1 = hal_fdi_source_preprobe;
- s2 = NULL;
- } else {
- s1 = PACKAGE_DATA_DIR "/hal/fdi/preprobe";
- s2 = PACKAGE_SYSCONF_DIR "/hal/fdi/preprobe";
- }
+ HAL_INFO(("apply fdi preprobe to device %p", d));
+ rules_match_and_merge_device (fdi_rules_preprobe, d);
break;
case DEVICE_INFO_TYPE_INFORMATION:
- if (hal_fdi_source_information != NULL) {
- s1 = hal_fdi_source_information;
- s2 = NULL;
- } else {
- s1 = PACKAGE_DATA_DIR "/hal/fdi/information";
- s2 = PACKAGE_SYSCONF_DIR "/hal/fdi/information";
- }
+ HAL_INFO(("apply fdi info to device %p", d));
+ rules_match_and_merge_device (fdi_rules_information, d);
break;
case DEVICE_INFO_TYPE_POLICY:
- if (hal_fdi_source_policy != NULL) {
- s1 = hal_fdi_source_policy;
- s2 = NULL;
- } else {
- s1 = PACKAGE_DATA_DIR "/hal/fdi/policy";
- s2 = PACKAGE_SYSCONF_DIR "/hal/fdi/policy";
- }
+ HAL_INFO(("apply fdi policy to device %p", d));
+ rules_match_and_merge_device (fdi_rules_policy, d);
break;
default:
- s1 = NULL;
- s2 = NULL;
- HAL_ERROR (("Bogus device information type %d", type));
break;
}
- if (s1 != NULL)
- ret = scan_fdi_files (s1, d) || ret;
- if (s2 != NULL)
- ret = scan_fdi_files (s2, d) || ret;
-
- return ret;
+ return TRUE;
}
-
-/** @} */
diff --git a/hald/device_info.h b/hald/device_info.h
index e37973f..24b1567 100644
--- a/hald/device_info.h
+++ b/hald/device_info.h
@@ -38,6 +38,8 @@ typedef enum {
DEVICE_INFO_TYPE_POLICY
} DeviceInfoType;
-dbus_bool_t di_search_and_merge (HalDevice *d, DeviceInfoType type);
+extern void di_rules_init (void);
+extern void di_rules_cleanup (void);
+extern gboolean di_search_and_merge (HalDevice *d, DeviceInfoType type);
#endif /* DEVICE_INFO_H */
diff-tree 195222c1b1115e62a55b3a21898176c8d01c8da8 (from ec7b3fc5f01a75dd749d05c70ba2a842c16d3c66)
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 19:30:38 2006 -0400
revert hald/device_info.c back to state from June 2006
diff --git a/hald/device_info.c b/hald/device_info.c
index 78ba7cf..17751d3 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -36,7 +36,6 @@
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <math.h>
-#include <errno.h>
#include "hald.h"
#include "logger.h"
@@ -345,10 +344,10 @@ handle_match (ParsingContext * pc, const
/* Resolve key paths like 'someudi/foo/bar/baz:prop.name' '@prop.here.is.an.udi:with.prop.name' */
if (!resolve_udiprop_path (key,
- hal_device_get_udi (pc->device),
+ 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, hal_device_get_udi (pc->device)));
+ HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", key, pc->device->udi));
return FALSE;
}
@@ -461,32 +460,19 @@ handle_match (ParsingContext * pc, const
return TRUE;
}
} else if (strcmp (attr[2], "empty") == 0) {
- int type;
dbus_bool_t is_empty = TRUE;
dbus_bool_t should_be_empty = TRUE;
-
if (strcmp (attr[3], "false") == 0)
should_be_empty = FALSE;
- type = hal_device_property_get_type (d, prop_to_check);
- switch (type) {
- case HAL_PROPERTY_TYPE_STRING:
- if (hal_device_has_property (d, prop_to_check))
- if (strlen (hal_device_property_get_string (d, prop_to_check)) > 0)
- is_empty = FALSE;
- break;
- case HAL_PROPERTY_TYPE_STRLIST:
- if (hal_device_has_property (d, prop_to_check))
- if (!hal_device_property_strlist_is_empty(d, prop_to_check))
- is_empty = FALSE;
- break;
- default:
- /* explicit fallthrough */
+ if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
return FALSE;
- break;
- }
-
+
+ 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;
@@ -537,7 +523,7 @@ handle_match (ParsingContext * pc, const
if (strcmp (attr[3], "false") == 0)
should_be_absolute_path = FALSE;
- /*HAL_INFO (("hal_device_get_udi (d)='%s', prop_to_check='%s'", hal_device_get_udi (d), prop_to_check));*/
+ /*HAL_INFO (("d->udi='%s', prop_to_check='%s'", d->udi, prop_to_check));*/
if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
return FALSE;
@@ -579,12 +565,12 @@ handle_match (ParsingContext * pc, const
}
} else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST &&
needle != NULL) {
- HalDeviceStrListIter iter;
+ GSList *i;
+ GSList *value;
- for (hal_device_property_strlist_iter_init (d, prop_to_check, &iter);
- hal_device_property_strlist_iter_is_valid (&iter);
- hal_device_property_strlist_iter_next (&iter)) {
- const char *str = hal_device_property_strlist_iter_get_value (&iter);
+ value = hal_device_property_get_strlist (d, prop_to_check);
+ for (i = value; i != NULL; i = g_slist_next (i)) {
+ const char *str = i->data;
if (strcmp (str, needle) == 0) {
contains = TRUE;
break;
@@ -617,12 +603,12 @@ handle_match (ParsingContext * pc, const
}
} else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST &&
needle != NULL) {
- HalDeviceStrListIter iter;
+ GSList *i;
+ GSList *value;
- for (hal_device_property_strlist_iter_init (d, prop_to_check, &iter);
- hal_device_property_strlist_iter_is_valid (&iter);
- hal_device_property_strlist_iter_next (&iter)) {
- const char *str = hal_device_property_strlist_iter_get_value (&iter);
+ value = hal_device_property_get_strlist (d, prop_to_check);
+ for (i = value; i != NULL; i = g_slist_next (i)) {
+ const char *str = i->data;
if (g_ascii_strcasecmp (str, needle) == 0) {
contains_ncase = TRUE;
break;
@@ -793,6 +779,7 @@ handle_spawn (ParsingContext * pc, const
strncpy (pc->merge_key, attr[1], MAX_KEY_SIZE);
pc->merge_type = MERGE_TYPE_SPAWN;
+
return;
}
@@ -897,8 +884,6 @@ start (ParsingContext * pc, const char *
pc->cdata_buf_len = 0;
- pc->merge_type = MERGE_TYPE_UNKNOWN;
-
/*
for (i = 0; i < pc->depth; i++)
printf(" ");
@@ -1074,7 +1059,7 @@ start (ParsingContext * pc, const char *
static void
spawned_device_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
{
- HAL_INFO (("Add callouts completed udi=%s", hal_device_get_udi (d)));
+ HAL_INFO (("Add callouts completed udi=%s", d->udi));
/* Move from temporary to global device store */
hal_device_store_remove (hald_get_tdl (), d);
@@ -1165,11 +1150,10 @@ end (ParsingContext * pc, const char *el
* '@prop.here.is.an.udi:with.prop.name'
*/
if (!resolve_udiprop_path (pc->cdata_buf,
- hal_device_get_udi (pc->device),
+ 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,
- hal_device_get_udi (pc->device)));
+ HAL_ERROR (("Could not resolve keypath '%s' on udi '%s'", pc->cdata_buf, pc->device->udi));
} else {
HalDevice *d;
@@ -1287,12 +1271,12 @@ end (ParsingContext * pc, const char *el
if (spawned == NULL) {
HAL_INFO (("Spawning new device object '%s' caused by <spawn> on udi '%s'",
- pc->merge_key, hal_device_get_udi (pc->device)));
+ pc->merge_key, pc->device->udi));
spawned = hal_device_new ();
hal_device_property_set_string (spawned, "info.bus", "unknown");
hal_device_property_set_string (spawned, "info.udi", pc->merge_key);
- hal_device_property_set_string (spawned, "info.parent", hal_device_get_udi (pc->device));
+ hal_device_property_set_string (spawned, "info.parent", pc->device->udi);
hal_device_set_udi (spawned, pc->merge_key);
hal_device_store_add (hald_get_tdl (), spawned);
@@ -1469,12 +1453,8 @@ out:
-static int
-#ifdef __GLIBC__
+static int
my_alphasort(const void *a, const void *b)
-#else
-my_alphasort(const struct dirent **a, const struct dirent **b)
-#endif
{
return -alphasort (a, b);
}
@@ -1500,7 +1480,7 @@ scan_fdi_files (const char *dir, HalDevi
num_entries = scandir (dir, &name_list, 0, my_alphasort);
if (num_entries == -1) {
- HAL_ERROR (("scandir failed for '%s' (errno=%d '%s')", dir, errno, strerror (errno)));
+ perror ("scandir");
return FALSE;
}
diff-tree ec7b3fc5f01a75dd749d05c70ba2a842c16d3c66 (from parents)
Merge: 74720d88576d7cf19947ec3fbe4b15e9d0e373a4 1a077e580cf552b09445c06e088bdb1982f3f052
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 17:45:12 2006 -0400
Merge branch 'master' of ssh://david@git.freedesktop.org/git/hal
diff-tree 74720d88576d7cf19947ec3fbe4b15e9d0e373a4 (from cf9f235164570bb6f6667822ccfca0e4c36b5580)
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 17:45:02 2006 -0400
switch running_processes to using a list + fix a few memory leaks
diff --git a/hald/hald.c b/hald/hald.c
index 71e73bd..c30ff76 100644
--- a/hald/hald.c
+++ b/hald/hald.c
@@ -371,7 +371,7 @@ main (int argc, char *argv[])
openlog ("hald", LOG_PID, LOG_DAEMON);
#ifdef HALD_MEMLEAK_DBG
- g_mem_set_vtable (glib_mem_profiler_table);
+ /*g_mem_set_vtable (glib_mem_profiler_table);*/
#endif
g_type_init ();
@@ -601,9 +601,9 @@ extern int dbg_hal_device_object_delta;
static gboolean
my_shutdown2 (gpointer data)
{
- g_mem_profile ();
- sleep (10000);
- /*exit (1);*/
+ /*g_mem_profile ();*/
+ /*sleep (10000);*/
+ exit (1);
return FALSE;
}
diff --git a/hald/hald_runner.c b/hald/hald_runner.c
index 7940065..32abd9c 100644
--- a/hald/hald_runner.c
+++ b/hald/hald_runner.c
@@ -64,31 +64,26 @@ typedef struct
gpointer data2;
} RunningProcess;
-/* mapping from PID to RunningProcess */
-static GHashTable *running_processes = NULL;
-
-static gboolean
-rprd_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- gboolean remove;
- RunningProcess *rp = value;
- HalDevice *device = user_data;
-
- if (device == NULL || rp->device == device) {
- remove = TRUE;
- g_free (rp);
- }
-
- return remove;
-}
+/* list of RunningProcess */
+static GSList *running_processes = NULL;
static void
running_processes_remove_device (HalDevice *device)
{
- if (running_processes != NULL) {
- g_hash_table_foreach_remove (running_processes, rprd_foreach, device);
+ GSList *i;
+ GSList *j;
+
+ for (i = running_processes; i != NULL; i = j) {
+ RunningProcess *rp;
+
+ j = g_slist_next (i);
+ rp = i->data;
+
+ if (rp->device == device) {
+ g_free (rp);
+ running_processes = g_slist_delete_link (running_processes, i);
+ }
+
}
}
@@ -119,18 +114,23 @@ runner_server_message_handler (DBusConne
if (dbus_message_get_args (message, &error,
DBUS_TYPE_INT64, &dpid,
DBUS_TYPE_INVALID)) {
- RunningProcess *rp;
+ GSList *i;
GPid pid;
pid = (GPid) dpid;
- if (running_processes != NULL) {
- /*HAL_INFO (("Previously started process with pid %d exited", pid));*/
- rp = g_hash_table_lookup (running_processes, (gpointer) pid);
- if (rp != NULL) {
+ HAL_INFO (("Previously started process with pid %d exited", pid));
+
+ for (i = running_processes; i != NULL; i = g_slist_next (i)) {
+ RunningProcess *rp;
+
+ rp = i->data;
+
+ if (rp->pid == pid) {
rp->cb (rp->device, 0, 0, NULL, rp->data1, rp->data2);
- g_hash_table_remove (running_processes, (gpointer) pid);
g_free (rp);
+ running_processes = g_slist_delete_link (running_processes, i);
+ break;
}
}
}
@@ -200,8 +200,11 @@ hald_runner_stop_runner (void)
DBusMessage *msg;
/* Don't care about running processes anymore */
- g_hash_table_foreach_remove (running_processes, rprd_foreach, NULL);
- g_hash_table_destroy (running_processes);
+
+ HAL_INFO (("running_processes %p, num = %d", running_processes, g_slist_length (running_processes)));
+
+ g_slist_foreach (running_processes, (GFunc) g_free, NULL);
+ g_slist_free (running_processes);
running_processes = NULL;
HAL_INFO (("Killing runner with pid %d", runner_pid));
@@ -235,7 +238,7 @@ hald_runner_start_runner(void)
const char *hald_runner_path;
char *server_address;
- running_processes = g_hash_table_new (g_direct_hash, g_direct_equal);
+ running_processes = NULL;
dbus_error_init(&err);
runner_server = dbus_server_listen(DBUS_SERVER_ADDRESS, &err);
@@ -446,7 +449,7 @@ hald_runner_start (HalDevice *device, co
if (dbus_message_get_args (reply, &err,
DBUS_TYPE_INT64, &pid_from_runner,
DBUS_TYPE_INVALID)) {
- if (cb != NULL && running_processes != NULL) {
+ if (cb != NULL) {
RunningProcess *rp;
rp = g_new0 (RunningProcess, 1);
rp->pid = (GPid) pid_from_runner;
@@ -455,7 +458,8 @@ hald_runner_start (HalDevice *device, co
rp->data1 = data1;
rp->data2 = data2;
- g_hash_table_insert (running_processes, (gpointer) rp->pid, rp);
+ running_processes = g_slist_prepend (running_processes, rp);
+ HAL_INFO (("running_processes %p, num = %d", running_processes, g_slist_length (running_processes)));
}
} else {
HAL_ERROR (("Error extracting out_pid from runner's Start()"));
diff --git a/hald/util.c b/hald/util.c
index 405cc23..a1e8197 100644
--- a/hald/util.c
+++ b/hald/util.c
@@ -932,10 +932,12 @@ hal_util_strdup_valid_utf8 (const char *
count++;
}
- if (strlen(newstr) == count)
+ if (strlen(newstr) == count) {
+ g_free (newstr);
return NULL;
- else
+ } else {
return newstr;
+ }
}
void
diff --git a/hald/valgrind-hald.sh b/hald/valgrind-hald.sh
index d9f3fec..2b6a8fe 100755
--- a/hald/valgrind-hald.sh
+++ b/hald/valgrind-hald.sh
@@ -13,4 +13,5 @@ export HAL_FDI_SOURCE_PREPROBE=.local-fd
export HAL_FDI_SOURCE_INFORMATION=.local-fdi/share/hal/fdi/information
export HAL_FDI_SOURCE_POLICY=.local-fdi/share/hal/fdi/policy
-valgrind --num-callers=20 --show-reachable=yes --leak-check=yes --tool=memcheck ./hald --daemon=no --verbose=yes $@
+#valgrind --num-callers=20 --show-reachable=yes --leak-check=yes --tool=memcheck ./hald --daemon=no --verbose=yes $@
+valgrind --show-reachable=yes --tool=memcheck --leak-check=full ./hald --daemon=no --verbose=yes $@
diff-tree cf9f235164570bb6f6667822ccfca0e4c36b5580 (from parents)
Merge: ef8985ccb67b0876156742d46d687f7f2174ec68 4e6f2c6c565374ad22cc9e0ba1d44479d020a86b
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 13:54:58 2006 -0400
Merge branch 'master' of ssh://david@git.freedesktop.org/git/hal
diff-tree ef8985ccb67b0876156742d46d687f7f2174ec68 (from dbffafacbf7b9143d82547b9eabe61d1a5b8fffc)
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 10 01:22:18 2006 -0400
free hash table before the private object to prevent segfault
diff --git a/hald/device.c b/hald/device.c
index 15b0d8f..e0b8a7b 100644
--- a/hald/device.c
+++ b/hald/device.c
@@ -37,7 +37,6 @@
#include "logger.h"
#include "hald_runner.h"
-
struct _HalProperty {
int type;
union {
@@ -382,10 +381,10 @@ hal_device_finalize (GObject *obj)
g_free (device->private->udi);
- g_free (device->private);
-
g_hash_table_destroy (device->private->props);
+ g_free (device->private);
+
if (parent_class->finalize)
parent_class->finalize (obj);
}
More information about the hal-commit
mailing list