1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <unistd.h>
5
6 #include "alloc-util.h"
7 #include "cgroup-util.h"
8 #include "dropin.h"
9 #include "escape.h"
10 #include "fd-util.h"
11 #include "fileio.h"
12 #include "fstab-util.h"
13 #include "generator.h"
14 #include "log.h"
15 #include "macro.h"
16 #include "mkdir-label.h"
17 #include "path-util.h"
18 #include "special.h"
19 #include "specifier.h"
20 #include "string-util.h"
21 #include "time-util.h"
22 #include "unit-name.h"
23 #include "util.h"
24
generator_open_unit_file(const char * dest,const char * source,const char * name,FILE ** file)25 int 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;
33 int r;
34
35 unit = prefix_roota(dest, name);
36
37 r = fopen_unlocked(unit, "wxe", &f);
38 if (r < 0) {
39 if (source && r == -EEXIST)
40 return log_error_errno(r,
41 "Failed to create unit file %s, as it already exists. Duplicate entry in %s?",
42 unit, source);
43 else
44 return log_error_errno(r,
45 "Failed to create unit file %s: %m",
46 unit);
47 }
48
49 fprintf(f,
50 "# Automatically generated by %s\n\n",
51 program_invocation_short_name);
52
53 *file = f;
54 return 0;
55 }
56
generator_add_symlink(const char * dir,const char * dst,const char * dep_type,const char * src)57 int 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). */
60
61 const char *from, *to;
62
63 from = path_is_absolute(src) ? src : strjoina("../", src);
64 to = strjoina(dir, "/", dst, ".", dep_type, "/", basename(src));
65
66 (void) mkdir_parents_label(to, 0755);
67 if (symlink(from, to) < 0)
68 if (errno != EEXIST)
69 return log_error_errno(errno, "Failed to create symlink \"%s\": %m", to);
70
71 return 0;
72 }
73
write_fsck_sysroot_service(const char * unit,const char * dir,const char * what,const char * extra_after)74 static 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
80 _cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL;
81 _cleanup_fclose_ FILE *f = NULL;
82 const char *fn;
83 int r;
84
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
90 escaped = specifier_escape(what);
91 if (!escaped)
92 return log_oom();
93
94 escaped2 = cescape(escaped);
95 if (!escaped2)
96 return log_oom();
97
98 fn = strjoina(dir, "/", unit);
99 log_debug("Creating %s", fn);
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
105 f = fopen(fn, "wxe");
106 if (!f)
107 return log_error_errno(errno, "Failed to create unit file %s: %m", fn);
108
109 fprintf(f,
110 "# Automatically generated by %1$s\n\n"
111 "[Unit]\n"
112 "Description=File System Check on %2$s\n"
113 "Documentation=man:%3$s(8)\n"
114 "DefaultDependencies=no\n"
115 "BindsTo=%4$s\n"
116 "Conflicts=shutdown.target\n"
117 "After=%5$s%6$slocal-fs-pre.target %4$s\n"
118 "Before=shutdown.target\n"
119 "\n"
120 "[Service]\n"
121 "Type=oneshot\n"
122 "RemainAfterExit=yes\n"
123 "ExecStart=" SYSTEMD_FSCK_PATH " %7$s\n"
124 "TimeoutSec=0\n",
125 program_invocation_short_name,
126 escaped,
127 unit,
128 device,
129 strempty(extra_after),
130 isempty(extra_after) ? "" : " ",
131 escaped2);
132
133 r = fflush_and_check(f);
134 if (r < 0)
135 return log_error_errno(r, "Failed to write unit file %s: %m", fn);
136
137 return 0;
138 }
139
generator_write_fsck_deps(FILE * f,const char * dir,const char * what,const char * where,const char * fstype)140 int generator_write_fsck_deps(
141 FILE *f,
142 const char *dir,
143 const char *what,
144 const char *where,
145 const char *fstype) {
146
147 int r;
148
149 assert(f);
150 assert(dir);
151 assert(what);
152 assert(where);
153
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
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
166 if (!isempty(fstype) && !streq(fstype, "auto")) {
167 r = fsck_exists(fstype);
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) {
171 /* treat missing check as essentially OK */
172 log_debug("Checking was requested for %s, but fsck.%s does not exist.", what, fstype);
173 return 0;
174 }
175 }
176
177 if (path_equal(where, "/")) {
178 const char *lnk;
179
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
185 lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/" SPECIAL_FSCK_ROOT_SERVICE);
186
187 (void) mkdir_parents(lnk, 0755);
188 if (symlink(SYSTEM_DATA_UNIT_DIR "/" SPECIAL_FSCK_ROOT_SERVICE, lnk) < 0)
189 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
190
191 } else {
192 _cleanup_free_ char *_fsck = NULL;
193 const char *fsck, *dep;
194
195 if (in_initrd() && path_equal(where, "/sysroot")) {
196 r = write_fsck_sysroot_service(SPECIAL_FSCK_ROOT_SERVICE, dir, what, SPECIAL_INITRD_ROOT_DEVICE_TARGET);
197 if (r < 0)
198 return r;
199
200 fsck = SPECIAL_FSCK_ROOT_SERVICE;
201 dep = "Requires";
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";
210 } else {
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
216 dep = path_equal(where, "/usr") ? "Wants" : "Requires";
217
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 }
224
225 fprintf(f,
226 "%1$s=%2$s\n"
227 "After=%2$s\n",
228 dep, fsck);
229 }
230
231 return 0;
232 }
233
generator_write_timeouts(const char * dir,const char * what,const char * where,const char * opts,char ** filtered)234 int generator_write_timeouts(
235 const char *dir,
236 const char *what,
237 const char *where,
238 const char *opts,
239 char **filtered) {
240
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. */
244
245 _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL;
246 usec_t u;
247 int r;
248
249 r = fstab_filter_options(opts, "comment=systemd.device-timeout\0"
250 "x-systemd.device-timeout\0",
251 NULL, &timeout, NULL, filtered);
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;
258
259 r = parse_sec_fix_0(timeout, &u);
260 if (r < 0) {
261 log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
262 return 0;
263 }
264
265 node = fstab_node_to_udev_node(what);
266 if (!node)
267 return log_oom();
268 if (!is_device_path(node)) {
269 log_warning("x-systemd.device-timeout ignored for %s", what);
270 return 0;
271 }
272
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");
276
277 return write_drop_in_format(dir, unit, 50, "device-timeout",
278 "# Automatically generated by %s\n"
279 "# from supplied options \"%s\"\n\n"
280 "[Unit]\n"
281 "JobRunningTimeoutSec=%s",
282 program_invocation_short_name,
283 opts,
284 timeout);
285 }
286
generator_write_device_deps(const char * dir,const char * what,const char * where,const char * opts)287 int 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
301 if (fstab_is_extrinsic(where, opts))
302 return 0;
303
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)
317 return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
318 node);
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
generator_write_initrd_root_device_deps(const char * dir,const char * what)330 int 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)
336 return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
337 what);
338
339 return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device",
340 "# Automatically generated by %s\n\n"
341 "[Unit]\n"
342 "Requires=%s\n"
343 "After=%s",
344 program_invocation_short_name,
345 unit,
346 unit);
347 }
348
generator_hook_up_mkswap(const char * dir,const char * what)349 int 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. */
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);
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
373 unit_file = prefix_roota(dir, unit);
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"
397 "Conflicts=shutdown.target\n"
398 "After=%%i.device\n"
399 "Before=shutdown.target %s\n"
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
generator_hook_up_mkfs(const char * dir,const char * what,const char * where,const char * type)417 int 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. */
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);
437
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);
442
443 r = unit_name_from_path_instance("systemd-makefs", node, ".service", &unit);
444 if (r < 0)
445 return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
446 node);
447
448 unit_file = prefix_roota(dir, unit);
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"
469 "Documentation=man:systemd-makefs@.service(8)\n"
470 "DefaultDependencies=no\n"
471 "BindsTo=%%i.device\n"
472 "Conflicts=shutdown.target\n"
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. */
476 "Before=shutdown.target systemd-fsck@%%i.service %s\n"
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 }
495
generator_hook_up_growfs(const char * dir,const char * where,const char * target)496 int 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
506 assert(dir);
507 assert(where);
508
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
523 unit_file = prefix_roota(dir, unit);
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"
538 "Conflicts=shutdown.target\n"
539 "After=%%i.mount\n"
540 "Before=shutdown.target%s%s\n",
541 program_invocation_short_name,
542 target ? " " : "",
543 strempty(target));
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,
550 "\n"
551 "[Service]\n"
552 "Type=oneshot\n"
553 "RemainAfterExit=yes\n"
554 "ExecStart="SYSTEMD_GROWFS_PATH " %s\n"
555 "TimeoutSec=0\n",
556 escaped);
557
558 return generator_add_symlink(dir, where_unit, "wants", unit);
559 }
560
generator_enable_remount_fs_service(const char * dir)561 int 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",
564 SYSTEM_DATA_UNIT_DIR "/" SPECIAL_REMOUNT_FS_SERVICE);
565 }
566
generator_write_blockdev_dependency(FILE * f,const char * what)567 int 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
generator_write_cryptsetup_unit_section(FILE * f,const char * source)591 int 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"
608 "After=cryptsetup-pre.target systemd-udevd-kernel.socket\n"
609 "Before=blockdev@dev-mapper-%%i.target\n"
610 "Wants=blockdev@dev-mapper-%%i.target\n");
611
612 return 0;
613 }
614
generator_write_cryptsetup_service_section(FILE * f,const char * name,const char * what,const char * key_file,const char * options)615 int generator_write_cryptsetup_service_section(
616 FILE *f,
617 const char *name,
618 const char *what,
619 const char *key_file,
620 const char *options) {
621
622 _cleanup_free_ char *name_escaped = NULL, *what_escaped = NULL, *key_file_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 (key_file) {
637 key_file_escaped = specifier_escape(key_file);
638 if (!key_file_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(key_file_escaped), strempty(options_escaped),
659 name_escaped);
660
661 return 0;
662 }
663
generator_write_veritysetup_unit_section(FILE * f,const char * source)664 int 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
generator_write_veritysetup_service_section(FILE * f,const char * name,const char * data_what,const char * hash_what,const char * roothash,const char * options)688 int 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
696 _cleanup_free_ char *name_escaped = NULL, *data_what_escaped = NULL, *hash_what_escaped = NULL,
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
log_setup_generator(void)739 void log_setup_generator(void) {
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();
747 }
748