#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; }