]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
d2c68822 | 2 | |
d2c68822 | 3 | #include <errno.h> |
07630cea | 4 | #include <stdio.h> |
d2c68822 | 5 | |
b5efdb8a | 6 | #include "alloc-util.h" |
6550203e | 7 | #include "fstab-util.h" |
afe44c8f | 8 | #include "generator.h" |
d2c68822 | 9 | #include "log.h" |
77182cc6 | 10 | #include "main-func.h" |
d2c68822 | 11 | #include "mkdir.h" |
4e731273 | 12 | #include "proc-cmdline.h" |
07630cea LP |
13 | #include "special.h" |
14 | #include "string-util.h" | |
d2c68822 | 15 | #include "unit-name.h" |
07630cea | 16 | #include "util.h" |
d2c68822 IS |
17 | |
18 | static const char *arg_dest = "/tmp"; | |
1d84ad94 | 19 | static char *arg_resume_device = NULL; |
e83419d0 | 20 | static bool arg_noresume = false; |
d2c68822 | 21 | |
77182cc6 YW |
22 | STATIC_DESTRUCTOR_REGISTER(arg_resume_device, freep); |
23 | ||
96287a49 | 24 | static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { |
7410616c | 25 | |
1d84ad94 LP |
26 | if (streq(key, "resume")) { |
27 | char *s; | |
28 | ||
29 | if (proc_cmdline_value_missing(key, value)) | |
30 | return 0; | |
31 | ||
32 | s = fstab_node_to_udev_node(value); | |
33 | if (!s) | |
d2c68822 | 34 | return log_oom(); |
1d84ad94 | 35 | |
e83419d0 ZJS |
36 | free_and_replace(arg_resume_device, s); |
37 | ||
38 | } else if (streq(key, "noresume")) { | |
39 | if (value) { | |
40 | log_warning("\"noresume\" kernel command line switch specified with an argument, ignoring."); | |
41 | return 0; | |
42 | } | |
43 | ||
44 | arg_noresume = true; | |
d2c68822 IS |
45 | } |
46 | ||
47 | return 0; | |
48 | } | |
49 | ||
50 | static int process_resume(void) { | |
51 | _cleanup_free_ char *name = NULL, *lnk = NULL; | |
7410616c | 52 | int r; |
d2c68822 | 53 | |
1d84ad94 | 54 | if (!arg_resume_device) |
b5884878 LP |
55 | return 0; |
56 | ||
1d84ad94 | 57 | r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_device, ".service", &name); |
7410616c LP |
58 | if (r < 0) |
59 | return log_error_errno(r, "Failed to generate unit name: %m"); | |
d2c68822 | 60 | |
605405c6 | 61 | lnk = strjoin(arg_dest, "/" SPECIAL_SYSINIT_TARGET ".wants/", name); |
d2c68822 IS |
62 | if (!lnk) |
63 | return log_oom(); | |
64 | ||
65 | mkdir_parents_label(lnk, 0755); | |
4a62c710 MS |
66 | if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-hibernate-resume@.service", lnk) < 0) |
67 | return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); | |
d2c68822 IS |
68 | |
69 | return 0; | |
70 | } | |
71 | ||
77182cc6 | 72 | static int run(int argc, char *argv[]) { |
d2c68822 IS |
73 | int r = 0; |
74 | ||
afe44c8f | 75 | log_setup_generator(); |
a79858bf | 76 | |
baaa35ad ZJS |
77 | if (argc > 1 && argc != 4) |
78 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), | |
79 | "This program takes three or no arguments."); | |
d2c68822 IS |
80 | |
81 | if (argc > 1) | |
82 | arg_dest = argv[1]; | |
83 | ||
d2c68822 | 84 | /* Don't even consider resuming outside of initramfs. */ |
a79858bf ZJS |
85 | if (!in_initrd()) { |
86 | log_debug("Not running in an initrd, quitting."); | |
77182cc6 | 87 | return 0; |
a79858bf | 88 | } |
d2c68822 | 89 | |
1d84ad94 | 90 | r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); |
b5884878 | 91 | if (r < 0) |
da927ba9 | 92 | log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); |
d2c68822 | 93 | |
e83419d0 ZJS |
94 | if (arg_noresume) { |
95 | log_notice("Found \"noresume\" on the kernel command line, quitting."); | |
77182cc6 | 96 | return 0; |
e83419d0 ZJS |
97 | } |
98 | ||
77182cc6 | 99 | return process_resume(); |
d2c68822 | 100 | } |
77182cc6 YW |
101 | |
102 | DEFINE_MAIN_FUNCTION(run); |