]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
42483a74 | 2 | |
42483a74 | 3 | #include <errno.h> |
42483a74 | 4 | #include <sys/stat.h> |
42483a74 | 5 | |
ec61371f | 6 | #include "devnum-util.h" |
a628d933 | 7 | #include "hibernate-resume-config.h" |
54d7fcc6 | 8 | #include "hibernate-util.h" |
baa6a42d | 9 | #include "initrd-util.h" |
42483a74 | 10 | #include "log.h" |
760e99bb MY |
11 | #include "main-func.h" |
12 | #include "parse-util.h" | |
a628d933 | 13 | #include "static-destruct.h" |
42483a74 | 14 | |
a3f7047f | 15 | static HibernateInfo arg_info = {}; |
a628d933 MY |
16 | |
17 | STATIC_DESTRUCTOR_REGISTER(arg_info, hibernate_info_done); | |
18 | ||
19 | static int setup_hibernate_info_and_warn(void) { | |
20 | int r; | |
21 | ||
22 | r = acquire_hibernate_info(&arg_info); | |
23 | if (r == -ENODEV) { | |
24 | log_info_errno(r, "No resume device found, exiting."); | |
25 | return 0; | |
26 | } | |
27 | if (r < 0) | |
28 | return r; | |
29 | ||
30 | compare_hibernate_location_and_warn(&arg_info); | |
31 | ||
32 | return 1; | |
33 | } | |
760e99bb MY |
34 | |
35 | static int run(int argc, char *argv[]) { | |
42483a74 | 36 | struct stat st; |
42483a74 IS |
37 | int r; |
38 | ||
d2acb93d | 39 | log_setup(); |
42483a74 | 40 | |
a628d933 MY |
41 | if (argc < 1 || argc > 3) |
42 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program expects zero, one, or two arguments."); | |
760e99bb | 43 | |
42483a74 IS |
44 | umask(0022); |
45 | ||
ac528e3e | 46 | if (!in_initrd()) |
760e99bb | 47 | return 0; |
ac528e3e | 48 | |
a628d933 MY |
49 | if (argc > 1) { |
50 | arg_info.device = argv[1]; | |
51 | ||
52 | if (argc == 3) { | |
53 | r = safe_atou64(argv[2], &arg_info.offset); | |
54 | if (r < 0) | |
55 | return log_error_errno(r, "Failed to parse resume offset %s: %m", argv[2]); | |
56 | } | |
57 | } else { | |
58 | r = setup_hibernate_info_and_warn(); | |
59 | if (r <= 0) | |
60 | return r; | |
42483a74 | 61 | |
24ab77c3 | 62 | if (arg_info.efi) |
fbc88824 | 63 | (void) clear_efi_hibernate_location_and_warn(); |
42483a74 IS |
64 | } |
65 | ||
a628d933 MY |
66 | if (stat(arg_info.device, &st) < 0) |
67 | return log_error_errno(errno, "Failed to stat resume device '%s': %m", arg_info.device); | |
42483a74 | 68 | |
760e99bb | 69 | if (!S_ISBLK(st.st_mode)) |
667b0c48 | 70 | return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), |
a628d933 | 71 | "Resume device '%s' is not a block device.", arg_info.device); |
42483a74 | 72 | |
760e99bb | 73 | /* The write shall not return if a resume takes place. */ |
a628d933 | 74 | r = write_resume_config(st.st_rdev, arg_info.offset, arg_info.device); |
760e99bb MY |
75 | log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, |
76 | r < 0 ? r : SYNTHETIC_ERRNO(ENOENT), | |
77 | "Unable to resume from device '%s' (" DEVNUM_FORMAT_STR ") offset %" PRIu64 ", continuing boot process.", | |
a628d933 | 78 | arg_info.device, DEVNUM_FORMAT_VAL(st.st_rdev), arg_info.offset); |
42483a74 | 79 | |
760e99bb | 80 | return r; |
42483a74 | 81 | } |
760e99bb MY |
82 | |
83 | DEFINE_MAIN_FUNCTION(run); |