>From db0c97b024bd061eb0d4b35d08913392f01fb873 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Wed, 20 May 2015 14:45:25 +0200
Subject: [PATCH 4/4] IFP: Export nodes

IFP now exports cached users and groups in introspection.
---
 Makefile.am                         |   1 +
 src/responder/ifp/ifp_cache.c       |  78 ++++++++++++++++------
 src/responder/ifp/ifp_cache.h       |  10 ++-
 src/responder/ifp/ifp_iface_nodes.c | 129 ++++++++++++++++++++++++++++++++++++
 src/responder/ifp/ifp_private.h     |   2 +
 src/responder/ifp/ifpsrv.c          |   2 +
 6 files changed, 200 insertions(+), 22 deletions(-)
 create mode 100644 src/responder/ifp/ifp_iface_nodes.c

diff --git a/Makefile.am b/Makefile.am
index 41db53bc175500e38f982756f9f3f2953076906c..34c18ebbf8f75abee0200892c395c9601b570472 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1094,6 +1094,7 @@ sssd_ifp_SOURCES = \
     src/responder/ifp/ifp_iface_generated.c \
     src/responder/ifp/ifp_iface_generated.h \
     src/responder/ifp/ifp_iface.c \
+    src/responder/ifp/ifp_iface_nodes.c \
     src/responder/ifp/ifpsrv_util.c \
     src/responder/ifp/ifp_domains.c \
     src/responder/ifp/ifp_components.c \
diff --git a/src/responder/ifp/ifp_cache.c b/src/responder/ifp/ifp_cache.c
index 0d963b8dbdb82197e82aebda3cd647d9d1f32aa6..949c3f90320bf4238814d93eb4ddcf131bde7f2c 100644
--- a/src/responder/ifp/ifp_cache.c
+++ b/src/responder/ifp/ifp_cache.c
@@ -149,45 +149,43 @@ done:
     return ret;
 }
 
-int ifp_cache_list(struct sbus_request *sbus_req,
-                   void *data,
-                   enum ifp_cache_type type)
+errno_t ifp_cache_list_domains(TALLOC_CTX *mem_ctx,
+                               struct sss_domain_info *domains,
+                               enum ifp_cache_type type,
+                               const char ***_paths,
+                               int *_num_paths)
 {
-    DBusError *error;
+    TALLOC_CTX *tmp_ctx;
     struct sss_domain_info *domain;
-    struct ifp_ctx *ifp_ctx;
     const char **tmp_paths;
     int num_tmp_paths;
     const char **paths;
     int num_paths;
     errno_t ret;
 
-    ifp_ctx = talloc_get_type(data, struct ifp_ctx);
-    if (ifp_ctx == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
-        return ERR_INTERNAL;
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
     }
 
-    domain = ifp_ctx->rctx->domains;
+    domain = domains;
     num_paths = 0;
     paths = NULL;
     while (domain != NULL) {
-        ret = ifp_cache_get_cached_objects(sbus_req, type, domain,
+        ret = ifp_cache_get_cached_objects(tmp_ctx, type, domain,
                                            &tmp_paths, &num_tmp_paths);
         if (ret != EOK) {
-            error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
-                                   "Unable to build object list [%d]: %s\n",
-                                   ret, sss_strerror(ret));
-            return sbus_request_fail_and_finish(sbus_req, error);
+            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build object list "
+                  "[%d]: %s\n", ret, sss_strerror(ret));
+            goto done;
         }
 
-        ret = add_strings_lists(sbus_req, paths, tmp_paths, false,
+        ret = add_strings_lists(tmp_ctx, paths, tmp_paths, true,
                                 discard_const(&paths));
         if (ret != EOK) {
-            error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
-                                   "Unable to build object list [%d]: %s\n",
-                                   ret, sss_strerror(ret));
-            return sbus_request_fail_and_finish(sbus_req, error);
+            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build object list "
+                  "[%d]: %s\n", ret, sss_strerror(ret));
+            goto done;
         }
 
         num_paths += num_tmp_paths;
@@ -195,6 +193,46 @@ int ifp_cache_list(struct sbus_request *sbus_req,
         domain = get_next_domain(domain, true);
     }
 
