Line data Source code
1 : /*
2 : * Copyright (C) 2018 Red Hat, Inc.
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Lesser General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2.1 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Lesser General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public
15 : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 : *
17 : * Author: Vojtech Trefny <vtrefny@redhat.com>
18 : */
19 :
20 : #include <glib.h>
21 : #include <gio/gio.h>
22 :
23 : #include "dbus.h"
24 :
25 : #define DBUS_TOP_IFACE "org.freedesktop.DBus"
26 : #define DBUS_TOP_OBJ "/org/freedesktop/DBus"
27 : #define DBUS_PROPS_IFACE "org.freedesktop.DBus.Properties"
28 : #define DBUS_INTRO_IFACE "org.freedesktop.DBus.Introspectable"
29 :
30 :
31 : /**
32 : * bd_utils_dbus_error_quark: (skip)
33 : */
34 0 : GQuark bd_utils_dbus_error_quark (void)
35 : {
36 0 : return g_quark_from_static_string ("g-bd-utils-dbus-error-quark");
37 : }
38 :
39 : /**
40 : * bd_utils_dbus_service_available:
41 : * @connection: (nullable): existing GDBusConnection or %NULL
42 : * @bus_type: bus type (system or session), ignored if @connection is specified
43 : * @bus_name: name of the service to check (e.g. "com.redhat.lvmdbus1")
44 : * @obj_prefix: object path prefix for the service (e.g. "/com/redhat/lvmdbus1")
45 : * @error: (out) (optional): place to store error (if any)
46 : *
47 : * Returns: whether the service was found in the system
48 : */
49 10 : gboolean bd_utils_dbus_service_available (GDBusConnection *connection, GBusType bus_type, const gchar *bus_name, const gchar *obj_prefix, GError **error) {
50 10 : GVariant *ret = NULL;
51 10 : GVariant *real_ret = NULL;
52 : GVariantIter iter;
53 10 : GVariant *service = NULL;
54 10 : gboolean found = FALSE;
55 10 : GDBusConnection *bus = NULL;
56 :
57 10 : if (connection)
58 0 : bus = g_object_ref (connection);
59 : else {
60 10 : bus = g_bus_get_sync (bus_type, NULL, error);
61 10 : if (!bus) {
62 0 : g_prefix_error (error, "Failed to get system bus: ");
63 0 : return FALSE;
64 : }
65 :
66 10 : ret = g_dbus_connection_call_sync (bus, DBUS_TOP_IFACE, DBUS_TOP_OBJ, DBUS_TOP_IFACE,
67 : "ListNames", NULL, NULL, G_DBUS_CALL_FLAGS_NONE,
68 : -1, NULL, error);
69 10 : if (!ret) {
70 0 : g_object_unref (bus);
71 0 : return FALSE;
72 : }
73 : }
74 :
75 10 : real_ret = g_variant_get_child_value (ret, 0);
76 10 : g_variant_unref (ret);
77 :
78 10 : g_variant_iter_init (&iter, real_ret);
79 803 : while (!found && (service = g_variant_iter_next_value (&iter))) {
80 793 : found = (g_strcmp0 (g_variant_get_string (service, NULL), bus_name) == 0);
81 793 : g_variant_unref (service);
82 : }
83 10 : g_variant_unref (real_ret);
84 :
85 10 : ret = g_dbus_connection_call_sync (bus, DBUS_TOP_IFACE, DBUS_TOP_OBJ, DBUS_TOP_IFACE,
86 : "ListActivatableNames", NULL, NULL, G_DBUS_CALL_FLAGS_NONE,
87 : -1, NULL, error);
88 10 : if (!ret) {
89 0 : g_object_unref (bus);
90 0 : return FALSE;
91 : }
92 :
93 10 : real_ret = g_variant_get_child_value (ret, 0);
94 10 : g_variant_unref (ret);
95 :
96 10 : g_variant_iter_init (&iter, real_ret);
97 13 : while (!found && (service = g_variant_iter_next_value (&iter))) {
98 3 : found = (g_strcmp0 (g_variant_get_string (service, NULL), bus_name) == 0);
99 3 : g_variant_unref (service);
100 : }
101 10 : g_variant_unref (real_ret);
102 :
103 10 : if (!found) {
104 0 : g_object_unref (bus);
105 0 : return FALSE;
106 : }
107 :
108 : /* try to introspect the root node - i.e. check we can access it and possibly
109 : autostart the service */
110 10 : ret = g_dbus_connection_call_sync (bus, bus_name, obj_prefix, DBUS_INTRO_IFACE,
111 : "Introspect", NULL, NULL, G_DBUS_CALL_FLAGS_NONE,
112 : -1, NULL, error);
113 10 : if (!ret) {
114 0 : g_object_unref (bus);
115 0 : return FALSE;
116 : }
117 :
118 10 : g_variant_unref (ret);
119 10 : g_object_unref (bus);
120 10 : return TRUE;
121 : }
|