]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sleep: use SleepOperation enum everywhere and drop sleep_settings()
authorLennart Poettering <lennart@poettering.net>
Fri, 21 May 2021 16:23:42 +0000 (18:23 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 22 May 2021 09:00:00 +0000 (11:00 +0200)
Instead of comparing strings everywhere, let's use the new enum. This
allows us to drop sleep_settings(), since the operation enum can be
directly used as index into the config settings.

Some minor other refactoring is done, but mostly just shifting thing
around a bit, no actual change in behaviour.

src/login/logind-action.c
src/login/logind-dbus.c
src/shared/sleep-config.c
src/shared/sleep-config.h
src/sleep/sleep.c
src/test/test-sleep.c

index 1a017c84145d3a5d615d5828aebf97621e5d8d11..8ed066c25e53a15d9fb2fb781a56fb5785704805 100644 (file)
@@ -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));
index 61353c7f1749364ae41b4428cb0da9d28f87d6a2..e48360100c91f24d75bf5332b13b49daddc16a5f 100644 (file)
@@ -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);
 }
 
index a1ef64f6e904ba49604b2d49a406881079e615fe..7277a55635f451a076c6f6ed3d2936090aee1b30 100644 (file)
@@ -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);
 }
index c17a5241ab18c103438f2332e0e69b5fc3723372..c049a55ad6d0ce4af87eeb638907db036c43ebb2 100644 (file)
@@ -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);
 
index 8aeaa1a5434514befd34a760528baae64abca3a8..86b155c9ea8a19b03a168dfbe96cc438c32f98b9 100644 (file)
@@ -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);
index d916254cc9b7a8318f8e58307f8ac21f149159ba..7b982c2df87ea33105cfd087c2832b55991cd8d2 100644 (file)
@@ -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));
 }