]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/generator.c
Merge pull request #22546 from poettering/resolved-bus-error-reply-rework
[thirdparty/systemd.git] / src / shared / generator.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
e48fdd84 2
a8fbdf54 3#include <errno.h>
e48fdd84
LP
4#include <unistd.h>
5
b5efdb8a 6#include "alloc-util.h"
dee29aeb 7#include "cgroup-util.h"
4f5dd394
LP
8#include "dropin.h"
9#include "escape.h"
3ffd4af2 10#include "fd-util.h"
4f5dd394
LP
11#include "fileio.h"
12#include "fstab-util.h"
3ffd4af2 13#include "generator.h"
a8fbdf54
TA
14#include "log.h"
15#include "macro.h"
35cd0ba5 16#include "mkdir-label.h"
4f5dd394
LP
17#include "path-util.h"
18#include "special.h"
98bad05e 19#include "specifier.h"
07630cea 20#include "string-util.h"
a8fbdf54 21#include "time-util.h"
e48fdd84 22#include "unit-name.h"
4f5dd394 23#include "util.h"
e48fdd84 24
fb883e75
ZJS
25int generator_open_unit_file(
26 const char *dest,
27 const char *source,
28 const char *name,
29 FILE **file) {
30
31 const char *unit;
32 FILE *f;
41f6e627 33 int r;
fb883e75 34
270384b2 35 unit = prefix_roota(dest, name);
fb883e75 36
41f6e627
ZJS
37 r = fopen_unlocked(unit, "wxe", &f);
38 if (r < 0) {
39 if (source && r == -EEXIST)
40 return log_error_errno(r,
fb883e75
ZJS
41 "Failed to create unit file %s, as it already exists. Duplicate entry in %s?",
42 unit, source);
43 else
41f6e627 44 return log_error_errno(r,
fb883e75
ZJS
45 "Failed to create unit file %s: %m",
46 unit);
47 }
48
fb883e75
ZJS
49 fprintf(f,
50 "# Automatically generated by %s\n\n",
51 program_invocation_short_name);
52
53 *file = f;
54 return 0;
55}
56
5c176eb4
ZJS
57int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src) {
58 /* Adds a symlink from <dst>.<dep_type>/ to <src> (if src is absolute)
59 * or ../<src> (otherwise). */
b559616f
ZJS
60
61 const char *from, *to;
62
5c176eb4
ZJS
63 from = path_is_absolute(src) ? src : strjoina("../", src);
64 to = strjoina(dir, "/", dst, ".", dep_type, "/", basename(src));
b559616f 65
35cd0ba5 66 (void) mkdir_parents_label(to, 0755);
b559616f 67 if (symlink(from, to) < 0)
7f0cc637
ZJS
68 if (errno != EEXIST)
69 return log_error_errno(errno, "Failed to create symlink \"%s\": %m", to);
b559616f
ZJS
70
71 return 0;
72}
73
2b66f48e
LP
74static int write_fsck_sysroot_service(
75 const char *unit, /* Either SPECIAL_FSCK_ROOT_SERVICE or SPECIAL_FSCK_USR_SERVICE */
76 const char *dir,
77 const char *what,
78 const char *extra_after) {
79
98bad05e 80 _cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL;
4dda4e63 81 _cleanup_fclose_ FILE *f = NULL;
2b66f48e 82 const char *fn;
4dda4e63
ZJS
83 int r;
84
2b66f48e
LP
85 /* Writes out special versions of systemd-root-fsck.service and systemd-usr-fsck.service for use in
86 * the initrd. The regular statically shipped versions of these unit files use / and /usr for as
87 * paths, which doesn't match what we need for the initrd (where the dirs are /sysroot +
88 * /sysusr/usr), hence we overwrite those versions here. */
89
98bad05e 90 escaped = specifier_escape(what);
fa05e972
AB
91 if (!escaped)
92 return log_oom();
93
98bad05e
LP
94 escaped2 = cescape(escaped);
95 if (!escaped2)
96 return log_oom();
97
2b66f48e
LP
98 fn = strjoina(dir, "/", unit);
99 log_debug("Creating %s", fn);
4dda4e63
ZJS
100
101 r = unit_name_from_path(what, ".device", &device);
102 if (r < 0)
103 return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what);
104
2b66f48e 105 f = fopen(fn, "wxe");
4dda4e63 106 if (!f)
2b66f48e 107 return log_error_errno(errno, "Failed to create unit file %s: %m", fn);
4dda4e63
ZJS
108
109 fprintf(f,
110 "# Automatically generated by %1$s\n\n"
111 "[Unit]\n"
4dda4e63 112 "Description=File System Check on %2$s\n"
2b66f48e 113 "Documentation=man:%3$s(8)\n"
4dda4e63 114 "DefaultDependencies=no\n"
2b66f48e 115 "BindsTo=%4$s\n"
ff9bf8d0 116 "Conflicts=shutdown.target\n"
2b66f48e 117 "After=%5$s%6$slocal-fs-pre.target %4$s\n"
4dda4e63
ZJS
118 "Before=shutdown.target\n"
119 "\n"
120 "[Service]\n"
121 "Type=oneshot\n"
122 "RemainAfterExit=yes\n"
2b66f48e 123 "ExecStart=" SYSTEMD_FSCK_PATH " %7$s\n"
4dda4e63
ZJS
124 "TimeoutSec=0\n",
125 program_invocation_short_name,
98bad05e 126 escaped,
2b66f48e 127 unit,
fa05e972 128 device,
2b66f48e
LP
129 strempty(extra_after),
130 isempty(extra_after) ? "" : " ",
98bad05e 131 escaped2);
4dda4e63 132
2929b4a6
LP
133 r = fflush_and_check(f);
134 if (r < 0)
2b66f48e 135 return log_error_errno(r, "Failed to write unit file %s: %m", fn);
4dda4e63
ZJS
136
137 return 0;
138}
139
e48fdd84
LP
140int generator_write_fsck_deps(
141 FILE *f,
2e852276 142 const char *dir,
e48fdd84
LP
143 const char *what,
144 const char *where,
6db615c1 145 const char *fstype) {
e48fdd84 146
7410616c
LP
147 int r;
148
e48fdd84 149 assert(f);
2e852276 150 assert(dir);
6db615c1
LP
151 assert(what);
152 assert(where);
e48fdd84 153
122860f1
LP
154 /* Let's do an early exit if we are invoked for the root and /usr/ trees in the initrd, to avoid
155 * generating confusing log messages */
156 if (in_initrd() && PATH_IN_SET(where, "/", "/usr")) {
157 log_debug("Skipping fsck for %s in initrd.", where);
158 return 0;
159 }
160
e48fdd84
LP
161 if (!is_device_path(what)) {
162 log_warning("Checking was requested for \"%s\", but it is not a device.", what);
163 return 0;
164 }
165
6db615c1 166 if (!isempty(fstype) && !streq(fstype, "auto")) {
eb66db55 167 r = fsck_exists(fstype);
85eca92e
LP
168 if (r < 0)
169 log_warning_errno(r, "Checking was requested for %s, but couldn't detect if fsck.%s may be used, proceeding: %m", what, fstype);
170 else if (r == 0) {
e48fdd84 171 /* treat missing check as essentially OK */
85eca92e 172 log_debug("Checking was requested for %s, but fsck.%s does not exist.", what, fstype);
571d0134 173 return 0;
85eca92e 174 }
e48fdd84
LP
175 }
176
2e852276 177 if (path_equal(where, "/")) {
85eca92e 178 const char *lnk;
e48fdd84 179
599aee40
LP
180 /* We support running the fsck instance for the root fs while it is already mounted, for
181 * compatibility with non-initrd boots. It's ugly, but it is how it is. Since – unlike for
182 * regular file systems – this means the ordering is reversed (i.e. mount *before* fsck) we
183 * have a separate fsck unit for this, independent of systemd-fsck@.service. */
184
cbdc9cfe 185 lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/" SPECIAL_FSCK_ROOT_SERVICE);
e48fdd84 186
37dc34f7 187 (void) mkdir_parents(lnk, 0755);
835cf75a 188 if (symlink(SYSTEM_DATA_UNIT_DIR "/" SPECIAL_FSCK_ROOT_SERVICE, lnk) < 0)
4a62c710 189 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
e48fdd84
LP
190
191 } else {
4dda4e63 192 _cleanup_free_ char *_fsck = NULL;
afacf3fc 193 const char *fsck, *dep;
4dda4e63
ZJS
194
195 if (in_initrd() && path_equal(where, "/sysroot")) {
2b66f48e 196 r = write_fsck_sysroot_service(SPECIAL_FSCK_ROOT_SERVICE, dir, what, SPECIAL_INITRD_ROOT_DEVICE_TARGET);
4dda4e63
ZJS
197 if (r < 0)
198 return r;
199
5ff8da10 200 fsck = SPECIAL_FSCK_ROOT_SERVICE;
afacf3fc 201 dep = "Requires";
2b66f48e
LP
202
203 } else if (in_initrd() && path_equal(where, "/sysusr/usr")) {
204 r = write_fsck_sysroot_service(SPECIAL_FSCK_USR_SERVICE, dir, what, NULL);
205 if (r < 0)
206 return r;
207
208 fsck = SPECIAL_FSCK_USR_SERVICE;
209 dep = "Requires";
4dda4e63 210 } else {
afacf3fc
LP
211 /* When this is /usr, then let's add a Wants= dependency, otherwise a Requires=
212 * dependency. Why? We can't possibly unmount /usr during shutdown, but if we have a
213 * Requires= from /usr onto a fsck@.service unit and that unit is shut down, then
214 * we'd have to unmount /usr too. */
215
122860f1 216 dep = path_equal(where, "/usr") ? "Wants" : "Requires";
afacf3fc 217
4dda4e63
ZJS
218 r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck);
219 if (r < 0)
220 return log_error_errno(r, "Failed to create fsck service name: %m");
221
222 fsck = _fsck;
223 }
e48fdd84
LP
224
225 fprintf(f,
afacf3fc
LP
226 "%1$s=%2$s\n"
227 "After=%2$s\n",
228 dep, fsck);
e48fdd84
LP
229 }
230
231 return 0;
232}
29686440 233
2e852276
ZJS
234int generator_write_timeouts(
235 const char *dir,
236 const char *what,
237 const char *where,
238 const char *opts,
239 char **filtered) {
29686440 240
c2f4bcfc
ZJS
241 /* Configure how long we wait for a device that backs a mount point or a
242 * swap partition to show up. This is useful to support endless device timeouts
243 * for devices that show up only after user input, like crypto devices. */
29686440 244
d15d0333 245 _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL;
29686440
ZJS
246 usec_t u;
247 int r;
29686440 248
0004f698
ZJS
249 r = fstab_filter_options(opts, "comment=systemd.device-timeout\0"
250 "x-systemd.device-timeout\0",
ff0c31bc 251 NULL, &timeout, NULL, filtered);
924f6503
ZJS
252 if (r < 0) {
253 log_warning_errno(r, "Failed to parse fstab options, ignoring: %m");
254 return 0;
255 }
256 if (r == 0)
257 return 0;
b3208b66 258
0004f698 259 r = parse_sec_fix_0(timeout, &u);
29686440 260 if (r < 0) {
7410616c 261 log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
29686440
ZJS
262 return 0;
263 }
264
265 node = fstab_node_to_udev_node(what);
266 if (!node)
267 return log_oom();
c67bd1f7
N
268 if (!is_device_path(node)) {
269 log_warning("x-systemd.device-timeout ignored for %s", what);
270 return 0;
271 }
29686440 272
7410616c
LP
273 r = unit_name_from_path(node, ".device", &unit);
274 if (r < 0)
275 return log_error_errno(r, "Failed to make unit name from path: %m");
29686440 276
8eea8687 277 return write_drop_in_format(dir, unit, 50, "device-timeout",
7cecc563
ZJS
278 "# Automatically generated by %s\n"
279 "# from supplied options \"%s\"\n\n"
acd53eaa
LP
280 "[Unit]\n"
281 "JobRunningTimeoutSec=%s",
282 program_invocation_short_name,
7cecc563 283 opts,
acd53eaa 284 timeout);
29686440 285}
7163e1ca 286
4195077a
MK
287int generator_write_device_deps(
288 const char *dir,
289 const char *what,
290 const char *where,
291 const char *opts) {
292
293 /* fstab records that specify _netdev option should apply the network
294 * ordering on the actual device depending on network connection. If we
295 * are not mounting real device (NFS, CIFS), we rely on _netdev effect
296 * on the mount unit itself. */
297
298 _cleanup_free_ char *node = NULL, *unit = NULL;
299 int r;
300
ad8f1b0f
FB
301 if (fstab_is_extrinsic(where, opts))
302 return 0;
303
4195077a
MK
304 if (!fstab_test_option(opts, "_netdev\0"))
305 return 0;
306
307 node = fstab_node_to_udev_node(what);
308 if (!node)
309 return log_oom();
310
311 /* Nothing to apply dependencies to. */
312 if (!is_device_path(node))
313 return 0;
314
315 r = unit_name_from_path(node, ".device", &unit);
316 if (r < 0)
da495a03
ZJS
317 return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
318 node);
4195077a
MK
319
320 /* See mount_add_default_dependencies for explanation why we create such
321 * dependencies. */
322 return write_drop_in_format(dir, unit, 50, "netdev-dependencies",
323 "# Automatically generated by %s\n\n"
324 "[Unit]\n"
325 "After=" SPECIAL_NETWORK_ONLINE_TARGET " " SPECIAL_NETWORK_TARGET "\n"
326 "Wants=" SPECIAL_NETWORK_ONLINE_TARGET "\n",
327 program_invocation_short_name);
328}
329
7163e1ca
DD
330int generator_write_initrd_root_device_deps(const char *dir, const char *what) {
331 _cleanup_free_ char *unit = NULL;
332 int r;
333
334 r = unit_name_from_path(what, ".device", &unit);
335 if (r < 0)
da495a03
ZJS
336 return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
337 what);
7163e1ca
DD
338
339 return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device",
340 "# Automatically generated by %s\n\n"
acd53eaa
LP
341 "[Unit]\n"
342 "Requires=%s\n"
343 "After=%s",
344 program_invocation_short_name,
345 unit,
346 unit);
7163e1ca 347}
da495a03
ZJS
348
349int generator_hook_up_mkswap(
350 const char *dir,
351 const char *what) {
352
353 _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL;
354 _cleanup_fclose_ FILE *f = NULL;
355 const char *unit_file;
356 int r;
357
358 node = fstab_node_to_udev_node(what);
359 if (!node)
360 return log_oom();
361
362 /* Nothing to work on. */
baaa35ad
ZJS
363 if (!is_device_path(node))
364 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
365 "Cannot format something that is not a device node: %s",
366 node);
da495a03
ZJS
367
368 r = unit_name_from_path_instance("systemd-mkswap", node, ".service", &unit);
369 if (r < 0)
370 return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
371 node);
372
270384b2 373 unit_file = prefix_roota(dir, unit);
da495a03
ZJS
374 log_debug("Creating %s", unit_file);
375
376 escaped = cescape(node);
377 if (!escaped)
378 return log_oom();
379
380 r = unit_name_from_path(what, ".swap", &where_unit);
381 if (r < 0)
382 return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
383 what);
384
385 f = fopen(unit_file, "wxe");
386 if (!f)
387 return log_error_errno(errno, "Failed to create unit file %s: %m",
388 unit_file);
389
390 fprintf(f,
391 "# Automatically generated by %s\n\n"
392 "[Unit]\n"
393 "Description=Make Swap on %%f\n"
394 "Documentation=man:systemd-mkswap@.service(8)\n"
395 "DefaultDependencies=no\n"
396 "BindsTo=%%i.device\n"
ff9bf8d0 397 "Conflicts=shutdown.target\n"
da495a03 398 "After=%%i.device\n"
ff9bf8d0 399 "Before=shutdown.target %s\n"
da495a03
ZJS
400 "\n"
401 "[Service]\n"
402 "Type=oneshot\n"
403 "RemainAfterExit=yes\n"
404 "ExecStart="SYSTEMD_MAKEFS_PATH " swap %s\n"
405 "TimeoutSec=0\n",
406 program_invocation_short_name,
407 where_unit,
408 escaped);
409
410 r = fflush_and_check(f);
411 if (r < 0)
412 return log_error_errno(r, "Failed to write unit file %s: %m", unit_file);
413
414 return generator_add_symlink(dir, where_unit, "requires", unit);
415}
416
417int generator_hook_up_mkfs(
418 const char *dir,
419 const char *what,
420 const char *where,
421 const char *type) {
422
423 _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL;
424 _cleanup_fclose_ FILE *f = NULL;
425 const char *unit_file;
426 int r;
427
428 node = fstab_node_to_udev_node(what);
429 if (!node)
430 return log_oom();
431
432 /* Nothing to work on. */
baaa35ad
ZJS
433 if (!is_device_path(node))
434 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
435 "Cannot format something that is not a device node: %s",
436 node);
da495a03 437
baaa35ad
ZJS
438 if (!type || streq(type, "auto"))
439 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
440 "Cannot format partition %s, filesystem type is not specified",
441 node);
da495a03 442
804f8e17 443 r = unit_name_from_path_instance("systemd-makefs", node, ".service", &unit);
da495a03
ZJS
444 if (r < 0)
445 return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
446 node);
447
270384b2 448 unit_file = prefix_roota(dir, unit);
da495a03
ZJS
449 log_debug("Creating %s", unit_file);
450
451 escaped = cescape(node);
452 if (!escaped)
453 return log_oom();
454
455 r = unit_name_from_path(where, ".mount", &where_unit);
456 if (r < 0)
457 return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
458 where);
459
460 f = fopen(unit_file, "wxe");
461 if (!f)
462 return log_error_errno(errno, "Failed to create unit file %s: %m",
463 unit_file);
464
465 fprintf(f,
466 "# Automatically generated by %s\n\n"
467 "[Unit]\n"
468 "Description=Make File System on %%f\n"
804f8e17 469 "Documentation=man:systemd-makefs@.service(8)\n"
da495a03
ZJS
470 "DefaultDependencies=no\n"
471 "BindsTo=%%i.device\n"
ff9bf8d0 472 "Conflicts=shutdown.target\n"
da495a03
ZJS
473 "After=%%i.device\n"
474 /* fsck might or might not be used, so let's be safe and order
475 * ourselves before both systemd-fsck@.service and the mount unit. */
ff9bf8d0 476 "Before=shutdown.target systemd-fsck@%%i.service %s\n"
da495a03
ZJS
477 "\n"
478 "[Service]\n"
479 "Type=oneshot\n"
480 "RemainAfterExit=yes\n"
481 "ExecStart="SYSTEMD_MAKEFS_PATH " %s %s\n"
482 "TimeoutSec=0\n",
483 program_invocation_short_name,
484 where_unit,
485 type,
486 escaped);
487 // XXX: what about local-fs-pre.target?
488
489 r = fflush_and_check(f);
490 if (r < 0)
491 return log_error_errno(r, "Failed to write unit file %s: %m", unit_file);
492
493 return generator_add_symlink(dir, where_unit, "requires", unit);
494}
7f2806d5
ZJS
495
496int generator_hook_up_growfs(
497 const char *dir,
498 const char *where,
499 const char *target) {
500
501 _cleanup_free_ char *unit = NULL, *escaped = NULL, *where_unit = NULL;
502 _cleanup_fclose_ FILE *f = NULL;
503 const char *unit_file;
504 int r;
505
400c1e8f
LP
506 assert(dir);
507 assert(where);
508
7f2806d5
ZJS
509 escaped = cescape(where);
510 if (!escaped)
511 return log_oom();
512
513 r = unit_name_from_path_instance("systemd-growfs", where, ".service", &unit);
514 if (r < 0)
515 return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
516 where);
517
518 r = unit_name_from_path(where, ".mount", &where_unit);
519 if (r < 0)
520 return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
521 where);
522
270384b2 523 unit_file = prefix_roota(dir, unit);
7f2806d5
ZJS
524 log_debug("Creating %s", unit_file);
525
526 f = fopen(unit_file, "wxe");
527 if (!f)
528 return log_error_errno(errno, "Failed to create unit file %s: %m",
529 unit_file);
530
531 fprintf(f,
532 "# Automatically generated by %s\n\n"
533 "[Unit]\n"
534 "Description=Grow File System on %%f\n"
535 "Documentation=man:systemd-growfs@.service(8)\n"
536 "DefaultDependencies=no\n"
537 "BindsTo=%%i.mount\n"
ff9bf8d0 538 "Conflicts=shutdown.target\n"
7f2806d5 539 "After=%%i.mount\n"
400c1e8f 540 "Before=shutdown.target%s%s\n",
18e6e863 541 program_invocation_short_name,
400c1e8f
LP
542 target ? " " : "",
543 strempty(target));
18e6e863
LP
544
545 if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */
546 fprintf(f,
547 "After=systemd-remount-fs.service\n");
548
549 fprintf(f,
7f2806d5
ZJS
550 "\n"
551 "[Service]\n"
552 "Type=oneshot\n"
553 "RemainAfterExit=yes\n"
554 "ExecStart="SYSTEMD_GROWFS_PATH " %s\n"
555 "TimeoutSec=0\n",
7f2806d5
ZJS
556 escaped);
557
558 return generator_add_symlink(dir, where_unit, "wants", unit);
559}
afe44c8f 560
9b69569d
ZJS
561int generator_enable_remount_fs_service(const char *dir) {
562 /* Pull in systemd-remount-fs.service */
563 return generator_add_symlink(dir, SPECIAL_LOCAL_FS_TARGET, "wants",
835cf75a 564 SYSTEM_DATA_UNIT_DIR "/" SPECIAL_REMOUNT_FS_SERVICE);
9b69569d
ZJS
565}
566
a7e88558
LP
567int generator_write_blockdev_dependency(
568 FILE *f,
569 const char *what) {
570
571 _cleanup_free_ char *escaped = NULL;
572 int r;
573
574 assert(f);
575 assert(what);
576
577 if (!path_startswith(what, "/dev/"))
578 return 0;
579
580 r = unit_name_path_escape(what, &escaped);
581 if (r < 0)
582 return log_error_errno(r, "Failed to escape device node path %s: %m", what);
583
584 fprintf(f,
585 "After=blockdev@%s.target\n",
586 escaped);
587
588 return 0;
589}
590
591int generator_write_cryptsetup_unit_section(
592 FILE *f,
593 const char *source) {
594
595 assert(f);
596
597 fprintf(f,
598 "[Unit]\n"
599 "Description=Cryptography Setup for %%I\n"
600 "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n");
601
602 if (source)
603 fprintf(f, "SourcePath=%s\n", source);
604
605 fprintf(f,
606 "DefaultDependencies=no\n"
607 "IgnoreOnIsolate=true\n"
239952e8 608 "After=cryptsetup-pre.target systemd-udevd-kernel.socket\n"
a7e88558
LP
609 "Before=blockdev@dev-mapper-%%i.target\n"
610 "Wants=blockdev@dev-mapper-%%i.target\n");
611
612 return 0;
613}
614
615int generator_write_cryptsetup_service_section(
616 FILE *f,
617 const char *name,
618 const char *what,
619 const char *password,
620 const char *options) {
621
622 _cleanup_free_ char *name_escaped = NULL, *what_escaped = NULL, *password_escaped = NULL, *options_escaped = NULL;
623
624 assert(f);
625 assert(name);
626 assert(what);
627
628 name_escaped = specifier_escape(name);
629 if (!name_escaped)
630 return log_oom();
631
632 what_escaped = specifier_escape(what);
633 if (!what_escaped)
634 return log_oom();
635
636 if (password) {
637 password_escaped = specifier_escape(password);
638 if (!password_escaped)
639 return log_oom();
640 }
641
642 if (options) {
643 options_escaped = specifier_escape(options);
644 if (!options_escaped)
645 return log_oom();
646 }
647
648 fprintf(f,
649 "\n"
650 "[Service]\n"
651 "Type=oneshot\n"
652 "RemainAfterExit=yes\n"
653 "TimeoutSec=0\n" /* The binary handles timeouts on its own */
654 "KeyringMode=shared\n" /* Make sure we can share cached keys among instances */
655 "OOMScoreAdjust=500\n" /* Unlocking can allocate a lot of memory if Argon2 is used */
656 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
657 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
658 name_escaped, what_escaped, strempty(password_escaped), strempty(options_escaped),
659 name_escaped);
660
661 return 0;
662}
663
08b04ec7
GP
664int generator_write_veritysetup_unit_section(
665 FILE *f,
666 const char *source) {
667
668 assert(f);
669
670 fprintf(f,
671 "[Unit]\n"
672 "Description=Integrity Protection Setup for %%I\n"
673 "Documentation=man:veritytab(5) man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n");
674
675 if (source)
676 fprintf(f, "SourcePath=%s\n", source);
677
678 fprintf(f,
679 "DefaultDependencies=no\n"
680 "IgnoreOnIsolate=true\n"
681 "After=cryptsetup-pre.target systemd-udevd-kernel.socket\n"
682 "Before=blockdev@dev-mapper-%%i.target\n"
683 "Wants=blockdev@dev-mapper-%%i.target\n");
684
685 return 0;
686}
687
688int generator_write_veritysetup_service_section(
689 FILE *f,
690 const char *name,
691 const char *data_what,
692 const char *hash_what,
693 const char *roothash,
694 const char *options) {
695
47237e0e 696 _cleanup_free_ char *name_escaped = NULL, *data_what_escaped = NULL, *hash_what_escaped = NULL,
08b04ec7
GP
697 *roothash_escaped = NULL, *options_escaped = NULL;
698
699 assert(f);
700 assert(name);
701 assert(data_what);
702 assert(hash_what);
703
704 name_escaped = specifier_escape(name);
705 if (!name_escaped)
706 return log_oom();
707
708 data_what_escaped = specifier_escape(data_what);
709 if (!data_what_escaped)
710 return log_oom();
711
712 hash_what_escaped = specifier_escape(hash_what);
713 if (!hash_what_escaped)
714 return log_oom();
715
716 roothash_escaped = specifier_escape(roothash);
717 if (!roothash_escaped)
718 return log_oom();
719
720 if (options) {
721 options_escaped = specifier_escape(options);
722 if (!options_escaped)
723 return log_oom();
724 }
725
726 fprintf(f,
727 "\n"
728 "[Service]\n"
729 "Type=oneshot\n"
730 "RemainAfterExit=yes\n"
731 "ExecStart=" SYSTEMD_VERITYSETUP_PATH " attach '%s' '%s' '%s' '%s' '%s'\n"
732 "ExecStop=" SYSTEMD_VERITYSETUP_PATH " detach '%s'\n",
733 name_escaped, data_what_escaped, hash_what_escaped, roothash_escaped, strempty(options_escaped),
734 name_escaped);
735
736 return 0;
737}
738
afe44c8f 739void log_setup_generator(void) {
dee29aeb
LP
740 /* Disable talking to syslog/journal (i.e. the two IPC-based loggers) if we run in system context. */
741 if (cg_pid_get_owner_uid(0, NULL) == -ENXIO /* not running in a per-user slice */)
742 log_set_prohibit_ipc(true);
743
744 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); /* This effectively means: journal for per-user generators, kmsg otherwise */
745 log_parse_environment();
746 (void) log_open();
afe44c8f 747}