]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-scope.c
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
[thirdparty/systemd.git] / src / core / dbus-scope.c
CommitLineData
6c12b52e
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
b5efdb8a 22#include "alloc-util.h"
96aad8d1 23#include "bus-common-errors.h"
b5efdb8a
LP
24#include "bus-internal.h"
25#include "bus-util.h"
1d22e906
LP
26#include "dbus-cgroup.h"
27#include "dbus-kill.h"
28#include "dbus-scope.h"
b5efdb8a
LP
29#include "dbus-unit.h"
30#include "dbus.h"
31#include "scope.h"
32#include "selinux-access.h"
33#include "unit.h"
6c12b52e 34
19070062 35static int bus_scope_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) {
a911bb9a 36 Scope *s = userdata;
4e2f8d27 37 int r;
a911bb9a 38
a911bb9a
LP
39 assert(message);
40 assert(s);
41
1d22e906
LP
42 r = mac_selinux_unit_access_check(UNIT(s), message, "stop", error);
43 if (r < 0)
44 return r;
45
46 r = bus_verify_manage_units_async(UNIT(s)->manager, message, error);
283868e1
SW
47 if (r < 0)
48 return r;
49 if (r == 0)
50 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
51
4e2f8d27 52 r = scope_abandon(s);
4e2f8d27
LP
53 if (r == -ESTALE)
54 return sd_bus_error_setf(error, BUS_ERROR_SCOPE_NOT_RUNNING, "Scope %s is not running, cannot abandon.", UNIT(s)->id);
1d22e906
LP
55 if (r < 0)
56 return r;
4e2f8d27
LP
57
58 return sd_bus_reply_method_return(message, NULL);
a911bb9a
LP
59}
60
718db961 61static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
6c12b52e 62
718db961
LP
63const sd_bus_vtable bus_scope_vtable[] = {
64 SD_BUS_VTABLE_START(0),
2d4a39e7 65 SD_BUS_PROPERTY("Controller", "s", NULL, offsetof(Scope, controller), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 66 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
718db961 67 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2d4a39e7 68 SD_BUS_SIGNAL("RequestStop", NULL, 0),
1d22e906 69 SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_abandon, SD_BUS_VTABLE_UNPRIVILEGED),
718db961
LP
70 SD_BUS_VTABLE_END
71};
6c12b52e 72
9f2e86af 73static int bus_scope_set_transient_property(
6c12b52e
LP
74 Scope *s,
75 const char *name,
718db961 76 sd_bus_message *message,
6c12b52e 77 UnitSetPropertiesMode mode,
718db961 78 sd_bus_error *error) {
6c12b52e
LP
79
80 int r;
81
6c12b52e 82 assert(s);
718db961
LP
83 assert(name);
84 assert(message);
6c12b52e
LP
85
86 if (streq(name, "PIDs")) {
294a90cc 87 unsigned n = 0;
718db961 88 uint32_t pid;
6c12b52e 89
718db961
LP
90 r = sd_bus_message_enter_container(message, 'a', "u");
91 if (r < 0)
92 return r;
6c12b52e 93
718db961 94 while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {
6c12b52e
LP
95
96 if (pid <= 1)
97 return -EINVAL;
98
adb3a45d 99 if (mode != UNIT_CHECK) {
a911bb9a 100 r = unit_watch_pid(UNIT(s), pid);
adb3a45d
LP
101 if (r < 0 && r != -EEXIST)
102 return r;
103 }
6c12b52e 104
adb3a45d 105 n++;
6c12b52e 106 }
718db961
LP
107 if (r < 0)
108 return r;
109
110 r = sd_bus_message_exit_container(message);
111 if (r < 0)
112 return r;
6c12b52e 113
adb3a45d 114 if (n <= 0)
6c12b52e
LP
115 return -EINVAL;
116
117 return 1;
cc23f9f1 118
2d4a39e7
LP
119 } else if (streq(name, "Controller")) {
120 const char *controller;
121 char *c;
122
123 r = sd_bus_message_read(message, "s", &controller);
124 if (r < 0)
125 return r;
126
127 if (!isempty(controller) && !service_name_is_valid(controller))
128 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
129
130 if (mode != UNIT_CHECK) {
131 if (isempty(controller))
132 c = NULL;
133 else {
134 c = strdup(controller);
135 if (!c)
136 return -ENOMEM;
137 }
138
139 free(s->controller);
140 s->controller = c;
141 }
142
143 return 1;
144
cc23f9f1
LP
145 } else if (streq(name, "TimeoutStopUSec")) {
146
cc23f9f1 147 if (mode != UNIT_CHECK) {
718db961
LP
148 r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
149 if (r < 0)
150 return r;
151
de0671ee 152 unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec="USEC_FMT"us\n", s->timeout_stop_usec);
718db961
LP
153 } else {
154 r = sd_bus_message_skip(message, "t");
155 if (r < 0)
156 return r;
cc23f9f1
LP
157 }
158
159 return 1;
6c12b52e
LP
160 }
161
162 return 0;
163}
164
165int bus_scope_set_property(
166 Unit *u,
167 const char *name,
718db961 168 sd_bus_message *message,
6c12b52e 169 UnitSetPropertiesMode mode,
718db961 170 sd_bus_error *error) {
6c12b52e
LP
171
172 Scope *s = SCOPE(u);
173 int r;
174
718db961 175 assert(s);
6c12b52e 176 assert(name);
718db961 177 assert(message);
6c12b52e 178
718db961 179 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
6c12b52e
LP
180 if (r != 0)
181 return r;
182
183 if (u->load_state == UNIT_STUB) {
184 /* While we are created we still accept PIDs */
185
718db961 186 r = bus_scope_set_transient_property(s, name, message, mode, error);
6c12b52e
LP
187 if (r != 0)
188 return r;
a6c0353b 189
718db961 190 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
a6c0353b
LP
191 if (r != 0)
192 return r;
6c12b52e
LP
193 }
194
195 return 0;
196}
197
198int bus_scope_commit_properties(Unit *u) {
199 assert(u);
200
bc432dc7 201 unit_update_cgroup_members_masks(u);
6c12b52e 202 unit_realize_cgroup(u);
bc432dc7 203
6c12b52e
LP
204 return 0;
205}
2d4a39e7
LP
206
207int bus_scope_send_request_stop(Scope *s) {
4afd3348 208 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2d4a39e7
LP
209 _cleanup_free_ char *p = NULL;
210 int r;
211
212 assert(s);
213
214 if (!s->controller)
215 return 0;
216
217 p = unit_dbus_path(UNIT(s));
218 if (!p)
219 return -ENOMEM;
220
221 r = sd_bus_message_new_signal(
222 UNIT(s)->manager->api_bus,
151b9b96 223 &m,
2d4a39e7
LP
224 p,
225 "org.freedesktop.systemd1.Scope",
151b9b96 226 "RequestStop");
2d4a39e7
LP
227 if (r < 0)
228 return r;
229
230 return sd_bus_send_to(UNIT(s)->manager->api_bus, m, /* s->controller */ NULL, NULL);
231}