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