]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
Add snapper dbus client example C code
authorDavid Disseldorp <ddiss@suse.de>
Tue, 2 Oct 2012 14:42:48 +0000 (16:42 +0200)
committerDavid Disseldorp <ddiss@suse.de>
Tue, 9 Oct 2012 14:08:29 +0000 (16:08 +0200)
Connect to snapperd over dbus and dispatch requests. Requests are
manually unmarshalled based on the response signature.
Currently only ListSnapshots and ListConfigs commands are supported.

configure.in
examples/C/.gitignore [new file with mode: 0644]
examples/C/Makefile.am [new file with mode: 0644]
examples/C/snapper_dbus_cli.c [new file with mode: 0644]
examples/Makefile.am

index bbdf04e729410a7b85a4f4a58c701082a2a90744..05b85dfbe1a30a18f98d88edcfd9da2d341fa78b 100644 (file)
@@ -69,6 +69,7 @@ AC_OUTPUT(
        Makefile
        snapper/Makefile
        examples/Makefile
+       examples/C/Makefile
        bindings/Makefile
        bindings/python/Makefile
        dbus/Makefile
diff --git a/examples/C/.gitignore b/examples/C/.gitignore
new file mode 100644 (file)
index 0000000..f3ef809
--- /dev/null
@@ -0,0 +1,2 @@
+csnap
+snapper_dbus_cli.o
diff --git a/examples/C/Makefile.am b/examples/C/Makefile.am
new file mode 100644 (file)
index 0000000..529ea72
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile.am for snapper/examples/C
+#
+
+INCLUDES = -I$(top_srcdir) -I/usr/include/dbus-1.0 -I$(libdir)/dbus-1.0/include
+
+noinst_PROGRAMS = csnap
+
+csnap_SOURCES =                                                \
+       snapper_dbus_cli.c
+
+csnap_LDADD = -ldbus-1
+
diff --git a/examples/C/snapper_dbus_cli.c b/examples/C/snapper_dbus_cli.c
new file mode 100644 (file)
index 0000000..60945d7
--- /dev/null
@@ -0,0 +1,749 @@
+/*
+ * Copyright (c) [2011-2012] Novell, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * 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, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+#include <dbus/dbus.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define CDBUS_SIG_LIST_SNAPS_RSP "a(uqutussa{ss})"
+#define CDBUS_SIG_LIST_CONFS_RSP "a(ssa{ss})"
+
+struct dict {
+       char *key;
+       char *val;
+};
+
+struct snap {
+       uint32_t id;
+       uint16_t type;
+       uint32_t pre_id;
+       uint64_t time;
+       uint32_t creator_uid;
+       char *desc;
+       char *cleanup;
+       uint32_t num_user_data;
+       struct dict *user_data;
+};
+
+struct config {
+       char *name;
+       char *mnt;
+       uint32_t num_attrs;
+       struct dict *attrs;
+};
+
+static DBusConnection *cdbus_conn(void)
+{
+       DBusError err;
+       DBusConnection *conn;
+
+       dbus_error_init(&err);
+
+       /* bus connection */
+       conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+       if (dbus_error_is_set(&err)) {
+               fprintf(stderr, "connection error: %s\n", err.message);
+               dbus_error_free(&err);
+       }
+       if (NULL == conn) {
+               return NULL;
+       }
+
+       return conn;
+}
+
+static int cdbus_msg_send(DBusConnection *conn,
+                         DBusMessage *msg,
+                         DBusPendingCall **pend_out)
+{
+       DBusPendingCall *pending;
+
+       /* send message and get a handle for a reply */
+       if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
+               return -ENOMEM;
+       }
+       if (NULL == pending) {
+               fprintf(stderr, "Pending Call Null\n");
+               return -EINVAL;
+       }
+
+       dbus_connection_flush(conn);
+       *pend_out = pending;
+
+       return 0;
+}
+
+static int cdbus_msg_recv(DBusConnection *conn,
+                         DBusPendingCall *pending,
+                         DBusMessage **msg_out)
+{
+       DBusMessage *msg;
+
+       /* block until we receive a reply */
+       dbus_pending_call_block(pending);
+
+       /* get the reply message */
+       msg = dbus_pending_call_steal_reply(pending);
+       if (msg == NULL) {
+               fprintf(stderr, "Reply Null\n");
+               return -ENOMEM;
+       }
+       /* free the pending message handle */
+       dbus_pending_call_unref(pending);
+       *msg_out = msg;
+
+       return 0;
+}
+
+
+static int cdbus_list_snaps_pack(char *snapper_conf,
+                                DBusMessage **req_msg_out)
+{
+       DBusMessage *msg;
+       DBusMessageIter args;
+
+       msg = dbus_message_new_method_call("org.opensuse.Snapper", /* target for the method call */
+                                          "/org/opensuse/Snapper", /* object to call on */
+                                          "org.opensuse.Snapper", /* interface to call on */
+                                          "ListSnapshots"); /* method name */
+       if (NULL == msg) {
+               fprintf(stderr, "Message Null\n");
+               return -ENOMEM;
+       }
+
+       /* append arguments */
+       dbus_message_iter_init_append(msg, &args);
+       if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,
+                                           &snapper_conf)) {
+               fprintf(stderr, "Out Of Memory!\n");
+               return -ENOMEM;
+       }
+
+       *req_msg_out = msg;
+
+       return 0;
+}
+
+static int cdbus_type_check(DBusMessageIter *iter, int expected_type)
+{
+       int type = dbus_message_iter_get_arg_type(iter);
+       if (type != expected_type) {
+               fprintf(stderr, "got type %d, expecting %d\n",
+                       type, expected_type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int cdbus_type_check_get(DBusMessageIter *iter, int expected_type,
+                               void *val)
+{
+       int ret;
+       ret = cdbus_type_check(iter, expected_type);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_get_basic(iter, val);
+
+       return 0;
+}
+
+static int dict_unpack(DBusMessageIter *iter,
+                      struct dict *dict_out)
+
+{
+       int ret;
+       DBusMessageIter dct_iter;
+
+       if (cdbus_type_check(iter, DBUS_TYPE_DICT_ENTRY) < 0) {
+               return -EINVAL;
+       }
+       dbus_message_iter_recurse(iter, &dct_iter);
+
+       ret = cdbus_type_check_get(&dct_iter, DBUS_TYPE_STRING, &dict_out->key);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&dct_iter);
+       ret = cdbus_type_check_get(&dct_iter, DBUS_TYPE_STRING, &dict_out->val);
+       if (ret < 0) {
+               return ret;
+       }
+
+       return 0;
+}
+
+static void dict_array_print(uint32_t num_dicts,
+                            struct dict *dicts)
+{
+       int i;
+
+       for (i = 0; i < num_dicts; i++) {
+               printf("dict (\n"
+                      "\tkey: %s\n"
+                      "\tval: %s\n"
+                      ")\n",
+                      dicts[i].key, dicts[i].val);
+       }
+}
+
+static int dict_array_unpack(DBusMessageIter *iter,
+                            uint32_t *num_dicts_out,
+                            struct dict **dicts_out)
+{
+       int ret;
+       DBusMessageIter array_iter;
+       uint32_t num_dicts;
+       struct dict *dicts = NULL;
+
+       if (cdbus_type_check(iter, DBUS_TYPE_ARRAY) < 0) {
+               return -EINVAL;
+       }
+       dbus_message_iter_recurse(iter, &array_iter);
+
+       num_dicts = 0;
+       while (dbus_message_iter_get_arg_type(&array_iter)
+                                                       != DBUS_TYPE_INVALID) {
+               num_dicts++;
+               dicts = realloc(dicts, sizeof(struct dict) * num_dicts);
+               if (dicts == NULL)
+                       abort();
+
+               ret = dict_unpack(&array_iter, &dicts[num_dicts - 1]);
+               if (ret < 0) {
+                       free(dicts);
+                       return ret;
+               }
+               dbus_message_iter_next(&array_iter);
+       }
+
+       *num_dicts_out = num_dicts;
+       *dicts_out = dicts;
+
+       return 0;
+}
+
+static int snap_struct_unpack(DBusMessageIter *iter,
+                             struct snap *snap_out)
+{
+       int ret;
+       DBusMessageIter st_iter;
+
+       if (cdbus_type_check(iter, DBUS_TYPE_STRUCT) < 0) {
+               return -EINVAL;
+       }
+       dbus_message_iter_recurse(iter, &st_iter);
+
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_UINT32,
+                               &snap_out->id);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_UINT16,
+                                  &snap_out->type);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_UINT32,
+                                  &snap_out->pre_id);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_UINT64,
+                                  &snap_out->time);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_UINT32,
+                                  &snap_out->creator_uid);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_STRING,
+                                  &snap_out->desc);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_STRING,
+                                  &snap_out->cleanup);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = dict_array_unpack(&st_iter, &snap_out->num_user_data,
+                               &snap_out->user_data);
+
+       return ret;
+}
+
+static void snap_array_free(int32_t num_snaps,
+                           struct snap *snaps)
+{
+       int i;
+
+       for (i = 0; i < num_snaps; i++) {
+               free(snaps[i].user_data);
+       }
+       free(snaps);
+}
+
+static void snap_array_print(int32_t num_snaps,
+                            struct snap *snaps)
+{
+       int i;
+
+       for (i = 0; i < num_snaps; i++) {
+               printf("id: %u\n"
+                      "type: %u\n"
+                      "pre_id: %u\n"
+                      "time: %lu\n"
+                      "creator_uid: %u\n"
+                      "desc: %s\n"
+                      "cleanup: %s\n",
+                      snaps[i].id,
+                      snaps[i].type,
+                      snaps[i].pre_id,
+                      snaps[i].time,
+                      snaps[i].creator_uid,
+                      snaps[i].desc,
+                      snaps[i].cleanup);
+               dict_array_print(snaps[i].num_user_data, snaps[i].user_data);
+               printf("---\n");
+       }
+}
+
+static int snap_array_unpack(DBusMessageIter *iter,
+                            uint32_t *num_snaps_out,
+                            struct snap **snaps_out)
+{
+       uint32_t num_snaps;
+       int ret;
+       struct snap *snaps = NULL;
+       DBusMessageIter array_iter;
+
+
+       if (cdbus_type_check(iter, DBUS_TYPE_ARRAY) < 0) {
+               return -EINVAL;
+       }
+       dbus_message_iter_recurse(iter, &array_iter);
+
+       num_snaps = 0;
+       while (dbus_message_iter_get_arg_type(&array_iter)
+                                                       != DBUS_TYPE_INVALID) {
+               num_snaps++;
+               snaps = realloc(snaps, sizeof(struct snap) * num_snaps);
+               if (snaps == NULL)
+                       abort();
+
+               ret = snap_struct_unpack(&array_iter, &snaps[num_snaps - 1]);
+               if (ret < 0) {
+                       free(snaps);
+                       return ret;
+               }
+               dbus_message_iter_next(&array_iter);
+       }
+
+       *num_snaps_out = num_snaps;
+       *snaps_out = snaps;
+
+       return 0;
+}
+
+static int cdbus_list_snaps_unpack(DBusConnection *conn,
+                                  DBusMessage *rsp_msg,
+                                  uint32_t *num_snaps_out,
+                                  struct snap **snaps_out)
+{
+       int ret;
+       DBusMessageIter iter;
+       int msg_type;
+       uint32_t num_snaps;
+       struct snap *snaps;
+       const char *sig;
+
+       msg_type = dbus_message_get_type(rsp_msg);
+       if (msg_type == DBUS_MESSAGE_TYPE_ERROR) {
+               fprintf(stderr, "list_snaps error response: %s\n",
+                       dbus_message_get_error_name(rsp_msg));
+               return -EINVAL;
+       }
+
+       if (msg_type != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+               fprintf(stderr, "unexpected list_snaps ret type: %d\n",
+                       msg_type);
+               return -EINVAL;
+       }
+
+       sig = dbus_message_get_signature(rsp_msg);
+       if ((sig == NULL)
+        || (strcmp(sig, CDBUS_SIG_LIST_SNAPS_RSP) != 0)) {
+               fprintf(stderr, "bad list snaps response sig: %s, "
+                               "expected: %s\n",
+                       (sig ? sig : "NULL"), CDBUS_SIG_LIST_SNAPS_RSP);
+               return -EINVAL;
+       }
+
+       /* read the parameters */
+       if (!dbus_message_iter_init(rsp_msg, &iter)) {
+               fprintf(stderr, "Message has no arguments!\n");
+               return -EINVAL;
+       }
+
+       ret = snap_array_unpack(&iter, &num_snaps, &snaps);
+       if (ret < 0) {
+               fprintf(stderr, "failed to unpack snap array\n");
+               return -EINVAL;
+       }
+
+       *num_snaps_out = num_snaps;
+       *snaps_out = snaps;
+
+       return 0;
+}
+
+static int cdbus_list_snaps_call(DBusConnection *conn)
+{
+       int ret;
+       DBusMessage *req_msg;
+       DBusMessage *rsp_msg;
+       DBusPendingCall *pending;
+       uint32_t num_snaps = 0;
+       struct snap *snaps = NULL;
+
+       ret = cdbus_list_snaps_pack("root", &req_msg);
+       if (ret < 0) {
+               fprintf(stderr, "failed to pack list snaps request\n");
+               return ret;
+       }
+
+       ret = cdbus_msg_send(conn, req_msg, &pending);
+       if (ret < 0) {
+               dbus_message_unref(req_msg);
+               return ret;
+       }
+
+       ret = cdbus_msg_recv(conn, pending, &rsp_msg);
+       if (ret < 0) {
+               dbus_message_unref(req_msg);
+               dbus_pending_call_unref(pending);
+               return ret;
+       }
+
+       ret = cdbus_list_snaps_unpack(conn, rsp_msg,
+                                     &num_snaps, &snaps);
+       if (ret < 0) {
+               fprintf(stderr, "failed to unpack list snaps response\n");
+               dbus_message_unref(req_msg);
+               dbus_message_unref(rsp_msg);
+               return ret;
+       }
+
+       snap_array_print(num_snaps, snaps);
+
+       snap_array_free(num_snaps, snaps);
+
+       dbus_message_unref(req_msg);
+       dbus_message_unref(rsp_msg);
+
+       return 0;
+}
+
+static int cdbus_list_confs_pack(DBusMessage **req_msg_out)
+{
+       DBusMessage *msg;
+
+       msg = dbus_message_new_method_call("org.opensuse.Snapper",
+                                          "/org/opensuse/Snapper",
+                                          "org.opensuse.Snapper",
+                                          "ListConfigs");
+       if (NULL == msg) {
+               fprintf(stderr, "Message Null\n");
+               return -ENOMEM;
+       }
+
+       /* no arguments to append */
+       *req_msg_out = msg;
+
+       return 0;
+}
+
+static int conf_struct_unpack(DBusMessageIter *iter,
+                             struct config *conf_out)
+{
+       int ret;
+       DBusMessageIter st_iter;
+
+       if (cdbus_type_check(iter, DBUS_TYPE_STRUCT) < 0) {
+               return -EINVAL;
+       }
+       dbus_message_iter_recurse(iter, &st_iter);
+
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_STRING,
+                                  &conf_out->name);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = cdbus_type_check_get(&st_iter, DBUS_TYPE_STRING,
+                                  &conf_out->mnt);
+       if (ret < 0) {
+               return ret;
+       }
+
+       dbus_message_iter_next(&st_iter);
+       ret = dict_array_unpack(&st_iter, &conf_out->num_attrs,
+                               &conf_out->attrs);
+
+       return ret;
+}
+
+static void conf_array_free(int32_t num_confs,
+                           struct config *confs)
+{
+       int i;
+
+       for (i = 0; i < num_confs; i++) {
+               free(confs[i].attrs);
+       }
+       free(confs);
+}
+
+static void conf_array_print(int32_t num_confs,
+                            struct config *confs)
+{
+       int i;
+
+       for (i = 0; i < num_confs; i++) {
+               printf("name: %s\n"
+                      "mnt: %s\n",
+                      confs[i].name, confs[i].mnt);
+               dict_array_print(confs[i].num_attrs, confs[i].attrs);
+               printf("---\n");
+       }
+}
+
+static int conf_array_unpack(DBusMessageIter *iter,
+                            uint32_t *num_confs_out,
+                            struct config **confs_out)
+{
+       uint32_t num_confs;
+       int ret;
+       struct config *confs = NULL;
+       DBusMessageIter array_iter;
+
+
+       if (cdbus_type_check(iter, DBUS_TYPE_ARRAY) < 0) {
+               return -EINVAL;
+       }
+       dbus_message_iter_recurse(iter, &array_iter);
+
+       num_confs = 0;
+       while (dbus_message_iter_get_arg_type(&array_iter)
+                                                       != DBUS_TYPE_INVALID) {
+               num_confs++;
+               confs = realloc(confs, sizeof(struct config) * num_confs);
+               if (confs == NULL)
+                       abort();
+
+               ret = conf_struct_unpack(&array_iter, &confs[num_confs - 1]);
+               if (ret < 0) {
+                       free(confs);
+                       return ret;
+               }
+               dbus_message_iter_next(&array_iter);
+       }
+
+       *num_confs_out = num_confs;
+       *confs_out = confs;
+
+       return 0;
+}
+
+static int cdbus_list_confs_unpack(DBusConnection *conn,
+                                  DBusMessage *rsp_msg,
+                                  uint32_t *num_confs_out,
+                                  struct config **confs_out)
+{
+       int ret;
+       DBusMessageIter iter;
+       int msg_type;
+       uint32_t num_confs;
+       struct config *confs;
+       const char *sig;
+
+       msg_type = dbus_message_get_type(rsp_msg);
+       if (msg_type == DBUS_MESSAGE_TYPE_ERROR) {
+               fprintf(stderr, "list_confs error response: %s\n",
+                       dbus_message_get_error_name(rsp_msg));
+               return -EINVAL;
+       }
+
+       if (msg_type != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+               fprintf(stderr, "unexpected list_confs ret type: %d\n",
+                       msg_type);
+               return -EINVAL;
+       }
+
+       sig = dbus_message_get_signature(rsp_msg);
+       if ((sig == NULL)
+        || (strcmp(sig, CDBUS_SIG_LIST_CONFS_RSP) != 0)) {
+               fprintf(stderr, "bad list confs response sig: %s, "
+                               "expected: %s\n",
+                       (sig ? sig : "NULL"), CDBUS_SIG_LIST_CONFS_RSP);
+               return -EINVAL;
+       }
+
+       if (!dbus_message_iter_init(rsp_msg, &iter)) {
+               /* FIXME return empty? */
+               fprintf(stderr, "Message has no arguments!\n");
+               return -EINVAL;
+       }
+
+       ret = conf_array_unpack(&iter, &num_confs, &confs);
+       if (ret < 0) {
+               fprintf(stderr, "failed to unpack conf array\n");
+               return -EINVAL;
+       }
+
+       *num_confs_out = num_confs;
+       *confs_out = confs;
+
+       return 0;
+}
+
+static int cdbus_list_confs_call(DBusConnection *conn)
+{
+       int ret;
+       DBusMessage *req_msg;
+       DBusMessage *rsp_msg;
+       DBusPendingCall *pending;
+       uint32_t num_confs = 0;
+       struct config *confs = NULL;
+       const char *sig;
+
+       ret = cdbus_list_confs_pack(&req_msg);
+       if (ret < 0) {
+               fprintf(stderr, "failed to pack list confs request\n");
+               return ret;
+       }
+
+       ret = cdbus_msg_send(conn, req_msg, &pending);
+       if (ret < 0) {
+               dbus_message_unref(req_msg);
+               return ret;
+       }
+
+       ret = cdbus_msg_recv(conn, pending, &rsp_msg);
+       if (ret < 0) {
+               dbus_message_unref(req_msg);
+               dbus_pending_call_unref(pending);
+               return ret;
+       }
+
+       sig = dbus_message_get_signature(rsp_msg);
+       if ((sig == NULL)
+        || (strcmp(sig, CDBUS_SIG_LIST_CONFS_RSP) != 0)) {
+               fprintf(stderr, "bad list confs response sig: %s, "
+                               "expected: %s\n",
+                       (sig ? sig : "NULL"), CDBUS_SIG_LIST_CONFS_RSP);
+               dbus_message_unref(req_msg);
+               dbus_message_unref(rsp_msg);
+               return -EINVAL;
+       }
+
+       ret = cdbus_list_confs_unpack(conn, rsp_msg,
+                                     &num_confs, &confs);
+       if (ret < 0) {
+               fprintf(stderr, "failed to unpack list confs response\n");
+               dbus_message_unref(req_msg);
+               dbus_message_unref(rsp_msg);
+               return ret;
+       }
+
+       conf_array_print(num_confs, confs);
+
+       conf_array_free(num_confs, confs);
+
+       dbus_message_unref(req_msg);
+       dbus_message_unref(rsp_msg);
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       DBusConnection *conn;
+       int ret = -EINVAL;
+
+       if (argc != 2) {
+               fprintf(stderr, "Syntax: %s <list_confs | list_snaps>\n",
+                       argv[0]);
+               return -EINVAL;
+       }
+
+       conn = cdbus_conn();
+       if (conn == NULL) {
+               fprintf(stderr, "connect failed\n");
+               return -ENOMEM;
+       }
+
+       if (!strcmp(argv[1], "list_confs")) {
+               ret = cdbus_list_confs_call(conn);
+       } else if (!strcmp(argv[1], "list_snaps")) {
+               ret = cdbus_list_snaps_call(conn);
+       } else {
+               fprintf(stderr, "Syntax: %s <list_confs | list_snaps>\n",
+                       argv[0]);
+               ret = -EINVAL;
+               goto err_conn_close;
+       }
+
+       if (ret < 0) {
+               fprintf(stderr, "%s call failed: %s\n",
+                       argv[1], strerror(-ret));
+       }
+
+err_conn_close:
+       dbus_connection_unref(conn);
+
+       return ret;
+}
index f0fe1b809c44caedd5c9f7478ef732c465051376..526c1852ce68c0c1f53fd6bed7cebd8bbdf9d149 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile.am for snapper/examples
 #
 
+SUBDIRS = C
+
 INCLUDES = -I$(top_srcdir)
 
 LDADD = ../snapper/libsnapper.la