]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/hibernate-resume/hibernate-resume-generator.c
basic: create new basic/initrd-util.[ch] for initrd-related functions
[thirdparty/systemd.git] / src / hibernate-resume / hibernate-resume-generator.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
d2c68822 2
d2c68822 3#include <errno.h>
07630cea 4#include <stdio.h>
ca78ad1d 5#include <unistd.h>
d2c68822 6
b5efdb8a 7#include "alloc-util.h"
ff757c9d 8#include "dropin.h"
6550203e 9#include "fstab-util.h"
afe44c8f 10#include "generator.h"
baa6a42d 11#include "initrd-util.h"
d2c68822 12#include "log.h"
77182cc6 13#include "main-func.h"
35cd0ba5 14#include "mkdir-label.h"
4e731273 15#include "proc-cmdline.h"
07630cea
LP
16#include "special.h"
17#include "string-util.h"
d2c68822
IS
18#include "unit-name.h"
19
b8110a3e 20static const char *arg_dest = NULL;
1d84ad94 21static char *arg_resume_device = NULL;
8b6805a2 22static char *arg_resume_options = NULL;
70e843fe 23static char *arg_root_options = NULL;
e83419d0 24static bool arg_noresume = false;
d2c68822 25
77182cc6 26STATIC_DESTRUCTOR_REGISTER(arg_resume_device, freep);
8b6805a2 27STATIC_DESTRUCTOR_REGISTER(arg_resume_options, freep);
70e843fe 28STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep);
77182cc6 29
96287a49 30static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
7410616c 31
1d84ad94
LP
32 if (streq(key, "resume")) {
33 char *s;
34
35 if (proc_cmdline_value_missing(key, value))
36 return 0;
37
38 s = fstab_node_to_udev_node(value);
39 if (!s)
d2c68822 40 return log_oom();
1d84ad94 41
e83419d0
ZJS
42 free_and_replace(arg_resume_device, s);
43
8b6805a2
JR
44 } else if (streq(key, "resumeflags")) {
45
46 if (proc_cmdline_value_missing(key, value))
47 return 0;
48
c2bc710b 49 if (!strextend_with_separator(&arg_resume_options, ",", value))
8b6805a2
JR
50 return log_oom();
51
70e843fe
JR
52 } else if (streq(key, "rootflags")) {
53
54 if (proc_cmdline_value_missing(key, value))
55 return 0;
56
c2bc710b 57 if (!strextend_with_separator(&arg_root_options, ",", value))
70e843fe
JR
58 return log_oom();
59
e83419d0
ZJS
60 } else if (streq(key, "noresume")) {
61 if (value) {
62 log_warning("\"noresume\" kernel command line switch specified with an argument, ignoring.");
63 return 0;
64 }
65
66 arg_noresume = true;
d2c68822
IS
67 }
68
69 return 0;
70}
71
72static int process_resume(void) {
ff757c9d 73 _cleanup_free_ char *service_unit = NULL, *device_unit = NULL, *lnk = NULL;
7410616c 74 int r;
d2c68822 75
1d84ad94 76 if (!arg_resume_device)
b5884878
LP
77 return 0;
78
ff757c9d
ZJS
79 r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_device, ".service",
80 &service_unit);
7410616c
LP
81 if (r < 0)
82 return log_error_errno(r, "Failed to generate unit name: %m");
d2c68822 83
ff757c9d 84 lnk = strjoin(arg_dest, "/" SPECIAL_SYSINIT_TARGET ".wants/", service_unit);
d2c68822
IS
85 if (!lnk)
86 return log_oom();
87
35cd0ba5 88 (void) mkdir_parents_label(lnk, 0755);
835cf75a 89 if (symlink(SYSTEM_DATA_UNIT_DIR "/systemd-hibernate-resume@.service", lnk) < 0)
4a62c710 90 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
d2c68822 91
ff757c9d
ZJS
92 r = unit_name_from_path(arg_resume_device, ".device", &device_unit);
93 if (r < 0)
94 return log_error_errno(r, "Failed to generate unit name: %m");
95
96 r = write_drop_in(arg_dest, device_unit, 40, "device-timeout",
90198bcb 97 "# Automatically generated by systemd-hibernate-resume-generator\n\n"
ff757c9d
ZJS
98 "[Unit]\nJobTimeoutSec=0");
99 if (r < 0)
100 log_warning_errno(r, "Failed to write device timeout drop-in: %m");
8b6805a2 101
ff757c9d
ZJS
102 r = generator_write_timeouts(arg_dest,
103 arg_resume_device,
104 arg_resume_device,
105 arg_resume_options ?: arg_root_options,
106 NULL);
70e843fe
JR
107 if (r < 0)
108 return r;
109
d2c68822
IS
110 return 0;
111}
112
b8110a3e 113static int run(const char *dest, const char *dest_early, const char *dest_late) {
d2c68822
IS
114 int r = 0;
115
b8110a3e 116 arg_dest = ASSERT_PTR(dest);
d2c68822 117
32e27670 118 /* Don't even consider resuming outside of initrd. */
a79858bf
ZJS
119 if (!in_initrd()) {
120 log_debug("Not running in an initrd, quitting.");
77182cc6 121 return 0;
a79858bf 122 }
d2c68822 123
1d84ad94 124 r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
b5884878 125 if (r < 0)
da927ba9 126 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
d2c68822 127
e83419d0
ZJS
128 if (arg_noresume) {
129 log_notice("Found \"noresume\" on the kernel command line, quitting.");
77182cc6 130 return 0;
e83419d0
ZJS
131 }
132
77182cc6 133 return process_resume();
d2c68822 134}
77182cc6 135
b8110a3e 136DEFINE_MAIN_GENERATOR_FUNCTION(run);