Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <sys/prctl.h>
5 : : #include <sys/statvfs.h>
6 : : #include <unistd.h>
7 : :
8 : : #include "alloc-util.h"
9 : : #include "architecture.h"
10 : : #include "build.h"
11 : : #include "bus-common-errors.h"
12 : : #include "dbus-execute.h"
13 : : #include "dbus-job.h"
14 : : #include "dbus-manager.h"
15 : : #include "dbus-scope.h"
16 : : #include "dbus-unit.h"
17 : : #include "dbus.h"
18 : : #include "env-util.h"
19 : : #include "fd-util.h"
20 : : #include "fileio.h"
21 : : #include "format-util.h"
22 : : #include "fs-util.h"
23 : : #include "install.h"
24 : : #include "log.h"
25 : : #include "os-util.h"
26 : : #include "parse-util.h"
27 : : #include "path-util.h"
28 : : #include "selinux-access.h"
29 : : #include "stat-util.h"
30 : : #include "string-util.h"
31 : : #include "strv.h"
32 : : #include "syslog-util.h"
33 : : #include "user-util.h"
34 : : #include "virt.h"
35 : : #include "watchdog.h"
36 : :
37 : : /* Require 16MiB free in /run/systemd for reloading/reexecing. After all we need to serialize our state there, and if
38 : : * we can't we'll fail badly. */
39 : : #define RELOAD_DISK_SPACE_MIN (UINT64_C(16) * UINT64_C(1024) * UINT64_C(1024))
40 : :
41 : 0 : static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
42 : 0 : return (runtime ? UNIT_FILE_RUNTIME : 0) |
43 [ # # ]: 0 : (force ? UNIT_FILE_FORCE : 0);
44 : : }
45 : :
46 [ # # # # : 0 : BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_oom_policy, oom_policy, OOMPolicy);
# # ]
47 : :
48 [ # # # # ]: 0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", GIT_VERSION);
49 [ # # # # ]: 0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", SYSTEMD_FEATURES);
50 [ # # # # ]: 0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture()));
51 [ # # # # ]: 0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_log_target, "s", log_target_to_string(log_get_target()));
52 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET2(property_get_system_state, "s", Manager, manager_state, manager_state_to_string);
# # ]
53 [ # # # # ]: 0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));
54 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "u", Hashmap *, hashmap_size);
# # ]
55 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET_REF(property_get_set_size, "u", Set *, set_size);
# # ]
56 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET(property_get_default_timeout_abort_usec, "t", Manager, manager_default_timeout_abort_usec);
# # ]
57 : :
58 : 0 : static int property_get_virtualization(
59 : : sd_bus *bus,
60 : : const char *path,
61 : : const char *interface,
62 : : const char *property,
63 : : sd_bus_message *reply,
64 : : void *userdata,
65 : : sd_bus_error *error) {
66 : :
67 : : int v;
68 : :
69 [ # # ]: 0 : assert(bus);
70 [ # # ]: 0 : assert(reply);
71 : :
72 : 0 : v = detect_virtualization();
73 : :
74 : : /* Make sure to return the empty string when we detect no virtualization, as that is the API.
75 : : *
76 : : * https://github.com/systemd/systemd/issues/1423
77 : : */
78 : :
79 [ # # ]: 0 : return sd_bus_message_append(
80 : : reply, "s",
81 : 0 : v == VIRTUALIZATION_NONE ? NULL : virtualization_to_string(v));
82 : : }
83 : :
84 : 0 : static int property_get_tainted(
85 : : sd_bus *bus,
86 : : const char *path,
87 : : const char *interface,
88 : : const char *property,
89 : : sd_bus_message *reply,
90 : : void *userdata,
91 : : sd_bus_error *error) {
92 : :
93 : 0 : _cleanup_free_ char *s = NULL;
94 : 0 : Manager *m = userdata;
95 : :
96 [ # # ]: 0 : assert(bus);
97 [ # # ]: 0 : assert(reply);
98 [ # # ]: 0 : assert(m);
99 : :
100 : 0 : s = manager_taint_string(m);
101 [ # # ]: 0 : if (!s)
102 : 0 : return log_oom();
103 : :
104 : 0 : return sd_bus_message_append(reply, "s", s);
105 : : }
106 : :
107 : 0 : static int property_set_log_target(
108 : : sd_bus *bus,
109 : : const char *path,
110 : : const char *interface,
111 : : const char *property,
112 : : sd_bus_message *value,
113 : : void *userdata,
114 : : sd_bus_error *error) {
115 : :
116 : 0 : Manager *m = userdata;
117 : : const char *t;
118 : : int r;
119 : :
120 [ # # ]: 0 : assert(bus);
121 [ # # ]: 0 : assert(value);
122 : :
123 : 0 : r = sd_bus_message_read(value, "s", &t);
124 [ # # ]: 0 : if (r < 0)
125 : 0 : return r;
126 : :
127 [ # # ]: 0 : if (isempty(t))
128 : 0 : manager_restore_original_log_target(m);
129 : : else {
130 : : LogTarget target;
131 : :
132 : 0 : target = log_target_from_string(t);
133 [ # # ]: 0 : if (target < 0)
134 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log target '%s'", t);
135 : :
136 : 0 : manager_override_log_target(m, target);
137 : : }
138 : :
139 : 0 : return 0;
140 : : }
141 : :
142 : 0 : static int property_get_log_level(
143 : : sd_bus *bus,
144 : : const char *path,
145 : : const char *interface,
146 : : const char *property,
147 : : sd_bus_message *reply,
148 : : void *userdata,
149 : : sd_bus_error *error) {
150 : :
151 : 0 : _cleanup_free_ char *t = NULL;
152 : : int r;
153 : :
154 [ # # ]: 0 : assert(bus);
155 [ # # ]: 0 : assert(reply);
156 : :
157 : 0 : r = log_level_to_string_alloc(log_get_max_level(), &t);
158 [ # # ]: 0 : if (r < 0)
159 : 0 : return r;
160 : :
161 : 0 : return sd_bus_message_append(reply, "s", t);
162 : : }
163 : :
164 : 0 : static int property_set_log_level(
165 : : sd_bus *bus,
166 : : const char *path,
167 : : const char *interface,
168 : : const char *property,
169 : : sd_bus_message *value,
170 : : void *userdata,
171 : : sd_bus_error *error) {
172 : :
173 : 0 : Manager *m = userdata;
174 : : const char *t;
175 : : int r;
176 : :
177 [ # # ]: 0 : assert(bus);
178 [ # # ]: 0 : assert(value);
179 : :
180 : 0 : r = sd_bus_message_read(value, "s", &t);
181 [ # # ]: 0 : if (r < 0)
182 : 0 : return r;
183 : :
184 [ # # ]: 0 : if (isempty(t))
185 : 0 : manager_restore_original_log_level(m);
186 : : else {
187 : : int level;
188 : :
189 : 0 : level = log_level_from_string(t);
190 [ # # ]: 0 : if (level < 0)
191 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t);
192 : :
193 : 0 : manager_override_log_level(m, level);
194 : : }
195 : :
196 : 0 : return 0;
197 : : }
198 : :
199 : 0 : static int property_get_progress(
200 : : sd_bus *bus,
201 : : const char *path,
202 : : const char *interface,
203 : : const char *property,
204 : : sd_bus_message *reply,
205 : : void *userdata,
206 : : sd_bus_error *error) {
207 : :
208 : 0 : Manager *m = userdata;
209 : : double d;
210 : :
211 [ # # ]: 0 : assert(bus);
212 [ # # ]: 0 : assert(reply);
213 [ # # ]: 0 : assert(m);
214 : :
215 [ # # ]: 0 : if (MANAGER_IS_FINISHED(m))
216 : 0 : d = 1.0;
217 : : else
218 : 0 : d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
219 : :
220 : 0 : return sd_bus_message_append(reply, "d", d);
221 : : }
222 : :
223 : 0 : static int property_get_environment(
224 : : sd_bus *bus,
225 : : const char *path,
226 : : const char *interface,
227 : : const char *property,
228 : : sd_bus_message *reply,
229 : : void *userdata,
230 : : sd_bus_error *error) {
231 : :
232 : 0 : _cleanup_strv_free_ char **l = NULL;
233 : 0 : Manager *m = userdata;
234 : : int r;
235 : :
236 [ # # ]: 0 : assert(bus);
237 [ # # ]: 0 : assert(reply);
238 [ # # ]: 0 : assert(m);
239 : :
240 : 0 : r = manager_get_effective_environment(m, &l);
241 [ # # ]: 0 : if (r < 0)
242 : 0 : return r;
243 : :
244 : 0 : return sd_bus_message_append_strv(reply, l);
245 : : }
246 : :
247 : 0 : static int property_get_show_status(
248 : : sd_bus *bus,
249 : : const char *path,
250 : : const char *interface,
251 : : const char *property,
252 : : sd_bus_message *reply,
253 : : void *userdata,
254 : : sd_bus_error *error) {
255 : :
256 : 0 : Manager *m = userdata;
257 : : int b;
258 : :
259 [ # # ]: 0 : assert(bus);
260 [ # # ]: 0 : assert(reply);
261 [ # # ]: 0 : assert(m);
262 : :
263 [ # # ]: 0 : b = IN_SET(m->show_status, SHOW_STATUS_TEMPORARY, SHOW_STATUS_YES);
264 : 0 : return sd_bus_message_append_basic(reply, 'b', &b);
265 : : }
266 : :
267 : 0 : static int property_set_runtime_watchdog(
268 : : sd_bus *bus,
269 : : const char *path,
270 : : const char *interface,
271 : : const char *property,
272 : : sd_bus_message *value,
273 : : void *userdata,
274 : : sd_bus_error *error) {
275 : :
276 : 0 : usec_t *t = userdata;
277 : : int r;
278 : :
279 [ # # ]: 0 : assert(bus);
280 [ # # ]: 0 : assert(value);
281 : :
282 : : assert_cc(sizeof(usec_t) == sizeof(uint64_t));
283 : :
284 : 0 : r = sd_bus_message_read(value, "t", t);
285 [ # # ]: 0 : if (r < 0)
286 : 0 : return r;
287 : :
288 : 0 : return watchdog_set_timeout(t);
289 : : }
290 : :
291 : 0 : static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
292 : : Unit *u;
293 : : int r;
294 : :
295 [ # # ]: 0 : assert(m);
296 [ # # ]: 0 : assert(message);
297 [ # # ]: 0 : assert(ret_unit);
298 : :
299 : : /* More or less a wrapper around manager_get_unit() that generates nice errors and has one trick up its sleeve:
300 : : * if the name is specified empty we use the client's unit. */
301 : :
302 [ # # ]: 0 : if (isempty(name)) {
303 [ # # ]: 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
304 : : pid_t pid;
305 : :
306 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
307 [ # # ]: 0 : if (r < 0)
308 : 0 : return r;
309 : :
310 : 0 : r = sd_bus_creds_get_pid(creds, &pid);
311 [ # # ]: 0 : if (r < 0)
312 : 0 : return r;
313 : :
314 : 0 : u = manager_get_unit_by_pid(m, pid);
315 [ # # ]: 0 : if (!u)
316 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
317 : : } else {
318 : 0 : u = manager_get_unit(m, name);
319 [ # # ]: 0 : if (!u)
320 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
321 : : }
322 : :
323 : 0 : *ret_unit = u;
324 : 0 : return 0;
325 : : }
326 : :
327 : 0 : static int bus_load_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
328 [ # # ]: 0 : assert(m);
329 [ # # ]: 0 : assert(message);
330 [ # # ]: 0 : assert(ret_unit);
331 : :
332 : : /* Pretty much the same as bus_get_unit_by_name(), but we also load the unit if necessary. */
333 : :
334 [ # # ]: 0 : if (isempty(name))
335 : 0 : return bus_get_unit_by_name(m, message, name, ret_unit, error);
336 : :
337 : 0 : return manager_load_unit(m, name, NULL, error, ret_unit);
338 : : }
339 : :
340 : 0 : static int reply_unit_path(Unit *u, sd_bus_message *message, sd_bus_error *error) {
341 : 0 : _cleanup_free_ char *path = NULL;
342 : : int r;
343 : :
344 [ # # ]: 0 : assert(u);
345 [ # # ]: 0 : assert(message);
346 : :
347 : 0 : r = mac_selinux_unit_access_check(u, message, "status", error);
348 [ # # ]: 0 : if (r < 0)
349 : 0 : return r;
350 : :
351 : 0 : path = unit_dbus_path(u);
352 [ # # ]: 0 : if (!path)
353 : 0 : return log_oom();
354 : :
355 : 0 : return sd_bus_reply_method_return(message, "o", path);
356 : : }
357 : :
358 : 0 : static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
359 : 0 : Manager *m = userdata;
360 : : const char *name;
361 : : Unit *u;
362 : : int r;
363 : :
364 [ # # ]: 0 : assert(message);
365 [ # # ]: 0 : assert(m);
366 : :
367 : : /* Anyone can call this method */
368 : :
369 : 0 : r = sd_bus_message_read(message, "s", &name);
370 [ # # ]: 0 : if (r < 0)
371 : 0 : return r;
372 : :
373 : 0 : r = bus_get_unit_by_name(m, message, name, &u, error);
374 [ # # ]: 0 : if (r < 0)
375 : 0 : return r;
376 : :
377 : 0 : return reply_unit_path(u, message, error);
378 : : }
379 : :
380 : 0 : static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
381 : 0 : Manager *m = userdata;
382 : : pid_t pid;
383 : : Unit *u;
384 : : int r;
385 : :
386 [ # # ]: 0 : assert(message);
387 [ # # ]: 0 : assert(m);
388 : :
389 : : assert_cc(sizeof(pid_t) == sizeof(uint32_t));
390 : :
391 : : /* Anyone can call this method */
392 : :
393 : 0 : r = sd_bus_message_read(message, "u", &pid);
394 [ # # ]: 0 : if (r < 0)
395 : 0 : return r;
396 [ # # ]: 0 : if (pid < 0)
397 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid);
398 : :
399 [ # # ]: 0 : if (pid == 0) {
400 [ # # ]: 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
401 : :
402 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
403 [ # # ]: 0 : if (r < 0)
404 : 0 : return r;
405 : :
406 : 0 : r = sd_bus_creds_get_pid(creds, &pid);
407 [ # # ]: 0 : if (r < 0)
408 : 0 : return r;
409 : : }
410 : :
411 : 0 : u = manager_get_unit_by_pid(m, pid);
412 [ # # ]: 0 : if (!u)
413 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
414 : :
415 : 0 : return reply_unit_path(u, message, error);
416 : : }
417 : :
418 : 0 : static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userdata, sd_bus_error *error) {
419 : 0 : _cleanup_free_ char *path = NULL;
420 : 0 : Manager *m = userdata;
421 : : sd_id128_t id;
422 : : const void *a;
423 : : Unit *u;
424 : : size_t sz;
425 : : int r;
426 : :
427 [ # # ]: 0 : assert(message);
428 [ # # ]: 0 : assert(m);
429 : :
430 : : /* Anyone can call this method */
431 : :
432 : 0 : r = sd_bus_message_read_array(message, 'y', &a, &sz);
433 [ # # ]: 0 : if (r < 0)
434 : 0 : return r;
435 [ # # ]: 0 : if (sz == 0)
436 : 0 : id = SD_ID128_NULL;
437 [ # # ]: 0 : else if (sz == 16)
438 : 0 : memcpy(&id, a, sz);
439 : : else
440 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid invocation ID");
441 : :
442 [ # # ]: 0 : if (sd_id128_is_null(id)) {
443 [ # # ]: 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
444 : : pid_t pid;
445 : :
446 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
447 [ # # ]: 0 : if (r < 0)
448 : 0 : return r;
449 : :
450 : 0 : r = sd_bus_creds_get_pid(creds, &pid);
451 [ # # ]: 0 : if (r < 0)
452 : 0 : return r;
453 : :
454 : 0 : u = manager_get_unit_by_pid(m, pid);
455 [ # # ]: 0 : if (!u)
456 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client " PID_FMT " not member of any unit.", pid);
457 : : } else {
458 : 0 : u = hashmap_get(m->units_by_invocation_id, &id);
459 [ # # ]: 0 : if (!u)
460 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(id));
461 : : }
462 : :
463 : 0 : r = mac_selinux_unit_access_check(u, message, "status", error);
464 [ # # ]: 0 : if (r < 0)
465 : 0 : return r;
466 : :
467 : : /* So here's a special trick: the bus path we return actually references the unit by its invocation ID instead
468 : : * of the unit name. This means it stays valid only as long as the invocation ID stays the same. */
469 : 0 : path = unit_dbus_path_invocation_id(u);
470 [ # # ]: 0 : if (!path)
471 : 0 : return -ENOMEM;
472 : :
473 : 0 : return sd_bus_reply_method_return(message, "o", path);
474 : : }
475 : :
476 : 0 : static int method_get_unit_by_control_group(sd_bus_message *message, void *userdata, sd_bus_error *error) {
477 : 0 : Manager *m = userdata;
478 : : const char *cgroup;
479 : : Unit *u;
480 : : int r;
481 : :
482 : 0 : r = sd_bus_message_read(message, "s", &cgroup);
483 [ # # ]: 0 : if (r < 0)
484 : 0 : return r;
485 : :
486 : 0 : u = manager_get_unit_by_cgroup(m, cgroup);
487 [ # # ]: 0 : if (!u)
488 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup);
489 : :
490 : 0 : return reply_unit_path(u, message, error);
491 : : }
492 : :
493 : 0 : static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
494 : 0 : Manager *m = userdata;
495 : : const char *name;
496 : : Unit *u;
497 : : int r;
498 : :
499 [ # # ]: 0 : assert(message);
500 [ # # ]: 0 : assert(m);
501 : :
502 : : /* Anyone can call this method */
503 : :
504 : 0 : r = sd_bus_message_read(message, "s", &name);
505 [ # # ]: 0 : if (r < 0)
506 : 0 : return r;
507 : :
508 : 0 : r = bus_load_unit_by_name(m, message, name, &u, error);
509 [ # # ]: 0 : if (r < 0)
510 : 0 : return r;
511 : :
512 : 0 : return reply_unit_path(u, message, error);
513 : : }
514 : :
515 : 0 : static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
516 : : const char *name;
517 : : Unit *u;
518 : : int r;
519 : :
520 [ # # ]: 0 : assert(message);
521 [ # # ]: 0 : assert(m);
522 : :
523 : 0 : r = sd_bus_message_read(message, "s", &name);
524 [ # # ]: 0 : if (r < 0)
525 : 0 : return r;
526 : :
527 : 0 : r = manager_load_unit(m, name, NULL, error, &u);
528 [ # # ]: 0 : if (r < 0)
529 : 0 : return r;
530 : :
531 : 0 : return bus_unit_method_start_generic(message, u, job_type, reload_if_possible, error);
532 : : }
533 : :
534 : 0 : static int method_start_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
535 : 0 : return method_start_unit_generic(message, userdata, JOB_START, false, error);
536 : : }
537 : :
538 : 0 : static int method_stop_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
539 : 0 : return method_start_unit_generic(message, userdata, JOB_STOP, false, error);
540 : : }
541 : :
542 : 0 : static int method_reload_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
543 : 0 : return method_start_unit_generic(message, userdata, JOB_RELOAD, false, error);
544 : : }
545 : :
546 : 0 : static int method_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
547 : 0 : return method_start_unit_generic(message, userdata, JOB_RESTART, false, error);
548 : : }
549 : :
550 : 0 : static int method_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
551 : 0 : return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, false, error);
552 : : }
553 : :
554 : 0 : static int method_reload_or_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
555 : 0 : return method_start_unit_generic(message, userdata, JOB_RESTART, true, error);
556 : : }
557 : :
558 : 0 : static int method_reload_or_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
559 : 0 : return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, true, error);
560 : : }
561 : :
562 : : typedef enum GenericUnitOperationFlags {
563 : : GENERIC_UNIT_LOAD = 1 << 0, /* Load if the unit is not loaded yet */
564 : : GENERIC_UNIT_VALIDATE_LOADED = 1 << 1, /* Verify unit is properly loaded before forwarding call */
565 : : } GenericUnitOperationFlags;
566 : :
567 : 0 : static int method_generic_unit_operation(
568 : : sd_bus_message *message,
569 : : Manager *m,
570 : : sd_bus_error *error,
571 : : sd_bus_message_handler_t handler,
572 : : GenericUnitOperationFlags flags) {
573 : :
574 : : const char *name;
575 : : Unit *u;
576 : : int r;
577 : :
578 [ # # ]: 0 : assert(message);
579 [ # # ]: 0 : assert(m);
580 : :
581 : : /* Read the first argument from the command and pass the operation to the specified per-unit
582 : : * method. */
583 : :
584 : 0 : r = sd_bus_message_read(message, "s", &name);
585 [ # # ]: 0 : if (r < 0)
586 : 0 : return r;
587 : :
588 [ # # # # ]: 0 : if (!isempty(name) && FLAGS_SET(flags, GENERIC_UNIT_LOAD))
589 : 0 : r = manager_load_unit(m, name, NULL, error, &u);
590 : : else
591 : 0 : r = bus_get_unit_by_name(m, message, name, &u, error);
592 [ # # ]: 0 : if (r < 0)
593 : 0 : return r;
594 : :
595 [ # # ]: 0 : if (FLAGS_SET(flags, GENERIC_UNIT_VALIDATE_LOADED)) {
596 : 0 : r = bus_unit_validate_load_state(u, error);
597 [ # # ]: 0 : if (r < 0)
598 : 0 : return r;
599 : : }
600 : :
601 : 0 : return handler(message, u, error);
602 : : }
603 : :
604 : 0 : static int method_enqueue_unit_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
605 : : /* We don't bother with GENERIC_UNIT_VALIDATE_LOADED here, as the job logic validates that anyway */
606 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_enqueue_job, GENERIC_UNIT_LOAD);
607 : : }
608 : :
609 : 0 : static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd_bus_error *error) {
610 : 0 : Manager *m = userdata;
611 : : const char *old_name;
612 : : Unit *u;
613 : : int r;
614 : :
615 [ # # ]: 0 : assert(message);
616 [ # # ]: 0 : assert(m);
617 : :
618 : 0 : r = sd_bus_message_read(message, "s", &old_name);
619 [ # # ]: 0 : if (r < 0)
620 : 0 : return r;
621 : :
622 : 0 : r = bus_get_unit_by_name(m, message, old_name, &u, error);
623 [ # # ]: 0 : if (r < 0)
624 : 0 : return r;
625 [ # # # # ]: 0 : if (!u->job || u->job->type != JOB_START)
626 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
627 : :
628 : 0 : return method_start_unit_generic(message, m, JOB_START, false, error);
629 : : }
630 : :
631 : 0 : static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
632 : : /* We don't bother with GENERIC_UNIT_LOAD nor GENERIC_UNIT_VALIDATE_LOADED here, as it shouldn't
633 : : * matter whether a unit is loaded for killing any processes possibly in the unit's cgroup. */
634 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill, 0);
635 : : }
636 : :
637 : 0 : static int method_clean_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
638 : : /* Load the unit if necessary, in order to load it, and insist on the unit being loaded to be
639 : : * cleaned */
640 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_clean, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED);
641 : : }
642 : :
643 : 0 : static int method_reset_failed_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
644 : : /* Don't load the unit (because unloaded units can't be in failed state), and don't insist on the
645 : : * unit to be loaded properly (since a failed unit might have its unit file disappeared) */
646 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_reset_failed, 0);
647 : : }
648 : :
649 : 0 : static int method_set_unit_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
650 : : /* Only change properties on fully loaded units, and load them in order to set properties */
651 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_set_properties, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED);
652 : : }
653 : :
654 : 0 : static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
655 : : /* Only allow reffing of fully loaded units, and make sure reffing a unit loads it. */
656 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_ref, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED);
657 : : }
658 : :
659 : 0 : static int method_unref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
660 : : /* Dropping a ref OTOH should not require the unit to still be loaded. And since a reffed unit is a
661 : : * loaded unit there's no need to load the unit for unreffing it. */
662 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_unref, 0);
663 : : }
664 : :
665 : 0 : static int reply_unit_info(sd_bus_message *reply, Unit *u) {
666 : 0 : _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
667 : : Unit *following;
668 : :
669 : 0 : following = unit_following(u);
670 : :
671 : 0 : unit_path = unit_dbus_path(u);
672 [ # # ]: 0 : if (!unit_path)
673 : 0 : return -ENOMEM;
674 : :
675 [ # # ]: 0 : if (u->job) {
676 : 0 : job_path = job_dbus_path(u->job);
677 [ # # ]: 0 : if (!job_path)
678 : 0 : return -ENOMEM;
679 : : }
680 : :
681 [ # # ]: 0 : return sd_bus_message_append(
682 : : reply, "(ssssssouso)",
683 : : u->id,
684 : : unit_description(u),
685 : : unit_load_state_to_string(u->load_state),
686 : : unit_active_state_to_string(unit_active_state(u)),
687 : : unit_sub_state_to_string(u),
688 : : following ? following->id : "",
689 : : unit_path,
690 [ # # ]: 0 : u->job ? u->job->id : 0,
691 [ # # ]: 0 : u->job ? job_type_to_string(u->job->type) : "",
692 : : empty_to_root(job_path));
693 : : }
694 : :
695 : 0 : static int method_list_units_by_names(sd_bus_message *message, void *userdata, sd_bus_error *error) {
696 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
697 : 0 : Manager *m = userdata;
698 : : int r;
699 : : char **unit;
700 : 0 : _cleanup_strv_free_ char **units = NULL;
701 : :
702 [ # # ]: 0 : assert(message);
703 [ # # ]: 0 : assert(m);
704 : :
705 : 0 : r = sd_bus_message_read_strv(message, &units);
706 [ # # ]: 0 : if (r < 0)
707 : 0 : return r;
708 : :
709 : 0 : r = sd_bus_message_new_method_return(message, &reply);
710 [ # # ]: 0 : if (r < 0)
711 : 0 : return r;
712 : :
713 : 0 : r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
714 [ # # ]: 0 : if (r < 0)
715 : 0 : return r;
716 : :
717 [ # # # # ]: 0 : STRV_FOREACH(unit, units) {
718 : : Unit *u;
719 : :
720 [ # # ]: 0 : if (!unit_name_is_valid(*unit, UNIT_NAME_ANY))
721 : 0 : continue;
722 : :
723 : 0 : r = bus_load_unit_by_name(m, message, *unit, &u, error);
724 [ # # ]: 0 : if (r < 0)
725 : 0 : return r;
726 : :
727 : 0 : r = reply_unit_info(reply, u);
728 [ # # ]: 0 : if (r < 0)
729 : 0 : return r;
730 : : }
731 : :
732 : 0 : r = sd_bus_message_close_container(reply);
733 [ # # ]: 0 : if (r < 0)
734 : 0 : return r;
735 : :
736 : 0 : return sd_bus_send(NULL, reply, NULL);
737 : : }
738 : :
739 : 0 : static int method_get_unit_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
740 : : /* Don't load a unit (since it won't have any processes if it's not loaded), but don't insist on the
741 : : * unit being loaded (because even improperly loaded units might still have processes around */
742 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_get_processes, 0);
743 : : }
744 : :
745 : 0 : static int method_attach_processes_to_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
746 : : /* Don't allow attaching new processes to units that aren't loaded. Don't bother with loading a unit
747 : : * for this purpose though, as an unloaded unit is a stopped unit, and we don't allow attaching
748 : : * processes to stopped units anyway. */
749 : 0 : return method_generic_unit_operation(message, userdata, error, bus_unit_method_attach_processes, GENERIC_UNIT_VALIDATE_LOADED);
750 : : }
751 : :
752 : 0 : static int transient_unit_from_message(
753 : : Manager *m,
754 : : sd_bus_message *message,
755 : : const char *name,
756 : : Unit **unit,
757 : : sd_bus_error *error) {
758 : :
759 : : UnitType t;
760 : : Unit *u;
761 : : int r;
762 : :
763 [ # # ]: 0 : assert(m);
764 [ # # ]: 0 : assert(message);
765 [ # # ]: 0 : assert(name);
766 : :
767 : 0 : t = unit_name_to_type(name);
768 [ # # ]: 0 : if (t < 0)
769 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name or type.");
770 : :
771 [ # # ]: 0 : if (!unit_vtable[t]->can_transient)
772 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
773 : :
774 : 0 : r = manager_load_unit(m, name, NULL, error, &u);
775 [ # # ]: 0 : if (r < 0)
776 : 0 : return r;
777 : :
778 [ # # ]: 0 : if (!unit_is_pristine(u))
779 : 0 : return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
780 : :
781 : : /* OK, the unit failed to load and is unreferenced, now let's
782 : : * fill in the transient data instead */
783 : 0 : r = unit_make_transient(u);
784 [ # # ]: 0 : if (r < 0)
785 : 0 : return r;
786 : :
787 : : /* Set our properties */
788 : 0 : r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
789 [ # # ]: 0 : if (r < 0)
790 : 0 : return r;
791 : :
792 : : /* If the client asked for it, automatically add a reference to this unit. */
793 [ # # ]: 0 : if (u->bus_track_add) {
794 : 0 : r = bus_unit_track_add_sender(u, message);
795 [ # # ]: 0 : if (r < 0)
796 [ # # ]: 0 : return log_error_errno(r, "Failed to watch sender: %m");
797 : : }
798 : :
799 : : /* Now load the missing bits of the unit we just created */
800 : 0 : unit_add_to_load_queue(u);
801 : 0 : manager_dispatch_load_queue(m);
802 : :
803 : 0 : *unit = u;
804 : :
805 : 0 : return 0;
806 : : }
807 : :
808 : 0 : static int transient_aux_units_from_message(
809 : : Manager *m,
810 : : sd_bus_message *message,
811 : : sd_bus_error *error) {
812 : :
813 : : int r;
814 : :
815 [ # # ]: 0 : assert(m);
816 [ # # ]: 0 : assert(message);
817 : :
818 : 0 : r = sd_bus_message_enter_container(message, 'a', "(sa(sv))");
819 [ # # ]: 0 : if (r < 0)
820 : 0 : return r;
821 : :
822 [ # # ]: 0 : while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) {
823 : 0 : const char *name = NULL;
824 : : Unit *u;
825 : :
826 : 0 : r = sd_bus_message_read(message, "s", &name);
827 [ # # ]: 0 : if (r < 0)
828 : 0 : return r;
829 : :
830 : 0 : r = transient_unit_from_message(m, message, name, &u, error);
831 [ # # ]: 0 : if (r < 0)
832 : 0 : return r;
833 : :
834 : 0 : r = sd_bus_message_exit_container(message);
835 [ # # ]: 0 : if (r < 0)
836 : 0 : return r;
837 : : }
838 [ # # ]: 0 : if (r < 0)
839 : 0 : return r;
840 : :
841 : 0 : r = sd_bus_message_exit_container(message);
842 [ # # ]: 0 : if (r < 0)
843 : 0 : return r;
844 : :
845 : 0 : return 0;
846 : : }
847 : :
848 : 0 : static int method_start_transient_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
849 : : const char *name, *smode;
850 : 0 : Manager *m = userdata;
851 : : JobMode mode;
852 : : Unit *u;
853 : : int r;
854 : :
855 [ # # ]: 0 : assert(message);
856 [ # # ]: 0 : assert(m);
857 : :
858 : 0 : r = mac_selinux_access_check(message, "start", error);
859 [ # # ]: 0 : if (r < 0)
860 : 0 : return r;
861 : :
862 : 0 : r = sd_bus_message_read(message, "ss", &name, &smode);
863 [ # # ]: 0 : if (r < 0)
864 : 0 : return r;
865 : :
866 : 0 : mode = job_mode_from_string(smode);
867 [ # # ]: 0 : if (mode < 0)
868 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
869 : :
870 : 0 : r = bus_verify_manage_units_async(m, message, error);
871 [ # # ]: 0 : if (r < 0)
872 : 0 : return r;
873 [ # # ]: 0 : if (r == 0)
874 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
875 : :
876 : 0 : r = transient_unit_from_message(m, message, name, &u, error);
877 [ # # ]: 0 : if (r < 0)
878 : 0 : return r;
879 : :
880 : 0 : r = transient_aux_units_from_message(m, message, error);
881 [ # # ]: 0 : if (r < 0)
882 : 0 : return r;
883 : :
884 : : /* Finally, start it */
885 : 0 : return bus_unit_queue_job(message, u, JOB_START, mode, 0, error);
886 : : }
887 : :
888 : 0 : static int method_get_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
889 : 0 : _cleanup_free_ char *path = NULL;
890 : 0 : Manager *m = userdata;
891 : : uint32_t id;
892 : : Job *j;
893 : : int r;
894 : :
895 [ # # ]: 0 : assert(message);
896 [ # # ]: 0 : assert(m);
897 : :
898 : : /* Anyone can call this method */
899 : :
900 : 0 : r = sd_bus_message_read(message, "u", &id);
901 [ # # ]: 0 : if (r < 0)
902 : 0 : return r;
903 : :
904 : 0 : j = manager_get_job(m, id);
905 [ # # ]: 0 : if (!j)
906 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
907 : :
908 : 0 : r = mac_selinux_unit_access_check(j->unit, message, "status", error);
909 [ # # ]: 0 : if (r < 0)
910 : 0 : return r;
911 : :
912 : 0 : path = job_dbus_path(j);
913 [ # # ]: 0 : if (!path)
914 : 0 : return -ENOMEM;
915 : :
916 : 0 : return sd_bus_reply_method_return(message, "o", path);
917 : : }
918 : :
919 : 0 : static int method_cancel_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
920 : 0 : Manager *m = userdata;
921 : : uint32_t id;
922 : : Job *j;
923 : : int r;
924 : :
925 [ # # ]: 0 : assert(message);
926 [ # # ]: 0 : assert(m);
927 : :
928 : 0 : r = sd_bus_message_read(message, "u", &id);
929 [ # # ]: 0 : if (r < 0)
930 : 0 : return r;
931 : :
932 : 0 : j = manager_get_job(m, id);
933 [ # # ]: 0 : if (!j)
934 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
935 : :
936 : 0 : return bus_job_method_cancel(message, j, error);
937 : : }
938 : :
939 : 0 : static int method_clear_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
940 : 0 : Manager *m = userdata;
941 : : int r;
942 : :
943 [ # # ]: 0 : assert(message);
944 [ # # ]: 0 : assert(m);
945 : :
946 : 0 : r = mac_selinux_access_check(message, "reload", error);
947 [ # # ]: 0 : if (r < 0)
948 : 0 : return r;
949 : :
950 : 0 : r = bus_verify_manage_units_async(m, message, error);
951 [ # # ]: 0 : if (r < 0)
952 : 0 : return r;
953 [ # # ]: 0 : if (r == 0)
954 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
955 : :
956 : 0 : manager_clear_jobs(m);
957 : :
958 : 0 : return sd_bus_reply_method_return(message, NULL);
959 : : }
960 : :
961 : 0 : static int method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
962 : 0 : Manager *m = userdata;
963 : : int r;
964 : :
965 [ # # ]: 0 : assert(message);
966 [ # # ]: 0 : assert(m);
967 : :
968 : 0 : r = mac_selinux_access_check(message, "reload", error);
969 [ # # ]: 0 : if (r < 0)
970 : 0 : return r;
971 : :
972 : 0 : r = bus_verify_manage_units_async(m, message, error);
973 [ # # ]: 0 : if (r < 0)
974 : 0 : return r;
975 [ # # ]: 0 : if (r == 0)
976 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
977 : :
978 : 0 : manager_reset_failed(m);
979 : :
980 : 0 : return sd_bus_reply_method_return(message, NULL);
981 : : }
982 : :
983 : 0 : static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) {
984 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
985 : 0 : Manager *m = userdata;
986 : : const char *k;
987 : : Iterator i;
988 : : Unit *u;
989 : : int r;
990 : :
991 [ # # ]: 0 : assert(message);
992 [ # # ]: 0 : assert(m);
993 : :
994 : : /* Anyone can call this method */
995 : :
996 : 0 : r = mac_selinux_access_check(message, "status", error);
997 [ # # ]: 0 : if (r < 0)
998 : 0 : return r;
999 : :
1000 : 0 : r = sd_bus_message_new_method_return(message, &reply);
1001 [ # # ]: 0 : if (r < 0)
1002 : 0 : return r;
1003 : :
1004 : 0 : r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
1005 [ # # ]: 0 : if (r < 0)
1006 : 0 : return r;
1007 : :
1008 [ # # ]: 0 : HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1009 [ # # ]: 0 : if (k != u->id)
1010 : 0 : continue;
1011 : :
1012 [ # # ]: 0 : if (!strv_isempty(states) &&
1013 [ # # ]: 0 : !strv_contains(states, unit_load_state_to_string(u->load_state)) &&
1014 [ # # ]: 0 : !strv_contains(states, unit_active_state_to_string(unit_active_state(u))) &&
1015 [ # # ]: 0 : !strv_contains(states, unit_sub_state_to_string(u)))
1016 : 0 : continue;
1017 : :
1018 [ # # ]: 0 : if (!strv_isempty(patterns) &&
1019 [ # # ]: 0 : !strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
1020 : 0 : continue;
1021 : :
1022 : 0 : r = reply_unit_info(reply, u);
1023 [ # # ]: 0 : if (r < 0)
1024 : 0 : return r;
1025 : : }
1026 : :
1027 : 0 : r = sd_bus_message_close_container(reply);
1028 [ # # ]: 0 : if (r < 0)
1029 : 0 : return r;
1030 : :
1031 : 0 : return sd_bus_send(NULL, reply, NULL);
1032 : : }
1033 : :
1034 : 0 : static int method_list_units(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1035 : 0 : return list_units_filtered(message, userdata, error, NULL, NULL);
1036 : : }
1037 : :
1038 : 0 : static int method_list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1039 : 0 : _cleanup_strv_free_ char **states = NULL;
1040 : : int r;
1041 : :
1042 : 0 : r = sd_bus_message_read_strv(message, &states);
1043 [ # # ]: 0 : if (r < 0)
1044 : 0 : return r;
1045 : :
1046 : 0 : return list_units_filtered(message, userdata, error, states, NULL);
1047 : : }
1048 : :
1049 : 0 : static int method_list_units_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1050 : 0 : _cleanup_strv_free_ char **states = NULL;
1051 : 0 : _cleanup_strv_free_ char **patterns = NULL;
1052 : : int r;
1053 : :
1054 : 0 : r = sd_bus_message_read_strv(message, &states);
1055 [ # # ]: 0 : if (r < 0)
1056 : 0 : return r;
1057 : :
1058 : 0 : r = sd_bus_message_read_strv(message, &patterns);
1059 [ # # ]: 0 : if (r < 0)
1060 : 0 : return r;
1061 : :
1062 : 0 : return list_units_filtered(message, userdata, error, states, patterns);
1063 : : }
1064 : :
1065 : 0 : static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1066 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1067 : 0 : Manager *m = userdata;
1068 : : Iterator i;
1069 : : Job *j;
1070 : : int r;
1071 : :
1072 [ # # ]: 0 : assert(message);
1073 [ # # ]: 0 : assert(m);
1074 : :
1075 : : /* Anyone can call this method */
1076 : :
1077 : 0 : r = mac_selinux_access_check(message, "status", error);
1078 [ # # ]: 0 : if (r < 0)
1079 : 0 : return r;
1080 : :
1081 : 0 : r = sd_bus_message_new_method_return(message, &reply);
1082 [ # # ]: 0 : if (r < 0)
1083 : 0 : return r;
1084 : :
1085 : 0 : r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
1086 [ # # ]: 0 : if (r < 0)
1087 : 0 : return r;
1088 : :
1089 [ # # ]: 0 : HASHMAP_FOREACH(j, m->jobs, i) {
1090 [ # # # # ]: 0 : _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
1091 : :
1092 : 0 : job_path = job_dbus_path(j);
1093 [ # # ]: 0 : if (!job_path)
1094 : 0 : return -ENOMEM;
1095 : :
1096 : 0 : unit_path = unit_dbus_path(j->unit);
1097 [ # # ]: 0 : if (!unit_path)
1098 : 0 : return -ENOMEM;
1099 : :
1100 : 0 : r = sd_bus_message_append(
1101 : : reply, "(usssoo)",
1102 : 0 : j->id,
1103 : 0 : j->unit->id,
1104 : 0 : job_type_to_string(j->type),
1105 : 0 : job_state_to_string(j->state),
1106 : : job_path,
1107 : : unit_path);
1108 [ # # ]: 0 : if (r < 0)
1109 : 0 : return r;
1110 : : }
1111 : :
1112 : 0 : r = sd_bus_message_close_container(reply);
1113 [ # # ]: 0 : if (r < 0)
1114 : 0 : return r;
1115 : :
1116 : 0 : return sd_bus_send(NULL, reply, NULL);
1117 : : }
1118 : :
1119 : 0 : static int method_subscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1120 : 0 : Manager *m = userdata;
1121 : : int r;
1122 : :
1123 [ # # ]: 0 : assert(message);
1124 [ # # ]: 0 : assert(m);
1125 : :
1126 : : /* Anyone can call this method */
1127 : :
1128 : 0 : r = mac_selinux_access_check(message, "status", error);
1129 [ # # ]: 0 : if (r < 0)
1130 : 0 : return r;
1131 : :
1132 [ # # ]: 0 : if (sd_bus_message_get_bus(message) == m->api_bus) {
1133 : :
1134 : : /* Note that direct bus connection subscribe by
1135 : : * default, we only track peers on the API bus here */
1136 : :
1137 [ # # ]: 0 : if (!m->subscribed) {
1138 : 0 : r = sd_bus_track_new(sd_bus_message_get_bus(message), &m->subscribed, NULL, NULL);
1139 [ # # ]: 0 : if (r < 0)
1140 : 0 : return r;
1141 : : }
1142 : :
1143 : 0 : r = sd_bus_track_add_sender(m->subscribed, message);
1144 [ # # ]: 0 : if (r < 0)
1145 : 0 : return r;
1146 [ # # ]: 0 : if (r == 0)
1147 : 0 : return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
1148 : : }
1149 : :
1150 : 0 : return sd_bus_reply_method_return(message, NULL);
1151 : : }
1152 : :
1153 : 0 : static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1154 : 0 : Manager *m = userdata;
1155 : : int r;
1156 : :
1157 [ # # ]: 0 : assert(message);
1158 [ # # ]: 0 : assert(m);
1159 : :
1160 : : /* Anyone can call this method */
1161 : :
1162 : 0 : r = mac_selinux_access_check(message, "status", error);
1163 [ # # ]: 0 : if (r < 0)
1164 : 0 : return r;
1165 : :
1166 [ # # ]: 0 : if (sd_bus_message_get_bus(message) == m->api_bus) {
1167 : 0 : r = sd_bus_track_remove_sender(m->subscribed, message);
1168 [ # # ]: 0 : if (r < 0)
1169 : 0 : return r;
1170 [ # # ]: 0 : if (r == 0)
1171 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1172 : : }
1173 : :
1174 : 0 : return sd_bus_reply_method_return(message, NULL);
1175 : : }
1176 : :
1177 : 0 : static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) {
1178 : 0 : _cleanup_free_ char *dump = NULL;
1179 : 0 : Manager *m = userdata;
1180 : : int r;
1181 : :
1182 [ # # ]: 0 : assert(message);
1183 [ # # ]: 0 : assert(m);
1184 : :
1185 : : /* Anyone can call this method */
1186 : :
1187 : 0 : r = mac_selinux_access_check(message, "status", error);
1188 [ # # ]: 0 : if (r < 0)
1189 : 0 : return r;
1190 : :
1191 : 0 : r = manager_get_dump_string(m, &dump);
1192 [ # # ]: 0 : if (r < 0)
1193 : 0 : return r;
1194 : :
1195 : 0 : return reply(message, dump);
1196 : : }
1197 : :
1198 : 0 : static int reply_dump(sd_bus_message *message, char *dump) {
1199 : 0 : return sd_bus_reply_method_return(message, "s", dump);
1200 : : }
1201 : :
1202 : 0 : static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1203 : 0 : return dump_impl(message, userdata, error, reply_dump);
1204 : : }
1205 : :
1206 : 0 : static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
1207 : 0 : _cleanup_close_ int fd = -1;
1208 : :
1209 : 0 : fd = acquire_data_fd(dump, strlen(dump), 0);
1210 [ # # ]: 0 : if (fd < 0)
1211 : 0 : return fd;
1212 : :
1213 : 0 : return sd_bus_reply_method_return(message, "h", fd);
1214 : : }
1215 : :
1216 : 0 : static int method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1217 : 0 : return dump_impl(message, userdata, error, reply_dump_by_fd);
1218 : : }
1219 : :
1220 : 0 : static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1221 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
1222 : : }
1223 : :
1224 : 0 : static int verify_run_space(const char *message, sd_bus_error *error) {
1225 : : struct statvfs svfs;
1226 : : uint64_t available;
1227 : :
1228 [ # # ]: 0 : if (statvfs("/run/systemd", &svfs) < 0)
1229 : 0 : return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m");
1230 : :
1231 : 0 : available = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize;
1232 : :
1233 [ # # ]: 0 : if (available < RELOAD_DISK_SPACE_MIN) {
1234 : : char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX];
1235 : 0 : return sd_bus_error_setf(error,
1236 : : BUS_ERROR_DISK_FULL,
1237 : : "%s, not enough space available on /run/systemd. "
1238 : : "Currently, %s are free, but a safety buffer of %s is enforced.",
1239 : : message,
1240 : : format_bytes(fb_available, sizeof(fb_available), available),
1241 : : format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN));
1242 : : }
1243 : :
1244 : 0 : return 0;
1245 : : }
1246 : :
1247 : 0 : int verify_run_space_and_log(const char *message) {
1248 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1249 : : int r;
1250 : :
1251 : 0 : r = verify_run_space(message, &error);
1252 [ # # ]: 0 : if (r < 0)
1253 [ # # ]: 0 : return log_error_errno(r, "%s", bus_error_message(&error, r));
1254 : :
1255 : 0 : return 0;
1256 : : }
1257 : :
1258 : 0 : static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1259 : 0 : Manager *m = userdata;
1260 : : int r;
1261 : :
1262 [ # # ]: 0 : assert(message);
1263 [ # # ]: 0 : assert(m);
1264 : :
1265 : 0 : r = verify_run_space("Refusing to reload", error);
1266 [ # # ]: 0 : if (r < 0)
1267 : 0 : return r;
1268 : :
1269 : 0 : r = mac_selinux_access_check(message, "reload", error);
1270 [ # # ]: 0 : if (r < 0)
1271 : 0 : return r;
1272 : :
1273 : 0 : r = bus_verify_reload_daemon_async(m, message, error);
1274 [ # # ]: 0 : if (r < 0)
1275 : 0 : return r;
1276 [ # # ]: 0 : if (r == 0)
1277 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1278 : :
1279 : : /* Instead of sending the reply back right away, we just
1280 : : * remember that we need to and then send it after the reload
1281 : : * is finished. That way the caller knows when the reload
1282 : : * finished. */
1283 : :
1284 [ # # ]: 0 : assert(!m->pending_reload_message);
1285 : 0 : r = sd_bus_message_new_method_return(message, &m->pending_reload_message);
1286 [ # # ]: 0 : if (r < 0)
1287 : 0 : return r;
1288 : :
1289 : 0 : m->objective = MANAGER_RELOAD;
1290 : :
1291 : 0 : return 1;
1292 : : }
1293 : :
1294 : 0 : static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1295 : 0 : Manager *m = userdata;
1296 : : int r;
1297 : :
1298 [ # # ]: 0 : assert(message);
1299 [ # # ]: 0 : assert(m);
1300 : :
1301 : 0 : r = verify_run_space("Refusing to reexecute", error);
1302 [ # # ]: 0 : if (r < 0)
1303 : 0 : return r;
1304 : :
1305 : 0 : r = mac_selinux_access_check(message, "reload", error);
1306 [ # # ]: 0 : if (r < 0)
1307 : 0 : return r;
1308 : :
1309 : 0 : r = bus_verify_reload_daemon_async(m, message, error);
1310 [ # # ]: 0 : if (r < 0)
1311 : 0 : return r;
1312 [ # # ]: 0 : if (r == 0)
1313 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1314 : :
1315 : : /* We don't send a reply back here, the client should
1316 : : * just wait for us disconnecting. */
1317 : :
1318 : 0 : m->objective = MANAGER_REEXECUTE;
1319 : 0 : return 1;
1320 : : }
1321 : :
1322 : 0 : static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1323 : 0 : Manager *m = userdata;
1324 : : int r;
1325 : :
1326 [ # # ]: 0 : assert(message);
1327 [ # # ]: 0 : assert(m);
1328 : :
1329 : 0 : r = mac_selinux_access_check(message, "halt", error);
1330 [ # # ]: 0 : if (r < 0)
1331 : 0 : return r;
1332 : :
1333 : : /* Exit() (in contrast to SetExitCode()) is actually allowed even if
1334 : : * we are running on the host. It will fall back on reboot() in
1335 : : * systemd-shutdown if it cannot do the exit() because it isn't a
1336 : : * container. */
1337 : :
1338 : 0 : m->objective = MANAGER_EXIT;
1339 : :
1340 : 0 : return sd_bus_reply_method_return(message, NULL);
1341 : : }
1342 : :
1343 : 0 : static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1344 : 0 : Manager *m = userdata;
1345 : : int r;
1346 : :
1347 [ # # ]: 0 : assert(message);
1348 [ # # ]: 0 : assert(m);
1349 : :
1350 : 0 : r = mac_selinux_access_check(message, "reboot", error);
1351 [ # # ]: 0 : if (r < 0)
1352 : 0 : return r;
1353 : :
1354 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1355 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1356 : :
1357 : 0 : m->objective = MANAGER_REBOOT;
1358 : :
1359 : 0 : return sd_bus_reply_method_return(message, NULL);
1360 : : }
1361 : :
1362 : 0 : static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1363 : 0 : Manager *m = userdata;
1364 : : int r;
1365 : :
1366 [ # # ]: 0 : assert(message);
1367 [ # # ]: 0 : assert(m);
1368 : :
1369 : 0 : r = mac_selinux_access_check(message, "halt", error);
1370 [ # # ]: 0 : if (r < 0)
1371 : 0 : return r;
1372 : :
1373 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1374 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1375 : :
1376 : 0 : m->objective = MANAGER_POWEROFF;
1377 : :
1378 : 0 : return sd_bus_reply_method_return(message, NULL);
1379 : : }
1380 : :
1381 : 0 : static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1382 : 0 : Manager *m = userdata;
1383 : : int r;
1384 : :
1385 [ # # ]: 0 : assert(message);
1386 [ # # ]: 0 : assert(m);
1387 : :
1388 : 0 : r = mac_selinux_access_check(message, "halt", error);
1389 [ # # ]: 0 : if (r < 0)
1390 : 0 : return r;
1391 : :
1392 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1393 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
1394 : :
1395 : 0 : m->objective = MANAGER_HALT;
1396 : :
1397 : 0 : return sd_bus_reply_method_return(message, NULL);
1398 : : }
1399 : :
1400 : 0 : static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1401 : 0 : Manager *m = userdata;
1402 : : int r;
1403 : :
1404 [ # # ]: 0 : assert(message);
1405 [ # # ]: 0 : assert(m);
1406 : :
1407 : 0 : r = mac_selinux_access_check(message, "reboot", error);
1408 [ # # ]: 0 : if (r < 0)
1409 : 0 : return r;
1410 : :
1411 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1412 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1413 : :
1414 : 0 : m->objective = MANAGER_KEXEC;
1415 : :
1416 : 0 : return sd_bus_reply_method_return(message, NULL);
1417 : : }
1418 : :
1419 : 0 : static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1420 : 0 : _cleanup_free_ char *ri = NULL, *rt = NULL;
1421 : : const char *root, *init;
1422 : 0 : Manager *m = userdata;
1423 : : struct statvfs svfs;
1424 : : uint64_t available;
1425 : : int r;
1426 : :
1427 [ # # ]: 0 : assert(message);
1428 [ # # ]: 0 : assert(m);
1429 : :
1430 [ # # ]: 0 : if (statvfs("/run/systemd", &svfs) < 0)
1431 : 0 : return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m");
1432 : :
1433 : 0 : available = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize;
1434 : :
1435 [ # # ]: 0 : if (available < RELOAD_DISK_SPACE_MIN) {
1436 : : char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX];
1437 [ # # ]: 0 : log_warning("Dangerously low amount of free space on /run/systemd, root switching operation might not complete successfully. "
1438 : : "Currently, %s are free, but %s are suggested. Proceeding anyway.",
1439 : : format_bytes(fb_available, sizeof(fb_available), available),
1440 : : format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN));
1441 : : }
1442 : :
1443 : 0 : r = mac_selinux_access_check(message, "reboot", error);
1444 [ # # ]: 0 : if (r < 0)
1445 : 0 : return r;
1446 : :
1447 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1448 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
1449 : :
1450 : 0 : r = sd_bus_message_read(message, "ss", &root, &init);
1451 [ # # ]: 0 : if (r < 0)
1452 : 0 : return r;
1453 : :
1454 [ # # ]: 0 : if (isempty(root))
1455 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory may not be the empty string.");
1456 [ # # ]: 0 : if (!path_is_absolute(root))
1457 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root path '%s' is not absolute.", root);
1458 [ # # ]: 0 : if (path_equal(root, "/"))
1459 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory cannot be the old root directory.");
1460 : :
1461 : : /* Safety check */
1462 [ # # ]: 0 : if (isempty(init)) {
1463 : 0 : r = path_is_os_tree(root);
1464 [ # # ]: 0 : if (r < 0)
1465 : 0 : return sd_bus_error_set_errnof(error, r, "Failed to determine whether root path '%s' contains an OS tree: %m", root);
1466 [ # # ]: 0 : if (r == 0)
1467 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path '%s' does not seem to be an OS tree. os-release file is missing.", root);
1468 : : } else {
1469 [ # # ]: 0 : _cleanup_free_ char *chased = NULL;
1470 : :
1471 [ # # ]: 0 : if (!path_is_absolute(init))
1472 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init);
1473 : :
1474 : 0 : r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased);
1475 [ # # ]: 0 : if (r < 0)
1476 : 0 : return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init);
1477 : :
1478 [ # # ]: 0 : if (laccess(chased, X_OK) < 0) {
1479 [ # # ]: 0 : if (errno == EACCES)
1480 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Init binary %s is not executable.", init);
1481 : :
1482 : 0 : return sd_bus_error_set_errnof(error, r, "Could not check whether init binary %s is executable: %m", init);
1483 : : }
1484 : : }
1485 : :
1486 : 0 : rt = strdup(root);
1487 [ # # ]: 0 : if (!rt)
1488 : 0 : return -ENOMEM;
1489 : :
1490 [ # # ]: 0 : if (!isempty(init)) {
1491 : 0 : ri = strdup(init);
1492 [ # # ]: 0 : if (!ri)
1493 : 0 : return -ENOMEM;
1494 : : }
1495 : :
1496 : 0 : free_and_replace(m->switch_root, rt);
1497 : 0 : free_and_replace(m->switch_root_init, ri);
1498 : :
1499 : 0 : m->objective = MANAGER_SWITCH_ROOT;
1500 : :
1501 : 0 : return sd_bus_reply_method_return(message, NULL);
1502 : : }
1503 : :
1504 : 0 : static int method_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1505 : 0 : _cleanup_strv_free_ char **plus = NULL;
1506 : 0 : Manager *m = userdata;
1507 : : int r;
1508 : :
1509 [ # # ]: 0 : assert(message);
1510 [ # # ]: 0 : assert(m);
1511 : :
1512 : 0 : r = mac_selinux_access_check(message, "reload", error);
1513 [ # # ]: 0 : if (r < 0)
1514 : 0 : return r;
1515 : :
1516 : 0 : r = sd_bus_message_read_strv(message, &plus);
1517 [ # # ]: 0 : if (r < 0)
1518 : 0 : return r;
1519 [ # # ]: 0 : if (!strv_env_is_valid(plus))
1520 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1521 : :
1522 : 0 : r = bus_verify_set_environment_async(m, message, error);
1523 [ # # ]: 0 : if (r < 0)
1524 : 0 : return r;
1525 [ # # ]: 0 : if (r == 0)
1526 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1527 : :
1528 : 0 : r = manager_client_environment_modify(m, NULL, plus);
1529 [ # # ]: 0 : if (r < 0)
1530 : 0 : return r;
1531 : :
1532 : 0 : return sd_bus_reply_method_return(message, NULL);
1533 : : }
1534 : :
1535 : 0 : static int method_unset_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1536 : 0 : _cleanup_strv_free_ char **minus = NULL;
1537 : 0 : Manager *m = userdata;
1538 : : int r;
1539 : :
1540 [ # # ]: 0 : assert(message);
1541 [ # # ]: 0 : assert(m);
1542 : :
1543 : 0 : r = mac_selinux_access_check(message, "reload", error);
1544 [ # # ]: 0 : if (r < 0)
1545 : 0 : return r;
1546 : :
1547 : 0 : r = sd_bus_message_read_strv(message, &minus);
1548 [ # # ]: 0 : if (r < 0)
1549 : 0 : return r;
1550 : :
1551 [ # # ]: 0 : if (!strv_env_name_or_assignment_is_valid(minus))
1552 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1553 : :
1554 : 0 : r = bus_verify_set_environment_async(m, message, error);
1555 [ # # ]: 0 : if (r < 0)
1556 : 0 : return r;
1557 [ # # ]: 0 : if (r == 0)
1558 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1559 : :
1560 : 0 : r = manager_client_environment_modify(m, minus, NULL);
1561 [ # # ]: 0 : if (r < 0)
1562 : 0 : return r;
1563 : :
1564 : 0 : return sd_bus_reply_method_return(message, NULL);
1565 : : }
1566 : :
1567 : 0 : static int method_unset_and_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1568 : 0 : _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1569 : 0 : Manager *m = userdata;
1570 : : int r;
1571 : :
1572 [ # # ]: 0 : assert(message);
1573 [ # # ]: 0 : assert(m);
1574 : :
1575 : 0 : r = mac_selinux_access_check(message, "reload", error);
1576 [ # # ]: 0 : if (r < 0)
1577 : 0 : return r;
1578 : :
1579 : 0 : r = sd_bus_message_read_strv(message, &minus);
1580 [ # # ]: 0 : if (r < 0)
1581 : 0 : return r;
1582 : :
1583 : 0 : r = sd_bus_message_read_strv(message, &plus);
1584 [ # # ]: 0 : if (r < 0)
1585 : 0 : return r;
1586 : :
1587 [ # # ]: 0 : if (!strv_env_name_or_assignment_is_valid(minus))
1588 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1589 [ # # ]: 0 : if (!strv_env_is_valid(plus))
1590 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1591 : :
1592 : 0 : r = bus_verify_set_environment_async(m, message, error);
1593 [ # # ]: 0 : if (r < 0)
1594 : 0 : return r;
1595 [ # # ]: 0 : if (r == 0)
1596 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1597 : :
1598 : 0 : r = manager_client_environment_modify(m, minus, plus);
1599 [ # # ]: 0 : if (r < 0)
1600 : 0 : return r;
1601 : :
1602 : 0 : return sd_bus_reply_method_return(message, NULL);
1603 : : }
1604 : :
1605 : 0 : static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1606 : 0 : Manager *m = userdata;
1607 : : uint8_t code;
1608 : : int r;
1609 : :
1610 [ # # ]: 0 : assert(message);
1611 [ # # ]: 0 : assert(m);
1612 : :
1613 : 0 : r = mac_selinux_access_check(message, "exit", error);
1614 [ # # ]: 0 : if (r < 0)
1615 : 0 : return r;
1616 : :
1617 : 0 : r = sd_bus_message_read_basic(message, 'y', &code);
1618 [ # # ]: 0 : if (r < 0)
1619 : 0 : return r;
1620 : :
1621 [ # # # # ]: 0 : if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0)
1622 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers.");
1623 : :
1624 : 0 : m->return_value = code;
1625 : :
1626 : 0 : return sd_bus_reply_method_return(message, NULL);
1627 : : }
1628 : :
1629 : 0 : static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1630 : 0 : Manager *m = userdata;
1631 : : const char *name;
1632 : : uid_t uid;
1633 : : int r;
1634 : :
1635 [ # # ]: 0 : assert(message);
1636 [ # # ]: 0 : assert(m);
1637 : :
1638 : 0 : r = sd_bus_message_read_basic(message, 's', &name);
1639 [ # # ]: 0 : if (r < 0)
1640 : 0 : return r;
1641 : :
1642 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1643 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
1644 [ # # ]: 0 : if (!valid_user_group_name(name))
1645 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name invalid: %s", name);
1646 : :
1647 : 0 : r = dynamic_user_lookup_name(m, name, &uid);
1648 [ # # ]: 0 : if (r == -ESRCH)
1649 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user %s does not exist.", name);
1650 [ # # ]: 0 : if (r < 0)
1651 : 0 : return r;
1652 : :
1653 : 0 : return sd_bus_reply_method_return(message, "u", (uint32_t) uid);
1654 : : }
1655 : :
1656 : 0 : static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1657 : 0 : _cleanup_free_ char *name = NULL;
1658 : 0 : Manager *m = userdata;
1659 : : uid_t uid;
1660 : : int r;
1661 : :
1662 [ # # ]: 0 : assert(message);
1663 [ # # ]: 0 : assert(m);
1664 : :
1665 : : assert_cc(sizeof(uid) == sizeof(uint32_t));
1666 : 0 : r = sd_bus_message_read_basic(message, 'u', &uid);
1667 [ # # ]: 0 : if (r < 0)
1668 : 0 : return r;
1669 : :
1670 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1671 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
1672 [ # # ]: 0 : if (!uid_is_valid(uid))
1673 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User ID invalid: " UID_FMT, uid);
1674 : :
1675 : 0 : r = dynamic_user_lookup_uid(m, uid, &name);
1676 [ # # ]: 0 : if (r == -ESRCH)
1677 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user ID " UID_FMT " does not exist.", uid);
1678 [ # # ]: 0 : if (r < 0)
1679 : 0 : return r;
1680 : :
1681 : 0 : return sd_bus_reply_method_return(message, "s", name);
1682 : : }
1683 : :
1684 : 0 : static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1685 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1686 : 0 : Manager *m = userdata;
1687 : : DynamicUser *d;
1688 : : Iterator i;
1689 : : int r;
1690 : :
1691 [ # # ]: 0 : assert(message);
1692 [ # # ]: 0 : assert(m);
1693 : :
1694 : : assert_cc(sizeof(uid_t) == sizeof(uint32_t));
1695 : :
1696 [ # # ]: 0 : if (!MANAGER_IS_SYSTEM(m))
1697 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
1698 : :
1699 : 0 : r = sd_bus_message_new_method_return(message, &reply);
1700 [ # # ]: 0 : if (r < 0)
1701 : 0 : return r;
1702 : :
1703 : 0 : r = sd_bus_message_open_container(reply, 'a', "(us)");
1704 [ # # ]: 0 : if (r < 0)
1705 : 0 : return r;
1706 : :
1707 [ # # ]: 0 : HASHMAP_FOREACH(d, m->dynamic_users, i) {
1708 : : uid_t uid;
1709 : :
1710 : 0 : r = dynamic_user_current(d, &uid);
1711 [ # # ]: 0 : if (r == -EAGAIN) /* not realized yet? */
1712 : 0 : continue;
1713 [ # # ]: 0 : if (r < 0)
1714 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to lookup a dynamic user.");
1715 : :
1716 : 0 : r = sd_bus_message_append(reply, "(us)", uid, d->name);
1717 [ # # ]: 0 : if (r < 0)
1718 : 0 : return r;
1719 : : }
1720 : :
1721 : 0 : r = sd_bus_message_close_container(reply);
1722 [ # # ]: 0 : if (r < 0)
1723 : 0 : return r;
1724 : :
1725 : 0 : return sd_bus_send(NULL, reply, NULL);
1726 : : }
1727 : :
1728 : 0 : static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) {
1729 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1730 : 0 : Manager *m = userdata;
1731 : : UnitFileList *item;
1732 : : Hashmap *h;
1733 : : Iterator i;
1734 : : int r;
1735 : :
1736 [ # # ]: 0 : assert(message);
1737 [ # # ]: 0 : assert(m);
1738 : :
1739 : : /* Anyone can call this method */
1740 : :
1741 : 0 : r = mac_selinux_access_check(message, "status", error);
1742 [ # # ]: 0 : if (r < 0)
1743 : 0 : return r;
1744 : :
1745 : 0 : r = sd_bus_message_new_method_return(message, &reply);
1746 [ # # ]: 0 : if (r < 0)
1747 : 0 : return r;
1748 : :
1749 : 0 : h = hashmap_new(&string_hash_ops);
1750 [ # # ]: 0 : if (!h)
1751 : 0 : return -ENOMEM;
1752 : :
1753 : 0 : r = unit_file_get_list(m->unit_file_scope, NULL, h, states, patterns);
1754 [ # # ]: 0 : if (r < 0)
1755 : 0 : goto fail;
1756 : :
1757 : 0 : r = sd_bus_message_open_container(reply, 'a', "(ss)");
1758 [ # # ]: 0 : if (r < 0)
1759 : 0 : goto fail;
1760 : :
1761 [ # # ]: 0 : HASHMAP_FOREACH(item, h, i) {
1762 : :
1763 : 0 : r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
1764 [ # # ]: 0 : if (r < 0)
1765 : 0 : goto fail;
1766 : : }
1767 : :
1768 : 0 : unit_file_list_free(h);
1769 : :
1770 : 0 : r = sd_bus_message_close_container(reply);
1771 [ # # ]: 0 : if (r < 0)
1772 : 0 : return r;
1773 : :
1774 : 0 : return sd_bus_send(NULL, reply, NULL);
1775 : :
1776 : 0 : fail:
1777 : 0 : unit_file_list_free(h);
1778 : 0 : return r;
1779 : : }
1780 : :
1781 : 0 : static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1782 : 0 : return list_unit_files_by_patterns(message, userdata, error, NULL, NULL);
1783 : : }
1784 : :
1785 : 0 : static int method_list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1786 : 0 : _cleanup_strv_free_ char **states = NULL;
1787 : 0 : _cleanup_strv_free_ char **patterns = NULL;
1788 : : int r;
1789 : :
1790 : 0 : r = sd_bus_message_read_strv(message, &states);
1791 [ # # ]: 0 : if (r < 0)
1792 : 0 : return r;
1793 : :
1794 : 0 : r = sd_bus_message_read_strv(message, &patterns);
1795 [ # # ]: 0 : if (r < 0)
1796 : 0 : return r;
1797 : :
1798 : 0 : return list_unit_files_by_patterns(message, userdata, error, states, patterns);
1799 : : }
1800 : :
1801 : 0 : static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1802 : 0 : Manager *m = userdata;
1803 : : const char *name;
1804 : : UnitFileState state;
1805 : : int r;
1806 : :
1807 [ # # ]: 0 : assert(message);
1808 [ # # ]: 0 : assert(m);
1809 : :
1810 : : /* Anyone can call this method */
1811 : :
1812 : 0 : r = mac_selinux_access_check(message, "status", error);
1813 [ # # ]: 0 : if (r < 0)
1814 : 0 : return r;
1815 : :
1816 : 0 : r = sd_bus_message_read(message, "s", &name);
1817 [ # # ]: 0 : if (r < 0)
1818 : 0 : return r;
1819 : :
1820 : 0 : r = unit_file_get_state(m->unit_file_scope, NULL, name, &state);
1821 [ # # ]: 0 : if (r < 0)
1822 : 0 : return r;
1823 : :
1824 : 0 : return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
1825 : : }
1826 : :
1827 : 0 : static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1828 : 0 : _cleanup_free_ char *default_target = NULL;
1829 : 0 : Manager *m = userdata;
1830 : : int r;
1831 : :
1832 [ # # ]: 0 : assert(message);
1833 [ # # ]: 0 : assert(m);
1834 : :
1835 : : /* Anyone can call this method */
1836 : :
1837 : 0 : r = mac_selinux_access_check(message, "status", error);
1838 [ # # ]: 0 : if (r < 0)
1839 : 0 : return r;
1840 : :
1841 : 0 : r = unit_file_get_default(m->unit_file_scope, NULL, &default_target);
1842 [ # # ]: 0 : if (r < 0)
1843 : 0 : return r;
1844 : :
1845 : 0 : return sd_bus_reply_method_return(message, "s", default_target);
1846 : : }
1847 : :
1848 : 0 : static int send_unit_files_changed(sd_bus *bus, void *userdata) {
1849 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
1850 : : int r;
1851 : :
1852 [ # # ]: 0 : assert(bus);
1853 : :
1854 : 0 : r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
1855 [ # # ]: 0 : if (r < 0)
1856 : 0 : return r;
1857 : :
1858 : 0 : return sd_bus_send(bus, message, NULL);
1859 : : }
1860 : :
1861 : : /* Create an error reply, using the error information from changes[]
1862 : : * if possible, and fall back to generating an error from error code c.
1863 : : * The error message only describes the first error.
1864 : : *
1865 : : * Coordinate with unit_file_dump_changes() in install.c.
1866 : : */
1867 : 0 : static int install_error(
1868 : : sd_bus_error *error,
1869 : : int c,
1870 : : UnitFileChange *changes,
1871 : : size_t n_changes) {
1872 : :
1873 : : size_t i;
1874 : : int r;
1875 : :
1876 [ # # ]: 0 : for (i = 0; i < n_changes; i++)
1877 : :
1878 [ # # # # : 0 : switch(changes[i].type) {
# # # ]
1879 : :
1880 : 0 : case 0 ... INT_MAX:
1881 : 0 : continue;
1882 : :
1883 : 0 : case -EEXIST:
1884 [ # # ]: 0 : if (changes[i].source)
1885 : 0 : r = sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS,
1886 : : "File %s already exists and is a symlink to %s.",
1887 : 0 : changes[i].path, changes[i].source);
1888 : : else
1889 : 0 : r = sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS,
1890 : : "File %s already exists.",
1891 : 0 : changes[i].path);
1892 : 0 : goto found;
1893 : :
1894 : 0 : case -ERFKILL:
1895 : 0 : r = sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED,
1896 : 0 : "Unit file %s is masked.", changes[i].path);
1897 : 0 : goto found;
1898 : :
1899 : 0 : case -EADDRNOTAVAIL:
1900 : 0 : r = sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED,
1901 : 0 : "Unit %s is transient or generated.", changes[i].path);
1902 : 0 : goto found;
1903 : :
1904 : 0 : case -ELOOP:
1905 : 0 : r = sd_bus_error_setf(error, BUS_ERROR_UNIT_LINKED,
1906 : 0 : "Refusing to operate on linked unit file %s", changes[i].path);
1907 : 0 : goto found;
1908 : :
1909 : 0 : case -ENOENT:
1910 : 0 : r = sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit file %s does not exist.", changes[i].path);
1911 : 0 : goto found;
1912 : :
1913 : 0 : default:
1914 : 0 : r = sd_bus_error_set_errnof(error, changes[i].type, "File %s: %m", changes[i].path);
1915 : 0 : goto found;
1916 : : }
1917 : :
1918 [ # # ]: 0 : r = c < 0 ? c : -EINVAL;
1919 : :
1920 : 0 : found:
1921 : 0 : unit_file_changes_free(changes, n_changes);
1922 : 0 : return r;
1923 : : }
1924 : :
1925 : 0 : static int reply_unit_file_changes_and_free(
1926 : : Manager *m,
1927 : : sd_bus_message *message,
1928 : : int carries_install_info,
1929 : : UnitFileChange *changes,
1930 : : size_t n_changes,
1931 : : sd_bus_error *error) {
1932 : :
1933 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1934 : 0 : bool bad = false, good = false;
1935 : : size_t i;
1936 : : int r;
1937 : :
1938 [ # # ]: 0 : if (unit_file_changes_have_modification(changes, n_changes)) {
1939 : 0 : r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
1940 [ # # ]: 0 : if (r < 0)
1941 [ # # ]: 0 : log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
1942 : : }
1943 : :
1944 : 0 : r = sd_bus_message_new_method_return(message, &reply);
1945 [ # # ]: 0 : if (r < 0)
1946 : 0 : goto fail;
1947 : :
1948 [ # # ]: 0 : if (carries_install_info >= 0) {
1949 : 0 : r = sd_bus_message_append(reply, "b", carries_install_info);
1950 [ # # ]: 0 : if (r < 0)
1951 : 0 : goto fail;
1952 : : }
1953 : :
1954 : 0 : r = sd_bus_message_open_container(reply, 'a', "(sss)");
1955 [ # # ]: 0 : if (r < 0)
1956 : 0 : goto fail;
1957 : :
1958 [ # # ]: 0 : for (i = 0; i < n_changes; i++) {
1959 : :
1960 [ # # ]: 0 : if (changes[i].type < 0) {
1961 : 0 : bad = true;
1962 : 0 : continue;
1963 : : }
1964 : :
1965 : 0 : r = sd_bus_message_append(
1966 : : reply, "(sss)",
1967 : 0 : unit_file_change_type_to_string(changes[i].type),
1968 : 0 : changes[i].path,
1969 : 0 : changes[i].source);
1970 [ # # ]: 0 : if (r < 0)
1971 : 0 : goto fail;
1972 : :
1973 : 0 : good = true;
1974 : : }
1975 : :
1976 : : /* If there was a failed change, and no successful change, then return the first failure as proper method call
1977 : : * error. */
1978 [ # # # # ]: 0 : if (bad && !good)
1979 : 0 : return install_error(error, 0, changes, n_changes);
1980 : :
1981 : 0 : r = sd_bus_message_close_container(reply);
1982 [ # # ]: 0 : if (r < 0)
1983 : 0 : goto fail;
1984 : :
1985 : 0 : unit_file_changes_free(changes, n_changes);
1986 : 0 : return sd_bus_send(NULL, reply, NULL);
1987 : :
1988 : 0 : fail:
1989 : 0 : unit_file_changes_free(changes, n_changes);
1990 : 0 : return r;
1991 : : }
1992 : :
1993 : 0 : static int method_enable_unit_files_generic(
1994 : : sd_bus_message *message,
1995 : : Manager *m,
1996 : : int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes),
1997 : : bool carries_install_info,
1998 : : sd_bus_error *error) {
1999 : :
2000 : 0 : _cleanup_strv_free_ char **l = NULL;
2001 : 0 : UnitFileChange *changes = NULL;
2002 : 0 : size_t n_changes = 0;
2003 : : UnitFileFlags flags;
2004 : : int runtime, force, r;
2005 : :
2006 [ # # ]: 0 : assert(message);
2007 [ # # ]: 0 : assert(m);
2008 : :
2009 : 0 : r = sd_bus_message_read_strv(message, &l);
2010 [ # # ]: 0 : if (r < 0)
2011 : 0 : return r;
2012 : :
2013 : 0 : r = sd_bus_message_read(message, "bb", &runtime, &force);
2014 [ # # ]: 0 : if (r < 0)
2015 : 0 : return r;
2016 : :
2017 : 0 : flags = unit_file_bools_to_flags(runtime, force);
2018 : :
2019 : 0 : r = bus_verify_manage_unit_files_async(m, message, error);
2020 [ # # ]: 0 : if (r < 0)
2021 : 0 : return r;
2022 [ # # ]: 0 : if (r == 0)
2023 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2024 : :
2025 : 0 : r = call(m->unit_file_scope, flags, NULL, l, &changes, &n_changes);
2026 [ # # ]: 0 : if (r < 0)
2027 : 0 : return install_error(error, r, changes, n_changes);
2028 : :
2029 [ # # ]: 0 : return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error);
2030 : : }
2031 : :
2032 : 0 : static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2033 : 0 : return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error);
2034 : : }
2035 : :
2036 : 0 : static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2037 : 0 : return method_enable_unit_files_generic(message, userdata, unit_file_reenable, true, error);
2038 : : }
2039 : :
2040 : 0 : static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2041 : 0 : return method_enable_unit_files_generic(message, userdata, unit_file_link, false, error);
2042 : : }
2043 : :
2044 : 0 : static int unit_file_preset_without_mode(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, size_t *n_changes) {
2045 : 0 : return unit_file_preset(scope, flags, root_dir, files, UNIT_FILE_PRESET_FULL, changes, n_changes);
2046 : : }
2047 : :
2048 : 0 : static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2049 : 0 : return method_enable_unit_files_generic(message, userdata, unit_file_preset_without_mode, true, error);
2050 : : }
2051 : :
2052 : 0 : static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2053 : 0 : return method_enable_unit_files_generic(message, userdata, unit_file_mask, false, error);
2054 : : }
2055 : :
2056 : 0 : static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2057 : :
2058 : 0 : _cleanup_strv_free_ char **l = NULL;
2059 : 0 : UnitFileChange *changes = NULL;
2060 : 0 : size_t n_changes = 0;
2061 : 0 : Manager *m = userdata;
2062 : : UnitFilePresetMode mm;
2063 : : int runtime, force, r;
2064 : : UnitFileFlags flags;
2065 : : const char *mode;
2066 : :
2067 [ # # ]: 0 : assert(message);
2068 [ # # ]: 0 : assert(m);
2069 : :
2070 : 0 : r = sd_bus_message_read_strv(message, &l);
2071 [ # # ]: 0 : if (r < 0)
2072 : 0 : return r;
2073 : :
2074 : 0 : r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
2075 [ # # ]: 0 : if (r < 0)
2076 : 0 : return r;
2077 : :
2078 : 0 : flags = unit_file_bools_to_flags(runtime, force);
2079 : :
2080 [ # # ]: 0 : if (isempty(mode))
2081 : 0 : mm = UNIT_FILE_PRESET_FULL;
2082 : : else {
2083 : 0 : mm = unit_file_preset_mode_from_string(mode);
2084 [ # # ]: 0 : if (mm < 0)
2085 : 0 : return -EINVAL;
2086 : : }
2087 : :
2088 : 0 : r = bus_verify_manage_unit_files_async(m, message, error);
2089 [ # # ]: 0 : if (r < 0)
2090 : 0 : return r;
2091 [ # # ]: 0 : if (r == 0)
2092 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2093 : :
2094 : 0 : r = unit_file_preset(m->unit_file_scope, flags, NULL, l, mm, &changes, &n_changes);
2095 [ # # ]: 0 : if (r < 0)
2096 : 0 : return install_error(error, r, changes, n_changes);
2097 : :
2098 : 0 : return reply_unit_file_changes_and_free(m, message, r, changes, n_changes, error);
2099 : : }
2100 : :
2101 : 0 : static int method_disable_unit_files_generic(
2102 : : sd_bus_message *message,
2103 : : Manager *m,
2104 : : int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes),
2105 : : sd_bus_error *error) {
2106 : :
2107 : 0 : _cleanup_strv_free_ char **l = NULL;
2108 : 0 : UnitFileChange *changes = NULL;
2109 : 0 : size_t n_changes = 0;
2110 : : int r, runtime;
2111 : :
2112 [ # # ]: 0 : assert(message);
2113 [ # # ]: 0 : assert(m);
2114 : :
2115 : 0 : r = sd_bus_message_read_strv(message, &l);
2116 [ # # ]: 0 : if (r < 0)
2117 : 0 : return r;
2118 : :
2119 : 0 : r = sd_bus_message_read(message, "b", &runtime);
2120 [ # # ]: 0 : if (r < 0)
2121 : 0 : return r;
2122 : :
2123 : 0 : r = bus_verify_manage_unit_files_async(m, message, error);
2124 [ # # ]: 0 : if (r < 0)
2125 : 0 : return r;
2126 [ # # ]: 0 : if (r == 0)
2127 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2128 : :
2129 : 0 : r = call(m->unit_file_scope, runtime ? UNIT_FILE_RUNTIME : 0, NULL, l, &changes, &n_changes);
2130 [ # # ]: 0 : if (r < 0)
2131 : 0 : return install_error(error, r, changes, n_changes);
2132 : :
2133 : 0 : return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
2134 : : }
2135 : :
2136 : 0 : static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2137 : 0 : return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
2138 : : }
2139 : :
2140 : 0 : static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2141 : 0 : return method_disable_unit_files_generic(message, userdata, unit_file_unmask, error);
2142 : : }
2143 : :
2144 : 0 : static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2145 : 0 : _cleanup_strv_free_ char **l = NULL;
2146 : 0 : UnitFileChange *changes = NULL;
2147 : 0 : size_t n_changes = 0;
2148 : 0 : Manager *m = userdata;
2149 : : int r;
2150 : :
2151 [ # # ]: 0 : assert(message);
2152 [ # # ]: 0 : assert(m);
2153 : :
2154 : 0 : r = sd_bus_message_read_strv(message, &l);
2155 [ # # ]: 0 : if (r < 0)
2156 : 0 : return r;
2157 : :
2158 : 0 : r = bus_verify_manage_unit_files_async(m, message, error);
2159 [ # # ]: 0 : if (r < 0)
2160 : 0 : return r;
2161 [ # # ]: 0 : if (r == 0)
2162 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2163 : :
2164 : 0 : r = unit_file_revert(m->unit_file_scope, NULL, l, &changes, &n_changes);
2165 [ # # ]: 0 : if (r < 0)
2166 : 0 : return install_error(error, r, changes, n_changes);
2167 : :
2168 : 0 : return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
2169 : : }
2170 : :
2171 : 0 : static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2172 : 0 : UnitFileChange *changes = NULL;
2173 : 0 : size_t n_changes = 0;
2174 : 0 : Manager *m = userdata;
2175 : : const char *name;
2176 : : int force, r;
2177 : :
2178 [ # # ]: 0 : assert(message);
2179 [ # # ]: 0 : assert(m);
2180 : :
2181 : 0 : r = mac_selinux_access_check(message, "enable", error);
2182 [ # # ]: 0 : if (r < 0)
2183 : 0 : return r;
2184 : :
2185 : 0 : r = sd_bus_message_read(message, "sb", &name, &force);
2186 [ # # ]: 0 : if (r < 0)
2187 : 0 : return r;
2188 : :
2189 : 0 : r = bus_verify_manage_unit_files_async(m, message, error);
2190 [ # # ]: 0 : if (r < 0)
2191 : 0 : return r;
2192 [ # # ]: 0 : if (r == 0)
2193 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2194 : :
2195 [ # # ]: 0 : r = unit_file_set_default(m->unit_file_scope, force ? UNIT_FILE_FORCE : 0, NULL, name, &changes, &n_changes);
2196 [ # # ]: 0 : if (r < 0)
2197 : 0 : return install_error(error, r, changes, n_changes);
2198 : :
2199 : 0 : return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
2200 : : }
2201 : :
2202 : 0 : static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2203 : 0 : UnitFileChange *changes = NULL;
2204 : 0 : size_t n_changes = 0;
2205 : 0 : Manager *m = userdata;
2206 : : UnitFilePresetMode mm;
2207 : : const char *mode;
2208 : : UnitFileFlags flags;
2209 : : int force, runtime, r;
2210 : :
2211 [ # # ]: 0 : assert(message);
2212 [ # # ]: 0 : assert(m);
2213 : :
2214 : 0 : r = mac_selinux_access_check(message, "enable", error);
2215 [ # # ]: 0 : if (r < 0)
2216 : 0 : return r;
2217 : :
2218 : 0 : r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
2219 [ # # ]: 0 : if (r < 0)
2220 : 0 : return r;
2221 : :
2222 : 0 : flags = unit_file_bools_to_flags(runtime, force);
2223 : :
2224 [ # # ]: 0 : if (isempty(mode))
2225 : 0 : mm = UNIT_FILE_PRESET_FULL;
2226 : : else {
2227 : 0 : mm = unit_file_preset_mode_from_string(mode);
2228 [ # # ]: 0 : if (mm < 0)
2229 : 0 : return -EINVAL;
2230 : : }
2231 : :
2232 : 0 : r = bus_verify_manage_unit_files_async(m, message, error);
2233 [ # # ]: 0 : if (r < 0)
2234 : 0 : return r;
2235 [ # # ]: 0 : if (r == 0)
2236 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2237 : :
2238 : 0 : r = unit_file_preset_all(m->unit_file_scope, flags, NULL, mm, &changes, &n_changes);
2239 [ # # ]: 0 : if (r < 0)
2240 : 0 : return install_error(error, r, changes, n_changes);
2241 : :
2242 : 0 : return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
2243 : : }
2244 : :
2245 : 0 : static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2246 : 0 : _cleanup_strv_free_ char **l = NULL;
2247 : 0 : Manager *m = userdata;
2248 : 0 : UnitFileChange *changes = NULL;
2249 : 0 : size_t n_changes = 0;
2250 : : int runtime, force, r;
2251 : : char *target, *type;
2252 : : UnitDependency dep;
2253 : : UnitFileFlags flags;
2254 : :
2255 [ # # ]: 0 : assert(message);
2256 [ # # ]: 0 : assert(m);
2257 : :
2258 : 0 : r = bus_verify_manage_unit_files_async(m, message, error);
2259 [ # # ]: 0 : if (r < 0)
2260 : 0 : return r;
2261 [ # # ]: 0 : if (r == 0)
2262 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2263 : :
2264 : 0 : r = sd_bus_message_read_strv(message, &l);
2265 [ # # ]: 0 : if (r < 0)
2266 : 0 : return r;
2267 : :
2268 : 0 : r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force);
2269 [ # # ]: 0 : if (r < 0)
2270 : 0 : return r;
2271 : :
2272 : 0 : flags = unit_file_bools_to_flags(runtime, force);
2273 : :
2274 : 0 : dep = unit_dependency_from_string(type);
2275 [ # # ]: 0 : if (dep < 0)
2276 : 0 : return -EINVAL;
2277 : :
2278 : 0 : r = unit_file_add_dependency(m->unit_file_scope, flags, NULL, l, target, dep, &changes, &n_changes);
2279 [ # # ]: 0 : if (r < 0)
2280 : 0 : return install_error(error, r, changes, n_changes);
2281 : :
2282 : 0 : return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
2283 : : }
2284 : :
2285 : 0 : static int method_get_unit_file_links(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2286 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2287 : 0 : UnitFileChange *changes = NULL;
2288 : 0 : size_t n_changes = 0, i;
2289 : : UnitFileFlags flags;
2290 : : const char *name;
2291 : : char **p;
2292 : : int runtime, r;
2293 : :
2294 : 0 : r = sd_bus_message_read(message, "sb", &name, &runtime);
2295 [ # # ]: 0 : if (r < 0)
2296 : 0 : return r;
2297 : :
2298 : 0 : r = sd_bus_message_new_method_return(message, &reply);
2299 [ # # ]: 0 : if (r < 0)
2300 : 0 : return r;
2301 : :
2302 : 0 : r = sd_bus_message_open_container(reply, SD_BUS_TYPE_ARRAY, "s");
2303 [ # # ]: 0 : if (r < 0)
2304 : 0 : return r;
2305 : :
2306 : 0 : p = STRV_MAKE(name);
2307 : 0 : flags = UNIT_FILE_DRY_RUN |
2308 [ # # ]: 0 : (runtime ? UNIT_FILE_RUNTIME : 0);
2309 : :
2310 : 0 : r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes);
2311 [ # # ]: 0 : if (r < 0)
2312 [ # # ]: 0 : return log_error_errno(r, "Failed to get file links for %s: %m", name);
2313 : :
2314 [ # # ]: 0 : for (i = 0; i < n_changes; i++)
2315 [ # # ]: 0 : if (changes[i].type == UNIT_FILE_UNLINK) {
2316 : 0 : r = sd_bus_message_append(reply, "s", changes[i].path);
2317 [ # # ]: 0 : if (r < 0)
2318 : 0 : return r;
2319 : : }
2320 : :
2321 : 0 : r = sd_bus_message_close_container(reply);
2322 [ # # ]: 0 : if (r < 0)
2323 : 0 : return r;
2324 : :
2325 : 0 : return sd_bus_send(NULL, reply, NULL);
2326 : : }
2327 : :
2328 : 0 : static int method_get_job_waiting(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2329 : 0 : Manager *m = userdata;
2330 : : uint32_t id;
2331 : : Job *j;
2332 : : int r;
2333 : :
2334 [ # # ]: 0 : assert(message);
2335 [ # # ]: 0 : assert(m);
2336 : :
2337 : 0 : r = sd_bus_message_read(message, "u", &id);
2338 [ # # ]: 0 : if (r < 0)
2339 : 0 : return r;
2340 : :
2341 : 0 : j = manager_get_job(m, id);
2342 [ # # ]: 0 : if (!j)
2343 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
2344 : :
2345 : 0 : return bus_job_method_get_waiting_jobs(message, j, error);
2346 : : }
2347 : :
2348 : 0 : static int method_abandon_scope(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2349 : 0 : Manager *m = userdata;
2350 : : const char *name;
2351 : : Unit *u;
2352 : : int r;
2353 : :
2354 [ # # ]: 0 : assert(message);
2355 [ # # ]: 0 : assert(m);
2356 : :
2357 : 0 : r = sd_bus_message_read(message, "s", &name);
2358 [ # # ]: 0 : if (r < 0)
2359 : 0 : return r;
2360 : :
2361 : 0 : r = bus_get_unit_by_name(m, message, name, &u, error);
2362 [ # # ]: 0 : if (r < 0)
2363 : 0 : return r;
2364 : :
2365 [ # # ]: 0 : if (u->type != UNIT_SCOPE)
2366 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit '%s' is not a scope unit, refusing.", name);
2367 : :
2368 : 0 : return bus_scope_method_abandon(message, u, error);
2369 : : }
2370 : :
2371 : : const sd_bus_vtable bus_manager_vtable[] = {
2372 : : SD_BUS_VTABLE_START(0),
2373 : :
2374 : : SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2375 : : SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2376 : : SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2377 : : SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2378 : : SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2379 : : BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_FIRMWARE]), SD_BUS_VTABLE_PROPERTY_CONST),
2380 : : BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_LOADER]), SD_BUS_VTABLE_PROPERTY_CONST),
2381 : : BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_KERNEL]), SD_BUS_VTABLE_PROPERTY_CONST),
2382 : : BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD]), SD_BUS_VTABLE_PROPERTY_CONST),
2383 : : BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_USERSPACE]), SD_BUS_VTABLE_PROPERTY_CONST),
2384 : : BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
2385 : : BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_SECURITY_START]), SD_BUS_VTABLE_PROPERTY_CONST),
2386 : : BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_SECURITY_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
2387 : : BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_GENERATORS_START]), SD_BUS_VTABLE_PROPERTY_CONST),
2388 : : BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_GENERATORS_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
2389 : : BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_START]), SD_BUS_VTABLE_PROPERTY_CONST),
2390 : : BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
2391 : : BUS_PROPERTY_DUAL_TIMESTAMP("InitRDSecurityStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_SECURITY_START]), SD_BUS_VTABLE_PROPERTY_CONST),
2392 : : BUS_PROPERTY_DUAL_TIMESTAMP("InitRDSecurityFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
2393 : : BUS_PROPERTY_DUAL_TIMESTAMP("InitRDGeneratorsStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_GENERATORS_START]), SD_BUS_VTABLE_PROPERTY_CONST),
2394 : : BUS_PROPERTY_DUAL_TIMESTAMP("InitRDGeneratorsFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
2395 : : BUS_PROPERTY_DUAL_TIMESTAMP("InitRDUnitsLoadStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START]), SD_BUS_VTABLE_PROPERTY_CONST),
2396 : : BUS_PROPERTY_DUAL_TIMESTAMP("InitRDUnitsLoadFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
2397 : : SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
2398 : : SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
2399 : : SD_BUS_PROPERTY("NNames", "u", property_get_hashmap_size, offsetof(Manager, units), 0),
2400 : : SD_BUS_PROPERTY("NFailedUnits", "u", property_get_set_size, offsetof(Manager, failed_units), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2401 : : SD_BUS_PROPERTY("NJobs", "u", property_get_hashmap_size, offsetof(Manager, jobs), 0),
2402 : : SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
2403 : : SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
2404 : : SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
2405 : : SD_BUS_PROPERTY("Environment", "as", property_get_environment, 0, 0),
2406 : : SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
2407 : : SD_BUS_PROPERTY("ShowStatus", "b", property_get_show_status, 0, 0),
2408 : : SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.search_path), SD_BUS_VTABLE_PROPERTY_CONST),
2409 : : SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
2410 : : SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
2411 : : SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
2412 : : SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), 0),
2413 : : /* The following item is an obsolete alias */
2414 : : SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), SD_BUS_VTABLE_HIDDEN),
2415 : : SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0),
2416 : : SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0),
2417 : : SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
2418 : : SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
2419 : : SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0),
2420 : : SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2421 : : SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2422 : : SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2423 : : SD_BUS_PROPERTY("DefaultTimeoutAbortUSec", "t", property_get_default_timeout_abort_usec, 0, 0),
2424 : : SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2425 : : SD_BUS_PROPERTY("DefaultStartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
2426 : : /* The following two items are obsolete alias */
2427 : : SD_BUS_PROPERTY("DefaultStartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
2428 : : SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
2429 : : SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
2430 : : SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
2431 : : SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
2432 : : SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
2433 : : SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
2434 : : SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
2435 : : SD_BUS_PROPERTY("DefaultLimitCPUSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
2436 : : SD_BUS_PROPERTY("DefaultLimitFSIZE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
2437 : : SD_BUS_PROPERTY("DefaultLimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
2438 : : SD_BUS_PROPERTY("DefaultLimitDATA", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
2439 : : SD_BUS_PROPERTY("DefaultLimitDATASoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
2440 : : SD_BUS_PROPERTY("DefaultLimitSTACK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
2441 : : SD_BUS_PROPERTY("DefaultLimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
2442 : : SD_BUS_PROPERTY("DefaultLimitCORE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
2443 : : SD_BUS_PROPERTY("DefaultLimitCORESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
2444 : : SD_BUS_PROPERTY("DefaultLimitRSS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
2445 : : SD_BUS_PROPERTY("DefaultLimitRSSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
2446 : : SD_BUS_PROPERTY("DefaultLimitNOFILE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
2447 : : SD_BUS_PROPERTY("DefaultLimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
2448 : : SD_BUS_PROPERTY("DefaultLimitAS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
2449 : : SD_BUS_PROPERTY("DefaultLimitASSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
2450 : : SD_BUS_PROPERTY("DefaultLimitNPROC", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
2451 : : SD_BUS_PROPERTY("DefaultLimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
2452 : : SD_BUS_PROPERTY("DefaultLimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
2453 : : SD_BUS_PROPERTY("DefaultLimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
2454 : : SD_BUS_PROPERTY("DefaultLimitLOCKS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
2455 : : SD_BUS_PROPERTY("DefaultLimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
2456 : : SD_BUS_PROPERTY("DefaultLimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
2457 : : SD_BUS_PROPERTY("DefaultLimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
2458 : : SD_BUS_PROPERTY("DefaultLimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
2459 : : SD_BUS_PROPERTY("DefaultLimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
2460 : : SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
2461 : : SD_BUS_PROPERTY("DefaultLimitNICESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
2462 : : SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
2463 : : SD_BUS_PROPERTY("DefaultLimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
2464 : : SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
2465 : : SD_BUS_PROPERTY("DefaultLimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
2466 : : SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2467 : : SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2468 : : SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, default_oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),
2469 : :
2470 : : SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2471 : : SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2472 : : SD_BUS_METHOD("GetUnitByInvocationID", "ay", "o", method_get_unit_by_invocation_id, SD_BUS_VTABLE_UNPRIVILEGED),
2473 : : SD_BUS_METHOD("GetUnitByControlGroup", "s", "o", method_get_unit_by_control_group, SD_BUS_VTABLE_UNPRIVILEGED),
2474 : : SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2475 : : SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2476 : : SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
2477 : : SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2478 : : SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2479 : : SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2480 : : SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2481 : : SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2482 : : SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2483 : : SD_BUS_METHOD("EnqueueUnitJob", "sss", "uososa(uosos)", method_enqueue_unit_job, SD_BUS_VTABLE_UNPRIVILEGED),
2484 : : SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2485 : : SD_BUS_METHOD("CleanUnit", "sas", NULL, method_clean_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2486 : : SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2487 : : SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
2488 : : SD_BUS_METHOD("RefUnit", "s", NULL, method_ref_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2489 : : SD_BUS_METHOD("UnrefUnit", "s", NULL, method_unref_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2490 : : SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2491 : : SD_BUS_METHOD("GetUnitProcesses", "s", "a(sus)", method_get_unit_processes, SD_BUS_VTABLE_UNPRIVILEGED),
2492 : : SD_BUS_METHOD("AttachProcessesToUnit", "ssau", NULL, method_attach_processes_to_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2493 : : SD_BUS_METHOD("AbandonScope", "s", NULL, method_abandon_scope, SD_BUS_VTABLE_UNPRIVILEGED),
2494 : : SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
2495 : : SD_BUS_METHOD("GetJobAfter", "u", "a(usssoo)", method_get_job_waiting, SD_BUS_VTABLE_UNPRIVILEGED),
2496 : : SD_BUS_METHOD("GetJobBefore", "u", "a(usssoo)", method_get_job_waiting, SD_BUS_VTABLE_UNPRIVILEGED),
2497 : : SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED),
2498 : : SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
2499 : : SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
2500 : : SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
2501 : : SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED),
2502 : : SD_BUS_METHOD("ListUnitsByPatterns", "asas", "a(ssssssouso)", method_list_units_by_patterns, SD_BUS_VTABLE_UNPRIVILEGED),
2503 : : SD_BUS_METHOD("ListUnitsByNames", "as", "a(ssssssouso)", method_list_units_by_names, SD_BUS_VTABLE_UNPRIVILEGED),
2504 : : SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
2505 : : SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
2506 : : SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
2507 : : SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
2508 : : SD_BUS_METHOD("DumpByFileDescriptor", NULL, "h", method_dump_by_fd, SD_BUS_VTABLE_UNPRIVILEGED),
2509 : : SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN),
2510 : : SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN),
2511 : : SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
2512 : : SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
2513 : : SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
2514 : : SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2515 : : SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2516 : : SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2517 : : SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2518 : : SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2519 : : SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
2520 : : SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, SD_BUS_VTABLE_UNPRIVILEGED),
2521 : : SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
2522 : : SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2523 : : SD_BUS_METHOD("ListUnitFilesByPatterns", "asas", "a(ss)", method_list_unit_files_by_patterns, SD_BUS_VTABLE_UNPRIVILEGED),
2524 : : SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
2525 : : SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2526 : : SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2527 : : SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2528 : : SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2529 : : SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2530 : : SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED),
2531 : : SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2532 : : SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2533 : : SD_BUS_METHOD("RevertUnitFiles", "as", "a(sss)", method_revert_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2534 : : SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
2535 : : SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
2536 : : SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2537 : : SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2538 : : SD_BUS_METHOD("GetUnitFileLinks", "sb", "as", method_get_unit_file_links, SD_BUS_VTABLE_UNPRIVILEGED),
2539 : : SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED),
2540 : : SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
2541 : : SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED),
2542 : : SD_BUS_METHOD("GetDynamicUsers", NULL, "a(us)", method_get_dynamic_users, SD_BUS_VTABLE_UNPRIVILEGED),
2543 : :
2544 : : SD_BUS_SIGNAL("UnitNew", "so", 0),
2545 : : SD_BUS_SIGNAL("UnitRemoved", "so", 0),
2546 : : SD_BUS_SIGNAL("JobNew", "uos", 0),
2547 : : SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
2548 : : SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
2549 : : SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
2550 : : SD_BUS_SIGNAL("Reloading", "b", 0),
2551 : :
2552 : : SD_BUS_VTABLE_END
2553 : : };
2554 : :
2555 : 0 : static int send_finished(sd_bus *bus, void *userdata) {
2556 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
2557 : 0 : usec_t *times = userdata;
2558 : : int r;
2559 : :
2560 [ # # ]: 0 : assert(bus);
2561 [ # # ]: 0 : assert(times);
2562 : :
2563 : 0 : r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
2564 [ # # ]: 0 : if (r < 0)
2565 : 0 : return r;
2566 : :
2567 : 0 : r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
2568 [ # # ]: 0 : if (r < 0)
2569 : 0 : return r;
2570 : :
2571 : 0 : return sd_bus_send(bus, message, NULL);
2572 : : }
2573 : :
2574 : 0 : void bus_manager_send_finished(
2575 : : Manager *m,
2576 : : usec_t firmware_usec,
2577 : : usec_t loader_usec,
2578 : : usec_t kernel_usec,
2579 : : usec_t initrd_usec,
2580 : : usec_t userspace_usec,
2581 : : usec_t total_usec) {
2582 : :
2583 : : int r;
2584 : :
2585 [ # # ]: 0 : assert(m);
2586 : :
2587 : 0 : r = bus_foreach_bus(
2588 : : m,
2589 : : NULL,
2590 : : send_finished,
2591 : 0 : (usec_t[6]) {
2592 : : firmware_usec,
2593 : : loader_usec,
2594 : : kernel_usec,
2595 : : initrd_usec,
2596 : : userspace_usec,
2597 : : total_usec
2598 : : });
2599 [ # # ]: 0 : if (r < 0)
2600 [ # # ]: 0 : log_debug_errno(r, "Failed to send finished signal: %m");
2601 : 0 : }
2602 : :
2603 : 0 : static int send_reloading(sd_bus *bus, void *userdata) {
2604 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
2605 : : int r;
2606 : :
2607 [ # # ]: 0 : assert(bus);
2608 : :
2609 : 0 : r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
2610 [ # # ]: 0 : if (r < 0)
2611 : 0 : return r;
2612 : :
2613 : 0 : r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
2614 [ # # ]: 0 : if (r < 0)
2615 : 0 : return r;
2616 : :
2617 : 0 : return sd_bus_send(bus, message, NULL);
2618 : : }
2619 : :
2620 : 0 : void bus_manager_send_reloading(Manager *m, bool active) {
2621 : : int r;
2622 : :
2623 [ # # ]: 0 : assert(m);
2624 : :
2625 : 0 : r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active));
2626 [ # # ]: 0 : if (r < 0)
2627 [ # # ]: 0 : log_debug_errno(r, "Failed to send reloading signal: %m");
2628 : 0 : }
2629 : :
2630 : 0 : static int send_changed_signal(sd_bus *bus, void *userdata) {
2631 [ # # ]: 0 : assert(bus);
2632 : :
2633 : 0 : return sd_bus_emit_properties_changed_strv(bus,
2634 : : "/org/freedesktop/systemd1",
2635 : : "org.freedesktop.systemd1.Manager",
2636 : : NULL);
2637 : : }
2638 : :
2639 : 0 : void bus_manager_send_change_signal(Manager *m) {
2640 : : int r;
2641 : :
2642 [ # # ]: 0 : assert(m);
2643 : :
2644 : 0 : r = bus_foreach_bus(m, NULL, send_changed_signal, NULL);
2645 [ # # ]: 0 : if (r < 0)
2646 [ # # ]: 0 : log_debug_errno(r, "Failed to send manager change signal: %m");
2647 : 0 : }
|