summaryrefslogtreecommitdiffstats
path: root/src/realmd/rdcp_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/realmd/rdcp_util.c')
-rw-r--r--src/realmd/rdcp_util.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/src/realmd/rdcp_util.c b/src/realmd/rdcp_util.c
new file mode 100644
index 0000000..73ba17b
--- /dev/null
+++ b/src/realmd/rdcp_util.c
@@ -0,0 +1,311 @@
+#include "rdcp_util.h"
+#include "rdcp_dbus.h"
+
+#define VERBOSE
+
+void
+print_properties (GVariant *properties, gchar *format, ...)
+{
+ va_list args;
+ GVariantClass class;
+ GVariantIter iter;
+ GVariant *value;
+ gchar *key;
+ gchar *value_as_string;
+ gsize n_children, i;
+
+ if (format) {
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf("\n");
+ }
+
+ g_variant_iter_init (&iter, properties);
+ while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) {
+ class = g_variant_classify(value);
+
+ if (class == G_VARIANT_CLASS_ARRAY) {
+ n_children = g_variant_n_children(value);
+ if (n_children == 0) {
+ printf(" %s: []\n", key);
+
+ } else {
+ GVariant *child;
+
+ printf(" %s: [\n", key);
+ for (i = 0; i < n_children; i++) {
+ child = g_variant_get_child_value(value, i);
+ value_as_string = g_variant_print(child, TRUE);
+ printf(" %s", value_as_string);
+ g_free(value_as_string);
+ G_VARIANT_FREE(child);
+ if (i < n_children-1) {
+ printf("\n");
+ } else {
+ printf("]\n");
+ }
+ }
+ }
+ } else {
+ value_as_string = g_variant_print(value, TRUE);
+ printf(" %s: %s\n", key, value_as_string);
+ g_free(value_as_string);
+ }
+ }
+ printf("\n");
+}
+
+void
+print_paths(gchar **paths, gchar *format, ...) {
+ va_list args;
+ gchar *path, **pp;
+ int i, n_items;
+
+ pp = paths;
+ for (path = *pp++, n_items = 0; path; path = *pp++, n_items++);
+
+ if (format) {
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ }
+
+ printf(" [%d paths:]\n", n_items);
+
+ pp = paths;
+ for (path = *pp++, i = 0; path; path = *pp++, i++) {
+ printf(" path[%d]: %s\n", i, path);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * build_g_variant_options_from_KStringA
+ * @keys An array of dictionary keys.
+ * @values An array of dictionary values.
+ * @g_variant_return Pointer to location where GVariant will be returned,
+ * will be NULL if error.
+ * @g_error initialized to error info when FALSE is returned.
+ *
+ * Builds a GVariant dictionay of Realmd options.
+ *
+ * The keys and values in the dict are strings. The keys and values
+ * are passed as independent arrays, each value is paired with it's
+ * key by using the same index into keys and values array. It is an
+ * error if the length of the two arrays are not equal. If the length
+ * of the keys & values array is zero then the dictionary will be
+ * empty.
+ *
+ * If the option is not a string you must initialize the value for it
+ * as a string. The string value will be parsed and converted to the
+ * appropriate type for the option. Boolean values must be either
+ * "TRUE" or "FALSE" (case insensitive).
+ *
+ * Returns: return TRUE if successful, @g_variant_return will be non-NULL.
+ * FALSE if error with @g_error initialized, @g_variant_return will be NULL.
+ */
+gboolean
+build_g_variant_options_from_KStringA(const KStringA *keys, const KStringA *values,
+ GVariant **g_variant_return, GError **g_error)
+{
+ GVariantBuilder builder;
+ GVariant *g_variant;
+ CMPICount i, count;
+
+ g_return_val_if_fail (keys != NULL, FALSE);
+ g_return_val_if_fail (values != NULL, FALSE);
+ g_return_val_if_fail (g_variant_return != NULL, FALSE);
+ g_return_val_if_fail (g_error == NULL || *g_error == NULL, FALSE);
+
+ *g_variant_return = NULL;
+
+ if (keys->count != values->count) {
+ g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_INVALID_ARG,
+ "length of keys array (%d) != length of values array (%d)",
+ keys->count, values->count);
+ return FALSE;
+ }
+
+ count = keys->count;
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+
+ for (i = 0; i < count; i++) {
+ const char *key;
+ const char *value;
+
+ key = KStringA_Get((KStringA *)keys, i);
+ value = KStringA_Get((KStringA *)values, i);
+
+ if (g_str_equal(key, "assume-packages")) {
+ gboolean g_boolean;
+
+ if (g_ascii_strcasecmp(value, "true") == 0) {
+ g_boolean = TRUE;
+ } else if (g_ascii_strcasecmp(value, "false") == 0) {
+ g_boolean = FALSE;
+ } else {
+ g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_INVALID_ARG,
+ "invalid value for assume-packages option (%s), must be TRUE or FALSE", value);
+ g_variant_builder_clear(&builder);
+ return FALSE;
+ }
+ g_variant_builder_add_parsed (&builder, "{%s, <%b>}", key, g_boolean);
+ } else {
+ g_variant_builder_add_parsed (&builder, "{%s, <%s>}", key, value);
+ }
+ }
+
+ if ((g_variant = g_variant_builder_end(&builder)) == NULL) {
+ g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
+ "unable to build GVariant options array");
+ return FALSE;
+ }
+
+ *g_variant_return = g_variant;
+ return TRUE;
+}
+
+/**
+ * build_g_variant_string_array_from_KStringA:
+ * @values The KStringA source array
+ * @g_variant_return Pointer to location where GVariant will be returned,
+ * will be NULL if error.
+ * @g_error initialized to error info when FALSE is returned.
+ *
+ * Builds a GVariant array of strings "as" from a KStringA.
+ *
+ * Returns: return TRUE if successful, @g_variant_return will be non-NULL.
+ * FALSE if error with @g_error initialized, @g_variant_return will be NULL.
+ */
+gboolean
+build_g_variant_string_array_from_KStringA(const KStringA *values,
+ GVariant **g_variant_return, GError **g_error)
+{
+ GVariantBuilder builder;
+ GVariant *g_variant;
+ CMPICount i, count;
+
+ g_return_val_if_fail (values != NULL, FALSE);
+ g_return_val_if_fail (g_variant_return != NULL, FALSE);
+ g_return_val_if_fail (g_error == NULL || *g_error == NULL, FALSE);
+
+ *g_variant_return = NULL;
+
+ count = values->count;
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_STRING_ARRAY);
+
+ for (i = 0; i < count; i++) {
+ const char *value;
+
+ value = KStringA_Get((KStringA *)values, i);
+ g_variant_builder_add (&builder, "s", value);
+ }
+
+ if ((g_variant = g_variant_builder_end(&builder)) == NULL) {
+ g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
+ "unable to build GVariant options array");
+ return FALSE;
+ }
+
+ *g_variant_return = g_variant;
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * dbus_path_from_instance_id
+ * @instance_id A CIM Class InstanceID with a dbus_path encapsulated inside
+ * @dbus_path_return Pointer to location where DBus object path will be returned,
+ * will be NULL if error occurs. Must be freed with g_free()
+ * @g_error initialized to error info when FALSE is returned.
+ *
+ * CIM class instances bound to a DBus object embed the DBus object
+ * path into their InstanceID. This is one element contributing to the
+ * InstanceID's uniqueness. It also allows us to retrieve the DBus
+ * object path in order to operate on the matching DBus object.
+ *
+ * Returns: return TRUE if successful, FALSE if error with @g_error initialized
+ */
+gboolean
+dbus_path_from_instance_id(const char *instance_id, gchar **dbus_path_return, GError **g_error)
+{
+ gchar *dbus_path = NULL;
+
+ g_return_val_if_fail (instance_id != NULL, FALSE);
+ g_return_val_if_fail (dbus_path_return != NULL, FALSE);
+ g_return_val_if_fail (g_error == NULL || *g_error == NULL, FALSE);
+
+ *dbus_path_return = NULL;
+
+ if ((dbus_path = strchr(instance_id, ':')) != NULL) {
+ dbus_path++; /* skip ':' */
+ *dbus_path_return = g_strdup(dbus_path);
+ return TRUE;
+ } else {
+ g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_INVALID_INSTANCE_ID,
+ "could not locate DBus path in CIM InstanceID = \"%s\"",
+ instance_id);
+ return FALSE;
+ }
+}
+
+/**
+ * instance_id_from_dbus_path
+ * @dbus_path The DBus object path to encode in the CIM InstanceID
+ *
+ * Returns: InstanceID, must be freed with g_free()
+ */
+gchar *
+instance_id_from_dbus_path(const char *dbus_path)
+{
+ GString *g_instance_id = NULL;
+
+ g_instance_id = g_string_new(NULL);
+ g_string_printf(g_instance_id, "%s:%s", ORGID, dbus_path);
+ return g_string_free(g_instance_id, FALSE);
+}
+
+/**
+ * get_data_from_KUint8A
+ *
+ * @ka KUint8 Array containing binary data
+ * @size_return Length of the returned buffer is returned here if non-NULL.
+ *
+ * Binary data passed in a CMPI Uint8 array cannot be accessed as a
+ * pointer to the data. Instead each element of the array must be read
+ * and inserted into a contiguous buffer.
+ *
+ * Returns: data buffer, must be freed with g_free()
+ */
+gchar *
+get_data_from_KUint8A(const KUint8A *ka, gsize *size_return)
+{
+ gsize n_octets;
+ gchar *buffer, *p;
+ CMPICount count, i;
+ KUint8 octet;
+
+ count = ka->count;
+ n_octets = count;
+
+ if ((buffer = g_malloc(n_octets)) == NULL) {
+ if (size_return)
+ *size_return = 0;
+ return NULL;
+ }
+
+ for (i = 0, p = buffer; i < count; i++) {
+ octet = KUint8A_Get(ka, i);
+ *p++ = octet.value;
+ }
+
+ if (size_return)
+ *size_return = n_octets;
+
+ return buffer;
+}