[RFC] Add persistent storage capability to HAL
Matthew Garrett
mjg59 at srcf.ucam.org
Thu Aug 17 14:52:56 PDT 2006
The attached patch adds the ability to save devices (optionally
recursively) and then reload them into HAL at a later stage. This is
useful for Bluetooth, where it's impractical to rediscover devices when
the device is no longer discoverable - instead, the device state should
be stored and recreated when the HCI is connected. Somewhat draft code,
but comments welcome.
--
Matthew Garrett | mjg59 at srcf.ucam.org
-------------- next part --------------
diff --git a/hald/linux2/probing/shared.h b/hald/linux2/probing/shared.h
index 3805b71..6202c35 100644
--- a/hald/linux2/probing/shared.h
+++ b/hald/linux2/probing/shared.h
@@ -171,4 +171,221 @@ out:
#endif
}
+void
+hal_save_device (const char *udi, gboolean recursive)
+{
+ LibHalPropertySet *properties;
+ LibHalPropertySetIterator iter;
+ DBusError error;
+ GKeyFile* keyfile;
+ const char *device = udi + 29; // Strip /org/freedesktop/Hal/devices/
+ const char *dirname = g_strdup_printf ("/var/lib/hal/persistent/%s",
+ device);
+ const char *filename = g_strdup_printf ("%s/properties", dirname);
+ gsize length;
+ char *data;
+
+ dbus_error_init (&error);
+
+ g_mkdir_with_parents (dirname, 0644);
+
+ properties = libhal_device_get_all_properties (ctx, udi, NULL);
+
+ keyfile = g_key_file_new ();
+
+ libhal_psi_init (&iter, properties);
+
+ for (libhal_psi_init (&iter, properties); libhal_psi_has_more (&iter);
+ libhal_psi_next (&iter)) {
+ char *type;
+ char *key;
+
+ key = libhal_psi_get_key (&iter);
+
+ switch (libhal_psi_get_type (&iter)) {
+ case LIBHAL_PROPERTY_TYPE_INVALID:
+ break;
+ case LIBHAL_PROPERTY_TYPE_INT32:
+ {
+ dbus_int32_t value = libhal_psi_get_int (&iter);
+ type = g_strdup_printf ("int32");
+ g_key_file_set_string (keyfile, key, "type", type);
+ g_key_file_set_integer (keyfile, key, "value", value);
+ break;
+ }
+ case LIBHAL_PROPERTY_TYPE_UINT64:
+ {
+ // FIXME - fails to deal with 64 bit values
+ dbus_uint64_t value = libhal_psi_get_uint64 (&iter);
+ type = g_strdup_printf ("uint64");
+ g_key_file_set_string (keyfile, key, "type", type);
+ g_key_file_set_integer (keyfile, key, "value", value);
+ break;
+ }
+ case LIBHAL_PROPERTY_TYPE_DOUBLE:
+ {
+ double value = libhal_psi_get_double (&iter);
+ type = g_strdup_printf ("double");
+ g_key_file_set_string (keyfile, key, "type", type);
+ g_key_file_set_double (keyfile, key, "value", value);
+ break;
+ }
+ case LIBHAL_PROPERTY_TYPE_BOOLEAN:
+ {
+ dbus_bool_t value = libhal_psi_get_bool (&iter);
+ type = g_strdup_printf ("bool");
+ g_key_file_set_string (keyfile, key, "type", type);
+ g_key_file_set_boolean (keyfile, key, "value", value);
+ break;
+ }
+ case LIBHAL_PROPERTY_TYPE_STRING:
+ {
+ char *value = libhal_psi_get_string (&iter);
+ type = g_strdup_printf ("string");
+ g_key_file_set_string (keyfile, key, "type", type);
+ g_key_file_set_string (keyfile, key, "value", value);
+ break;
+ }
+ case LIBHAL_PROPERTY_TYPE_STRLIST:
+ {
+ char **value = libhal_psi_get_strlist (&iter);
+ type = g_strdup_printf ("strlist");
+ g_key_file_set_string (keyfile, key, "type", type);
+ g_key_file_set_string_list (keyfile, key, "value",
+ value,
+ libhal_string_array_length (value));
+ break;
+ }
+ }
+
+ g_free (type);
+ }
+
+ libhal_free_property_set (properties);
+
+ /* This is a touch insane */
+
+ data = g_key_file_to_data (keyfile, &length, NULL);
+ g_file_set_contents (filename, data, length, NULL);
+ g_free (data);
+ g_key_file_free (keyfile);
+
+ if (recursive) {
+ int numchildren;
+ char **children;
+
+ children = libhal_manager_find_device_string_match (ctx, "info.parent",
+ udi, &numchildren,
+ &error);
+ if (numchildren) {
+ int i;
+ for (i=0; i<numchildren; i++) {
+ save_device (children[i], TRUE);
+ }
+ }
+ }
+}
+
+void
+hal_load_device (const char *udi, gboolean recursive)
+{
+ int i;
+ gsize numkeys;
+ GDir *dir;
+ DBusError error;
+ gchar **keys;
+ GKeyFile* keyfile = g_key_file_new ();
+ const char *device = udi + 29; // Strip /org/freedesktop/Hal/devices/
+ const char *dirname = g_strdup_printf ("/var/lib/hal/persistent/%s",
+ device);
+ const char *filename = g_strdup_printf ("%s/properties", dirname);
+
+ g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL);
+
+ keys = g_key_file_get_groups (keyfile, &numkeys);
+
+ dbus_error_init (&error);
+
+ if (!libhal_device_exists (ctx, udi, &error)) {
+ gchar *temp_udi = libhal_new_device (ctx, &error);
+ libhal_device_commit_to_gdl (ctx, temp_udi, udi, &error);
+ g_free (temp_udi);
+ }
+
+ for (i=0; i<numkeys; i++) {
+ gchar *type = g_key_file_get_string (keyfile, keys[i], "type",
+ NULL);
+ if (strcmp (type, "int32") == 0) {
+ libhal_device_set_property_int (ctx, udi, keys[i],
+ g_key_file_get_integer (keyfile,
+ keys[i],
+ "value",
+ NULL),
+ NULL);
+ }
+ else if (strcmp (type, "uint64") == 0) {
+ libhal_device_set_property_uint64 (ctx, udi, keys[i],
+ g_key_file_get_integer (keyfile,
+ keys[i],
+ "value",
+ NULL),
+ NULL);
+ }
+ else if (strcmp (type, "double") == 0) {
+ libhal_device_set_property_double (ctx, udi, keys[i],
+ g_key_file_get_double (keyfile,
+ keys[i],
+ "value",
+ NULL),
+ NULL);
+ }
+ else if (strcmp (type, "bool") == 0) {
+ libhal_device_set_property_bool (ctx, udi, keys[i],
+ g_key_file_get_boolean (keyfile,
+ keys[i],
+ "value",
+ NULL),
+ NULL);
+ }
+ else if (strcmp (type, "string") == 0) {
+ gchar *string = g_key_file_get_string (keyfile, keys[i], "value", NULL);
+ libhal_device_set_property_string (ctx, udi, keys[i], string,
+ NULL);
+ g_free (string);
+ }
+ else if (strcmp (type, "strlist") == 0) {
+ gsize length;
+ int j=0;
+ gchar **values = g_key_file_get_string_list (keyfile, keys[i], "value", &length, NULL);
+
+ while (values[j]) {
+ libhal_device_property_strlist_append (ctx, udi, keys[i], values[j], NULL);
+ j++;
+ }
+ }
+ }
+
+ g_key_file_free (keyfile);
+
+ if (!recursive)
+ return;
+
+ dir = g_dir_open (dirname, 0, NULL);
+ while ((filename = g_dir_read_name (dir))) {
+ gchar *new_dirname;
+
+ new_dirname = g_build_filename (dirname, filename, NULL);
+
+ if (g_file_test (new_dirname, G_FILE_TEST_IS_DIR)) {
+ gchar *new_dev;
+ new_dev = g_strdup_printf ("%s/%s", udi, filename);
+ load_device (new_dev, TRUE);
+ g_free (new_dev);
+ }
+ g_free (new_dirname);
+ }
+ g_dir_close (dir);
+}
+
+
#endif /* SHARED_H */
More information about the hal
mailing list