+    if (_paths != NULL) {
+        *_paths = talloc_steal(mem_ctx, paths);
+    }
+
+    if (_num_paths != NULL) {
+        *_num_paths = num_paths;
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+int ifp_cache_list(struct sbus_request *sbus_req,
+                   void *data,
+                   enum ifp_cache_type type)
+{
+    DBusError *error;
+    struct ifp_ctx *ifp_ctx;
+    const char **paths;
+    int num_paths;
+    errno_t ret;
+
+    ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+    if (ifp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+        return ERR_INTERNAL;
+    }
+
+    ret = ifp_cache_list_domains(sbus_req, ifp_ctx->rctx->domains, type,
+                                 &paths, &num_paths);
+    if (ret != EOK) {
+        error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
+                               "Unable to build object list [%d]: %s\n",
+                               ret, sss_strerror(ret));
+        return sbus_request_fail_and_finish(sbus_req, error);
+    }
+
     iface_ifp_cache_List_finish(sbus_req, paths, num_paths);
 
     return EOK;
diff --git a/src/responder/ifp/ifp_cache.h b/src/responder/ifp/ifp_cache.h
index 56e90bb9c791d5f63d98e8e94b83f3695d88c742..eb16309543d938b94d8c8fde18bfb30709f8e975 100644
--- a/src/responder/ifp/ifp_cache.h
+++ b/src/responder/ifp/ifp_cache.h
@@ -24,13 +24,19 @@
 #include "responder/common/responder.h"
 #include "responder/ifp/ifp_iface_generated.h"
 
-/* org.freedesktop-sssd-infopipe.Cache */
-
 enum ifp_cache_type {
     IFP_CACHE_USER,
     IFP_CACHE_GROUP
 };
 
+errno_t ifp_cache_list_domains(TALLOC_CTX *mem_ctx,
+                               struct sss_domain_info *domains,
+                               enum ifp_cache_type type,
+                               const char ***_paths,
+                               int *_num_paths);
+
+/* org.freedesktop-sssd-infopipe.Cache */
+
 int ifp_cache_list(struct sbus_request *sbus_req,
                    void *data,
                    enum ifp_cache_type type);
diff --git a/src/responder/ifp/ifp_iface_nodes.c b/src/responder/ifp/ifp_iface_nodes.c
new file mode 100644
index 0000000000000000000000000000000000000000..ecb9ba32405b6a78904bcee70c02425c3bcc4cdd
--- /dev/null
+++ b/src/responder/ifp/ifp_iface_nodes.c
@@ -0,0 +1,129 @@
+/*
+    Authors:
+        Pavel Březina <pbrezina@redhat.com>
+
+    Copyright (C) 2015 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 "sbus/sssd_dbus.h"
+#include "responder/ifp/ifp_iface_generated.h"
+#include "responder/ifp/ifp_users.h"
+#include "responder/ifp/ifp_groups.h"
+#include "responder/ifp/ifp_cache.h"
+
+static const char **
+nodes_ifp(TALLOC_CTX *mem_ctx, const char *path, void *data)
+{
+    static const char *nodes[] = {"Users", "Groups", NULL};
+
+    return nodes;
+}
+
+static const char **
+nodes_cached_objects(TALLOC_CTX *mem_ctx,
+                     void *data,
+                     enum ifp_cache_type type,
+                     const char *prefix)
+{
+    TALLOC_CTX *tmp_ctx;
+    struct ifp_ctx *ifp_ctx;
+    const char **paths;
+    const char **nodes;
+    const char *node;
+    int num_paths;
+    errno_t ret;
+    int i;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
+        return NULL;
+    }
+
+    ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+    if (ifp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+        goto fail;
+    }
+
+    ret = ifp_cache_list_domains(tmp_ctx, ifp_ctx->rctx->domains,
+                                 type, &paths, &num_paths);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain cache objects list "
+              "[%d]: %s\n", ret, sss_strerror(ret));
+        goto fail;
+    }
+
+    nodes = talloc_zero_array(tmp_ctx, const char *, num_paths + 1);
+    if (nodes == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+        goto fail;
+    }
+
+    for (i = 0; i < num_paths; i++) {
+        node = sbus_opath_strip_prefix(paths[i], prefix);
+        nodes[i] = talloc_strdup(nodes, node);
+        if (nodes[i] == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
+            goto fail;
+        }
+    }
+
+    talloc_steal(mem_ctx, nodes);
+    talloc_free(tmp_ctx);
+
+    return nodes;
+
+fail:
+    talloc_free(tmp_ctx);
+    return NULL;
+}
+
+static const char **
+nodes_users(TALLOC_CTX *mem_ctx, const char *path, void *data)
+{
+    return nodes_cached_objects(mem_ctx, data, IFP_CACHE_USER,
+                                IFP_PATH_USERS "/");
+}
+
+static const char **
+nodes_groups(TALLOC_CTX *mem_ctx, const char *path, void *data)
+{
+    return nodes_cached_objects(mem_ctx, data, IFP_CACHE_GROUP,
+                                IFP_PATH_GROUPS "/");
+}
+
+struct nodes_map {
+    const char *path;
+    sbus_nodes_fn fn;
+};
+
+static struct nodes_map nodes_map[] = {
+    { IFP_PATH, nodes_ifp },
+    { IFP_PATH_USERS, nodes_users },
+    { IFP_PATH_GROUPS, nodes_groups },
+    { NULL, NULL}
+};
+
+void ifp_register_nodes(struct ifp_ctx *ctx, struct sbus_connection *conn)
+{
+    int i;
+
+    for (i = 0; nodes_map[i].path != NULL; i++) {
+        sbus_conn_register_nodes(conn, nodes_map[i].path,
+                                 nodes_map[i].fn, ctx);
+    }
+}
diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h
index 94c9a4b85e2db7fd100dd7ea0b664081d6ba322e..304e4dc535aac4215cf318a0bea845c161c5f079 100644
--- a/src/responder/ifp/ifp_private.h
+++ b/src/responder/ifp/ifp_private.h
@@ -49,6 +49,8 @@ struct ifp_ctx {
 errno_t ifp_register_sbus_interface(struct sbus_connection *conn,
                                     void *handler_data);
 
+void ifp_register_nodes(struct ifp_ctx *ctx, struct sbus_connection *conn);
+
 /* This is a throwaway method to ease the review of the patch.
  * It will be removed later */
 int ifp_ping(struct sbus_request *dbus_req, void *data);
diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
index f804ea1978b6b32590c67fa34e00f94008b7b423..631bcd266d7e06154dbf1f37f9f439119b2b8944 100644
--- a/src/responder/ifp/ifpsrv.c
+++ b/src/responder/ifp/ifpsrv.c
@@ -165,6 +165,8 @@ sysbus_init(TALLOC_CTX *mem_ctx,
         goto fail;
     }
 
+    ifp_register_nodes(pvt, system_bus->conn);
+
     *sysbus = system_bus;
     return EOK;
 
-- 
1.9.3

