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