diff options
-rw-r--r-- | src/login/logind-action.c | 10 | ||||
-rw-r--r-- | src/login/logind-dbus.c | 44 | ||||
-rw-r--r-- | src/shared/sleep-config.c | 147 | ||||
-rw-r--r-- | src/shared/sleep-config.h | 21 | ||||
-rw-r--r-- | src/sleep/sleep.c | 79 | ||||
-rw-r--r-- | src/test/test-sleep.c | 28 |
6 files changed, 150 insertions, 179 deletions
diff --git a/src/login/logind-action.c b/src/login/logind-action.c index 1a017c8414..8ed066c25e 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -102,20 +102,20 @@ int manager_handle_action( } if (handle == HANDLE_SUSPEND) - supported = can_sleep("suspend") > 0; + supported = can_sleep(SLEEP_SUSPEND) > 0; else if (handle == HANDLE_HIBERNATE) - supported = can_sleep("hibernate") > 0; + supported = can_sleep(SLEEP_HIBERNATE) > 0; else if (handle == HANDLE_HYBRID_SLEEP) - supported = can_sleep("hybrid-sleep") > 0; + supported = can_sleep(SLEEP_HYBRID_SLEEP) > 0; else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE) - supported = can_sleep("suspend-then-hibernate") > 0; + supported = can_sleep(SLEEP_SUSPEND_THEN_HIBERNATE) > 0; else if (handle == HANDLE_KEXEC) supported = access(KEXEC, X_OK) >= 0; else supported = true; if (!supported && IN_SET(handle, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP, HANDLE_SUSPEND_THEN_HIBERNATE)) { - supported = can_sleep("suspend") > 0; + supported = can_sleep(SLEEP_SUSPEND) > 0; if (supported) { log_notice("Requested %s operation is not supported, using regular suspend instead.", handle_action_to_string(handle)); diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 61353c7f17..e48360100c 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1851,7 +1851,7 @@ static int method_do_shutdown_or_sleep( const char *action, const char *action_multiple_sessions, const char *action_ignore_inhibit, - const char *sleep_verb, + SleepOperation sleep_operation, bool with_flags, sd_bus_error *error) { @@ -1894,14 +1894,14 @@ static int method_do_shutdown_or_sleep( return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress"); - if (sleep_verb) { - r = can_sleep(sleep_verb); + if (sleep_operation >= 0) { + r = can_sleep(sleep_operation); if (r == -ENOSPC) return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Not enough swap space for hibernation"); if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, - "Sleep verb \"%s\" not supported", sleep_verb); + "Sleep verb \"%s\" not supported", sleep_operation_to_string(sleep_operation)); if (r < 0) return r; } @@ -1928,7 +1928,7 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error "org.freedesktop.login1.power-off", "org.freedesktop.login1.power-off-multiple-sessions", "org.freedesktop.login1.power-off-ignore-inhibit", - NULL, + _SLEEP_OPERATION_INVALID, sd_bus_message_is_method_call(message, NULL, "PowerOffWithFlags"), error); } @@ -1943,7 +1943,7 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error * "org.freedesktop.login1.reboot", "org.freedesktop.login1.reboot-multiple-sessions", "org.freedesktop.login1.reboot-ignore-inhibit", - NULL, + _SLEEP_OPERATION_INVALID, sd_bus_message_is_method_call(message, NULL, "RebootWithFlags"), error); } @@ -1958,7 +1958,7 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er "org.freedesktop.login1.halt", "org.freedesktop.login1.halt-multiple-sessions", "org.freedesktop.login1.halt-ignore-inhibit", - NULL, + _SLEEP_OPERATION_INVALID, sd_bus_message_is_method_call(message, NULL, "HaltWithFlags"), error); } @@ -1973,7 +1973,7 @@ static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error "org.freedesktop.login1.suspend", "org.freedesktop.login1.suspend-multiple-sessions", "org.freedesktop.login1.suspend-ignore-inhibit", - "suspend", + SLEEP_SUSPEND, sd_bus_message_is_method_call(message, NULL, "SuspendWithFlags"), error); } @@ -1988,7 +1988,7 @@ static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_erro "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "hibernate", + SLEEP_HIBERNATE, sd_bus_message_is_method_call(message, NULL, "HibernateWithFlags"), error); } @@ -2003,7 +2003,7 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "hybrid-sleep", + SLEEP_HYBRID_SLEEP, sd_bus_message_is_method_call(message, NULL, "HybridSleepWithFlags"), error); } @@ -2018,7 +2018,7 @@ static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "hybrid-sleep", + SLEEP_SUSPEND_THEN_HIBERNATE, sd_bus_message_is_method_call(message, NULL, "SuspendThenHibernateWithFlags"), error); } @@ -2317,7 +2317,7 @@ static int method_can_shutdown_or_sleep( const char *action, const char *action_multiple_sessions, const char *action_ignore_inhibit, - const char *sleep_verb, + SleepOperation sleep_operation, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; @@ -2335,8 +2335,8 @@ static int method_can_shutdown_or_sleep( assert(action_multiple_sessions); assert(action_ignore_inhibit); - if (sleep_verb) { - r = can_sleep(sleep_verb); + if (sleep_operation >= 0) { + r = can_sleep(sleep_operation); if (IN_SET(r, 0, -ENOSPC)) return sd_bus_reply_method_return(message, "s", "na"); if (r < 0) @@ -2358,7 +2358,7 @@ static int method_can_shutdown_or_sleep( multiple_sessions = r > 0; blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); - handle = handle_action_from_string(sleep_verb); + handle = handle_action_from_string(sleep_operation_to_string(sleep_operation)); if (handle >= 0) { const char *target; @@ -2434,7 +2434,7 @@ static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_e "org.freedesktop.login1.power-off", "org.freedesktop.login1.power-off-multiple-sessions", "org.freedesktop.login1.power-off-ignore-inhibit", - NULL, + _SLEEP_OPERATION_INVALID, error); } @@ -2447,7 +2447,7 @@ static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_err "org.freedesktop.login1.reboot", "org.freedesktop.login1.reboot-multiple-sessions", "org.freedesktop.login1.reboot-ignore-inhibit", - NULL, + _SLEEP_OPERATION_INVALID, error); } @@ -2460,7 +2460,7 @@ static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error "org.freedesktop.login1.halt", "org.freedesktop.login1.halt-multiple-sessions", "org.freedesktop.login1.halt-ignore-inhibit", - NULL, + _SLEEP_OPERATION_INVALID, error); } @@ -2473,7 +2473,7 @@ static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_er "org.freedesktop.login1.suspend", "org.freedesktop.login1.suspend-multiple-sessions", "org.freedesktop.login1.suspend-ignore-inhibit", - "suspend", + SLEEP_SUSPEND, error); } @@ -2486,7 +2486,7 @@ static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_ "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "hibernate", + SLEEP_HIBERNATE, error); } @@ -2499,7 +2499,7 @@ static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_b "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "hybrid-sleep", + SLEEP_HYBRID_SLEEP, error); } @@ -2512,7 +2512,7 @@ static int method_can_suspend_then_hibernate(sd_bus_message *message, void *user "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "suspend-then-hibernate", + SLEEP_SUSPEND_THEN_HIBERNATE, error); } diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index a1ef64f6e9..7277a55635 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -44,19 +44,19 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) { return log_oom(); const ConfigTableItem items[] = { - { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend }, - { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate }, - { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h }, - { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep }, - - { "Sleep", "SuspendMode", config_parse_strv, 0, &sc->suspend_modes }, - { "Sleep", "SuspendState", config_parse_strv, 0, &sc->suspend_states }, - { "Sleep", "HibernateMode", config_parse_strv, 0, &sc->hibernate_modes }, - { "Sleep", "HibernateState", config_parse_strv, 0, &sc->hibernate_states }, - { "Sleep", "HybridSleepMode", config_parse_strv, 0, &sc->hybrid_modes }, - { "Sleep", "HybridSleepState", config_parse_strv, 0, &sc->hybrid_states }, - - { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_sec}, + { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend }, + { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate }, + { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h }, + { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep }, + + { "Sleep", "SuspendMode", config_parse_strv, 0, sc->modes + SLEEP_SUSPEND }, + { "Sleep", "SuspendState", config_parse_strv, 0, sc->states + SLEEP_SUSPEND }, + { "Sleep", "HibernateMode", config_parse_strv, 0, sc->modes + SLEEP_HIBERNATE }, + { "Sleep", "HibernateState", config_parse_strv, 0, sc->states + SLEEP_HIBERNATE }, + { "Sleep", "HybridSleepMode", config_parse_strv, 0, sc->modes + SLEEP_HYBRID_SLEEP }, + { "Sleep", "HybridSleepState", config_parse_strv, 0, sc->states + SLEEP_HYBRID_SLEEP }, + + { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_sec }, {} }; @@ -70,29 +70,29 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) { NULL); /* use default values unless set */ - sc->allow_suspend = allow_suspend != 0; - sc->allow_hibernate = allow_hibernate != 0; - sc->allow_hybrid_sleep = allow_hybrid_sleep >= 0 ? allow_hybrid_sleep + sc->allow[SLEEP_SUSPEND] = allow_suspend != 0; + sc->allow[SLEEP_HIBERNATE] = allow_hibernate != 0; + sc->allow[SLEEP_HYBRID_SLEEP] = allow_hybrid_sleep >= 0 ? allow_hybrid_sleep : (allow_suspend != 0 && allow_hibernate != 0); - sc->allow_s2h = allow_s2h >= 0 ? allow_s2h + sc->allow[SLEEP_SUSPEND_THEN_HIBERNATE] = allow_s2h >= 0 ? allow_s2h : (allow_suspend != 0 && allow_hibernate != 0); - if (!sc->suspend_states) - sc->suspend_states = strv_new("mem", "standby", "freeze"); - if (!sc->hibernate_modes) - sc->hibernate_modes = strv_new("platform", "shutdown"); - if (!sc->hibernate_states) - sc->hibernate_states = strv_new("disk"); - if (!sc->hybrid_modes) - sc->hybrid_modes = strv_new("suspend", "platform", "shutdown"); - if (!sc->hybrid_states) - sc->hybrid_states = strv_new("disk"); + if (!sc->states[SLEEP_SUSPEND]) + sc->states[SLEEP_SUSPEND] = strv_new("mem", "standby", "freeze"); + if (!sc->modes[SLEEP_HIBERNATE]) + sc->modes[SLEEP_HIBERNATE] = strv_new("platform", "shutdown"); + if (!sc->states[SLEEP_HIBERNATE]) + sc->states[SLEEP_HIBERNATE] = strv_new("disk"); + if (!sc->modes[SLEEP_HYBRID_SLEEP]) + sc->modes[SLEEP_HYBRID_SLEEP] = strv_new("suspend", "platform", "shutdown"); + if (!sc->states[SLEEP_HYBRID_SLEEP]) + sc->states[SLEEP_HYBRID_SLEEP] = strv_new("disk"); if (sc->hibernate_delay_sec == 0) sc->hibernate_delay_sec = 2 * USEC_PER_HOUR; /* ensure values set for all required fields */ - if (!sc->suspend_states || !sc->hibernate_modes - || !sc->hibernate_states || !sc->hybrid_modes || !sc->hybrid_states) + if (!sc->states[SLEEP_SUSPEND] || !sc->modes[SLEEP_HIBERNATE] + || !sc->states[SLEEP_HIBERNATE] || !sc->modes[SLEEP_HYBRID_SLEEP] || !sc->states[SLEEP_HYBRID_SLEEP]) return log_oom(); *ret_sleep_config = TAKE_PTR(sc); @@ -589,10 +589,15 @@ int read_fiemap(int fd, struct fiemap **ret) { return 0; } -static int can_sleep_internal(const char *verb, bool check_allowed, const SleepConfig *sleep_config); +static int can_sleep_internal(const SleepConfig *sleep_config, SleepOperation operation, bool check_allowed); static bool can_s2h(const SleepConfig *sleep_config) { - const char *p; + + static const SleepOperation operations[] = { + SLEEP_SUSPEND, + SLEEP_HIBERNATE, + }; + int r; if (!clock_supported(CLOCK_BOOTTIME_ALARM)) { @@ -600,42 +605,40 @@ static bool can_s2h(const SleepConfig *sleep_config) { return false; } - FOREACH_STRING(p, "suspend", "hibernate") { - r = can_sleep_internal(p, false, sleep_config); + for (size_t i = 0; i < ELEMENTSOF(operations); i++) { + r = can_sleep_internal(sleep_config, operations[i], false); if (IN_SET(r, 0, -ENOSPC, -EADV)) { - log_debug("Unable to %s system.", p); + log_debug("Unable to %s system.", sleep_operation_to_string(operations[i])); return false; } if (r < 0) - return log_debug_errno(r, "Failed to check if %s is possible: %m", p); + return log_debug_errno(r, "Failed to check if %s is possible: %m", sleep_operation_to_string(operations[i])); } return true; } -static int can_sleep_internal(const char *verb, bool check_allowed, const SleepConfig *sleep_config) { - bool allow; - char **modes = NULL, **states = NULL; - int r; - - assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); +static int can_sleep_internal( + const SleepConfig *sleep_config, + SleepOperation operation, + bool check_allowed) { - r = sleep_settings(verb, sleep_config, &allow, &modes, &states); - if (r < 0) - return false; + assert(operation >= 0); + assert(operation < _SLEEP_OPERATION_MAX); - if (check_allowed && !allow) { - log_debug("Sleep mode \"%s\" is disabled by configuration.", verb); + if (check_allowed && !sleep_config->allow[operation]) { + log_debug("Sleep mode \"%s\" is disabled by configuration.", sleep_operation_to_string(operation)); return false; } - if (streq(verb, "suspend-then-hibernate")) + if (operation == SLEEP_SUSPEND_THEN_HIBERNATE) return can_s2h(sleep_config); - if (!can_sleep_state(states) || !can_sleep_disk(modes)) + if (!can_sleep_state(sleep_config->states[operation]) || + !can_sleep_disk(sleep_config->modes[operation])) return false; - if (streq(verb, "suspend")) + if (operation == SLEEP_SUSPEND) return true; if (!enough_swap_for_hibernation()) @@ -644,7 +647,7 @@ static int can_sleep_internal(const char *verb, bool check_allowed, const SleepC return true; } -int can_sleep(const char *verb) { +int can_sleep(SleepOperation operation) { _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; int r; @@ -652,51 +655,17 @@ int can_sleep(const char *verb) { if (r < 0) return r; - return can_sleep_internal(verb, true, sleep_config); -} - -int sleep_settings(const char *verb, const SleepConfig *sleep_config, bool *ret_allow, char ***ret_modes, char ***ret_states) { - - assert(verb); - assert(sleep_config); - assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); - - if (streq(verb, "suspend")) { - *ret_allow = sleep_config->allow_suspend; - *ret_modes = sleep_config->suspend_modes; - *ret_states = sleep_config->suspend_states; - } else if (streq(verb, "hibernate")) { - *ret_allow = sleep_config->allow_hibernate; - *ret_modes = sleep_config->hibernate_modes; - *ret_states = sleep_config->hibernate_states; - } else if (streq(verb, "hybrid-sleep")) { - *ret_allow = sleep_config->allow_hybrid_sleep; - *ret_modes = sleep_config->hybrid_modes; - *ret_states = sleep_config->hybrid_states; - } else if (streq(verb, "suspend-then-hibernate")) { - *ret_allow = sleep_config->allow_s2h; - *ret_modes = *ret_states = NULL; - } - - /* suspend modes empty by default */ - if ((!ret_modes && !streq(verb, "suspend")) || !ret_states) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No modes or states set for %s; Check sleep.conf", verb); - - return 0; + return can_sleep_internal(sleep_config, operation, true); } SleepConfig* free_sleep_config(SleepConfig *sc) { if (!sc) return NULL; - strv_free(sc->suspend_modes); - strv_free(sc->suspend_states); - - strv_free(sc->hibernate_modes); - strv_free(sc->hibernate_states); - - strv_free(sc->hybrid_modes); - strv_free(sc->hybrid_states); + for (SleepOperation i = 0; i < _SLEEP_OPERATION_MAX; i++) { + strv_free(sc->modes[i]); + strv_free(sc->states[i]); + } return mfree(sc); } diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h index c17a5241ab..c049a55ad6 100644 --- a/src/shared/sleep-config.h +++ b/src/shared/sleep-config.h @@ -14,19 +14,10 @@ typedef enum SleepOperation { } SleepOperation; typedef struct SleepConfig { - bool allow_suspend; /* AllowSuspend */ - bool allow_hibernate; /* AllowHibernation */ - bool allow_s2h; /* AllowSuspendThenHibernate */ - bool allow_hybrid_sleep; /* AllowHybridSleep */ - - char **suspend_modes; /* SuspendMode */ - char **suspend_states; /* SuspendState */ - char **hibernate_modes; /* HibernateMode */ - char **hibernate_states; /* HibernateState */ - char **hybrid_modes; /* HybridSleepMode */ - char **hybrid_states; /* HybridSleepState */ - - usec_t hibernate_delay_sec; /* HibernateDelaySec */ + bool allow[_SLEEP_OPERATION_MAX]; + char **modes[_SLEEP_OPERATION_MAX]; + char **states[_SLEEP_OPERATION_MAX]; + usec_t hibernate_delay_sec; } SleepConfig; SleepConfig* free_sleep_config(SleepConfig *sc); @@ -57,13 +48,11 @@ typedef struct HibernateLocation { HibernateLocation* hibernate_location_free(HibernateLocation *hl); DEFINE_TRIVIAL_CLEANUP_FUNC(HibernateLocation*, hibernate_location_free); -int sleep_settings(const char *verb, const SleepConfig *sleep_config, bool *ret_allow, char ***ret_modes, char ***ret_states); - int read_fiemap(int fd, struct fiemap **ret); int parse_sleep_config(SleepConfig **sleep_config); int find_hibernate_location(HibernateLocation **ret_hibernate_location); -int can_sleep(const char *verb); +int can_sleep(SleepOperation operation); int can_sleep_disk(char **types); int can_sleep_state(char **types); diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index 8aeaa1a543..86b155c9ea 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -35,9 +35,7 @@ #include "time-util.h" #include "util.h" -static char* arg_verb = NULL; - -STATIC_DESTRUCTOR_REGISTER(arg_verb, freep); +static SleepOperation arg_operation = _SLEEP_OPERATION_INVALID; static int write_hibernate_location_info(const HibernateLocation *hibernate_location) { char offset_str[DECIMAL_STR_MAX(uint64_t)]; @@ -169,11 +167,17 @@ static int lock_all_homes(void) { return 0; } -static int execute(char **modes, char **states, const char *action) { +static int execute( + const SleepConfig *sleep_config, + SleepOperation operation, + const char *action) { + char *arguments[] = { NULL, (char*) "pre", - arg_verb, + /* NB: we use 'arg_operation' instead of 'operation' here, as we want to communicate the overall + * operation here, not the specific one, in case of s2h. */ + (char*) sleep_operation_to_string(arg_operation), NULL }; static const char* const dirs[] = { @@ -181,10 +185,24 @@ static int execute(char **modes, char **states, const char *action) { NULL }; - _cleanup_fclose_ FILE *f = NULL; _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL; + _cleanup_fclose_ FILE *f = NULL; + char **modes, **states; int r; + assert(sleep_config); + assert(operation >= 0); + assert(operation < _SLEEP_OPERATION_MAX); + assert(operation != SLEEP_SUSPEND_THEN_HIBERNATE); /* Handled by execute_s2h() instead */ + + states = sleep_config->states[operation]; + modes = sleep_config->modes[operation]; + + if (strv_isempty(states)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "No sleep states configured for sleep operation %s, can't sleep.", + sleep_operation_to_string(operation)); + /* This file is opened first, so that if we hit an error, * we can abort before modifying any state. */ f = fopen("/sys/power/state", "we"); @@ -211,6 +229,11 @@ static int execute(char **modes, char **states, const char *action) { return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");; } + /* Pass an action string to the call-outs. This is mostly our operation string, except if the + * hibernate step of s-t-h fails, in which case we communicate that with a separate action. */ + if (!action) + action = sleep_operation_to_string(operation); + r = setenv("SYSTEMD_SLEEP_ACTION", action, 1); if (r != 0) log_warning_errno(errno, "Error setting SYSTEMD_SLEEP_ACTION=%s: %m", action); @@ -220,20 +243,20 @@ static int execute(char **modes, char **states, const char *action) { log_struct(LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, - LOG_MESSAGE("Suspending system..."), - "SLEEP=%s", arg_verb); + LOG_MESSAGE("Entering sleep state '%s'...", sleep_operation_to_string(operation)), + "SLEEP=%s", sleep_operation_to_string(arg_operation)); r = write_state(&f, states); if (r < 0) log_struct_errno(LOG_ERR, r, "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, - LOG_MESSAGE("Failed to suspend system. System resumed again: %m"), - "SLEEP=%s", arg_verb); + LOG_MESSAGE("Failed to put system to sleep. System resumed again: %m"), + "SLEEP=%s", sleep_operation_to_string(arg_operation)); else log_struct(LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, - LOG_MESSAGE("System resumed."), - "SLEEP=%s", arg_verb); + LOG_MESSAGE("System returned from sleep state."), + "SLEEP=%s", sleep_operation_to_string(arg_operation)); arguments[1] = (char*) "post"; (void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); @@ -262,7 +285,7 @@ static int execute_s2h(const SleepConfig *sleep_config) { if (r < 0) return log_error_errno(errno, "Error setting hibernate timer: %m"); - r = execute(sleep_config->suspend_modes, sleep_config->suspend_states, "suspend"); + r = execute(sleep_config, SLEEP_SUSPEND, NULL); if (r < 0) return r; @@ -278,11 +301,11 @@ static int execute_s2h(const SleepConfig *sleep_config) { log_debug("Attempting to hibernate after waking from %s timer", format_timespan(buf, sizeof(buf), sleep_config->hibernate_delay_sec, USEC_PER_SEC)); - r = execute(sleep_config->hibernate_modes, sleep_config->hibernate_states, "hibernate"); + r = execute(sleep_config, SLEEP_HIBERNATE, NULL); if (r < 0) { log_notice_errno(r, "Couldn't hibernate, will try to suspend again: %m"); - r = execute(sleep_config->suspend_modes, sleep_config->suspend_states, "suspend-after-failed-hibernate"); + r = execute(sleep_config, SLEEP_SUSPEND, "suspend-after-failed-hibernate"); if (r < 0) return log_error_errno(r, "Could neither hibernate nor suspend, giving up: %m"); } @@ -351,20 +374,14 @@ static int parse_argv(int argc, char *argv[]) { "Usage: %s COMMAND", program_invocation_short_name); - arg_verb = strdup(argv[optind]); - if (!arg_verb) - return log_oom(); - - if (!STR_IN_SET(arg_verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Unknown command '%s'.", arg_verb); + arg_operation = sleep_operation_from_string(argv[optind]); + if (arg_operation < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown command '%s'.", argv[optind]); return 1 /* work to do */; } static int run(int argc, char *argv[]) { - bool allow; - char **modes = NULL, **states = NULL; _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; int r; @@ -378,19 +395,15 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; - r = sleep_settings(arg_verb, sleep_config, &allow, &modes, &states); - if (r < 0) - return r; - - if (!allow) + if (!sleep_config->allow[arg_operation]) return log_error_errno(SYNTHETIC_ERRNO(EACCES), - "Sleep mode \"%s\" is disabled by configuration, refusing.", - arg_verb); + "Sleep operation \"%s\" is disabled by configuration, refusing.", + sleep_operation_to_string(arg_operation)); - if (streq(arg_verb, "suspend-then-hibernate")) + if (arg_operation == SLEEP_SUSPEND_THEN_HIBERNATE) return execute_s2h(sleep_config); else - return execute(modes, states, arg_verb); + return execute(sleep_config, arg_operation, NULL); } DEFINE_MAIN_FUNCTION(run); diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c index d916254cc9..7b982c2df8 100644 --- a/src/test/test-sleep.c +++ b/src/test/test-sleep.c @@ -25,16 +25,16 @@ static void test_parse_sleep_config(void) { _cleanup_free_ char *sum, *sus, *him, *his, *hym, *hys; - sum = strv_join(sleep_config->suspend_modes, ", "); - sus = strv_join(sleep_config->suspend_states, ", "); - him = strv_join(sleep_config->hibernate_modes, ", "); - his = strv_join(sleep_config->hibernate_states, ", "); - hym = strv_join(sleep_config->hybrid_modes, ", "); - hys = strv_join(sleep_config->hybrid_states, ", "); - log_debug(" allow_suspend: %u", sleep_config->allow_suspend); - log_debug(" allow_hibernate: %u", sleep_config->allow_hibernate); - log_debug(" allow_s2h: %u", sleep_config->allow_s2h); - log_debug(" allow_hybrid_sleep: %u", sleep_config->allow_hybrid_sleep); + sum = strv_join(sleep_config->modes[SLEEP_SUSPEND], ", "); + sus = strv_join(sleep_config->states[SLEEP_SUSPEND], ", "); + him = strv_join(sleep_config->modes[SLEEP_HIBERNATE], ", "); + his = strv_join(sleep_config->states[SLEEP_HIBERNATE], ", "); + hym = strv_join(sleep_config->modes[SLEEP_HYBRID_SLEEP], ", "); + hys = strv_join(sleep_config->states[SLEEP_HYBRID_SLEEP], ", "); + log_debug(" allow_suspend: %u", sleep_config->allow[SLEEP_SUSPEND]); + log_debug(" allow_hibernate: %u", sleep_config->allow[SLEEP_HIBERNATE]); + log_debug(" allow_s2h: %u", sleep_config->allow[SLEEP_SUSPEND_THEN_HIBERNATE]); + log_debug(" allow_hybrid_sleep: %u", sleep_config->allow[SLEEP_HYBRID_SLEEP]); log_debug(" suspend modes: %s", sum); log_debug(" states: %s", sus); log_debug(" hibernate modes: %s", him); @@ -98,13 +98,13 @@ static void test_sleep(void) { log_info("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0)); log_info("/= high-level sleep verbs =/"); - r = can_sleep("suspend"); + r = can_sleep(SLEEP_SUSPEND); log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); - r = can_sleep("hibernate"); + r = can_sleep(SLEEP_HIBERNATE); log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); - r = can_sleep("hybrid-sleep"); + r = can_sleep(SLEEP_HYBRID_SLEEP); log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); - r = can_sleep("suspend-then-hibernate"); + r = can_sleep(SLEEP_SUSPEND_THEN_HIBERNATE); log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); } |