summaryrefslogtreecommitdiffstats
path: root/src/lib/sifp/sss_sifp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/sifp/sss_sifp.c')
-rw-r--r--src/lib/sifp/sss_sifp.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/src/lib/sifp/sss_sifp.c b/src/lib/sifp/sss_sifp.c
new file mode 100644
index 000000000..0bf29075e
--- /dev/null
+++ b/src/lib/sifp/sss_sifp.c
@@ -0,0 +1,437 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2014 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <dbus/dbus.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/sifp/sss_sifp.h"
+#include "lib/sifp/sss_sifp_dbus.h"
+#include "lib/sifp/sss_sifp_private.h"
+
+#define DBUS_IFACE_PROP "org.freedesktop.DBus.Properties"
+
+static void * default_alloc(size_t size, void *pvt)
+{
+ return malloc(size);
+}
+
+static void default_free(void *ptr, void *pvt)
+{
+ free(ptr);
+}
+
+static DBusMessage * sss_sifp_create_prop_msg(const char *object_path,
+ const char *method)
+{
+ return sss_sifp_create_message(object_path, DBUS_IFACE_PROP, method);
+}
+
+sss_sifp_error
+sss_sifp_init(sss_sifp_ctx **_ctx)
+{
+ return sss_sifp_init_ex(NULL, default_alloc, default_free, _ctx);
+}
+
+sss_sifp_error
+sss_sifp_init_ex(void *alloc_pvt,
+ sss_sifp_alloc_func *alloc_func,
+ sss_sifp_free_func *free_func,
+ sss_sifp_ctx **_ctx)
+{
+ sss_sifp_ctx *ctx = NULL;
+ DBusConnection *conn = NULL;
+ DBusError dbus_error;
+ sss_sifp_error ret;
+
+ if (_ctx == NULL || alloc_func == NULL || free_func == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ dbus_error_init(&dbus_error);
+
+ ctx = alloc_func(sizeof(sss_sifp_ctx), alloc_pvt);
+ if (ctx == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ctx->conn = NULL;
+ ctx->alloc_fn = alloc_func;
+ ctx->free_fn = free_func;
+ ctx->alloc_pvt = alloc_pvt;
+ ctx->io_error = alloc_func(sizeof(DBusError), alloc_pvt);
+ if (ctx->io_error == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ dbus_error_init(ctx->io_error);
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
+ if (dbus_error_is_set(&dbus_error)) {
+ sss_sifp_set_io_error(ctx, &dbus_error);
+ ret = SSS_SIFP_IO_ERROR;
+ goto done;
+ }
+
+ ctx->conn = conn;
+ *_ctx = ctx;
+
+ ret = SSS_SIFP_OK;
+
+done:
+ if (ret != SSS_SIFP_OK) {
+ sss_sifp_free(&ctx);
+ }
+
+ dbus_error_free(&dbus_error);
+ return ret;
+}
+
+const char *
+sss_sifp_get_last_io_error_name(sss_sifp_ctx *ctx)
+{
+ if (ctx == NULL) {
+ return "Invalid sss_sifp context";
+ }
+
+ if (!dbus_error_is_set(ctx->io_error)) {
+ return NULL;
+ }
+
+ return ctx->io_error->name;
+}
+
+const char *
+sss_sifp_get_last_io_error_message(sss_sifp_ctx *ctx)
+{
+ if (ctx == NULL) {
+ return "Invalid sss_sifp context";
+ }
+
+ if (!dbus_error_is_set(ctx->io_error)) {
+ return NULL;
+ }
+
+ return ctx->io_error->message;
+}
+
+sss_sifp_error
+sss_sifp_fetch_attr(sss_sifp_ctx *ctx,
+ const char *object_path,
+ const char *interface,
+ const char *name,
+ sss_sifp_attr ***_attrs)
+{
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ dbus_bool_t bret;
+ sss_sifp_error ret;
+
+ if (ctx == NULL || object_path == NULL || interface == NULL
+ || name == NULL || _attrs == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ /* Message format:
+ * In: string:interface
+ * In: string:attribute
+ * Out: variant(misc:value)
+ */
+
+ msg = sss_sifp_create_prop_msg(object_path, "Get");
+ if (msg == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ bret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID);
+ if (!bret) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ret = sss_sifp_send_message(ctx, msg, &reply);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_parse_attr(ctx, name, reply, _attrs);
+
+done:
+ if (msg != NULL) {
+ dbus_message_unref(msg);
+ }
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_fetch_all_attrs(sss_sifp_ctx *ctx,
+ const char *object_path,
+ const char *interface,
+ sss_sifp_attr ***_attrs)
+{
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ dbus_bool_t bret;
+ sss_sifp_error ret;
+
+ if (ctx == NULL || object_path == NULL || interface == NULL
+ || _attrs == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ msg = sss_sifp_create_prop_msg(object_path, "GetAll");
+ if (msg == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ bret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_INVALID);
+ if (!bret) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ret = sss_sifp_send_message(ctx, msg, &reply);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_parse_attr_list(ctx, reply, _attrs);
+
+done:
+ if (msg != NULL) {
+ dbus_message_unref(msg);
+ }
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_fetch_object(sss_sifp_ctx *ctx,
+ const char *object_path,
+ const char *interface,
+ sss_sifp_object **_object)
+{
+ sss_sifp_object *object = NULL;
+ sss_sifp_attr **attrs = NULL;
+ const char *name = NULL;
+ sss_sifp_error ret;
+
+ if (ctx == NULL || object_path == NULL || interface == NULL
+ || _object == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ ret = sss_sifp_fetch_all_attrs(ctx, object_path, interface, &attrs);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_find_attr_as_string(attrs, "name", &name);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ object = _alloc_zero(ctx, sss_sifp_object, 1);
+ if (object == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ object->attrs = attrs;
+
+ object->name = sss_sifp_strdup(ctx, name);
+ if (object->name == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ object->object_path = sss_sifp_strdup(ctx, object_path);
+ if (object->object_path == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ object->interface = sss_sifp_strdup(ctx, interface);
+ if (object->interface == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ *_object = object;
+
+ ret = SSS_SIFP_OK;
+
+done:
+ if (ret != SSS_SIFP_OK) {
+ sss_sifp_free_object(ctx, &object);
+ }
+
+ return ret;
+}
+
+void
+sss_sifp_free(sss_sifp_ctx **_ctx)
+{
+ sss_sifp_ctx *ctx = NULL;
+
+ if (_ctx == NULL || *_ctx == NULL) {
+ return;
+ }
+
+ ctx = *_ctx;
+
+ if (ctx->conn != NULL) {
+ dbus_connection_unref(ctx->conn);
+ }
+
+ if (ctx->io_error != NULL) {
+ dbus_error_free(ctx->io_error);
+ _free(ctx, ctx->io_error);
+ }
+
+ _free(ctx, ctx);
+ *_ctx = NULL;
+
+ return;
+}
+
+void
+sss_sifp_free_attrs(sss_sifp_ctx *ctx,
+ sss_sifp_attr ***_attrs)
+{
+ sss_sifp_attr **attrs = NULL;
+ unsigned int i, j;
+
+ if (_attrs == NULL || *_attrs == NULL) {
+ return;
+ }
+
+ attrs = *_attrs;
+
+ for (i = 0; attrs[i] != NULL; i++) {
+ switch (attrs[i]->type) {
+ case SSS_SIFP_ATTR_TYPE_BOOL:
+ _free(ctx, attrs[i]->data.boolean);
+ break;
+ case SSS_SIFP_ATTR_TYPE_INT16:
+ _free(ctx, attrs[i]->data.int16);
+ break;
+ case SSS_SIFP_ATTR_TYPE_UINT16:
+ _free(ctx, attrs[i]->data.uint16);
+ break;
+ case SSS_SIFP_ATTR_TYPE_INT32:
+ _free(ctx, attrs[i]->data.int32);
+ break;
+ case SSS_SIFP_ATTR_TYPE_UINT32:
+ _free(ctx, attrs[i]->data.uint32);
+ break;
+ case SSS_SIFP_ATTR_TYPE_INT64:
+ _free(ctx, attrs[i]->data.int64);
+ break;
+ case SSS_SIFP_ATTR_TYPE_UINT64:
+ _free(ctx, attrs[i]->data.uint64);
+ break;
+ case SSS_SIFP_ATTR_TYPE_STRING:
+ for (j = 0; j < attrs[i]->num_values; j++) {
+ _free(ctx, attrs[i]->data.str[j]);
+ }
+ _free(ctx, attrs[i]->data.str);
+ break;
+ }
+ _free(ctx, attrs[i]->name);
+ _free(ctx, attrs[i]);
+ }
+
+ _free(ctx, attrs);
+
+ *_attrs = NULL;
+}
+
+void
+sss_sifp_free_object(sss_sifp_ctx *ctx,
+ sss_sifp_object **_object)
+{
+ sss_sifp_object *object = NULL;
+
+ if (_object == NULL || *_object == NULL) {
+ return;
+ }
+
+ object = *_object;
+
+ sss_sifp_free_attrs(ctx, &object->attrs);
+ _free(ctx, object->object_path);
+ _free(ctx, object->interface);
+ _free(ctx, object->name);
+ _free(ctx, object);
+
+ *_object = NULL;
+}
+
+void
+sss_sifp_free_string(sss_sifp_ctx *ctx,
+ char **_str)
+{
+ if (_str == NULL || *_str == NULL) {
+ return;
+ }
+
+ _free(ctx, *_str);
+
+ *_str = NULL;
+}
+
+void
+sss_sifp_free_string_array(sss_sifp_ctx *ctx,
+ char ***_str_array)
+{
+ char **str_array = NULL;
+ int i;
+
+ if (_str_array == NULL || *_str_array == NULL) {
+ return;
+ }
+
+ str_array = *_str_array;
+
+ for (i = 0; str_array[i] != NULL; i++) {
+ _free(ctx, str_array[i]);
+ }
+
+ _free(ctx, str_array);
+
+ *_str_array = NULL;
+}