]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-server.c
tmpfiles: accurately report creation results
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-server.c
CommitLineData
11c4c249
LP
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#include <assert.h>
23#include <stdlib.h>
24#include <pthread.h>
25#include <unistd.h>
26#include <fcntl.h>
27
28#include "log.h"
29#include "util.h"
30#include "macro.h"
31
32#include "sd-bus.h"
33#include "bus-internal.h"
34#include "bus-message.h"
40ca29a1 35#include "bus-util.h"
11c4c249
LP
36
37struct context {
38 int fds[2];
39
40 bool client_negotiate_unix_fds;
41 bool server_negotiate_unix_fds;
42
43 bool client_anonymous_auth;
44 bool server_anonymous_auth;
45};
46
47static void *server(void *p) {
48 struct context *c = p;
49 sd_bus *bus = NULL;
50 sd_id128_t id;
51 bool quit = false;
52 int r;
53
54 assert_se(sd_id128_randomize(&id) >= 0);
55
56 assert_se(sd_bus_new(&bus) >= 0);
e82c9509 57 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
11c4c249 58 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
11c4c249 59 assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
264ad849 60 assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
11c4c249
LP
61 assert_se(sd_bus_start(bus) >= 0);
62
63 while (!quit) {
64 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
65
66 r = sd_bus_process(bus, &m);
67 if (r < 0) {
da927ba9 68 log_error_errno(r, "Failed to process requests: %m");
11c4c249
LP
69 goto fail;
70 }
71
72 if (r == 0) {
73 r = sd_bus_wait(bus, (uint64_t) -1);
74 if (r < 0) {
da927ba9 75 log_error_errno(r, "Failed to wait: %m");
11c4c249
LP
76 goto fail;
77 }
78
79 continue;
80 }
81
82 if (!m)
83 continue;
84
85 log_info("Got message! member=%s", strna(sd_bus_message_get_member(m)));
86
87 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
88
89 assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
90
df2d202e 91 r = sd_bus_message_new_method_return(m, &reply);
11c4c249 92 if (r < 0) {
da927ba9 93 log_error_errno(r, "Failed to allocate return: %m");
11c4c249
LP
94 goto fail;
95 }
96
97 quit = true;
98
99 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
c784c5ce 100 r = sd_bus_message_new_method_error(
df2d202e 101 m,
151b9b96
LP
102 &reply,
103 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
11c4c249 104 if (r < 0) {
da927ba9 105 log_error_errno(r, "Failed to allocate return: %m");
11c4c249
LP
106 goto fail;
107 }
108 }
109
110 if (reply) {
111 r = sd_bus_send(bus, reply, NULL);
112 if (r < 0) {
da927ba9 113 log_error_errno(r, "Failed to send reply: %m");
11c4c249
LP
114 goto fail;
115 }
116 }
117 }
118
119 r = 0;
120
121fail:
122 if (bus) {
123 sd_bus_flush(bus);
124 sd_bus_unref(bus);
125 }
126
127 return INT_TO_PTR(r);
128}
129
130static int client(struct context *c) {
131 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
132 _cleanup_bus_unref_ sd_bus *bus = NULL;
c784c5ce 133 sd_bus_error error = SD_BUS_ERROR_NULL;
11c4c249
LP
134 int r;
135
136 assert_se(sd_bus_new(&bus) >= 0);
e82c9509 137 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
264ad849 138 assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
11c4c249
LP
139 assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
140 assert_se(sd_bus_start(bus) >= 0);
141
142 r = sd_bus_message_new_method_call(
143 bus,
151b9b96 144 &m,
11c4c249
LP
145 "org.freedesktop.systemd.test",
146 "/",
147 "org.freedesktop.systemd.test",
151b9b96 148 "Exit");
f647962d
MS
149 if (r < 0)
150 return log_error_errno(r, "Failed to allocate method call: %m");
11c4c249 151
c49b30a2 152 r = sd_bus_call(bus, m, 0, &error, &reply);
11c4c249
LP
153 if (r < 0) {
154 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
155 return r;
156 }
157
158 return 0;
159}
160
161static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds,
162 bool client_anonymous_auth, bool server_anonymous_auth) {
163
164 struct context c;
165 pthread_t s;
166 void *p;
167 int r, q;
168
169 zero(c);
170
171 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
172
173 c.client_negotiate_unix_fds = client_negotiate_unix_fds;
174 c.server_negotiate_unix_fds = server_negotiate_unix_fds;
175 c.client_anonymous_auth = client_anonymous_auth;
176 c.server_anonymous_auth = server_anonymous_auth;
177
178 r = pthread_create(&s, NULL, server, &c);
179 if (r != 0)
180 return -r;
181
182 r = client(&c);
183
184 q = pthread_join(s, &p);
185 if (q != 0)
186 return -q;
187
188 if (r < 0)
189 return r;
190
191 if (PTR_TO_INT(p) < 0)
192 return PTR_TO_INT(p);
193
194 return 0;
195}
196
197int main(int argc, char *argv[]) {
198 int r;
199
200 r = test_one(true, true, false, false);
201 assert_se(r >= 0);
202
203 r = test_one(true, false, false, false);
204 assert_se(r >= 0);
205
206 r = test_one(false, true, false, false);
207 assert_se(r >= 0);
208
209 r = test_one(false, false, false, false);
210 assert_se(r >= 0);
211
212 r = test_one(true, true, true, true);
213 assert_se(r >= 0);
214
215 r = test_one(true, true, false, true);
216 assert_se(r >= 0);
217
218 r = test_one(true, true, true, false);
219 assert_se(r == -EPERM);
220
221 return EXIT_SUCCESS;
222}