>From 3b2f3727fbdd738d631cd16d520ee83f04ef1c01 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Tue, 15 Apr 2014 15:29:44 +0200
Subject: [PATCH 03/11] SBUS: Add a convenience function sbus_error_new

Adds a convenience function that constructs a DBusError on top of a talloc
context and as such can be used to mark an sbus request as failed without
having to create a DBusError instance by the caller.
---
 src/sbus/sssd_dbus.h         | 16 ++++++++++++++++
 src/sbus/sssd_dbus_request.c | 27 +++++++++++++++++++++++++++
 src/tests/sbus_tests.c       | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)

diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 3bf70c8cceaeed45d57dad802d196c931d7f030d..0fd499cbe90e7163ca87ff1fefe7f97471468470 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -27,6 +27,7 @@ struct sbus_interface;
 struct sbus_request;
 
 #include <dbus/dbus.h>
+#include "util/util.h"
 
 typedef int (*sbus_msg_handler_fn)(struct sbus_request *dbus_req,
                                    void *instance_data);
@@ -253,6 +254,21 @@ int sbus_request_fail_and_finish(struct sbus_request *dbus_req,
                                  const DBusError *error);
 
 /*
+ * Construct a new DBusError instance which can be consumed by functions such
+ * as @sbus_request_fail_and_finish().
+ *
+ * The @error is a string constant representing a DBus error as documented at
+ * http://dbus.freedesktop.org/doc/api/html/group__DBusProtocol.html.
+ * The parameter @err_msg is a human-readable error representation (or
+ * NULL for none). The returned DBusError is a talloc context and the err_msg
+ * is duplicated using the returned DBusError instance as a talloc parent.
+ */
+DBusError *sbus_error_new(TALLOC_CTX *mem_ctx,
+                          const char *dbus_err_name,
+                          const char *fmt,
+                          ...) SSS_ATTRIBUTE_PRINTF(3,4);
+
+/*
  * Parse a DBus method call request.
  *
  * If parsing the method call message does not succeed, then an error is
diff --git a/src/sbus/sssd_dbus_request.c b/src/sbus/sssd_dbus_request.c
index d8b189095d26c9cd5f951e23e892571cb0c9375c..0021ce0e9e1e102b99c11fea3fc67669c3dac88e 100644
--- a/src/sbus/sssd_dbus_request.c
+++ b/src/sbus/sssd_dbus_request.c
@@ -143,6 +143,33 @@ int sbus_request_fail_and_finish(struct sbus_request *dbus_req,
     return ret;
 }
 
+DBusError *sbus_error_new(TALLOC_CTX *mem_ctx,
+                          const char *dbus_err_name,
+                          const char *fmt,
+                          ...)
+{
+    DBusError *dberr;
+    const char *err_msg_dup = NULL;
+    va_list ap;
+
+    dberr = talloc(mem_ctx, DBusError);
+    if (dberr == NULL) return NULL;
+
+    if (fmt) {
+        va_start(ap, fmt);
+        err_msg_dup = talloc_vasprintf(dberr, fmt, ap);
+        va_end(ap);
+        if (err_msg_dup == NULL) {
+            talloc_free(dberr);
+            return NULL;
+        }
+    }
+
+    dbus_error_init(dberr);
+    dbus_set_error_const(dberr, dbus_err_name, err_msg_dup);
+    return dberr;
+}
+
 struct array_arg {
     char **dbus_array;
 };
diff --git a/src/tests/sbus_tests.c b/src/tests/sbus_tests.c
index 1a6354ab5a70de196d8ed3509ab7c77d2bc90446..30b713530551ad5b3911accac087af47e03c0c78 100644
--- a/src/tests/sbus_tests.c
+++ b/src/tests/sbus_tests.c
@@ -326,6 +326,37 @@ START_TEST(test_introspection)
 }
 END_TEST
 
+START_TEST(test_sbus_new_error)
+{
+    TALLOC_CTX *ctx;
+    DBusError *error;
+
+    ctx = talloc_new(NULL);
+
+    error = sbus_error_new(ctx, DBUS_ERROR_IO_ERROR, "Input-output error");
+    ck_assert(error != NULL);
+    ck_assert(dbus_error_is_set(error));
+    ck_assert(dbus_error_has_name(error, DBUS_ERROR_IO_ERROR));
+    talloc_free(error);
+
+    error = sbus_error_new(ctx, DBUS_ERROR_IO_ERROR,
+                           "The answer should have been %d", 42);
+    ck_assert(error != NULL);
+    ck_assert(dbus_error_is_set(error));
+    ck_assert(dbus_error_has_name(error, DBUS_ERROR_IO_ERROR));
+    talloc_free(error);
+
+    /* NULL message must also work */
+    error = sbus_error_new(ctx, DBUS_ERROR_IO_ERROR, NULL);
+    ck_assert(error != NULL);
+    ck_assert(dbus_error_is_set(error));
+    ck_assert(dbus_error_has_name(error, DBUS_ERROR_IO_ERROR));
+    talloc_free(error);
+
+    talloc_free(ctx);
+}
+END_TEST
+
 TCase *create_sbus_tests(void)
 {
     TCase *tc = tcase_create("tests");
@@ -334,6 +365,7 @@ TCase *create_sbus_tests(void)
     tcase_add_test(tc, test_request_parse_ok);
     tcase_add_test(tc, test_request_parse_bad_args);
     tcase_add_test(tc, test_introspection);
+    tcase_add_test(tc, test_sbus_new_error);
 
     return tc;
 }
-- 
1.9.0

