chiark / gitweb /
kdbus: make name acquirement ioctls valgrind clean
[elogind.git] / src / libsystemd-bus / bus-control.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <stddef.h>
27 #include <errno.h>
28
29 #include "strv.h"
30
31 #include "sd-bus.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-control.h"
35
36 int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
37         int r;
38
39         if (!bus)
40                 return -EINVAL;
41         if (!unique)
42                 return -EINVAL;
43
44         r = bus_ensure_running(bus);
45         if (r < 0)
46                 return r;
47
48         *unique = bus->unique_name;
49         return 0;
50 }
51
52 int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
53         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
54         uint32_t ret;
55         int r;
56
57         if (!bus)
58                 return -EINVAL;
59         if (!name)
60                 return -EINVAL;
61         if (!bus->bus_client)
62                 return -EINVAL;
63
64         if (bus->is_kernel) {
65                 struct kdbus_cmd_name *n;
66                 size_t l;
67
68                 l = strlen(name);
69                 n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
70                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
71                 n->name_flags = flags;
72                 n->id = 0;
73                 memcpy(n->name, name, l+1);
74
75 #ifdef HAVE_VALGRIND_MEMCHECK_H
76                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
77 #endif
78
79                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
80                 if (r < 0)
81                         return -errno;
82
83                 return n->name_flags;
84         } else {
85                 r = sd_bus_call_method(
86                                 bus,
87                                 "org.freedesktop.DBus",
88                                 "/",
89                                 "org.freedesktop.DBus",
90                                 "RequestName",
91                                 NULL,
92                                 &reply,
93                                 "su",
94                                 name,
95                                 flags);
96                 if (r < 0)
97                         return r;
98
99                 r = sd_bus_message_read(reply, "u", &ret);
100                 if (r < 0)
101                         return r;
102
103                 return ret;
104         }
105 }
106
107 int sd_bus_release_name(sd_bus *bus, const char *name) {
108         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
109         uint32_t ret;
110         int r;
111
112         if (!bus)
113                 return -EINVAL;
114         if (!name)
115                 return -EINVAL;
116         if (!bus->bus_client)
117                 return -EINVAL;
118
119         if (bus->is_kernel) {
120                 struct kdbus_cmd_name *n;
121                 size_t l;
122
123                 l = strlen(name);
124                 n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
125                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
126                 n->name_flags = 0;
127                 n->id = 0;
128                 memcpy(n->name, name, l+1);
129
130 #ifdef HAVE_VALGRIND_MEMCHECK_H
131                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
132 #endif
133                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
134                 if (r < 0)
135                         return -errno;
136
137                 return n->name_flags;
138         } else {
139                 r = sd_bus_call_method(
140                                 bus,
141                                 "org.freedesktop.DBus",
142                                 "/",
143                                 "org.freedesktop.DBus",
144                                 "ReleaseName",
145                                 NULL,
146                                 &reply,
147                                 "s",
148                                 name);
149                 if (r < 0)
150                         return r;
151
152                 r = sd_bus_message_read(reply, "u", &ret);
153                 if (r < 0)
154                         return r;
155         }
156
157         return ret;
158 }
159
160 int sd_bus_list_names(sd_bus *bus, char ***l) {
161         _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
162         char **x = NULL;
163         int r;
164
165         if (!bus)
166                 return -EINVAL;
167         if (!l)
168                 return -EINVAL;
169
170         r = sd_bus_call_method(
171                         bus,
172                         "org.freedesktop.DBus",
173                         "/",
174                         "org.freedesktop.DBus",
175                         "ListNames",
176                         NULL,
177                         &reply1,
178                         NULL);
179         if (r < 0)
180                 return r;
181
182         r = sd_bus_call_method(
183                         bus,
184                         "org.freedesktop.DBus",
185                         "/",
186                         "org.freedesktop.DBus",
187                         "ListActivatableNames",
188                         NULL,
189                         &reply2,
190                         NULL);
191         if (r < 0)
192                 return r;
193
194         r = bus_message_read_strv_extend(reply1, &x);
195         if (r < 0) {
196                 strv_free(x);
197                 return r;
198         }
199
200         r = bus_message_read_strv_extend(reply2, &x);
201         if (r < 0) {
202                 strv_free(x);
203                 return r;
204         }
205
206         *l = strv_uniq(x);
207         return 0;
208 }
209
210 int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
211         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
212         const char *found;
213         int r;
214
215         if (!bus)
216                 return -EINVAL;
217         if (!name)
218                 return -EINVAL;
219
220         r = sd_bus_call_method(
221                         bus,
222                         "org.freedesktop.DBus",
223                         "/",
224                         "org.freedesktop.DBus",
225                         "GetNameOwner",
226                         NULL,
227                         &reply,
228                         "s",
229                         name);
230         if (r < 0)
231                 return r;
232
233         r = sd_bus_message_read(reply, "s", &found);
234         if (r < 0)
235                 return r;
236
237         if (owner) {
238                 char *t;
239
240                 t = strdup(found);
241                 if (!t)
242                         return -ENOMEM;
243
244                 *owner = t;
245         }
246
247         return 0;
248 }
249
250 int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
251         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
252         uint32_t u;
253         int r;
254
255         if (!bus)
256                 return -EINVAL;
257         if (!name)
258                 return -EINVAL;
259         if (!uid)
260                 return -EINVAL;
261
262         r = sd_bus_call_method(
263                         bus,
264                         "org.freedesktop.DBus",
265                         "/",
266                         "org.freedesktop.DBus",
267                         "GetConnectionUnixUser",
268                         NULL,
269                         &reply,
270                         "s",
271                         name);
272         if (r < 0)
273                 return r;
274
275         r = sd_bus_message_read(reply, "u", &u);
276         if (r < 0)
277                 return r;
278
279         *uid = (uid_t) u;
280         return 0;
281 }
282
283 int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
284         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
285         uint32_t u;
286         int r;
287
288         if (!bus)
289                 return -EINVAL;
290         if (!name)
291                 return -EINVAL;
292         if (!pid)
293                 return -EINVAL;
294
295         r = sd_bus_call_method(
296                         bus,
297                         "org.freedesktop.DBus",
298                         "/",
299                         "org.freedesktop.DBus",
300                         "GetConnectionUnixProcessID",
301                         NULL,
302                         &reply,
303                         "s",
304                         name);
305         if (r < 0)
306                 return r;
307
308         r = sd_bus_message_read(reply, "u", &u);
309         if (r < 0)
310                 return r;
311
312         if (u == 0)
313                 return -EIO;
314
315         *pid = (uid_t) u;
316         return 0;
317 }
318
319 int bus_add_match_internal(sd_bus *bus, const char *match) {
320         assert(bus);
321         assert(match);
322
323         return sd_bus_call_method(
324                         bus,
325                         "org.freedesktop.DBus",
326                         "/",
327                         "org.freedesktop.DBus",
328                         "AddMatch",
329                         NULL,
330                         NULL,
331                         "s",
332                         match);
333 }
334
335 int bus_remove_match_internal(sd_bus *bus, const char *match) {
336         assert(bus);
337         assert(match);
338
339         return sd_bus_call_method(
340                         bus,
341                         "org.freedesktop.DBus",
342                         "/",
343                         "org.freedesktop.DBus",
344                         "RemoveMatch",
345                         NULL,
346                         NULL,
347                         "s",
348                         match);
349 }