]> git.proxmox.com Git - systemd.git/blame - src/core/dbus-scope.c
Imported Upstream version 214
[systemd.git] / src / core / dbus-scope.c
CommitLineData
14228c0d
MB
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
60f067b4
JS
22#include "unit.h"
23#include "scope.h"
14228c0d 24#include "dbus-unit.h"
14228c0d
MB
25#include "dbus-cgroup.h"
26#include "dbus-kill.h"
14228c0d 27#include "dbus-scope.h"
60f067b4
JS
28#include "bus-util.h"
29#include "bus-internal.h"
30#include "bus-errors.h"
14228c0d 31
60f067b4
JS
32static int bus_scope_abandon(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
33 Scope *s = userdata;
34 int r;
14228c0d 35
60f067b4
JS
36 assert(bus);
37 assert(message);
38 assert(s);
14228c0d 39
60f067b4
JS
40 r = scope_abandon(s);
41 if (sd_bus_error_is_set(error))
42 return r;
14228c0d 43
60f067b4
JS
44 if (r == -ESTALE)
45 return sd_bus_error_setf(error, BUS_ERROR_SCOPE_NOT_RUNNING, "Scope %s is not running, cannot abandon.", UNIT(s)->id);
14228c0d 46
60f067b4 47 return sd_bus_reply_method_return(message, NULL);
14228c0d
MB
48}
49
60f067b4
JS
50static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
51
52const sd_bus_vtable bus_scope_vtable[] = {
53 SD_BUS_VTABLE_START(0),
54 SD_BUS_PROPERTY("Controller", "s", NULL, offsetof(Scope, controller), SD_BUS_VTABLE_PROPERTY_CONST),
55 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
56 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
57 SD_BUS_SIGNAL("RequestStop", NULL, 0),
58 SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_abandon, 0),
59 SD_BUS_VTABLE_END
60};
61
14228c0d
MB
62static int bus_scope_set_transient_property(
63 Scope *s,
64 const char *name,
60f067b4 65 sd_bus_message *message,
14228c0d 66 UnitSetPropertiesMode mode,
60f067b4 67 sd_bus_error *error) {
14228c0d
MB
68
69 int r;
70
14228c0d 71 assert(s);
60f067b4
JS
72 assert(name);
73 assert(message);
14228c0d
MB
74
75 if (streq(name, "PIDs")) {
14228c0d 76 unsigned n = 0;
60f067b4 77 uint32_t pid;
14228c0d 78
60f067b4 79 r = sd_bus_message_enter_container(message, 'a', "u");
14228c0d
MB
80 if (r < 0)
81 return r;
82
60f067b4 83 while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {
14228c0d
MB
84
85 if (pid <= 1)
86 return -EINVAL;
87
88 if (mode != UNIT_CHECK) {
60f067b4 89 r = unit_watch_pid(UNIT(s), pid);
14228c0d
MB
90 if (r < 0 && r != -EEXIST)
91 return r;
92 }
93
14228c0d
MB
94 n++;
95 }
60f067b4
JS
96 if (r < 0)
97 return r;
98
99 r = sd_bus_message_exit_container(message);
100 if (r < 0)
101 return r;
14228c0d
MB
102
103 if (n <= 0)
104 return -EINVAL;
105
106 return 1;
107
60f067b4
JS
108 } else if (streq(name, "Controller")) {
109 const char *controller;
110 char *c;
14228c0d 111
60f067b4
JS
112 r = sd_bus_message_read(message, "s", &controller);
113 if (r < 0)
114 return r;
115
116 if (!isempty(controller) && !service_name_is_valid(controller))
117 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
14228c0d
MB
118
119 if (mode != UNIT_CHECK) {
60f067b4
JS
120 if (isempty(controller))
121 c = NULL;
122 else {
123 c = strdup(controller);
124 if (!c)
125 return -ENOMEM;
126 }
14228c0d 127
60f067b4
JS
128 free(s->controller);
129 s->controller = c;
130 }
14228c0d 131
60f067b4 132 return 1;
14228c0d 133
60f067b4
JS
134 } else if (streq(name, "TimeoutStopUSec")) {
135
136 if (mode != UNIT_CHECK) {
137 r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
138 if (r < 0)
139 return r;
140
141 unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec="USEC_FMT"us\n", s->timeout_stop_usec);
142 } else {
143 r = sd_bus_message_skip(message, "t");
144 if (r < 0)
145 return r;
14228c0d
MB
146 }
147
148 return 1;
149 }
150
151 return 0;
152}
153
154int bus_scope_set_property(
155 Unit *u,
156 const char *name,
60f067b4 157 sd_bus_message *message,
14228c0d 158 UnitSetPropertiesMode mode,
60f067b4 159 sd_bus_error *error) {
14228c0d
MB
160
161 Scope *s = SCOPE(u);
162 int r;
163
60f067b4 164 assert(s);
14228c0d 165 assert(name);
60f067b4 166 assert(message);
14228c0d 167
60f067b4 168 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
14228c0d
MB
169 if (r != 0)
170 return r;
171
172 if (u->load_state == UNIT_STUB) {
173 /* While we are created we still accept PIDs */
174
60f067b4 175 r = bus_scope_set_transient_property(s, name, message, mode, error);
14228c0d
MB
176 if (r != 0)
177 return r;
178
60f067b4 179 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
14228c0d
MB
180 if (r != 0)
181 return r;
182 }
183
184 return 0;
185}
186
187int bus_scope_commit_properties(Unit *u) {
188 assert(u);
189
60f067b4 190 unit_update_cgroup_members_masks(u);
14228c0d 191 unit_realize_cgroup(u);
60f067b4 192
14228c0d
MB
193 return 0;
194}
60f067b4
JS
195
196int bus_scope_send_request_stop(Scope *s) {
197 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
198 _cleanup_free_ char *p = NULL;
199 int r;
200
201 assert(s);
202
203 if (!s->controller)
204 return 0;
205
206 p = unit_dbus_path(UNIT(s));
207 if (!p)
208 return -ENOMEM;
209
210 r = sd_bus_message_new_signal(
211 UNIT(s)->manager->api_bus,
212 &m,
213 p,
214 "org.freedesktop.systemd1.Scope",
215 "RequestStop");
216 if (r < 0)
217 return r;
218
219 return sd_bus_send_to(UNIT(s)->manager->api_bus, m, /* s->controller */ NULL, NULL);
220}