Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <stdio.h>
5 : : #include <unistd.h>
6 : :
7 : : #include "alloc-util.h"
8 : : #include "fstab-util.h"
9 : : #include "generator.h"
10 : : #include "log.h"
11 : : #include "main-func.h"
12 : : #include "mkdir.h"
13 : : #include "proc-cmdline.h"
14 : : #include "special.h"
15 : : #include "string-util.h"
16 : : #include "unit-name.h"
17 : :
18 : : static const char *arg_dest = "/tmp";
19 : : static char *arg_resume_device = NULL;
20 : : static char *arg_resume_options = NULL;
21 : : static char *arg_root_options = NULL;
22 : : static bool arg_noresume = false;
23 : :
24 : 0 : STATIC_DESTRUCTOR_REGISTER(arg_resume_device, freep);
25 : 0 : STATIC_DESTRUCTOR_REGISTER(arg_resume_options, freep);
26 : 0 : STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep);
27 : :
28 : 0 : static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
29 : :
30 [ # # ]: 0 : if (streq(key, "resume")) {
31 : : char *s;
32 : :
33 [ # # ]: 0 : if (proc_cmdline_value_missing(key, value))
34 : 0 : return 0;
35 : :
36 : 0 : s = fstab_node_to_udev_node(value);
37 [ # # ]: 0 : if (!s)
38 : 0 : return log_oom();
39 : :
40 : 0 : free_and_replace(arg_resume_device, s);
41 : :
42 [ # # ]: 0 : } else if (streq(key, "resumeflags")) {
43 : :
44 [ # # ]: 0 : if (proc_cmdline_value_missing(key, value))
45 : 0 : return 0;
46 : :
47 [ # # ]: 0 : if (!strextend_with_separator(&arg_resume_options, ",", value, NULL))
48 : 0 : return log_oom();
49 : :
50 [ # # ]: 0 : } else if (streq(key, "rootflags")) {
51 : :
52 [ # # ]: 0 : if (proc_cmdline_value_missing(key, value))
53 : 0 : return 0;
54 : :
55 [ # # ]: 0 : if (!strextend_with_separator(&arg_root_options, ",", value, NULL))
56 : 0 : return log_oom();
57 : :
58 [ # # ]: 0 : } else if (streq(key, "noresume")) {
59 [ # # ]: 0 : if (value) {
60 [ # # ]: 0 : log_warning("\"noresume\" kernel command line switch specified with an argument, ignoring.");
61 : 0 : return 0;
62 : : }
63 : :
64 : 0 : arg_noresume = true;
65 : : }
66 : :
67 : 0 : return 0;
68 : : }
69 : :
70 : 0 : static int process_resume(void) {
71 : 0 : _cleanup_free_ char *name = NULL, *lnk = NULL;
72 : : const char *opts;
73 : : int r;
74 : :
75 [ # # ]: 0 : if (!arg_resume_device)
76 : 0 : return 0;
77 : :
78 : 0 : r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_device, ".service", &name);
79 [ # # ]: 0 : if (r < 0)
80 [ # # ]: 0 : return log_error_errno(r, "Failed to generate unit name: %m");
81 : :
82 : 0 : lnk = strjoin(arg_dest, "/" SPECIAL_SYSINIT_TARGET ".wants/", name);
83 [ # # ]: 0 : if (!lnk)
84 : 0 : return log_oom();
85 : :
86 : 0 : mkdir_parents_label(lnk, 0755);
87 [ # # ]: 0 : if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-hibernate-resume@.service", lnk) < 0)
88 [ # # ]: 0 : return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
89 : :
90 [ # # ]: 0 : if (arg_resume_options)
91 : 0 : opts = arg_resume_options;
92 : : else
93 : 0 : opts = arg_root_options;
94 : :
95 : 0 : r = generator_write_timeouts(arg_dest, arg_resume_device, arg_resume_device, opts, NULL);
96 [ # # ]: 0 : if (r < 0)
97 : 0 : return r;
98 : :
99 : 0 : return 0;
100 : : }
101 : :
102 : 0 : static int run(int argc, char *argv[]) {
103 : 0 : int r = 0;
104 : :
105 : 0 : log_setup_generator();
106 : :
107 [ # # # # ]: 0 : if (argc > 1 && argc != 4)
108 [ # # ]: 0 : return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
109 : : "This program takes three or no arguments.");
110 : :
111 [ # # ]: 0 : if (argc > 1)
112 : 0 : arg_dest = argv[1];
113 : :
114 : : /* Don't even consider resuming outside of initramfs. */
115 [ # # ]: 0 : if (!in_initrd()) {
116 [ # # ]: 0 : log_debug("Not running in an initrd, quitting.");
117 : 0 : return 0;
118 : : }
119 : :
120 : 0 : r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
121 [ # # ]: 0 : if (r < 0)
122 [ # # ]: 0 : log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
123 : :
124 [ # # ]: 0 : if (arg_noresume) {
125 [ # # ]: 0 : log_notice("Found \"noresume\" on the kernel command line, quitting.");
126 : 0 : return 0;
127 : : }
128 : :
129 : 0 : return process_resume();
130 : : }
131 : :
132 : 0 : DEFINE_MAIN_FUNCTION(run);
|