]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/bus-unit-util.c
pidref: add trivial helper pidref_set_self() to set pidref to our handle to our own...
[thirdparty/systemd.git] / src / shared / bus-unit-util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
291d565a 2
a4817536 3#include "af-list.h"
291d565a 4#include "alloc-util.h"
e45c81b8 5#include "bus-error.h"
a9399358 6#include "bus-locator.h"
291d565a
LP
7#include "bus-unit-util.h"
8#include "bus-util.h"
cffaed83 9#include "cap-list.h"
fdb3deca 10#include "cgroup-setup.h"
291d565a 11#include "cgroup-util.h"
3d63c749 12#include "condition.h"
ad21e542 13#include "coredump-util.h"
cffaed83 14#include "cpu-set-util.h"
9ece6444 15#include "dissect-image.h"
291d565a 16#include "escape.h"
b3d59367 17#include "exec-util.h"
2e2ed880 18#include "exit-status.h"
0389f4fa 19#include "fileio.h"
dc7d69b3 20#include "firewall-util.h"
08f3be7a 21#include "hexdecoct.h"
3dc5ca97
LP
22#include "hostname-util.h"
23#include "in-addr-util.h"
032b3afb 24#include "ioprio-util.h"
da96ad5a 25#include "ip-protocol-list.h"
b3d13314 26#include "libmount-util.h"
291d565a 27#include "locale-util.h"
e45c81b8 28#include "log.h"
211a3d87 29#include "macro.h"
89382935 30#include "missing_fs.h"
049af8ad 31#include "mountpoint-util.h"
add00535 32#include "nsflags.h"
1808f768 33#include "numa-util.h"
cd48e23f 34#include "open-file.h"
3fb72d63 35#include "parse-helpers.h"
291d565a 36#include "parse-util.h"
0389f4fa 37#include "path-util.h"
ed5033fd 38#include "percent-util.h"
291d565a
LP
39#include "process-util.h"
40#include "rlimit-util.h"
005bfaf1 41#include "seccomp-util.h"
cffaed83 42#include "securebits-util.h"
291d565a 43#include "signal-util.h"
e45c81b8 44#include "socket-util.h"
760877e9 45#include "sort-util.h"
e2b2fb7f 46#include "stdio-util.h"
291d565a
LP
47#include "string-util.h"
48#include "syslog-util.h"
49#include "terminal-util.h"
89ada3ba 50#include "unit-def.h"
cffaed83 51#include "user-util.h"
291d565a 52#include "utf8.h"
291d565a 53
20b16441
LP
54int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
55 assert(message);
56 assert(u);
57
58 u->machine = NULL;
59
60 return sd_bus_message_read(
61 message,
62 "(ssssssouso)",
63 &u->id,
64 &u->description,
65 &u->load_state,
66 &u->active_state,
67 &u->sub_state,
68 &u->following,
69 &u->unit_path,
70 &u->job_id,
71 &u->job_type,
72 &u->job_path);
73}
74
0cf6628e
YW
75#define DEFINE_BUS_APPEND_PARSE_PTR(bus_type, cast_type, type, parse_func) \
76 static int bus_append_##parse_func( \
77 sd_bus_message *m, \
78 const char *field, \
79 const char *eq) { \
80 type val; \
81 int r; \
82 \
83 r = parse_func(eq, &val); \
84 if (r < 0) \
85 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); \
86 \
87 r = sd_bus_message_append(m, "(sv)", field, \
88 bus_type, (cast_type) val); \
89 if (r < 0) \
90 return bus_log_create_error(r); \
91 \
92 return 1; \
f6a8265b 93 }
3dc5ca97 94
0cf6628e
YW
95#define DEFINE_BUS_APPEND_PARSE(bus_type, parse_func) \
96 static int bus_append_##parse_func( \
97 sd_bus_message *m, \
98 const char *field, \
99 const char *eq) { \
100 int r; \
101 \
102 r = parse_func(eq); \
baaa35ad
ZJS
103 if (r < 0) \
104 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse %s: %s", field, eq); \
0cf6628e
YW
105 \
106 r = sd_bus_message_append(m, "(sv)", field, \
107 bus_type, (int32_t) r); \
108 if (r < 0) \
109 return bus_log_create_error(r); \
110 \
111 return 1; \
f6a8265b 112 }
3dc5ca97 113
0cf6628e
YW
114DEFINE_BUS_APPEND_PARSE("b", parse_boolean);
115DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string);
116DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string);
117DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string);
118DEFINE_BUS_APPEND_PARSE("i", log_level_from_string);
005bfaf1 119DEFINE_BUS_APPEND_PARSE("i", seccomp_parse_errno_or_action);
0cf6628e
YW
120DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string);
121DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string);
29a3db75 122DEFINE_BUS_APPEND_PARSE("i", signal_from_string);
d2b42d63 123DEFINE_BUS_APPEND_PARSE("i", parse_ip_protocol);
0cf6628e
YW
124DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority);
125DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice);
126DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, safe_atoi);
127DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, nsec_t, parse_nsec);
128DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_blkio_weight_parse);
129DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_shares_parse);
130DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_weight_parse);
c8340822 131DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_weight_parse);
b205e59a 132DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, unsigned long, mount_propagation_flag_from_string);
0cf6628e
YW
133DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, safe_atou64);
134DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode);
135DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou);
136DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64);
ad21e542 137DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, coredump_filter_mask_from_string);
89ada3ba 138
a1e92eee 139static int bus_append_string(sd_bus_message *m, const char *field, const char *eq) {
89ada3ba
YW
140 int r;
141
142 r = sd_bus_message_append(m, "(sv)", field, "s", eq);
3dc5ca97 143 if (r < 0)
89ada3ba 144 return bus_log_create_error(r);
3dc5ca97 145
89ada3ba
YW
146 return 1;
147}
148
149static int bus_append_strv(sd_bus_message *m, const char *field, const char *eq, ExtractFlags flags) {
150 const char *p;
151 int r;
152
153 r = sd_bus_message_open_container(m, 'r', "sv");
3dc5ca97 154 if (r < 0)
89ada3ba 155 return bus_log_create_error(r);
3dc5ca97 156
89ada3ba 157 r = sd_bus_message_append_basic(m, 's', field);
3dc5ca97 158 if (r < 0)
89ada3ba 159 return bus_log_create_error(r);
3dc5ca97 160
89ada3ba 161 r = sd_bus_message_open_container(m, 'v', "as");
3dc5ca97 162 if (r < 0)
89ada3ba 163 return bus_log_create_error(r);
3dc5ca97 164
89ada3ba
YW
165 r = sd_bus_message_open_container(m, 'a', "s");
166 if (r < 0)
167 return bus_log_create_error(r);
3dc5ca97 168
89ada3ba
YW
169 for (p = eq;;) {
170 _cleanup_free_ char *word = NULL;
20b16441 171
89ada3ba
YW
172 r = extract_first_word(&p, &word, NULL, flags);
173 if (r == 0)
174 break;
175 if (r == -ENOMEM)
176 return log_oom();
177 if (r < 0)
178 return log_error_errno(r, "Invalid syntax: %s", eq);
20b16441 179
89ada3ba
YW
180 r = sd_bus_message_append_basic(m, 's', word);
181 if (r < 0)
182 return bus_log_create_error(r);
20b16441
LP
183 }
184
89ada3ba 185 r = sd_bus_message_close_container(m);
20b16441
LP
186 if (r < 0)
187 return bus_log_create_error(r);
188
89ada3ba
YW
189 r = sd_bus_message_close_container(m);
190 if (r < 0)
191 return bus_log_create_error(r);
20b16441 192
89ada3ba
YW
193 r = sd_bus_message_close_container(m);
194 if (r < 0)
195 return bus_log_create_error(r);
20b16441 196
89ada3ba
YW
197 return 1;
198}
20b16441 199
89ada3ba
YW
200static int bus_append_byte_array(sd_bus_message *m, const char *field, const void *buf, size_t n) {
201 int r;
20b16441 202
89ada3ba
YW
203 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
204 if (r < 0)
205 return bus_log_create_error(r);
20b16441 206
89ada3ba
YW
207 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
208 if (r < 0)
209 return bus_log_create_error(r);
20b16441 210
89ada3ba
YW
211 r = sd_bus_message_open_container(m, 'v', "ay");
212 if (r < 0)
213 return bus_log_create_error(r);
20b16441 214
89ada3ba
YW
215 r = sd_bus_message_append_array(m, 'y', buf, n);
216 if (r < 0)
217 return bus_log_create_error(r);
9184ca48 218
89ada3ba
YW
219 r = sd_bus_message_close_container(m);
220 if (r < 0)
221 return bus_log_create_error(r);
20b16441 222
89ada3ba
YW
223 r = sd_bus_message_close_container(m);
224 if (r < 0)
225 return bus_log_create_error(r);
20b16441 226
89ada3ba
YW
227 return 1;
228}
d58d600e 229
89ada3ba
YW
230static int bus_append_parse_sec_rename(sd_bus_message *m, const char *field, const char *eq) {
231 char *n;
232 usec_t t;
233 size_t l;
234 int r;
d3070fbd 235
89ada3ba
YW
236 r = parse_sec(eq, &t);
237 if (r < 0)
238 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq);
d3070fbd 239
89ada3ba
YW
240 l = strlen(field);
241 n = newa(char, l + 2);
242 /* Change suffix Sec → USec */
243 strcpy(mempcpy(n, field, l - 3), "USec");
d3070fbd 244
89ada3ba
YW
245 r = sd_bus_message_append(m, "(sv)", n, "t", t);
246 if (r < 0)
247 return bus_log_create_error(r);
d3070fbd 248
89ada3ba
YW
249 return 1;
250}
d3070fbd 251
b48e508d 252static int bus_append_parse_size(sd_bus_message *m, const char *field, const char *eq, uint64_t base) {
89ada3ba
YW
253 uint64_t v;
254 int r;
d3070fbd 255
b48e508d
YW
256 r = parse_size(eq, base, &v);
257 if (r < 0)
89ada3ba 258 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq);
d3070fbd 259
89ada3ba
YW
260 r = sd_bus_message_append(m, "(sv)", field, "t", v);
261 if (r < 0)
262 return bus_log_create_error(r);
d58d600e 263
89ada3ba
YW
264 return 1;
265}
d58d600e 266
89ada3ba 267static int bus_append_exec_command(sd_bus_message *m, const char *field, const char *eq) {
b3d59367
AZ
268 bool explicit_path = false, done = false;
269 _cleanup_strv_free_ char **l = NULL, **ex_opts = NULL;
270 _cleanup_free_ char *path = NULL, *upgraded_name = NULL;
271 ExecCommandFlags flags = 0;
272 bool is_ex_prop = endswith(field, "Ex");
89ada3ba 273 int r;
d58d600e 274
89ada3ba
YW
275 do {
276 switch (*eq) {
d58d600e 277
89ada3ba 278 case '-':
b3d59367 279 if (FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE))
89ada3ba
YW
280 done = true;
281 else {
b3d59367 282 flags |= EXEC_COMMAND_IGNORE_FAILURE;
89ada3ba 283 eq++;
d58d600e 284 }
89ada3ba 285 break;
02638280 286
89ada3ba
YW
287 case '@':
288 if (explicit_path)
289 done = true;
290 else {
291 explicit_path = true;
292 eq++;
02638280 293 }
89ada3ba 294 break;
02638280 295
b3d59367
AZ
296 case ':':
297 if (FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND))
298 done = true;
299 else {
300 flags |= EXEC_COMMAND_NO_ENV_EXPAND;
301 eq++;
302 }
303 break;
304
89ada3ba 305 case '+':
b3d59367
AZ
306 if (flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC))
307 done = true;
308 else {
309 flags |= EXEC_COMMAND_FULLY_PRIVILEGED;
310 eq++;
311 }
312 break;
313
89ada3ba 314 case '!':
b3d59367
AZ
315 if (flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_AMBIENT_MAGIC))
316 done = true;
317 else if (FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID)) {
318 flags &= ~EXEC_COMMAND_NO_SETUID;
319 flags |= EXEC_COMMAND_AMBIENT_MAGIC;
320 eq++;
321 } else {
322 flags |= EXEC_COMMAND_NO_SETUID;
323 eq++;
324 }
325 break;
83f8e808 326
89ada3ba
YW
327 default:
328 done = true;
329 break;
83f8e808 330 }
89ada3ba 331 } while (!done);
83f8e808 332
b3d59367
AZ
333 if (!is_ex_prop && (flags & (EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC))) {
334 /* Upgrade the ExecXYZ= property to ExecXYZEx= for convenience */
335 is_ex_prop = true;
b910cc72 336 upgraded_name = strjoin(field, "Ex");
b3d59367
AZ
337 if (!upgraded_name)
338 return log_oom();
339 }
340
341 if (is_ex_prop) {
342 r = exec_command_flags_to_strv(flags, &ex_opts);
343 if (r < 0)
344 return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m");
345 }
346
89ada3ba 347 if (explicit_path) {
4ec85141 348 r = extract_first_word(&eq, &path, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
89ada3ba
YW
349 if (r < 0)
350 return log_error_errno(r, "Failed to parse path: %m");
351 }
2038c3f5 352
90e30d76 353 r = strv_split_full(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
89ada3ba
YW
354 if (r < 0)
355 return log_error_errno(r, "Failed to parse command line: %m");
2038c3f5 356
89ada3ba
YW
357 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
358 if (r < 0)
359 return bus_log_create_error(r);
2038c3f5 360
b3d59367 361 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, upgraded_name ?: field);
89ada3ba
YW
362 if (r < 0)
363 return bus_log_create_error(r);
2038c3f5 364
b3d59367 365 r = sd_bus_message_open_container(m, 'v', is_ex_prop ? "a(sasas)" : "a(sasb)");
89ada3ba
YW
366 if (r < 0)
367 return bus_log_create_error(r);
08f3be7a 368
b3d59367 369 r = sd_bus_message_open_container(m, 'a', is_ex_prop ? "(sasas)" : "(sasb)");
89ada3ba
YW
370 if (r < 0)
371 return bus_log_create_error(r);
08f3be7a 372
89ada3ba 373 if (!strv_isempty(l)) {
08f3be7a 374
b3d59367 375 r = sd_bus_message_open_container(m, 'r', is_ex_prop ? "sasas" : "sasb");
89ada3ba
YW
376 if (r < 0)
377 return bus_log_create_error(r);
08f3be7a 378
89ada3ba 379 r = sd_bus_message_append(m, "s", path ?: l[0]);
08f3be7a
LP
380 if (r < 0)
381 return bus_log_create_error(r);
382
89ada3ba 383 r = sd_bus_message_append_strv(m, l);
08f3be7a
LP
384 if (r < 0)
385 return bus_log_create_error(r);
386
b3d59367 387 r = is_ex_prop ? sd_bus_message_append_strv(m, ex_opts) : sd_bus_message_append(m, "b", FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE));
08f3be7a
LP
388 if (r < 0)
389 return bus_log_create_error(r);
390
391 r = sd_bus_message_close_container(m);
89ada3ba
YW
392 if (r < 0)
393 return bus_log_create_error(r);
20b16441
LP
394 }
395
89ada3ba 396 r = sd_bus_message_close_container(m);
20b16441
LP
397 if (r < 0)
398 return bus_log_create_error(r);
399
89ada3ba
YW
400 r = sd_bus_message_close_container(m);
401 if (r < 0)
402 return bus_log_create_error(r);
20b16441 403
89ada3ba
YW
404 r = sd_bus_message_close_container(m);
405 if (r < 0)
406 return bus_log_create_error(r);
20b16441 407
89ada3ba
YW
408 return 1;
409}
20b16441 410
cd48e23f
RP
411static int bus_append_open_file(sd_bus_message *m, const char *field, const char *eq) {
412 _cleanup_(open_file_freep) OpenFile *of = NULL;
413 int r;
414
415 assert(m);
416
417 r = open_file_parse(eq, &of);
418 if (r < 0)
419 return log_error_errno(r, "Failed to parse OpenFile= setting: %m");
420
421 r = sd_bus_message_append(m, "(sv)", field, "a(sst)", (size_t) 1, of->path, of->fdname, of->flags);
422 if (r < 0)
423 return bus_log_create_error(r);
424
425 return 1;
426}
427
89ada3ba
YW
428static int bus_append_ip_address_access(sd_bus_message *m, int family, const union in_addr_union *prefix, unsigned char prefixlen) {
429 int r;
20b16441 430
89ada3ba
YW
431 assert(m);
432 assert(prefix);
20b16441 433
89ada3ba
YW
434 r = sd_bus_message_open_container(m, 'r', "iayu");
435 if (r < 0)
436 return r;
20b16441 437
89ada3ba
YW
438 r = sd_bus_message_append(m, "i", family);
439 if (r < 0)
440 return r;
66ebf6c0 441
89ada3ba
YW
442 r = sd_bus_message_append_array(m, 'y', prefix, FAMILY_ADDRESS_SIZE(family));
443 if (r < 0)
444 return r;
66ebf6c0 445
89ada3ba
YW
446 r = sd_bus_message_append(m, "u", prefixlen);
447 if (r < 0)
448 return r;
66ebf6c0 449
89ada3ba
YW
450 return sd_bus_message_close_container(m);
451}
20b16441 452
dc7d69b3
TM
453static int bus_append_nft_set(sd_bus_message *m, const char *field, const char *eq) {
454 int r;
455
456 assert(m);
457 assert(field);
458 assert(eq);
459
460 if (isempty(eq)) {
461 r = sd_bus_message_append(m, "(sv)", field, "a(iiss)", 0);
462 if (r < 0)
463 return bus_log_create_error(r);
464
465 return 1;
466 }
467
468 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
469 if (r < 0)
470 return bus_log_create_error(r);
471
472 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
473 if (r < 0)
474 return bus_log_create_error(r);
475
476 r = sd_bus_message_open_container(m, 'v', "a(iiss)");
477 if (r < 0)
478 return bus_log_create_error(r);
479
480 r = sd_bus_message_open_container(m, 'a', "(iiss)");
481 if (r < 0)
482 return bus_log_create_error(r);
483
484 for (const char *p = eq;;) {
485 _cleanup_free_ char *tuple = NULL, *source_str = NULL, *nfproto_str = NULL, *table = NULL, *set = NULL;
486 const char *q = NULL;
487 int source, nfproto;
488
489 r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
490 if (r == -ENOMEM)
491 return log_oom();
492 if (r < 0)
493 return log_error_errno(r, "Failed to parse %s: %m", field);
494 if (r == 0)
495 break;
496 if (isempty(tuple))
497 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse %s", field);
498
499 q = tuple;
500 r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE, &source_str, &nfproto_str, &table, &set, NULL);
501 if (r == -ENOMEM)
502 return log_oom();
503 if (r != 4 || !isempty(q))
504 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse %s", field);
505
506 assert(source_str);
507 assert(nfproto_str);
508 assert(table);
509 assert(set);
510
511 source = nft_set_source_from_string(source_str);
3bb48b19 512 if (!IN_SET(source, NFT_SET_SOURCE_CGROUP, NFT_SET_SOURCE_USER, NFT_SET_SOURCE_GROUP))
dc7d69b3
TM
513 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse %s", field);
514
515 nfproto = nfproto_from_string(nfproto_str);
516 if (nfproto < 0 || !nft_identifier_valid(table) || !nft_identifier_valid(set))
517 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse %s", field);
518
519 r = sd_bus_message_append(m, "(iiss)", source, nfproto, table, set);
520 if (r < 0)
521 return bus_log_create_error(r);
522 }
523 r = sd_bus_message_close_container(m);
524 if (r < 0)
525 return bus_log_create_error(r);
526
527 r = sd_bus_message_close_container(m);
528 if (r < 0)
529 return bus_log_create_error(r);
530
531 r = sd_bus_message_close_container(m);
532 if (r < 0)
533 return bus_log_create_error(r);
534
535 return 1;
536}
537
89ada3ba
YW
538static int bus_append_cgroup_property(sd_bus_message *m, const char *field, const char *eq) {
539 int r;
20b16441 540
4d824a4e
AZ
541 if (STR_IN_SET(field, "DevicePolicy",
542 "Slice",
543 "ManagedOOMSwap",
4e806bfa 544 "ManagedOOMMemoryPressure",
6bb00842 545 "ManagedOOMPreference",
a8b993dc
LP
546 "MemoryPressureWatch",
547 "DelegateSubgroup"))
89ada3ba 548 return bus_append_string(m, field, eq);
13c31542 549
0a9f9344 550 if (STR_IN_SET(field, "ManagedOOMMemoryPressureLimit")) {
0a9f9344
AZ
551 r = parse_permyriad(eq);
552 if (r < 0)
553 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
554
d9d3f05d
LP
555 /* Pass around scaled to 2^32-1 == 100% */
556 r = sd_bus_message_append(m, "(sv)", field, "u", UINT32_SCALE_FROM_PERMYRIAD(r));
0a9f9344
AZ
557 if (r < 0)
558 return bus_log_create_error(r);
559
560 return 1;
561 }
562
c57d2a76
ZJS
563 if (STR_IN_SET(field, "CPUAccounting",
564 "MemoryAccounting",
565 "IOAccounting",
566 "BlockIOAccounting",
567 "TasksAccounting",
568 "IPAccounting"))
89ada3ba 569 return bus_append_parse_boolean(m, field, eq);
13c31542 570
c57d2a76 571 if (STR_IN_SET(field, "CPUWeight",
c8340822 572 "StartupCPUWeight"))
573 return bus_append_cg_cpu_weight_parse(m, field, eq);
574
575 if (STR_IN_SET(field, "IOWeight",
c57d2a76 576 "StartupIOWeight"))
89ada3ba 577 return bus_append_cg_weight_parse(m, field, eq);
20b16441 578
c57d2a76
ZJS
579 if (STR_IN_SET(field, "CPUShares",
580 "StartupCPUShares"))
89ada3ba 581 return bus_append_cg_cpu_shares_parse(m, field, eq);
268833ed 582
c57d2a76 583 if (STR_IN_SET(field, "AllowedCPUs",
31d3a520
PM
584 "StartupAllowedCPUs",
585 "AllowedMemoryNodes",
586 "StartupAllowedMemoryNodes")) {
047f5d63
PH
587 _cleanup_(cpu_set_reset) CPUSet cpuset = {};
588 _cleanup_free_ uint8_t *array = NULL;
589 size_t allocated;
590
591 r = parse_cpu_set(eq, &cpuset);
592 if (r < 0)
593 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
594
595 r = cpu_set_to_dbus(&cpuset, &array, &allocated);
596 if (r < 0)
597 return log_error_errno(r, "Failed to serialize CPUSet: %m");
598
599 return bus_append_byte_array(m, field, array, allocated);
600 }
601
c57d2a76
ZJS
602 if (STR_IN_SET(field, "BlockIOWeight",
603 "StartupBlockIOWeight"))
89ada3ba 604 return bus_append_cg_blkio_weight_parse(m, field, eq);
08f3be7a 605
25cc30c4 606 if (streq(field, "DisableControllers"))
4ec85141 607 return bus_append_strv(m, "DisableControllers", eq, EXTRACT_UNQUOTE);
25cc30c4 608
89ada3ba 609 if (streq(field, "Delegate")) {
89ada3ba 610 r = parse_boolean(eq);
08f3be7a 611 if (r < 0)
4ec85141 612 return bus_append_strv(m, "DelegateControllers", eq, EXTRACT_UNQUOTE);
08f3be7a 613
89ada3ba 614 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", r);
08f3be7a
LP
615 if (r < 0)
616 return bus_log_create_error(r);
617
89ada3ba
YW
618 return 1;
619 }
08f3be7a 620
27e946a5
ZJS
621 if (STR_IN_SET(field, "MemoryMin",
622 "DefaultMemoryLow",
623 "DefaultMemoryMin",
624 "MemoryLow",
625 "MemoryHigh",
626 "MemoryMax",
627 "MemorySwapMax",
d7fe0a67 628 "MemoryZSwapMax",
27e946a5
ZJS
629 "MemoryLimit",
630 "TasksMax")) {
cffaed83 631
db2b8d2e 632 if (streq(eq, "infinity")) {
89ada3ba
YW
633 r = sd_bus_message_append(m, "(sv)", field, "t", CGROUP_LIMIT_MAX);
634 if (r < 0)
635 return bus_log_create_error(r);
636 return 1;
db2b8d2e 637 } else if (isempty(eq)) {
311a0e2e
ZJS
638 uint64_t empty_value = STR_IN_SET(field,
639 "DefaultMemoryLow",
640 "DefaultMemoryMin",
641 "MemoryLow",
642 "MemoryMin") ?
643 CGROUP_LIMIT_MIN :
644 CGROUP_LIMIT_MAX;
645
646 r = sd_bus_message_append(m, "(sv)", field, "t", empty_value);
89ada3ba
YW
647 if (r < 0)
648 return bus_log_create_error(r);
649 return 1;
cffaed83
YW
650 }
651
fe845b5e 652 r = parse_permyriad(eq);
89ada3ba
YW
653 if (r >= 0) {
654 char *n;
20b16441 655
f806dfd3
LP
656 /* When this is a percentage we'll convert this into a relative value in the range 0…UINT32_MAX
657 * and pass it in the MemoryLowScale property (and related ones). This way the physical memory
658 * size can be determined server-side. */
20b16441 659
89ada3ba 660 n = strjoina(field, "Scale");
9cba32bc 661 r = sd_bus_message_append(m, "(sv)", n, "u", UINT32_SCALE_FROM_PERMYRIAD(r));
89ada3ba
YW
662 if (r < 0)
663 return bus_log_create_error(r);
20b16441 664
89ada3ba 665 return 1;
20b16441
LP
666 }
667
89ada3ba 668 if (streq(field, "TasksMax"))
62b749a9 669 return bus_append_safe_atou64(m, field, eq);
20b16441 670
62b749a9 671 return bus_append_parse_size(m, field, eq, 1024);
89ada3ba 672 }
cffaed83 673
89ada3ba 674 if (streq(field, "CPUQuota")) {
89ada3ba
YW
675 if (isempty(eq))
676 r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
677 else {
fe845b5e 678 r = parse_permyriad_unbounded(eq);
baaa35ad
ZJS
679 if (r == 0)
680 return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
681 "CPU quota too small.");
f806dfd3
LP
682 if (r < 0)
683 return log_error_errno(r, "CPU quota '%s' invalid.", eq);
89ada3ba 684
fe845b5e 685 r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", (((uint64_t) r * USEC_PER_SEC) / 10000U));
cffaed83
YW
686 }
687
6bbfdc67 688 if (r < 0)
89ada3ba 689 return bus_log_create_error(r);
cffaed83 690
89ada3ba
YW
691 return 1;
692 }
cffaed83 693
10f28641
FB
694 if (streq(field, "CPUQuotaPeriodSec")) {
695 usec_t u = USEC_INFINITY;
696
697 r = parse_sec_def_infinity(eq, &u);
698 if (r < 0)
699 return log_error_errno(r, "CPU quota period '%s' invalid.", eq);
700
701 r = sd_bus_message_append(m, "(sv)", "CPUQuotaPeriodUSec", "t", u);
702 if (r < 0)
703 return bus_log_create_error(r);
704
705 return 1;
706 }
707
89ada3ba 708 if (streq(field, "DeviceAllow")) {
20b16441 709 if (isempty(eq))
89ada3ba 710 r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 0);
20b16441 711 else {
d9f7305f 712 const char *path = eq, *rwm = NULL, *e;
20b16441
LP
713
714 e = strchr(eq, ' ');
715 if (e) {
2f82562b 716 path = strndupa_safe(eq, e - eq);
20b16441 717 rwm = e+1;
20b16441
LP
718 }
719
d9f7305f 720 r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 1, path, strempty(rwm));
20b16441
LP
721 }
722
89ada3ba
YW
723 if (r < 0)
724 return bus_log_create_error(r);
725
726 return 1;
727 }
728
729 if (cgroup_io_limit_type_from_string(field) >= 0 || STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
20b16441 730 if (isempty(eq))
89ada3ba 731 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0);
20b16441
LP
732 else {
733 const char *path, *bandwidth, *e;
734 uint64_t bytes;
735
736 e = strchr(eq, ' ');
baaa35ad
ZJS
737 if (!e)
738 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
739 "Failed to parse %s value %s.",
740 field, eq);
20b16441 741
2f82562b 742 path = strndupa_safe(eq, e - eq);
d9f7305f 743 bandwidth = e+1;
20b16441 744
79d53eb8 745 if (streq(bandwidth, "infinity"))
13c31542 746 bytes = CGROUP_LIMIT_MAX;
79d53eb8 747 else {
13c31542 748 r = parse_size(bandwidth, 1000, &bytes);
6bbfdc67
LP
749 if (r < 0)
750 return log_error_errno(r, "Failed to parse byte value %s: %m", bandwidth);
20b16441
LP
751 }
752
89ada3ba 753 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, bytes);
20b16441
LP
754 }
755
89ada3ba
YW
756 if (r < 0)
757 return bus_log_create_error(r);
758
759 return 1;
760 }
761
c57d2a76
ZJS
762 if (STR_IN_SET(field, "IODeviceWeight",
763 "BlockIODeviceWeight")) {
20b16441 764 if (isempty(eq))
89ada3ba 765 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0);
20b16441
LP
766 else {
767 const char *path, *weight, *e;
768 uint64_t u;
769
770 e = strchr(eq, ' ');
baaa35ad
ZJS
771 if (!e)
772 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
773 "Failed to parse %s value %s.",
774 field, eq);
20b16441 775
2f82562b 776 path = strndupa_safe(eq, e - eq);
d9f7305f 777 weight = e+1;
20b16441
LP
778
779 r = safe_atou64(weight, &u);
6bbfdc67
LP
780 if (r < 0)
781 return log_error_errno(r, "Failed to parse %s value %s: %m", field, weight);
782
89ada3ba 783 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, u);
20b16441
LP
784 }
785
89ada3ba
YW
786 if (r < 0)
787 return bus_log_create_error(r);
3dc5ca97 788
89ada3ba
YW
789 return 1;
790 }
3dc5ca97 791
6ae4283c
TH
792 if (streq(field, "IODeviceLatencyTargetSec")) {
793 const char *field_usec = "IODeviceLatencyTargetUSec";
794
795 if (isempty(eq))
796 r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", USEC_INFINITY);
797 else {
798 const char *path, *target, *e;
799 usec_t usec;
800
801 e = strchr(eq, ' ');
baaa35ad
ZJS
802 if (!e)
803 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
804 "Failed to parse %s value %s.",
805 field, eq);
6ae4283c 806
2f82562b 807 path = strndupa_safe(eq, e - eq);
6ae4283c
TH
808 target = e+1;
809
810 r = parse_sec(target, &usec);
811 if (r < 0)
812 return log_error_errno(r, "Failed to parse %s value %s: %m", field, target);
813
814 r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", 1, path, usec);
815 }
816
817 if (r < 0)
818 return bus_log_create_error(r);
819
820 return 1;
821 }
822
c57d2a76
ZJS
823 if (STR_IN_SET(field, "IPAddressAllow",
824 "IPAddressDeny")) {
89ada3ba
YW
825 unsigned char prefixlen;
826 union in_addr_union prefix = {};
827 int family;
3dc5ca97 828
89ada3ba
YW
829 if (isempty(eq)) {
830 r = sd_bus_message_append(m, "(sv)", field, "a(iayu)", 0);
3dc5ca97
LP
831 if (r < 0)
832 return bus_log_create_error(r);
833
89ada3ba
YW
834 return 1;
835 }
3dc5ca97 836
89ada3ba
YW
837 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
838 if (r < 0)
839 return bus_log_create_error(r);
3dc5ca97 840
89ada3ba
YW
841 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
842 if (r < 0)
843 return bus_log_create_error(r);
3dc5ca97 844
89ada3ba
YW
845 r = sd_bus_message_open_container(m, 'v', "a(iayu)");
846 if (r < 0)
847 return bus_log_create_error(r);
3dc5ca97 848
89ada3ba
YW
849 r = sd_bus_message_open_container(m, 'a', "(iayu)");
850 if (r < 0)
851 return bus_log_create_error(r);
3dc5ca97 852
89ada3ba
YW
853 if (streq(eq, "any")) {
854 /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
3dc5ca97 855
89ada3ba
YW
856 r = bus_append_ip_address_access(m, AF_INET, &prefix, 0);
857 if (r < 0)
858 return bus_log_create_error(r);
3dc5ca97 859
89ada3ba
YW
860 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 0);
861 if (r < 0)
862 return bus_log_create_error(r);
3dc5ca97 863
89ada3ba
YW
864 } else if (is_localhost(eq)) {
865 /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
3dc5ca97 866
89ada3ba
YW
867 prefix.in.s_addr = htobe32(0x7f000000);
868 r = bus_append_ip_address_access(m, AF_INET, &prefix, 8);
869 if (r < 0)
870 return bus_log_create_error(r);
3dc5ca97 871
89ada3ba
YW
872 prefix.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
873 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 128);
874 if (r < 0)
875 return r;
3dc5ca97 876
89ada3ba
YW
877 } else if (streq(eq, "link-local")) {
878 /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
3dc5ca97 879
89ada3ba
YW
880 prefix.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
881 r = bus_append_ip_address_access(m, AF_INET, &prefix, 16);
882 if (r < 0)
883 return bus_log_create_error(r);
3dc5ca97 884
89ada3ba
YW
885 prefix.in6 = (struct in6_addr) {
886 .s6_addr32[0] = htobe32(0xfe800000)
887 };
888 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 64);
889 if (r < 0)
890 return bus_log_create_error(r);
3dc5ca97 891
89ada3ba
YW
892 } else if (streq(eq, "multicast")) {
893 /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
3dc5ca97 894
89ada3ba
YW
895 prefix.in.s_addr = htobe32((UINT32_C(224) << 24));
896 r = bus_append_ip_address_access(m, AF_INET, &prefix, 4);
897 if (r < 0)
898 return bus_log_create_error(r);
3dc5ca97 899
89ada3ba
YW
900 prefix.in6 = (struct in6_addr) {
901 .s6_addr32[0] = htobe32(0xff000000)
902 };
903 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 8);
3dc5ca97
LP
904 if (r < 0)
905 return bus_log_create_error(r);
906
89ada3ba 907 } else {
afc1feae
RC
908 for (;;) {
909 _cleanup_free_ char *word = NULL;
910
911 r = extract_first_word(&eq, &word, NULL, 0);
912 if (r == 0)
913 break;
914 if (r == -ENOMEM)
915 return log_oom();
916 if (r < 0)
917 return log_error_errno(r, "Failed to parse %s: %s", field, eq);
89ada3ba 918
afc1feae
RC
919 r = in_addr_prefix_from_string_auto(word, &family, &prefix, &prefixlen);
920 if (r < 0)
921 return log_error_errno(r, "Failed to parse IP address prefix: %s", word);
922
923 r = bus_append_ip_address_access(m, family, &prefix, prefixlen);
924 if (r < 0)
925 return bus_log_create_error(r);
926 }
3dc5ca97
LP
927 }
928
89ada3ba
YW
929 r = sd_bus_message_close_container(m);
930 if (r < 0)
931 return bus_log_create_error(r);
cffaed83 932
89ada3ba
YW
933 r = sd_bus_message_close_container(m);
934 if (r < 0)
935 return bus_log_create_error(r);
cffaed83 936
89ada3ba
YW
937 r = sd_bus_message_close_container(m);
938 if (r < 0)
939 return bus_log_create_error(r);
fab34748
KL
940
941 return 1;
942 }
943
c57d2a76
ZJS
944 if (STR_IN_SET(field, "IPIngressFilterPath",
945 "IPEgressFilterPath")) {
fab34748
KL
946 if (isempty(eq))
947 r = sd_bus_message_append(m, "(sv)", field, "as", 0);
948 else
949 r = sd_bus_message_append(m, "(sv)", field, "as", 1, eq);
950
951 if (r < 0)
952 return bus_log_create_error(r);
cffaed83 953
89ada3ba
YW
954 return 1;
955 }
cffaed83 956
9e009a14
JK
957 if (streq(field, "BPFProgram")) {
958 if (isempty(eq))
959 r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 0);
960 else {
961 _cleanup_free_ char *word = NULL;
962
963 r = extract_first_word(&eq, &word, ":", 0);
964 if (r == -ENOMEM)
965 return log_oom();
966 if (r < 0)
967 return log_error_errno(r, "Failed to parse %s: %m", field);
968
969 r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 1, word, eq);
970 }
971 if (r < 0)
972 return bus_log_create_error(r);
973
974 return 1;
975 }
976
dcf4781c
JK
977 if (STR_IN_SET(field, "SocketBindAllow",
978 "SocketBindDeny")) {
979 if (isempty(eq))
4883a04f 980 r = sd_bus_message_append(m, "(sv)", field, "a(iiqq)", 0);
dcf4781c 981 else {
60477eb9
JK
982 int32_t family, ip_protocol;
983 uint16_t nr_ports, port_min;
dcf4781c 984
60477eb9 985 r = parse_socket_bind_item(eq, &family, &ip_protocol, &nr_ports, &port_min);
dcf4781c
JK
986 if (r == -ENOMEM)
987 return log_oom();
988 if (r < 0)
60477eb9 989 return log_error_errno(r, "Failed to parse %s", field);
dcf4781c 990
60477eb9
JK
991 r = sd_bus_message_append(
992 m, "(sv)", field, "a(iiqq)", 1, family, ip_protocol, nr_ports, port_min);
dcf4781c
JK
993 }
994 if (r < 0)
995 return bus_log_create_error(r);
996
997 return 1;
998 }
999
6bb00842
LP
1000 if (streq(field, "MemoryPressureThresholdSec"))
1001 return bus_append_parse_sec_rename(m, field, eq);
1002
dc7d69b3
TM
1003 if (streq(field, "NFTSet"))
1004 return bus_append_nft_set(m, field, eq);
1005
89ada3ba
YW
1006 return 0;
1007}
cffaed83 1008
3d63c749 1009static int bus_append_automount_property(sd_bus_message *m, const char *field, const char *eq) {
7c5cef22
AS
1010 if (STR_IN_SET(field, "Where",
1011 "ExtraOptions"))
3d63c749
YW
1012 return bus_append_string(m, field, eq);
1013
1014 if (streq(field, "DirectoryMode"))
3d63c749
YW
1015 return bus_append_parse_mode(m, field, eq);
1016
1017 if (streq(field, "TimeoutIdleSec"))
3d63c749
YW
1018 return bus_append_parse_sec_rename(m, field, eq);
1019
1020 return 0;
1021}
1022
89ada3ba 1023static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) {
6550c24c
LP
1024 const char *suffix;
1025 int r;
cffaed83 1026
c57d2a76
ZJS
1027 if (STR_IN_SET(field, "User",
1028 "Group",
1029 "UtmpIdentifier",
1030 "UtmpMode",
1031 "PAMName",
1032 "TTYPath",
1033 "WorkingDirectory",
1034 "RootDirectory",
1035 "SyslogIdentifier",
1036 "ProtectSystem",
1037 "ProtectHome",
1038 "SELinuxContext",
1039 "RootImage",
0389f4fa 1040 "RootVerity",
c57d2a76
ZJS
1041 "RuntimeDirectoryPreserve",
1042 "Personality",
1043 "KeyringMode",
4e399953
LP
1044 "ProtectProc",
1045 "ProcSubset",
91dd5f7c 1046 "NetworkNamespacePath",
a70581ff 1047 "IPCNamespacePath",
84be0c71
LP
1048 "LogNamespace",
1049 "RootImagePolicy",
1050 "MountImagePolicy",
1051 "ExtensionImagePolicy"))
89ada3ba 1052 return bus_append_string(m, field, eq);
cffaed83 1053
c57d2a76
ZJS
1054 if (STR_IN_SET(field, "IgnoreSIGPIPE",
1055 "TTYVHangup",
1056 "TTYReset",
1057 "TTYVTDisallocate",
1058 "PrivateTmp",
1059 "PrivateDevices",
1060 "PrivateNetwork",
1061 "PrivateUsers",
1062 "PrivateMounts",
a70581ff 1063 "PrivateIPC",
c57d2a76
ZJS
1064 "NoNewPrivileges",
1065 "SyslogLevelPrefix",
1066 "MemoryDenyWriteExecute",
1067 "RestrictRealtime",
1068 "DynamicUser",
1069 "RemoveIPC",
1070 "ProtectKernelTunables",
1071 "ProtectKernelModules",
1072 "ProtectKernelLogs",
fc64760d 1073 "ProtectClock",
c57d2a76
ZJS
1074 "ProtectControlGroups",
1075 "MountAPIVFS",
1076 "CPUSchedulingResetOnFork",
1077 "LockPersonality",
1078 "ProtectHostname",
85614c6e 1079 "MemoryKSM",
9c0c6701
DDM
1080 "RestrictSUIDSGID",
1081 "RootEphemeral"))
89ada3ba 1082 return bus_append_parse_boolean(m, field, eq);
cffaed83 1083
c57d2a76
ZJS
1084 if (STR_IN_SET(field, "ReadWriteDirectories",
1085 "ReadOnlyDirectories",
1086 "InaccessibleDirectories",
1087 "ReadWritePaths",
1088 "ReadOnlyPaths",
1089 "InaccessiblePaths",
ddc155b2
TM
1090 "ExecPaths",
1091 "NoExecPaths",
8c35c10d 1092 "ExecSearchPath",
a07b9926 1093 "ExtensionDirectories",
c57d2a76
ZJS
1094 "ConfigurationDirectory",
1095 "SupplementaryGroups",
1096 "SystemCallArchitectures"))
4ec85141 1097 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
20b16441 1098
c57d2a76
ZJS
1099 if (STR_IN_SET(field, "SyslogLevel",
1100 "LogLevelMax"))
89ada3ba 1101 return bus_append_log_level_from_string(m, field, eq);
20b16441 1102
89ada3ba 1103 if (streq(field, "SyslogFacility"))
89ada3ba 1104 return bus_append_log_facility_unshifted_from_string(m, field, eq);
cffaed83 1105
89ada3ba 1106 if (streq(field, "SecureBits"))
89ada3ba 1107 return bus_append_secure_bits_from_string(m, field, eq);
cffaed83 1108
89ada3ba 1109 if (streq(field, "CPUSchedulingPolicy"))
89ada3ba 1110 return bus_append_sched_policy_from_string(m, field, eq);
cffaed83 1111
c57d2a76
ZJS
1112 if (STR_IN_SET(field, "CPUSchedulingPriority",
1113 "OOMScoreAdjust"))
89ada3ba 1114 return bus_append_safe_atoi(m, field, eq);
3f856a28 1115
ad21e542
ZJS
1116 if (streq(field, "CoredumpFilter"))
1117 return bus_append_coredump_filter_mask_from_string(m, field, eq);
1118
89ada3ba 1119 if (streq(field, "Nice"))
89ada3ba 1120 return bus_append_parse_nice(m, field, eq);
3f856a28 1121
89ada3ba 1122 if (streq(field, "SystemCallErrorNumber"))
005bfaf1 1123 return bus_append_seccomp_parse_errno_or_action(m, field, eq);
cffaed83 1124
89ada3ba 1125 if (streq(field, "IOSchedulingClass"))
89ada3ba 1126 return bus_append_ioprio_class_from_string(m, field, eq);
cffaed83 1127
89ada3ba 1128 if (streq(field, "IOSchedulingPriority"))
89ada3ba 1129 return bus_append_ioprio_parse_priority(m, field, eq);
cffaed83 1130
c57d2a76
ZJS
1131 if (STR_IN_SET(field, "RuntimeDirectoryMode",
1132 "StateDirectoryMode",
1133 "CacheDirectoryMode",
1134 "LogsDirectoryMode",
1135 "ConfigurationDirectoryMode",
1136 "UMask"))
89ada3ba 1137 return bus_append_parse_mode(m, field, eq);
cffaed83 1138
89ada3ba 1139 if (streq(field, "TimerSlackNSec"))
89ada3ba 1140 return bus_append_parse_nsec(m, field, eq);
cffaed83 1141
691d6f6d 1142 if (streq(field, "LogRateLimitIntervalSec"))
90fc172e
AZ
1143 return bus_append_parse_sec_rename(m, field, eq);
1144
51462135
DDM
1145 if (STR_IN_SET(field, "LogRateLimitBurst",
1146 "TTYRows",
1147 "TTYColumns"))
90fc172e
AZ
1148 return bus_append_safe_atou(m, field, eq);
1149
89ada3ba 1150 if (streq(field, "MountFlags"))
b205e59a 1151 return bus_append_mount_propagation_flag_from_string(m, field, eq);
cffaed83 1152
c57d2a76
ZJS
1153 if (STR_IN_SET(field, "Environment",
1154 "UnsetEnvironment",
1155 "PassEnvironment"))
4ec85141 1156 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
cffaed83 1157
89ada3ba 1158 if (streq(field, "EnvironmentFile")) {
89ada3ba
YW
1159 if (isempty(eq))
1160 r = sd_bus_message_append(m, "(sv)", "EnvironmentFiles", "a(sb)", 0);
1161 else
1162 r = sd_bus_message_append(m, "(sv)", "EnvironmentFiles", "a(sb)", 1,
1163 eq[0] == '-' ? eq + 1 : eq,
1164 eq[0] == '-');
1165 if (r < 0)
1166 return bus_log_create_error(r);
cffaed83 1167
89ada3ba
YW
1168 return 1;
1169 }
cffaed83 1170
43144be4 1171 if (STR_IN_SET(field, "SetCredential", "SetCredentialEncrypted")) {
bb0c0d6f
LP
1172 r = sd_bus_message_open_container(m, 'r', "sv");
1173 if (r < 0)
1174 return bus_log_create_error(r);
1175
43144be4 1176 r = sd_bus_message_append_basic(m, 's', field);
bb0c0d6f
LP
1177 if (r < 0)
1178 return bus_log_create_error(r);
1179
1180 r = sd_bus_message_open_container(m, 'v', "a(say)");
1181 if (r < 0)
1182 return bus_log_create_error(r);
1183
1184 if (isempty(eq))
1185 r = sd_bus_message_append(m, "a(say)", 0);
1186 else {
43144be4 1187 _cleanup_free_ char *word = NULL;
bb0c0d6f 1188 const char *p = eq;
bb0c0d6f
LP
1189
1190 r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
1191 if (r == -ENOMEM)
1192 return log_oom();
1193 if (r < 0)
43144be4 1194 return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
bb0c0d6f 1195 if (r == 0 || !p)
43144be4 1196 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing argument to %s=.", field);
bb0c0d6f
LP
1197
1198 r = sd_bus_message_open_container(m, 'a', "(say)");
1199 if (r < 0)
1200 return bus_log_create_error(r);
1201
1202 r = sd_bus_message_open_container(m, 'r', "say");
1203 if (r < 0)
1204 return bus_log_create_error(r);
1205
1206 r = sd_bus_message_append(m, "s", word);
1207 if (r < 0)
1208 return bus_log_create_error(r);
1209
43144be4
LP
1210 if (streq(field, "SetCredentialEncrypted")) {
1211 _cleanup_free_ void *decoded = NULL;
1212 size_t decoded_size;
1213
1214 r = unbase64mem(p, SIZE_MAX, &decoded, &decoded_size);
1215 if (r < 0)
1216 return log_error_errno(r, "Failed to base64 decode encrypted credential: %m");
1217
1218 r = sd_bus_message_append_array(m, 'y', decoded, decoded_size);
1219 } else {
1220 _cleanup_free_ char *unescaped = NULL;
e437538f 1221 ssize_t l;
43144be4
LP
1222
1223 l = cunescape(p, UNESCAPE_ACCEPT_NUL, &unescaped);
1224 if (l < 0)
1225 return log_error_errno(l, "Failed to unescape %s= value: %s", field, p);
1226
1227 r = sd_bus_message_append_array(m, 'y', unescaped, l);
1228 }
bb0c0d6f
LP
1229 if (r < 0)
1230 return bus_log_create_error(r);
1231
1232 r = sd_bus_message_close_container(m);
1233 if (r < 0)
1234 return bus_log_create_error(r);
1235
1236 r = sd_bus_message_close_container(m);
1237 }
1238 if (r < 0)
1239 return bus_log_create_error(r);
1240
1241 r = sd_bus_message_close_container(m);
1242 if (r < 0)
1243 return bus_log_create_error(r);
1244
1245 r = sd_bus_message_close_container(m);
1246 if (r < 0)
1247 return bus_log_create_error(r);
1248
1249 return 1;
1250 }
1251
43144be4 1252 if (STR_IN_SET(field, "LoadCredential", "LoadCredentialEncrypted")) {
bb0c0d6f
LP
1253 r = sd_bus_message_open_container(m, 'r', "sv");
1254 if (r < 0)
1255 return bus_log_create_error(r);
1256
43144be4 1257 r = sd_bus_message_append_basic(m, 's', field);
bb0c0d6f
LP
1258 if (r < 0)
1259 return bus_log_create_error(r);
1260
1261 r = sd_bus_message_open_container(m, 'v', "a(ss)");
1262 if (r < 0)
1263 return bus_log_create_error(r);
1264
1265 if (isempty(eq))
1266 r = sd_bus_message_append(m, "a(ss)", 0);
1267 else {
1268 _cleanup_free_ char *word = NULL;
1269 const char *p = eq;
1270
1271 r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
1272 if (r == -ENOMEM)
1273 return log_oom();
1274 if (r < 0)
43144be4 1275 return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
255689ae 1276 if (r == 0)
43144be4 1277 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing argument to %s=.", field);
bb0c0d6f 1278
255689ae
LP
1279 if (isempty(p)) /* If only one field is specified, then this means "inherit from above" */
1280 p = eq;
1281
bb0c0d6f
LP
1282 r = sd_bus_message_append(m, "a(ss)", 1, word, p);
1283 }
1284 if (r < 0)
1285 return bus_log_create_error(r);
1286
1287 r = sd_bus_message_close_container(m);
1288 if (r < 0)
1289 return bus_log_create_error(r);
1290
1291 r = sd_bus_message_close_container(m);
1292 if (r < 0)
1293 return bus_log_create_error(r);
1294
1295 return 1;
1296 }
1297
bbfb25f4
DDM
1298 if (streq(field, "ImportCredential")) {
1299 if (isempty(eq))
1300 r = sd_bus_message_append(m, "(sv)", field, "as", 0);
1301 else
1302 r = sd_bus_message_append(m, "(sv)", field, "as", 1, eq);
1303 if (r < 0)
1304 return bus_log_create_error(r);
1305
1306 return 1;
1307 }
1308
89ada3ba 1309 if (streq(field, "LogExtraFields")) {
89ada3ba 1310 r = sd_bus_message_open_container(m, 'r', "sv");
3f856a28
YW
1311 if (r < 0)
1312 return bus_log_create_error(r);
1313
89ada3ba 1314 r = sd_bus_message_append_basic(m, 's', "LogExtraFields");
3f856a28
YW
1315 if (r < 0)
1316 return bus_log_create_error(r);
1317
89ada3ba 1318 r = sd_bus_message_open_container(m, 'v', "aay");
3f856a28
YW
1319 if (r < 0)
1320 return bus_log_create_error(r);
1321
89ada3ba 1322 r = sd_bus_message_open_container(m, 'a', "ay");
cffaed83
YW
1323 if (r < 0)
1324 return bus_log_create_error(r);
1325
89ada3ba 1326 r = sd_bus_message_append_array(m, 'y', eq, strlen(eq));
3f856a28
YW
1327 if (r < 0)
1328 return bus_log_create_error(r);
cffaed83 1329
3f856a28
YW
1330 r = sd_bus_message_close_container(m);
1331 if (r < 0)
1332 return bus_log_create_error(r);
9f617cd0 1333
89ada3ba
YW
1334 r = sd_bus_message_close_container(m);
1335 if (r < 0)
1336 return bus_log_create_error(r);
9efb9df9 1337
89ada3ba 1338 r = sd_bus_message_close_container(m);
9efb9df9 1339 if (r < 0)
89ada3ba
YW
1340 return bus_log_create_error(r);
1341
1342 return 1;
1343 }
9efb9df9 1344
523ea123
QD
1345 if (streq(field, "LogFilterPatterns")) {
1346 r = sd_bus_message_append(m, "(sv)", "LogFilterPatterns", "a(bs)", 1,
1347 eq[0] != '~',
1348 eq[0] != '~' ? eq : eq + 1);
1349 if (r < 0)
1350 return bus_log_create_error(r);
1351
1352 return 1;
1353 }
1354
c57d2a76
ZJS
1355 if (STR_IN_SET(field, "StandardInput",
1356 "StandardOutput",
1357 "StandardError")) {
89ada3ba 1358 const char *n, *appended;
9efb9df9 1359
89ada3ba
YW
1360 if ((n = startswith(eq, "fd:"))) {
1361 appended = strjoina(field, "FileDescriptorName");
1362 r = sd_bus_message_append(m, "(sv)", appended, "s", n);
1363 } else if ((n = startswith(eq, "file:"))) {
1364 appended = strjoina(field, "File");
1365 r = sd_bus_message_append(m, "(sv)", appended, "s", n);
8d33232e
LP
1366 } else if ((n = startswith(eq, "append:"))) {
1367 appended = strjoina(field, "FileToAppend");
1368 r = sd_bus_message_append(m, "(sv)", appended, "s", n);
8d7dab1f
LW
1369 } else if ((n = startswith(eq, "truncate:"))) {
1370 appended = strjoina(field, "FileToTruncate");
1371 r = sd_bus_message_append(m, "(sv)", appended, "s", n);
89ada3ba
YW
1372 } else
1373 r = sd_bus_message_append(m, "(sv)", field, "s", eq);
89ada3ba
YW
1374 if (r < 0)
1375 return bus_log_create_error(r);
7f452159 1376
89ada3ba
YW
1377 return 1;
1378 }
7f452159 1379
89ada3ba
YW
1380 if (streq(field, "StandardInputText")) {
1381 _cleanup_free_ char *unescaped = NULL;
e437538f 1382 ssize_t l;
7f452159 1383
e437538f
ZJS
1384 l = cunescape(eq, 0, &unescaped);
1385 if (l < 0)
1386 return log_error_errno(l, "Failed to unescape text '%s': %m", eq);
7f452159 1387
c2bc710b 1388 if (!strextend(&unescaped, "\n"))
89ada3ba 1389 return log_oom();
7f452159 1390
e437538f
ZJS
1391 /* Note that we don't expand specifiers here, but that should be OK, as this is a
1392 * programmatic interface anyway */
20b16441 1393
e437538f 1394 return bus_append_byte_array(m, field, unescaped, l + 1);
89ada3ba 1395 }
20b16441 1396
89ada3ba
YW
1397 if (streq(field, "StandardInputData")) {
1398 _cleanup_free_ void *decoded = NULL;
1399 size_t sz;
1400
f5fbe71d 1401 r = unbase64mem(eq, SIZE_MAX, &decoded, &sz);
20b16441 1402 if (r < 0)
89ada3ba 1403 return log_error_errno(r, "Failed to decode base64 data '%s': %m", eq);
20b16441 1404
89ada3ba
YW
1405 return bus_append_byte_array(m, field, decoded, sz);
1406 }
20b16441 1407
6550c24c
LP
1408 if ((suffix = startswith(field, "Limit"))) {
1409 int rl;
20b16441 1410
6550c24c
LP
1411 rl = rlimit_from_string(suffix);
1412 if (rl >= 0) {
1413 const char *sn;
1414 struct rlimit l;
20b16441 1415
6550c24c
LP
1416 r = rlimit_parse(rl, eq, &l);
1417 if (r < 0)
1418 return log_error_errno(r, "Failed to parse resource limit: %s", eq);
20b16441 1419
6550c24c
LP
1420 r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max);
1421 if (r < 0)
1422 return bus_log_create_error(r);
20b16441 1423
6550c24c
LP
1424 sn = strjoina(field, "Soft");
1425 r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur);
1426 if (r < 0)
1427 return bus_log_create_error(r);
1428
1429 return 1;
1430 }
89ada3ba 1431 }
20b16441 1432
c57d2a76
ZJS
1433 if (STR_IN_SET(field, "AppArmorProfile",
1434 "SmackProcessLabel")) {
89ada3ba
YW
1435 int ignore = 0;
1436 const char *s = eq;
20b16441 1437
89ada3ba
YW
1438 if (eq[0] == '-') {
1439 ignore = 1;
1440 s = eq + 1;
20b16441
LP
1441 }
1442
89ada3ba 1443 r = sd_bus_message_append(m, "(sv)", field, "(bs)", ignore, s);
6bbfdc67 1444 if (r < 0)
89ada3ba 1445 return bus_log_create_error(r);
20b16441 1446
89ada3ba
YW
1447 return 1;
1448 }
20b16441 1449
c57d2a76
ZJS
1450 if (STR_IN_SET(field, "CapabilityBoundingSet",
1451 "AmbientCapabilities")) {
89ada3ba
YW
1452 uint64_t sum = 0;
1453 bool invert = false;
1454 const char *p = eq;
afcb1cd3 1455
89ada3ba
YW
1456 if (*p == '~') {
1457 invert = true;
1458 p++;
1459 }
20b16441 1460
89ada3ba 1461 r = capability_set_from_string(p, &sum);
20b16441 1462 if (r < 0)
89ada3ba 1463 return log_error_errno(r, "Failed to parse %s value %s: %m", field, eq);
20b16441 1464
89ada3ba
YW
1465 sum = invert ? ~sum : sum;
1466
1467 r = sd_bus_message_append(m, "(sv)", field, "t", sum);
20b16441
LP
1468 if (r < 0)
1469 return bus_log_create_error(r);
1470
89ada3ba
YW
1471 return 1;
1472 }
20b16441 1473
89ada3ba 1474 if (streq(field, "CPUAffinity")) {
0985c7c4 1475 _cleanup_(cpu_set_reset) CPUSet cpuset = {};
c367f996
MS
1476 _cleanup_free_ uint8_t *array = NULL;
1477 size_t allocated;
20b16441 1478
e2b2fb7f
MS
1479 if (eq && streq(eq, "numa")) {
1480 r = sd_bus_message_append(m, "(sv)", "CPUAffinityFromNUMA", "b", true);
1481 if (r < 0)
1482 return bus_log_create_error(r);
1483 return r;
1484 }
1485
89ada3ba
YW
1486 r = parse_cpu_set(eq, &cpuset);
1487 if (r < 0)
1488 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
20b16441 1489
c367f996
MS
1490 r = cpu_set_to_dbus(&cpuset, &array, &allocated);
1491 if (r < 0)
1492 return log_error_errno(r, "Failed to serialize CPUAffinity: %m");
1493
1494 return bus_append_byte_array(m, field, array, allocated);
89ada3ba 1495 }
20b7a007 1496
b070c7c0
MS
1497 if (streq(field, "NUMAPolicy")) {
1498 r = mpol_from_string(eq);
1499 if (r < 0)
1500 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
1501
1502 r = sd_bus_message_append(m, "(sv)", field, "i", (int32_t) r);
1503 if (r < 0)
1504 return bus_log_create_error(r);
1505
1506 return 1;
1507 }
1508
1509 if (streq(field, "NUMAMask")) {
1510 _cleanup_(cpu_set_reset) CPUSet nodes = {};
1511 _cleanup_free_ uint8_t *array = NULL;
1512 size_t allocated;
1513
332d387f
MS
1514 if (eq && streq(eq, "all")) {
1515 r = numa_mask_add_all(&nodes);
1516 if (r < 0)
1517 return log_error_errno(r, "Failed to create NUMA mask representing \"all\" NUMA nodes: %m");
1518 } else {
1519 r = parse_cpu_set(eq, &nodes);
1520 if (r < 0)
1521 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
1522 }
b070c7c0
MS
1523
1524 r = cpu_set_to_dbus(&nodes, &array, &allocated);
1525 if (r < 0)
1526 return log_error_errno(r, "Failed to serialize NUMAMask: %m");
1527
1528 return bus_append_byte_array(m, field, array, allocated);
1529 }
1530
c57d2a76 1531 if (STR_IN_SET(field, "RestrictAddressFamilies",
cc86a278 1532 "RestrictFileSystems",
9df2cdd8 1533 "SystemCallFilter",
a59cb62c
MV
1534 "SystemCallLog",
1535 "RestrictNetworkInterfaces")) {
6b000af4 1536 int allow_list = 1;
89ada3ba 1537 const char *p = eq;
20b16441 1538
89ada3ba 1539 if (*p == '~') {
6b000af4 1540 allow_list = 0;
89ada3ba 1541 p++;
20b16441
LP
1542 }
1543
89ada3ba 1544 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
20b16441
LP
1545 if (r < 0)
1546 return bus_log_create_error(r);
1547
89ada3ba
YW
1548 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1549 if (r < 0)
1550 return bus_log_create_error(r);
1551
1552 r = sd_bus_message_open_container(m, 'v', "(bas)");
1553 if (r < 0)
1554 return bus_log_create_error(r);
20b16441 1555
89ada3ba
YW
1556 r = sd_bus_message_open_container(m, 'r', "bas");
1557 if (r < 0)
1558 return bus_log_create_error(r);
cffaed83 1559
6b000af4 1560 r = sd_bus_message_append_basic(m, 'b', &allow_list);
cffaed83
YW
1561 if (r < 0)
1562 return bus_log_create_error(r);
1563
1564 r = sd_bus_message_open_container(m, 'a', "s");
1565 if (r < 0)
1566 return bus_log_create_error(r);
1567
98008caa 1568 for (;;) {
cffaed83
YW
1569 _cleanup_free_ char *word = NULL;
1570
4ec85141 1571 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
cffaed83
YW
1572 if (r == 0)
1573 break;
89ada3ba
YW
1574 if (r == -ENOMEM)
1575 return log_oom();
1576 if (r < 0)
1577 return log_error_errno(r, "Invalid syntax: %s", eq);
cffaed83
YW
1578
1579 r = sd_bus_message_append_basic(m, 's', word);
1580 if (r < 0)
1581 return bus_log_create_error(r);
1582 }
1583
1584 r = sd_bus_message_close_container(m);
1585 if (r < 0)
1586 return bus_log_create_error(r);
1587
1588 r = sd_bus_message_close_container(m);
20b16441
LP
1589 if (r < 0)
1590 return bus_log_create_error(r);
1591
89ada3ba 1592 r = sd_bus_message_close_container(m);
20b16441
LP
1593 if (r < 0)
1594 return bus_log_create_error(r);
1595
20b16441
LP
1596 r = sd_bus_message_close_container(m);
1597 if (r < 0)
1598 return bus_log_create_error(r);
1599
89ada3ba
YW
1600 return 1;
1601 }
20b16441 1602
89ada3ba 1603 if (streq(field, "RestrictNamespaces")) {
add00535 1604 bool invert = false;
aa9d574d 1605 unsigned long flags;
add00535
LP
1606
1607 r = parse_boolean(eq);
1608 if (r > 0)
1609 flags = 0;
1610 else if (r == 0)
1611 flags = NAMESPACE_FLAGS_ALL;
1612 else {
aa9d574d
YW
1613 if (eq[0] == '~') {
1614 invert = true;
1615 eq++;
1616 }
1617
86c2a9f1 1618 r = namespace_flags_from_string(eq, &flags);
add00535
LP
1619 if (r < 0)
1620 return log_error_errno(r, "Failed to parse %s value %s.", field, eq);
1621 }
1622
1623 if (invert)
1624 flags = (~flags) & NAMESPACE_FLAGS_ALL;
1625
89ada3ba
YW
1626 r = sd_bus_message_append(m, "(sv)", field, "t", (uint64_t) flags);
1627 if (r < 0)
1628 return bus_log_create_error(r);
afcb1cd3 1629
89ada3ba
YW
1630 return 1;
1631 }
afcb1cd3 1632
c57d2a76
ZJS
1633 if (STR_IN_SET(field, "BindPaths",
1634 "BindReadOnlyPaths")) {
89ada3ba 1635 const char *p = eq;
83555251 1636
89ada3ba 1637 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
c7383828 1638 if (r < 0)
89ada3ba 1639 return bus_log_create_error(r);
afcb1cd3 1640
89ada3ba
YW
1641 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1642 if (r < 0)
1643 return bus_log_create_error(r);
d2d6c096
LP
1644
1645 r = sd_bus_message_open_container(m, 'v', "a(ssbt)");
1646 if (r < 0)
89ada3ba 1647 return bus_log_create_error(r);
d2d6c096
LP
1648
1649 r = sd_bus_message_open_container(m, 'a', "(ssbt)");
1650 if (r < 0)
89ada3ba 1651 return bus_log_create_error(r);
d2d6c096
LP
1652
1653 for (;;) {
1654 _cleanup_free_ char *source = NULL, *destination = NULL;
1655 char *s = NULL, *d = NULL;
1656 bool ignore_enoent = false;
1657 uint64_t flags = MS_REC;
1658
4ec85141 1659 r = extract_first_word(&p, &source, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
d2d6c096
LP
1660 if (r < 0)
1661 return log_error_errno(r, "Failed to parse argument: %m");
1662 if (r == 0)
1663 break;
1664
1665 s = source;
1666 if (s[0] == '-') {
1667 ignore_enoent = true;
1668 s++;
1669 }
1670
1671 if (p && p[-1] == ':') {
4ec85141 1672 r = extract_first_word(&p, &destination, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
d2d6c096
LP
1673 if (r < 0)
1674 return log_error_errno(r, "Failed to parse argument: %m");
baaa35ad
ZJS
1675 if (r == 0)
1676 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1677 "Missing argument after ':': %s",
1678 eq);
d2d6c096
LP
1679
1680 d = destination;
1681
1682 if (p && p[-1] == ':') {
1683 _cleanup_free_ char *options = NULL;
1684
4ec85141 1685 r = extract_first_word(&p, &options, NULL, EXTRACT_UNQUOTE);
d2d6c096
LP
1686 if (r < 0)
1687 return log_error_errno(r, "Failed to parse argument: %m");
1688
1689 if (isempty(options) || streq(options, "rbind"))
1690 flags = MS_REC;
1691 else if (streq(options, "norbind"))
1692 flags = 0;
baaa35ad
ZJS
1693 else
1694 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1695 "Unknown options: %s",
1696 eq);
d2d6c096
LP
1697 }
1698 } else
1699 d = s;
1700
d2d6c096
LP
1701 r = sd_bus_message_append(m, "(ssbt)", s, d, ignore_enoent, flags);
1702 if (r < 0)
89ada3ba 1703 return bus_log_create_error(r);
d2d6c096
LP
1704 }
1705
1706 r = sd_bus_message_close_container(m);
1707 if (r < 0)
89ada3ba
YW
1708 return bus_log_create_error(r);
1709
1710 r = sd_bus_message_close_container(m);
1711 if (r < 0)
1712 return bus_log_create_error(r);
d2d6c096
LP
1713
1714 r = sd_bus_message_close_container(m);
89ada3ba
YW
1715 if (r < 0)
1716 return bus_log_create_error(r);
f6c66be1 1717
89ada3ba
YW
1718 return 1;
1719 }
f6c66be1 1720
784ad252
YW
1721 if (streq(field, "TemporaryFileSystem")) {
1722 const char *p = eq;
1723
1724 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1725 if (r < 0)
1726 return bus_log_create_error(r);
1727
1728 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1729 if (r < 0)
1730 return bus_log_create_error(r);
1731
1732 r = sd_bus_message_open_container(m, 'v', "a(ss)");
1733 if (r < 0)
1734 return bus_log_create_error(r);
1735
1736 r = sd_bus_message_open_container(m, 'a', "(ss)");
1737 if (r < 0)
1738 return bus_log_create_error(r);
1739
1740 for (;;) {
1741 _cleanup_free_ char *word = NULL, *path = NULL;
1742 const char *w;
1743
4ec85141 1744 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
784ad252
YW
1745 if (r < 0)
1746 return log_error_errno(r, "Failed to parse argument: %m");
1747 if (r == 0)
1748 break;
1749
1750 w = word;
1751 r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
1752 if (r < 0)
1753 return log_error_errno(r, "Failed to parse argument: %m");
baaa35ad
ZJS
1754 if (r == 0)
1755 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1756 "Failed to parse argument: %s",
1757 p);
784ad252
YW
1758
1759 r = sd_bus_message_append(m, "(ss)", path, w);
1760 if (r < 0)
1761 return bus_log_create_error(r);
1762 }
1763
1764 r = sd_bus_message_close_container(m);
1765 if (r < 0)
1766 return bus_log_create_error(r);
1767
1768 r = sd_bus_message_close_container(m);
1769 if (r < 0)
1770 return bus_log_create_error(r);
1771
1772 r = sd_bus_message_close_container(m);
1773 if (r < 0)
1774 return bus_log_create_error(r);
1775
1776 return 1;
1777 }
1778
0389f4fa
LB
1779 if (streq(field, "RootHash")) {
1780 _cleanup_free_ void *roothash_decoded = NULL;
1781 size_t roothash_decoded_size = 0;
1782
1783 /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
1784 if (path_is_absolute(eq))
1785 return bus_append_string(m, "RootHashPath", eq);
1786
1787 /* We have a roothash to decode, eg: RootHash=012345789abcdef */
1788 r = unhexmem(eq, strlen(eq), &roothash_decoded, &roothash_decoded_size);
1789 if (r < 0)
1790 return log_error_errno(r, "Failed to decode RootHash= '%s': %m", eq);
1791 if (roothash_decoded_size < sizeof(sd_id128_t))
1792 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RootHash= '%s' is too short: %m", eq);
1793
1794 return bus_append_byte_array(m, field, roothash_decoded, roothash_decoded_size);
1795 }
1796
d4d55b0d
LB
1797 if (streq(field, "RootHashSignature")) {
1798 _cleanup_free_ void *roothash_sig_decoded = NULL;
1799 char *value;
1800 size_t roothash_sig_decoded_size = 0;
1801
1802 /* We have the path to a roothash signature to load and decode, eg: RootHash=/foo/bar.roothash.p7s */
1803 if (path_is_absolute(eq))
1804 return bus_append_string(m, "RootHashSignaturePath", eq);
1805
1806 if (!(value = startswith(eq, "base64:")))
1807 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to decode RootHashSignature= '%s', not a path but doesn't start with 'base64:': %m", eq);
1808
1809 /* We have a roothash signature to decode, eg: RootHashSignature=base64:012345789abcdef */
1810 r = unbase64mem(value, strlen(value), &roothash_sig_decoded, &roothash_sig_decoded_size);
1811 if (r < 0)
1812 return log_error_errno(r, "Failed to decode RootHashSignature= '%s': %m", eq);
1813
1814 return bus_append_byte_array(m, field, roothash_sig_decoded, roothash_sig_decoded_size);
1815 }
1816
18d73705 1817 if (streq(field, "RootImageOptions")) {
bc8d56d3 1818 _cleanup_strv_free_ char **l = NULL;
18d73705
LB
1819 const char *p = eq;
1820
1821 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1822 if (r < 0)
1823 return bus_log_create_error(r);
1824
1825 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1826 if (r < 0)
1827 return bus_log_create_error(r);
1828
9ece6444 1829 r = sd_bus_message_open_container(m, 'v', "a(ss)");
18d73705
LB
1830 if (r < 0)
1831 return bus_log_create_error(r);
1832
9ece6444 1833 r = sd_bus_message_open_container(m, 'a', "(ss)");
18d73705
LB
1834 if (r < 0)
1835 return bus_log_create_error(r);
1836
bc8d56d3
LB
1837 r = strv_split_colon_pairs(&l, p);
1838 if (r < 0)
1839 return log_error_errno(r, "Failed to parse argument: %m");
18d73705 1840
bc8d56d3 1841 STRV_FOREACH_PAIR(first, second, l) {
9ece6444
LB
1842 r = sd_bus_message_append(m, "(ss)",
1843 !isempty(*second) ? *first : "root",
1844 !isempty(*second) ? *second : *first);
18d73705
LB
1845 if (r < 0)
1846 return bus_log_create_error(r);
1847 }
1848
1849 r = sd_bus_message_close_container(m);
1850 if (r < 0)
b3d13314
LB
1851 return bus_log_create_error(r);
1852
1853 r = sd_bus_message_close_container(m);
1854 if (r < 0)
1855 return bus_log_create_error(r);
1856
1857 r = sd_bus_message_close_container(m);
1858 if (r < 0)
1859 return bus_log_create_error(r);
1860
1861 return 1;
1862 }
1863
1864 if (streq(field, "MountImages")) {
b3d13314
LB
1865 const char *p = eq;
1866
1867 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1868 if (r < 0)
1869 return bus_log_create_error(r);
1870
1871 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1872 if (r < 0)
1873 return bus_log_create_error(r);
1874
427353f6 1875 r = sd_bus_message_open_container(m, 'v', "a(ssba(ss))");
b3d13314
LB
1876 if (r < 0)
1877 return bus_log_create_error(r);
1878
427353f6 1879 r = sd_bus_message_open_container(m, 'a', "(ssba(ss))");
b3d13314
LB
1880 if (r < 0)
1881 return bus_log_create_error(r);
1882
427353f6
LB
1883 for (;;) {
1884 _cleanup_free_ char *first = NULL, *second = NULL, *tuple = NULL;
1885 const char *q = NULL, *source = NULL;
b3d13314
LB
1886 bool permissive = false;
1887
427353f6
LB
1888 r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
1889 if (r < 0)
de4abc3f 1890 return log_error_errno(r, "Failed to parse MountImages= property: %s", eq);
427353f6
LB
1891 if (r == 0)
1892 break;
1893
1894 q = tuple;
1895 r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &first, &second, NULL);
1896 if (r < 0)
de4abc3f 1897 return log_error_errno(r, "Failed to parse MountImages= property: %s", eq);
427353f6
LB
1898 if (r == 0)
1899 continue;
1900
1901 source = first;
1902 if (source[0] == '-') {
b3d13314 1903 permissive = true;
427353f6 1904 source++;
b3d13314
LB
1905 }
1906
427353f6 1907 if (isempty(second))
b3d13314
LB
1908 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1909 "Missing argument after ':': %s",
1910 eq);
1911
427353f6
LB
1912 r = sd_bus_message_open_container(m, 'r', "ssba(ss)");
1913 if (r < 0)
1914 return bus_log_create_error(r);
1915
1916 r = sd_bus_message_append(m, "ssb", source, second, permissive);
1917 if (r < 0)
1918 return bus_log_create_error(r);
1919
1920 r = sd_bus_message_open_container(m, 'a', "(ss)");
1921 if (r < 0)
1922 return bus_log_create_error(r);
1923
1924 for (;;) {
1925 _cleanup_free_ char *partition = NULL, *mount_options = NULL;
1926
1927 r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL);
1928 if (r < 0)
de4abc3f 1929 return log_error_errno(r, "Failed to parse MountImages= property: %s", eq);
93f59701
LB
1930 if (r == 0)
1931 break;
1932 /* Single set of options, applying to the root partition/single filesystem */
1933 if (r == 1) {
1934 r = sd_bus_message_append(m, "(ss)", "root", partition);
1935 if (r < 0)
1936 return bus_log_create_error(r);
1937
1938 break;
1939 }
1940
93f59701
LB
1941 r = sd_bus_message_append(m, "(ss)", partition, mount_options);
1942 if (r < 0)
1943 return bus_log_create_error(r);
1944 }
1945
1946 r = sd_bus_message_close_container(m);
1947 if (r < 0)
1948 return bus_log_create_error(r);
1949
1950 r = sd_bus_message_close_container(m);
1951 if (r < 0)
1952 return bus_log_create_error(r);
1953 }
1954
1955 r = sd_bus_message_close_container(m);
1956 if (r < 0)
1957 return bus_log_create_error(r);
1958
1959 r = sd_bus_message_close_container(m);
1960 if (r < 0)
1961 return bus_log_create_error(r);
1962
1963 r = sd_bus_message_close_container(m);
1964 if (r < 0)
1965 return bus_log_create_error(r);
1966
1967 return 1;
1968 }
1969
1970 if (streq(field, "ExtensionImages")) {
1971 const char *p = eq;
1972
1973 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1974 if (r < 0)
1975 return bus_log_create_error(r);
1976
1977 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1978 if (r < 0)
1979 return bus_log_create_error(r);
1980
1981 r = sd_bus_message_open_container(m, 'v', "a(sba(ss))");
1982 if (r < 0)
1983 return bus_log_create_error(r);
1984
1985 r = sd_bus_message_open_container(m, 'a', "(sba(ss))");
1986 if (r < 0)
1987 return bus_log_create_error(r);
1988
1989 for (;;) {
1990 _cleanup_free_ char *source = NULL, *tuple = NULL;
1991 const char *q = NULL, *s = NULL;
1992 bool permissive = false;
1993
1994 r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
1995 if (r < 0)
de4abc3f 1996 return log_error_errno(r, "Failed to parse ExtensionImages= property: %s", eq);
93f59701
LB
1997 if (r == 0)
1998 break;
1999
2000 q = tuple;
2001 r = extract_first_word(&q, &source, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS);
2002 if (r < 0)
de4abc3f 2003 return log_error_errno(r, "Failed to parse ExtensionImages= property: %s", eq);
93f59701
LB
2004 if (r == 0)
2005 continue;
2006
2007 s = source;
2008 if (s[0] == '-') {
2009 permissive = true;
2010 s++;
2011 }
2012
2013 r = sd_bus_message_open_container(m, 'r', "sba(ss)");
2014 if (r < 0)
2015 return bus_log_create_error(r);
2016
2017 r = sd_bus_message_append(m, "sb", s, permissive);
2018 if (r < 0)
2019 return bus_log_create_error(r);
2020
2021 r = sd_bus_message_open_container(m, 'a', "(ss)");
2022 if (r < 0)
2023 return bus_log_create_error(r);
2024
2025 for (;;) {
2026 _cleanup_free_ char *partition = NULL, *mount_options = NULL;
2027
2028 r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL);
2029 if (r < 0)
de4abc3f 2030 return log_error_errno(r, "Failed to parse ExtensionImages= property: %s", eq);
427353f6
LB
2031 if (r == 0)
2032 break;
2033 /* Single set of options, applying to the root partition/single filesystem */
2034 if (r == 1) {
2035 r = sd_bus_message_append(m, "(ss)", "root", partition);
2036 if (r < 0)
2037 return bus_log_create_error(r);
2038
2039 break;
2040 }
2041
427353f6
LB
2042 r = sd_bus_message_append(m, "(ss)", partition, mount_options);
2043 if (r < 0)
2044 return bus_log_create_error(r);
2045 }
2046
2047 r = sd_bus_message_close_container(m);
2048 if (r < 0)
2049 return bus_log_create_error(r);
2050
2051 r = sd_bus_message_close_container(m);
b3d13314
LB
2052 if (r < 0)
2053 return bus_log_create_error(r);
2054 }
2055
2056 r = sd_bus_message_close_container(m);
2057 if (r < 0)
18d73705
LB
2058 return bus_log_create_error(r);
2059
2060 r = sd_bus_message_close_container(m);
2061 if (r < 0)
2062 return bus_log_create_error(r);
2063
2064 r = sd_bus_message_close_container(m);
2065 if (r < 0)
2066 return bus_log_create_error(r);
2067
2068 return 1;
2069 }
2070
211a3d87
LB
2071 if (STR_IN_SET(field, "StateDirectory", "RuntimeDirectory", "CacheDirectory", "LogsDirectory")) {
2072 _cleanup_strv_free_ char **symlinks = NULL, **sources = NULL;
2073 const char *p = eq;
2074
2075 /* Adding new directories is supported from both *DirectorySymlink methods and the
2076 * older ones, so first parse the input, and if we are given a new-style src:dst
2077 * tuple use the new method, else use the old one. */
2078
2079 for (;;) {
2080 _cleanup_free_ char *tuple = NULL, *source = NULL, *destination = NULL;
2081
2082 r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE);
2083 if (r < 0)
2084 return log_error_errno(r, "Failed to parse argument: %m");
2085 if (r == 0)
2086 break;
2087
2088 const char *t = tuple;
2089 r = extract_many_words(&t, ":", EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS, &source, &destination, NULL);
2090 if (r <= 0)
2091 return log_error_errno(r ?: SYNTHETIC_ERRNO(EINVAL), "Failed to parse argument: %m");
2092
2093 path_simplify(source);
2094
2095 if (isempty(destination)) {
2aaf6d40 2096 r = strv_consume(&sources, TAKE_PTR(source));
211a3d87
LB
2097 if (r < 0)
2098 return bus_log_create_error(r);
2099 } else {
2100 path_simplify(destination);
2101
2102 r = strv_consume_pair(&symlinks, TAKE_PTR(source), TAKE_PTR(destination));
2103 if (r < 0)
2104 return log_oom();
2105 }
2106 }
2107
2108 if (!strv_isempty(sources)) {
2109 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
2110 if (r < 0)
2111 return bus_log_create_error(r);
2112
2113 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
2114 if (r < 0)
2115 return bus_log_create_error(r);
2116
2117 r = sd_bus_message_open_container(m, 'v', "as");
2118 if (r < 0)
2119 return bus_log_create_error(r);
2120
2121 r = sd_bus_message_append_strv(m, sources);
2122 if (r < 0)
2123 return bus_log_create_error(r);
2124
2125 r = sd_bus_message_close_container(m);
2126 if (r < 0)
2127 return bus_log_create_error(r);
2128
2129 r = sd_bus_message_close_container(m);
2130 if (r < 0)
2131 return bus_log_create_error(r);
2132 }
2133
2134 /* For State and Runtime directories we support an optional destination parameter, which
2135 * will be used to create a symlink to the source. But it is new so we cannot change the
2136 * old DBUS signatures, so append a new message type. */
2137 if (!strv_isempty(symlinks)) {
2138 const char *symlink_field;
2139
2140 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
2141 if (r < 0)
2142 return bus_log_create_error(r);
2143
2144 if (streq(field, "StateDirectory"))
2145 symlink_field = "StateDirectorySymlink";
2146 else if (streq(field, "RuntimeDirectory"))
2147 symlink_field = "RuntimeDirectorySymlink";
2148 else if (streq(field, "CacheDirectory"))
2149 symlink_field = "CacheDirectorySymlink";
2150 else if (streq(field, "LogsDirectory"))
2151 symlink_field = "LogsDirectorySymlink";
2152 else
2153 assert_not_reached();
2154
2155 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, symlink_field);
2156 if (r < 0)
2157 return bus_log_create_error(r);
2158
2159 r = sd_bus_message_open_container(m, 'v', "a(sst)");
2160 if (r < 0)
2161 return bus_log_create_error(r);
2162
2163 r = sd_bus_message_open_container(m, 'a', "(sst)");
2164 if (r < 0)
2165 return bus_log_create_error(r);
2166
211a3d87
LB
2167 STRV_FOREACH_PAIR(source, destination, symlinks) {
2168 r = sd_bus_message_append(m, "(sst)", *source, *destination, 0);
2169 if (r < 0)
2170 return bus_log_create_error(r);
2171 }
2172
2173 r = sd_bus_message_close_container(m);
2174 if (r < 0)
2175 return bus_log_create_error(r);
2176
2177 r = sd_bus_message_close_container(m);
2178 if (r < 0)
2179 return bus_log_create_error(r);
2180
2181 r = sd_bus_message_close_container(m);
2182 if (r < 0)
2183 return bus_log_create_error(r);
2184 }
2185
2186 return 1;
2187 }
2188
89ada3ba
YW
2189 return 0;
2190}
f6c66be1 2191
89ada3ba 2192static int bus_append_kill_property(sd_bus_message *m, const char *field, const char *eq) {
89ada3ba 2193 if (streq(field, "KillMode"))
89ada3ba 2194 return bus_append_string(m, field, eq);
f6c66be1 2195
c57d2a76
ZJS
2196 if (STR_IN_SET(field, "SendSIGHUP",
2197 "SendSIGKILL"))
89ada3ba 2198 return bus_append_parse_boolean(m, field, eq);
f6c66be1 2199
c57d2a76
ZJS
2200 if (STR_IN_SET(field, "KillSignal",
2201 "RestartKillSignal",
2202 "FinalKillSignal",
3bd28bf7
LP
2203 "WatchdogSignal",
2204 "ReloadSignal"))
29a3db75 2205 return bus_append_signal_from_string(m, field, eq);
89ada3ba
YW
2206
2207 return 0;
2208}
2209
3d63c749 2210static int bus_append_mount_property(sd_bus_message *m, const char *field, const char *eq) {
89ada3ba 2211
c57d2a76
ZJS
2212 if (STR_IN_SET(field, "What",
2213 "Where",
2214 "Options",
2215 "Type"))
89ada3ba
YW
2216 return bus_append_string(m, field, eq);
2217
3d63c749 2218 if (streq(field, "TimeoutSec"))
3d63c749
YW
2219 return bus_append_parse_sec_rename(m, field, eq);
2220
2221 if (streq(field, "DirectoryMode"))
3d63c749
YW
2222 return bus_append_parse_mode(m, field, eq);
2223
c57d2a76
ZJS
2224 if (STR_IN_SET(field, "SloppyOptions",
2225 "LazyUnmount",
c600357b
MH
2226 "ForceUnmount",
2227 "ReadwriteOnly"))
3d63c749
YW
2228 return bus_append_parse_boolean(m, field, eq);
2229
2230 return 0;
2231}
2232
2233static int bus_append_path_property(sd_bus_message *m, const char *field, const char *eq) {
2234 int r;
2235
89ada3ba 2236 if (streq(field, "MakeDirectory"))
89ada3ba
YW
2237 return bus_append_parse_boolean(m, field, eq);
2238
2239 if (streq(field, "DirectoryMode"))
89ada3ba
YW
2240 return bus_append_parse_mode(m, field, eq);
2241
c57d2a76
ZJS
2242 if (STR_IN_SET(field, "PathExists",
2243 "PathExistsGlob",
2244 "PathChanged",
2245 "PathModified",
2246 "DirectoryNotEmpty")) {
3d63c749
YW
2247 if (isempty(eq))
2248 r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 0);
2249 else
2250 r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 1, field, eq);
2251 if (r < 0)
2252 return bus_log_create_error(r);
2253
2254 return 1;
2255 }
2256
2bec84e7 2257 if (STR_IN_SET(field, "TriggerLimitBurst", "PollLimitBurst"))
47dba9fb
LB
2258 return bus_append_safe_atou(m, field, eq);
2259
2bec84e7 2260 if (STR_IN_SET(field, "TriggerLimitIntervalSec", "PollLimitIntervalSec"))
47dba9fb
LB
2261 return bus_append_parse_sec_rename(m, field, eq);
2262
89ada3ba
YW
2263 return 0;
2264}
2265
5a70a68f 2266static int bus_append_scope_property(sd_bus_message *m, const char *field, const char *eq) {
9ed7de60 2267 if (streq(field, "RuntimeMaxSec"))
9ed7de60
PW
2268 return bus_append_parse_sec_rename(m, field, eq);
2269
5918a933
AB
2270 if (streq(field, "RuntimeRandomizedExtraSec"))
2271 return bus_append_parse_sec_rename(m, field, eq);
2272
5a70a68f 2273 if (streq(field, "TimeoutStopSec"))
5a70a68f
PW
2274 return bus_append_parse_sec_rename(m, field, eq);
2275
03860190
MS
2276 /* Scope units don't have execution context but we still want to allow setting these two,
2277 * so let's handle them separately. */
2278 if (STR_IN_SET(field, "User", "Group"))
2279 return bus_append_string(m, field, eq);
2280
5fa09835
ML
2281 if (streq(field, "OOMPolicy"))
2282 return bus_append_string(m, field, eq);
2283
5a70a68f
PW
2284 return 0;
2285}
2286
89ada3ba 2287static int bus_append_service_property(sd_bus_message *m, const char *field, const char *eq) {
3d63c749 2288 int r;
89ada3ba 2289
c57d2a76
ZJS
2290 if (STR_IN_SET(field, "PIDFile",
2291 "Type",
596e4470 2292 "ExitType",
c57d2a76 2293 "Restart",
e568fea9 2294 "RestartMode",
c57d2a76
ZJS
2295 "BusName",
2296 "NotifyAccess",
2297 "USBFunctionDescriptors",
2298 "USBFunctionStrings",
bf760801
JK
2299 "OOMPolicy",
2300 "TimeoutStartFailureMode",
b9c1883a
LP
2301 "TimeoutStopFailureMode",
2302 "FileDescriptorStorePreserve"))
89ada3ba 2303 return bus_append_string(m, field, eq);
f6c66be1 2304
c57d2a76
ZJS
2305 if (STR_IN_SET(field, "PermissionsStartOnly",
2306 "RootDirectoryStartOnly",
2307 "RemainAfterExit",
2308 "GuessMainPID"))
89ada3ba
YW
2309 return bus_append_parse_boolean(m, field, eq);
2310
c57d2a76 2311 if (STR_IN_SET(field, "RestartSec",
a559ea15 2312 "RestartMaxDelaySec",
c57d2a76
ZJS
2313 "TimeoutStartSec",
2314 "TimeoutStopSec",
e737017b 2315 "TimeoutAbortSec",
c57d2a76 2316 "RuntimeMaxSec",
5918a933 2317 "RuntimeRandomizedExtraSec",
c57d2a76 2318 "WatchdogSec"))
89ada3ba
YW
2319 return bus_append_parse_sec_rename(m, field, eq);
2320
3d63c749 2321 if (streq(field, "TimeoutSec")) {
3d63c749
YW
2322 r = bus_append_parse_sec_rename(m, "TimeoutStartSec", eq);
2323 if (r < 0)
2324 return r;
2325
2326 return bus_append_parse_sec_rename(m, "TimeoutStopSec", eq);
2327 }
2328
a559ea15
MY
2329 if (STR_IN_SET(field, "FileDescriptorStoreMax",
2330 "RestartSteps"))
89ada3ba
YW
2331 return bus_append_safe_atou(m, field, eq);
2332
c57d2a76
ZJS
2333 if (STR_IN_SET(field, "ExecCondition",
2334 "ExecStartPre",
2335 "ExecStart",
2336 "ExecStartPost",
2337 "ExecConditionEx",
2338 "ExecStartPreEx",
2339 "ExecStartEx",
2340 "ExecStartPostEx",
2341 "ExecReload",
2342 "ExecStop",
2343 "ExecStopPost",
2344 "ExecReloadEx",
2345 "ExecStopEx",
2346 "ExecStopPostEx"))
89ada3ba
YW
2347 return bus_append_exec_command(m, field, eq);
2348
c57d2a76
ZJS
2349 if (STR_IN_SET(field, "RestartPreventExitStatus",
2350 "RestartForceExitStatus",
2351 "SuccessExitStatus")) {
3d63c749 2352 _cleanup_free_ int *status = NULL, *signal = NULL;
62b21e2e 2353 size_t n_status = 0, n_signal = 0;
3d63c749
YW
2354 const char *p;
2355
2356 for (p = eq;;) {
2357 _cleanup_free_ char *word = NULL;
3d63c749 2358
4ec85141 2359 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
3d63c749
YW
2360 if (r == 0)
2361 break;
2362 if (r == -ENOMEM)
2363 return log_oom();
2364 if (r < 0)
2365 return log_error_errno(r, "Invalid syntax in %s: %s", field, eq);
2366
2e2ed880
ZJS
2367 /* We need to call exit_status_from_string() first, because we want
2368 * to parse numbers as exit statuses, not signals. */
3d63c749 2369
2e2ed880
ZJS
2370 r = exit_status_from_string(word);
2371 if (r >= 0) {
2372 assert(r >= 0 && r < 256);
3d63c749 2373
62b21e2e 2374 status = reallocarray(status, n_status + 1, sizeof(int));
3d63c749
YW
2375 if (!status)
2376 return log_oom();
2377
2e2ed880
ZJS
2378 status[n_status++] = r;
2379
2380 } else if ((r = signal_from_string(word)) >= 0) {
2381 signal = reallocarray(signal, n_signal + 1, sizeof(int));
2382 if (!signal)
2383 return log_oom();
2384
2385 signal[n_signal++] = r;
2386
2387 } else
2388 /* original r from exit_status_to_string() */
2389 return log_error_errno(r, "Invalid status or signal %s in %s: %m",
2390 word, field);
3d63c749
YW
2391 }
2392
2393 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
2394 if (r < 0)
2395 return bus_log_create_error(r);
2396
2397 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
2398 if (r < 0)
2399 return bus_log_create_error(r);
2400
2401 r = sd_bus_message_open_container(m, 'v', "(aiai)");
2402 if (r < 0)
2403 return bus_log_create_error(r);
2404
2405 r = sd_bus_message_open_container(m, 'r', "aiai");
2406 if (r < 0)
2407 return bus_log_create_error(r);
2408
62b21e2e 2409 r = sd_bus_message_append_array(m, 'i', status, n_status * sizeof(int));
3d63c749
YW
2410 if (r < 0)
2411 return bus_log_create_error(r);
2412
62b21e2e 2413 r = sd_bus_message_append_array(m, 'i', signal, n_signal * sizeof(int));
3d63c749
YW
2414 if (r < 0)
2415 return bus_log_create_error(r);
2416
2417 r = sd_bus_message_close_container(m);
2418 if (r < 0)
2419 return bus_log_create_error(r);
2420
2421 r = sd_bus_message_close_container(m);
2422 if (r < 0)
2423 return bus_log_create_error(r);
2424
2425 r = sd_bus_message_close_container(m);
2426 if (r < 0)
2427 return bus_log_create_error(r);
2428
2429 return 1;
2430 }
2431
cd48e23f
RP
2432 if (streq(field, "OpenFile"))
2433 return bus_append_open_file(m, field, eq);
2434
89ada3ba
YW
2435 return 0;
2436}
2437
2438static int bus_append_socket_property(sd_bus_message *m, const char *field, const char *eq) {
2439 int r;
2440
c57d2a76 2441 if (STR_IN_SET(field, "Accept",
3e5f04bf 2442 "FlushPending",
c57d2a76
ZJS
2443 "Writable",
2444 "KeepAlive",
2445 "NoDelay",
2446 "FreeBind",
2447 "Transparent",
2448 "Broadcast",
2449 "PassCredentials",
2450 "PassSecurity",
a3d19f5d 2451 "PassPacketInfo",
c57d2a76
ZJS
2452 "ReusePort",
2453 "RemoveOnStop",
2454 "SELinuxContextFromNet"))
89ada3ba
YW
2455 return bus_append_parse_boolean(m, field, eq);
2456
c57d2a76
ZJS
2457 if (STR_IN_SET(field, "Priority",
2458 "IPTTL",
2459 "Mark"))
89ada3ba
YW
2460 return bus_append_safe_atoi(m, field, eq);
2461
2462 if (streq(field, "IPTOS"))
89ada3ba
YW
2463 return bus_append_ip_tos_from_string(m, field, eq);
2464
c57d2a76
ZJS
2465 if (STR_IN_SET(field, "Backlog",
2466 "MaxConnections",
2467 "MaxConnectionsPerSource",
2468 "KeepAliveProbes",
2bec84e7
LP
2469 "TriggerLimitBurst",
2470 "PollLimitBurst"))
89ada3ba
YW
2471 return bus_append_safe_atou(m, field, eq);
2472
c57d2a76
ZJS
2473 if (STR_IN_SET(field, "SocketMode",
2474 "DirectoryMode"))
89ada3ba
YW
2475 return bus_append_parse_mode(m, field, eq);
2476
c57d2a76
ZJS
2477 if (STR_IN_SET(field, "MessageQueueMaxMessages",
2478 "MessageQueueMessageSize"))
89ada3ba
YW
2479 return bus_append_safe_atoi64(m, field, eq);
2480
c57d2a76
ZJS
2481 if (STR_IN_SET(field, "TimeoutSec",
2482 "KeepAliveTimeSec",
2483 "KeepAliveIntervalSec",
2484 "DeferAcceptSec",
2bec84e7
LP
2485 "TriggerLimitIntervalSec",
2486 "PollLimitIntervalSec"))
89ada3ba
YW
2487 return bus_append_parse_sec_rename(m, field, eq);
2488
c57d2a76
ZJS
2489 if (STR_IN_SET(field, "ReceiveBuffer",
2490 "SendBuffer",
2491 "PipeSize"))
b48e508d 2492 return bus_append_parse_size(m, field, eq, 1024);
89ada3ba 2493
c57d2a76
ZJS
2494 if (STR_IN_SET(field, "ExecStartPre",
2495 "ExecStartPost",
2496 "ExecReload",
2497 "ExecStopPost"))
89ada3ba
YW
2498 return bus_append_exec_command(m, field, eq);
2499
c57d2a76
ZJS
2500 if (STR_IN_SET(field, "SmackLabel",
2501 "SmackLabelIPIn",
2502 "SmackLabelIPOut",
2503 "TCPCongestion",
2504 "BindToDevice",
2505 "BindIPv6Only",
2506 "FileDescriptorName",
2507 "SocketUser",
9b191525
LP
2508 "SocketGroup",
2509 "Timestamping"))
89ada3ba
YW
2510 return bus_append_string(m, field, eq);
2511
2512 if (streq(field, "Symlinks"))
4ec85141 2513 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
89ada3ba 2514
e045e325 2515 if (streq(field, "SocketProtocol"))
d2b42d63 2516 return bus_append_parse_ip_protocol(m, field, eq);
89ada3ba 2517
c57d2a76
ZJS
2518 if (STR_IN_SET(field, "ListenStream",
2519 "ListenDatagram",
2520 "ListenSequentialPacket",
2521 "ListenNetlink",
2522 "ListenSpecial",
2523 "ListenMessageQueue",
2524 "ListenFIFO",
2525 "ListenUSBFunction")) {
3d63c749
YW
2526 if (isempty(eq))
2527 r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 0);
2528 else
81b1dc27 2529 r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 1, field + STRLEN("Listen"), eq);
f6c66be1 2530 if (r < 0)
89ada3ba
YW
2531 return bus_log_create_error(r);
2532
2533 return 1;
2534 }
2535
2536 return 0;
2537}
2538static int bus_append_timer_property(sd_bus_message *m, const char *field, const char *eq) {
3d63c749 2539 int r;
89ada3ba 2540
c57d2a76
ZJS
2541 if (STR_IN_SET(field, "WakeSystem",
2542 "RemainAfterElapse",
2543 "Persistent",
2544 "OnTimezoneChange",
acf24a1a
KG
2545 "OnClockChange",
2546 "FixedRandomDelay"))
89ada3ba
YW
2547 return bus_append_parse_boolean(m, field, eq);
2548
c57d2a76
ZJS
2549 if (STR_IN_SET(field, "AccuracySec",
2550 "RandomizedDelaySec"))
3d63c749
YW
2551 return bus_append_parse_sec_rename(m, field, eq);
2552
c57d2a76
ZJS
2553 if (STR_IN_SET(field, "OnActiveSec",
2554 "OnBootSec",
2555 "OnStartupSec",
2556 "OnUnitActiveSec",
2557 "OnUnitInactiveSec")) {
3d63c749
YW
2558 if (isempty(eq))
2559 r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 0);
2560 else {
2561 usec_t t;
2562 r = parse_sec(eq, &t);
2563 if (r < 0)
2564 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq);
89ada3ba 2565
3d63c749
YW
2566 r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 1, field, t);
2567 }
2568 if (r < 0)
2569 return bus_log_create_error(r);
89ada3ba 2570
3d63c749
YW
2571 return 1;
2572 }
2573
2574 if (streq(field, "OnCalendar")) {
3d63c749
YW
2575 if (isempty(eq))
2576 r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 0);
2577 else
2578 r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 1, field, eq);
2579 if (r < 0)
2580 return bus_log_create_error(r);
2581
2582 return 1;
2583 }
89ada3ba
YW
2584
2585 return 0;
2586}
2587
2588static int bus_append_unit_property(sd_bus_message *m, const char *field, const char *eq) {
3d63c749
YW
2589 ConditionType t = _CONDITION_TYPE_INVALID;
2590 bool is_condition = false;
2591 int r;
f6c66be1 2592
c57d2a76
ZJS
2593 if (STR_IN_SET(field, "Description",
2594 "SourcePath",
2595 "OnFailureJobMode",
2596 "JobTimeoutAction",
2597 "JobTimeoutRebootArgument",
2598 "StartLimitAction",
2599 "FailureAction",
2600 "SuccessAction",
2601 "RebootArgument",
2602 "CollectMode"))
89ada3ba
YW
2603 return bus_append_string(m, field, eq);
2604
c57d2a76
ZJS
2605 if (STR_IN_SET(field, "StopWhenUnneeded",
2606 "RefuseManualStart",
2607 "RefuseManualStop",
2608 "AllowIsolate",
2609 "IgnoreOnIsolate",
559214cb 2610 "SurviveFinalKillSignal",
c57d2a76 2611 "DefaultDependencies"))
89ada3ba
YW
2612 return bus_append_parse_boolean(m, field, eq);
2613
c57d2a76
ZJS
2614 if (STR_IN_SET(field, "JobTimeoutSec",
2615 "JobRunningTimeoutSec",
2616 "StartLimitIntervalSec"))
3d63c749
YW
2617 return bus_append_parse_sec_rename(m, field, eq);
2618
2619 if (streq(field, "StartLimitBurst"))
3d63c749
YW
2620 return bus_append_safe_atou(m, field, eq);
2621
c57d2a76
ZJS
2622 if (STR_IN_SET(field, "SuccessActionExitStatus",
2623 "FailureActionExitStatus")) {
7af67e9a
LP
2624 if (isempty(eq))
2625 r = sd_bus_message_append(m, "(sv)", field, "i", -1);
2626 else {
2627 uint8_t u;
2628
2629 r = safe_atou8(eq, &u);
2630 if (r < 0)
2631 return log_error_errno(r, "Failed to parse %s=%s", field, eq);
2632
2633 r = sd_bus_message_append(m, "(sv)", field, "i", (int) u);
2634 }
2635 if (r < 0)
2636 return bus_log_create_error(r);
2637
2638 return 1;
2639 }
2640
3d63c749 2641 if (unit_dependency_from_string(field) >= 0 ||
c57d2a76 2642 STR_IN_SET(field, "Documentation",
0dd3c090
ZJS
2643 "RequiresMountsFor",
2644 "Markers"))
4ec85141 2645 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
89ada3ba 2646
3d63c749
YW
2647 t = condition_type_from_string(field);
2648 if (t >= 0)
2649 is_condition = true;
2650 else
2651 t = assert_type_from_string(field);
2652 if (t >= 0) {
2653 if (isempty(eq))
2654 r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 0);
2655 else {
2656 const char *p = eq;
2657 int trigger, negate;
2658
2659 trigger = *p == '|';
2660 if (trigger)
2661 p++;
2662
2663 negate = *p == '!';
2664 if (negate)
2665 p++;
2666
2667 r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 1,
2668 field, trigger, negate, p);
2669 }
2670 if (r < 0)
2671 return bus_log_create_error(r);
2672
2673 return 1;
2674 }
2675
89ada3ba
YW
2676 return 0;
2677}
2678
2679int bus_append_unit_property_assignment(sd_bus_message *m, UnitType t, const char *assignment) {
2680 const char *eq, *field;
2681 int r;
2682
2683 assert(m);
2684 assert(assignment);
2685
2686 eq = strchr(assignment, '=');
baaa35ad
ZJS
2687 if (!eq)
2688 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2689 "Not an assignment: %s", assignment);
89ada3ba 2690
2f82562b 2691 field = strndupa_safe(assignment, eq - assignment);
89ada3ba
YW
2692 eq++;
2693
2694 switch (t) {
2695 case UNIT_SERVICE:
2696 r = bus_append_cgroup_property(m, field, eq);
2697 if (r != 0)
f6c66be1
LP
2698 return r;
2699
89ada3ba
YW
2700 r = bus_append_execute_property(m, field, eq);
2701 if (r != 0)
2702 return r;
f6c66be1 2703
89ada3ba
YW
2704 r = bus_append_kill_property(m, field, eq);
2705 if (r != 0)
2706 return r;
f6c66be1 2707
89ada3ba
YW
2708 r = bus_append_service_property(m, field, eq);
2709 if (r != 0)
2710 return r;
2711 break;
f6c66be1 2712
89ada3ba
YW
2713 case UNIT_SOCKET:
2714 r = bus_append_cgroup_property(m, field, eq);
2715 if (r != 0)
2716 return r;
f6c66be1 2717
89ada3ba
YW
2718 r = bus_append_execute_property(m, field, eq);
2719 if (r != 0)
2720 return r;
f6c66be1 2721
89ada3ba
YW
2722 r = bus_append_kill_property(m, field, eq);
2723 if (r != 0)
2724 return r;
f6c66be1 2725
89ada3ba
YW
2726 r = bus_append_socket_property(m, field, eq);
2727 if (r != 0)
f6c66be1 2728 return r;
89ada3ba 2729 break;
f6c66be1 2730
89ada3ba
YW
2731 case UNIT_TIMER:
2732 r = bus_append_timer_property(m, field, eq);
2733 if (r != 0)
2734 return r;
2735 break;
f6c66be1 2736
89ada3ba
YW
2737 case UNIT_PATH:
2738 r = bus_append_path_property(m, field, eq);
2739 if (r != 0)
2740 return r;
2741 break;
268833ed 2742
89ada3ba
YW
2743 case UNIT_SLICE:
2744 r = bus_append_cgroup_property(m, field, eq);
2745 if (r != 0)
2746 return r;
2747 break;
268833ed 2748
89ada3ba
YW
2749 case UNIT_SCOPE:
2750 r = bus_append_cgroup_property(m, field, eq);
2751 if (r != 0)
2752 return r;
268833ed 2753
89ada3ba 2754 r = bus_append_kill_property(m, field, eq);
5a70a68f
PW
2755 if (r != 0)
2756 return r;
2757
2758 r = bus_append_scope_property(m, field, eq);
89ada3ba
YW
2759 if (r != 0)
2760 return r;
2761 break;
535e0d19 2762
89ada3ba 2763 case UNIT_MOUNT:
3d63c749
YW
2764 r = bus_append_cgroup_property(m, field, eq);
2765 if (r != 0)
2766 return r;
2767
2768 r = bus_append_execute_property(m, field, eq);
2769 if (r != 0)
2770 return r;
2771
2772 r = bus_append_kill_property(m, field, eq);
2773 if (r != 0)
2774 return r;
2775
2776 r = bus_append_mount_property(m, field, eq);
2777 if (r != 0)
2778 return r;
2779
2780 break;
2781
89ada3ba 2782 case UNIT_AUTOMOUNT:
3d63c749
YW
2783 r = bus_append_automount_property(m, field, eq);
2784 if (r != 0)
2785 return r;
2786
89ada3ba 2787 break;
535e0d19 2788
89ada3ba
YW
2789 case UNIT_TARGET:
2790 case UNIT_DEVICE:
2791 case UNIT_SWAP:
eab62c01 2792 break;
535e0d19 2793
89ada3ba 2794 default:
eab62c01 2795 assert_not_reached();
20b16441
LP
2796 }
2797
89ada3ba
YW
2798 r = bus_append_unit_property(m, field, eq);
2799 if (r != 0)
2800 return r;
20b16441 2801
baaa35ad
ZJS
2802 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2803 "Unknown assignment: %s", assignment);
20b16441
LP
2804}
2805
89ada3ba 2806int bus_append_unit_property_assignment_many(sd_bus_message *m, UnitType t, char **l) {
8673cf13
LP
2807 int r;
2808
2809 assert(m);
2810
2811 STRV_FOREACH(i, l) {
89ada3ba 2812 r = bus_append_unit_property_assignment(m, t, *i);
8673cf13
LP
2813 if (r < 0)
2814 return r;
2815 }
2816
2817 return 0;
2818}
2819
5e891cbb 2820int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
20b16441 2821 const char *type, *path, *source;
5e891cbb
DT
2822 InstallChange *changes = NULL;
2823 size_t n_changes = 0;
20b16441
LP
2824 int r;
2825
5e891cbb 2826 CLEANUP_ARRAY(changes, n_changes, install_changes_free);
acc0269c 2827
20b16441
LP
2828 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
2829 if (r < 0)
2830 return bus_log_parse_error(r);
2831
2832 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
f8662fee
LP
2833 InstallChangeType t;
2834
2835 /* We expect only "success" changes to be sent over the bus. Hence, reject anything
2836 * negative. */
2837 t = install_change_type_from_string(type);
2838 if (t < 0) {
2839 log_notice_errno(t, "Manager reported unknown change type \"%s\" for path \"%s\", ignoring.",
c1b48a7f 2840 type, path);
20b16441
LP
2841 continue;
2842 }
2843
5e891cbb 2844 r = install_changes_add(&changes, &n_changes, t, path, source);
20b16441
LP
2845 if (r < 0)
2846 return r;
2847 }
2848 if (r < 0)
2849 return bus_log_parse_error(r);
2850
2851 r = sd_bus_message_exit_container(m);
2852 if (r < 0)
2853 return bus_log_parse_error(r);
2854
5e891cbb
DT
2855 install_changes_dump(0, NULL, changes, n_changes, quiet);
2856
20b16441
LP
2857 return 0;
2858}
2859
bd062910
ZJS
2860int unit_load_state(sd_bus *bus, const char *name, char **load_state) {
2861 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2862 _cleanup_free_ char *path = NULL;
2863 int r;
2864
2865 path = unit_dbus_path_from_name(name);
2866 if (!path)
2867 return log_oom();
2868
18fe76eb 2869 /* This function warns on its own, because otherwise it'd be awkward to pass
bd062910
ZJS
2870 * the dbus error message around. */
2871
2872 r = sd_bus_get_property_string(
2873 bus,
2874 "org.freedesktop.systemd1",
2875 path,
2876 "org.freedesktop.systemd1.Unit",
2877 "LoadState",
2878 &error,
2879 load_state);
2880 if (r < 0)
2881 return log_error_errno(r, "Failed to get load state of %s: %s", name, bus_error_message(&error, r));
2882
2883 return 0;
2884}
4dcc0653
LP
2885
2886int unit_info_compare(const UnitInfo *a, const UnitInfo *b) {
2887 int r;
2888
2889 /* First, order by machine */
2890 r = strcasecmp_ptr(a->machine, b->machine);
2891 if (r != 0)
2892 return r;
2893
2894 /* Second, order by unit type */
2895 r = strcasecmp_ptr(strrchr(a->id, '.'), strrchr(b->id, '.'));
2896 if (r != 0)
2897 return r;
2898
2899 /* Third, order by name */
2900 return strcasecmp(a->id, b->id);
2901}
a9399358
LP
2902
2903int bus_service_manager_reload(sd_bus *bus) {
2904 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2905 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2906 int r;
2907
2908 assert(bus);
2909
2910 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "Reload");
2911 if (r < 0)
2912 return bus_log_create_error(r);
2913
2914 /* Reloading the daemon may take long, hence set a longer timeout here */
2915 r = sd_bus_call(bus, m, DAEMON_RELOAD_TIMEOUT_SEC, &error, NULL);
2916 if (r < 0)
2917 return log_error_errno(r, "Failed to reload service manager: %s", bus_error_message(&error, r));
2918
2919 return 0;
2920}