#include "audit-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
+#include "bus-unit-util.h"
#include "bus-util.h"
#include "dirent-util.h"
#include "efivars.h"
InhibitWhat w,
sd_bus_error *error) {
+ _cleanup_free_ char *load_state = NULL;
bool delayed;
int r;
assert(w <= _INHIBIT_WHAT_MAX);
assert(!m->action_job);
+ r = unit_load_state(m->bus, unit_name, &load_state);
+ if (r < 0)
+ return r;
+
+ if (!streq(load_state, "loaded")) {
+ log_notice("Unit %s is %s, refusing operation.", unit_name, load_state);
+ return -EACCES;
+ }
+
/* Tell everybody to prepare for shutdown/sleep */
(void) send_prepare_for(m, w, true);
if (sleep_verb) {
r = can_sleep(sleep_verb);
+ 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);
if (r < 0)
return r;
-
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
}
r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ HandleAction handle;
bool multiple_sessions, challenge, blocked;
const char *result = NULL;
uid_t uid;
if (sleep_verb) {
r = can_sleep(sleep_verb);
+ if (IN_SET(r, 0, -ENOSPC))
+ return sd_bus_reply_method_return(message, "s", "na");
if (r < 0)
return r;
- if (r == 0)
- return sd_bus_reply_method_return(message, "s", "na");
}
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
+ handle = handle_action_from_string(sleep_verb);
+ if (handle >= 0) {
+ const char *target;
+
+ target = manager_target_for_action(handle);
+ if (target) {
+ _cleanup_free_ char *load_state = NULL;
+
+ r = unit_load_state(m->bus, target, &load_state);
+ if (r < 0)
+ return r;
+
+ if (!streq(load_state, "loaded")) {
+ result = "no";
+ goto finish;
+ }
+ }
+ }
+
if (multiple_sessions) {
r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
if (r < 0)
result = "no";
}
+ finish:
return sd_bus_reply_method_return(message, "s", result);
}