1 From 5660e2c036463e899fb0da69297e88cf1bb6bbd8 Mon Sep 17 00:00:00 2001
2 From: Eric Koegel <eric.koegel@gmail.com>
3 Date: Mon, 20 Oct 2014 14:26:27 +0300
4 Subject: [PATCH] Add HybridSleep support and change CanSleep
6 Emulate the logind API to make it more easier for porting to
7 ConsoleKit2 for the CanSuspend/CanHibernate/CanHybridSleep methods.
9 yes - system can and user explicitly authorized by polkit, rbac, or neither is running
10 no - system can and user explicitly unauthorized by polkit or rbac
11 challenge - system can and user requires elevation via polkit
12 na - system does not support it (hardware or backend support missing).
13 The auth methods have been removed.
14 Currently HybridSleep only works on Linux.
16 data/ConsoleKit.conf | 8 +-
17 data/org.freedesktop.consolekit.policy | 20 ++-
18 src/ck-manager.c | 274 +++++++++++++++++++++++++----
19 src/ck-manager.h | 21 ++-
20 src/ck-sysdeps-freebsd.c | 7 +
21 src/ck-sysdeps-gnu.c | 7 +
22 src/ck-sysdeps-linux.c | 6 +
23 src/ck-sysdeps-openbsd.c | 7 +
24 src/ck-sysdeps-solaris.c | 7 +
25 src/ck-sysdeps.h | 1 +
26 src/org.freedesktop.ConsoleKit.Manager.xml | 43 +++--
27 tools/freebsd/Makefile.am | 1 +
28 tools/freebsd/ck-system-hybridsleep | 4 +
29 tools/linux/Makefile.am | 1 +
30 tools/linux/ck-system-hybridsleep | 12 ++
31 tools/openbsd/Makefile.am | 1 +
32 tools/openbsd/ck-system-hybridsleep | 5 +
33 tools/solaris/Makefile.am | 1 +
34 tools/solaris/ck-system-hybridsleep | 4 +
35 19 files changed, 372 insertions(+), 58 deletions(-)
36 create mode 100644 tools/freebsd/ck-system-hybridsleep
37 create mode 100644 tools/linux/ck-system-hybridsleep
38 create mode 100644 tools/openbsd/ck-system-hybridsleep
39 create mode 100644 tools/solaris/ck-system-hybridsleep
41 diff --git a/data/ConsoleKit.conf b/data/ConsoleKit.conf
42 index 35c79a8..2b05219 100644
43 --- a/data/ConsoleKit.conf
44 +++ b/data/ConsoleKit.conf
46 <allow send_destination="org.freedesktop.ConsoleKit"
47 send_interface="org.freedesktop.ConsoleKit.Manager"
48 send_member="CanSuspend"/>
49 - <allow send_destination="org.freedesktop.ConsoleKit"
50 - send_interface="org.freedesktop.ConsoleKit.Manager"
51 - send_member="AuthSuspend"/>
52 <allow send_destination="org.freedesktop.ConsoleKit"
53 send_interface="org.freedesktop.ConsoleKit.Manager"
54 send_member="Hibernate"/>
56 send_member="CanHibernate"/>
57 <allow send_destination="org.freedesktop.ConsoleKit"
58 send_interface="org.freedesktop.ConsoleKit.Manager"
59 - send_member="AuthHibernate"/>
60 + send_member="HybridSleep"/>
61 + <allow send_destination="org.freedesktop.ConsoleKit"
62 + send_interface="org.freedesktop.ConsoleKit.Manager"
63 + send_member="CanHybridSleep"/>
64 <allow send_destination="org.freedesktop.ConsoleKit"
65 send_interface="org.freedesktop.ConsoleKit.Manager"
66 send_member="Inhibit"/>
67 diff --git a/data/org.freedesktop.consolekit.policy b/data/org.freedesktop.consolekit.policy
68 index 76a6cc8..3898d9a 100644
69 --- a/data/org.freedesktop.consolekit.policy
70 +++ b/data/org.freedesktop.consolekit.policy
71 @@ -63,7 +63,7 @@ Policy definitions for ConsoleKit
75 - <action id="org.freedesktop.consolekit.system.hibernate">
76 + <action id="org.freedesktop.consolekit.system.hibernate">
77 <description>Hibernate the system</description>
78 <message>System policy prevents hibernating the system</message>
80 @@ -80,4 +80,22 @@ Policy definitions for ConsoleKit
81 <allow_active>auth_admin_keep</allow_active>
85 + <action id="org.freedesktop.consolekit.system.hybridsleep">
86 + <description>Hybrid sleep the system (sleep + hibernate)</description>
87 + <message>System policy prevents hybrid sleeping the system</message>
89 + <allow_inactive>no</allow_inactive>
90 + <allow_active>yes</allow_active>
94 + <action id="org.freedesktop.consolekit.system.hybridsleep-multiple-users">
95 + <description>Hybrid sleep the system (sleep + hibernate) when multiple users are logged in</description>
96 + <message>System policy prevents hybrid sleeping the system when other users are logged in</message>
98 + <allow_inactive>no</allow_inactive>
99 + <allow_active>auth_admin_keep</allow_active>
103 diff --git a/src/ck-manager.c b/src/ck-manager.c
104 index 3ff8ec7..78b8092 100644
105 --- a/src/ck-manager.c
106 +++ b/src/ck-manager.c
107 @@ -856,6 +856,59 @@ ready_cb (PolkitAuthority *authority,
108 g_object_unref (ret);
112 +sleep_ready_cb (PolkitAuthority *authority,
114 + DBusGMethodInvocation *context)
116 + PolkitAuthorizationResult *ret;
120 + ret = polkit_authority_check_authorization_finish (authority, res, &error);
121 + if (error != NULL) {
122 + dbus_g_method_return_error (context, error);
123 + g_error_free (error);
125 + else if (polkit_authorization_result_get_is_authorized (ret)) {
126 + dbus_g_method_return (context, "yes");
128 + else if (polkit_authorization_result_get_is_challenge (ret)) {
129 + dbus_g_method_return (context, "challenge");
132 + dbus_g_method_return (context, "no");
135 + g_object_unref (ret);
138 +/* We use this and sleep_ready_cb to avoid breaking API compability with
139 + * ConsoleKit for Stop and Restart */
141 +get_polkit_sleep_permissions (CkManager *manager,
142 + const char *action,
143 + DBusGMethodInvocation *context)
145 + const char *sender;
146 + PolkitSubject *subject;
148 + g_debug ("get permissions for action %s", action);
150 + sender = dbus_g_method_get_sender (context);
151 + subject = polkit_system_bus_name_new (sender);
153 + polkit_authority_check_authorization (manager->priv->pol_ctx,
159 + (GAsyncReadyCallback) sleep_ready_cb,
161 + g_object_unref (subject);
165 get_polkit_permissions (CkManager *manager,
167 @@ -1314,38 +1367,55 @@ ck_manager_suspend (CkManager *manager,
172 + * ck_manager_can_suspend:
173 + * @manager: the @CkManager object
174 + * @context: We return a string here, either:
175 + * yes - system can and user explicitly authorized by polkit, rbac, or neither is running
176 + * no - system can and user explicitly unauthorized by polkit or rbac
177 + * challenge - system can and user requires elevation via polkit
178 + * na - system does not support it (hardware or backend support missing).
180 + * Determines if the system can suspend.
182 + dbus-send --system --dest=org.freedesktop.ConsoleKit \
183 + --type=method_call --print-reply --reply-timeout=2000 \
184 + /org/freedesktop/ConsoleKit/Manager \
185 + org.freedesktop.ConsoleKit.Manager.CanSuspend
190 -ck_manager_auth_suspend (CkManager *manager,
191 - DBusGMethodInvocation *context)
192 +ck_manager_can_suspend (CkManager *manager,
193 + DBusGMethodInvocation *context)
198 - action = "org.freedesktop.consolekit.system.suspend";
199 + if (get_system_num_users (manager) > 1) {
200 + action = "org.freedesktop.consolekit.system.suspend-multiple-users";
202 + action = "org.freedesktop.consolekit.system.suspend";
205 + if (ck_system_can_suspend ()) {
206 #if defined HAVE_POLKIT
207 - get_polkit_permissions (manager, action, context);
208 + /* polkit_sleep will return the yes, no, and challenge */
209 + get_polkit_sleep_permissions (manager, action, context);
210 #elif defined ENABLE_RBAC_SHUTDOWN
211 - if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY,
213 - dbus_g_method_return (context, TRUE);
214 + /* rbac determines either yes or no. There is no challenge with rbac */
215 + if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, NULL, NULL)) {
216 + dbus_g_method_return (context, "yes");
218 - dbus_g_method_return (context, FALSE);
219 + dbus_g_method_return (context, "no");
222 + /* neither polkit or rbac. assumed single user system */
223 + dbus_g_method_return (context, "yes");
230 -ck_manager_can_suspend (CkManager *manager,
231 - DBusGMethodInvocation *context)
234 - if (ck_system_can_suspend ()) {
235 - dbus_g_method_return (context, TRUE);
237 - dbus_g_method_return (context, FALSE);
238 + /* not supported by system (or consolekit backend) */
239 + dbus_g_method_return (context, "na");
243 @@ -1422,38 +1492,181 @@ ck_manager_hibernate (CkManager *manager,
248 + * ck_manager_can_hibernate:
249 + * @manager: the @CkManager object
250 + * @context: We return a string here, either:
251 + * yes - system can and user explicitly authorized by polkit, rbac, or neither is running
252 + * no - system can and user explicitly unauthorized by polkit or rbac
253 + * challenge - system can and user requires elevation via polkit
254 + * na - system does not support it (hardware or backend support missing).
256 + * Determines if the system can hibernate.
258 + dbus-send --system --dest=org.freedesktop.ConsoleKit \
259 + --type=method_call --print-reply --reply-timeout=2000 \
260 + /org/freedesktop/ConsoleKit/Manager \
261 + org.freedesktop.ConsoleKit.Manager.CanHibernate
266 -ck_manager_auth_hibernate (CkManager *manager,
267 - DBusGMethodInvocation *context)
268 +ck_manager_can_hibernate (CkManager *manager,
269 + DBusGMethodInvocation *context)
274 - action = "org.freedesktop.consolekit.system.hibernate";
275 + if (get_system_num_users (manager) > 1) {
276 + action = "org.freedesktop.consolekit.system.hibernate-multiple-users";
278 + action = "org.freedesktop.consolekit.system.hibernate";
281 + if (ck_system_can_hibernate ()) {
282 #if defined HAVE_POLKIT
283 - get_polkit_permissions (manager, action, context);
284 + /* polkit_sleep will return the yes, no, and challenge */
285 + get_polkit_sleep_permissions (manager, action, context);
286 #elif defined ENABLE_RBAC_SHUTDOWN
287 - if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY,
289 - dbus_g_method_return (context, TRUE);
290 + /* rbac determines either yes or no. There is no challenge with rbac */
291 + if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, NULL, NULL)) {
292 + dbus_g_method_return (context, "yes");
294 + dbus_g_method_return (context, "no");
297 + /* neither polkit or rbac. assumed single user system */
298 + dbus_g_method_return (context, "yes");
301 + /* not supported by system (or consolekit backend) */
302 + dbus_g_method_return (context, "na");
309 +do_hybrid_sleep (CkManager *manager,
310 + DBusGMethodInvocation *context,
316 + g_debug ("ConsoleKit preforming Hybrid Sleep");
318 + log_system_action_event (manager, CK_LOG_EVENT_SYSTEM_HIBERNATE);
321 + res = g_spawn_command_line_async (PREFIX "/lib/ConsoleKit/scripts/ck-system-hybridsleep",
326 + g_warning ("Unable to hybrid sleep system: %s", error->message);
328 + new_error = g_error_new (CK_MANAGER_ERROR,
329 + CK_MANAGER_ERROR_GENERAL,
330 + "Unable to hybrid sleep system: %s", error->message);
331 + dbus_g_method_return_error (context, new_error);
332 + g_error_free (new_error);
334 + g_error_free (error);
336 + dbus_g_method_return (context);
342 + dbus-send --system --dest=org.freedesktop.ConsoleKit \
343 + --type=method_call --print-reply --reply-timeout=2000 \
344 + /org/freedesktop/ConsoleKit/Manager \
345 + org.freedesktop.ConsoleKit.Manager.Hibernate
348 +ck_manager_hybrid_sleep (CkManager *manager,
349 + DBusGMethodInvocation *context)
351 + const char *action;
353 + /* Check if something in inhibiting that action */
354 + /* if (ck_inhibit_manager_is_suspend_inhibited (manager->priv->inhibit_manager)) {
355 + g_debug ("hybrid sleep inhibited");
356 dbus_g_method_return (context, FALSE);
360 + if (get_system_num_users (manager) > 1) {
361 + action = "org.freedesktop.consolekit.system.hybridsleep-multiple-users";
363 + action = "org.freedesktop.consolekit.system.hybridsleep";
366 + g_debug ("ConsoleKit Hibernate: %s", action);
368 +#if defined HAVE_POLKIT
369 + check_polkit_permissions (manager, context, action, do_hybrid_sleep);
370 +#elif defined ENABLE_RBAC_SHUTDOWN
371 + check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_hybrid_sleep, NULL);
373 + g_warning ("Compiled without PolicyKit or RBAC support!");
374 + do_hybrid_sleep(manager, context, NULL);
381 + * ck_manager_can_hybrid_sleep:
382 + * @manager: the @CkManager object
383 + * @context: We return a string here, either:
384 + * yes - system can and user explicitly authorized by polkit, rbac, or neither is running
385 + * no - system can and user explicitly unauthorized by polkit or rbac
386 + * challenge - system can and user requires elevation via polkit
387 + * na - system does not support it (hardware or backend support missing).
389 + * Determines if the system can hybrid sleep (suspend + hibernate).
391 + dbus-send --system --dest=org.freedesktop.ConsoleKit \
392 + --type=method_call --print-reply --reply-timeout=2000 \
393 + /org/freedesktop/ConsoleKit/Manager \
394 + org.freedesktop.ConsoleKit.Manager.CanHibernate
399 -ck_manager_can_hibernate (CkManager *manager,
400 - DBusGMethodInvocation *context)
401 +ck_manager_can_hybrid_sleep (CkManager *manager,
402 + DBusGMethodInvocation *context)
405 + const char *action;
407 + if (get_system_num_users (manager) > 1) {
408 + action = "org.freedesktop.consolekit.system.hybridsleep-multiple-users";
410 + action = "org.freedesktop.consolekit.system.hybridsleep";
413 if (ck_system_can_hibernate ()) {
414 - dbus_g_method_return (context, TRUE);
415 +#if defined HAVE_POLKIT
416 + /* polkit_sleep will return the yes, no, and challenge */
417 + get_polkit_sleep_permissions (manager, action, context);
418 +#elif defined ENABLE_RBAC_SHUTDOWN
419 + /* rbac determines either yes or no. There is no challenge with rbac */
420 + if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, NULL, NULL)) {
421 + dbus_g_method_return (context, "yes");
423 - dbus_g_method_return (context, FALSE);
424 + dbus_g_method_return (context, "no");
427 + /* neither polkit or rbac. assumed single user system */
428 + dbus_g_method_return (context, "yes");
431 + /* not supported by system (or consolekit backend) */
432 + dbus_g_method_return (context, "na");
436 diff --git a/src/ck-manager.h b/src/ck-manager.h
437 index d464056..7a58223 100644
438 --- a/src/ck-manager.h
439 +++ b/src/ck-manager.h
441 gboolean ck_manager_hibernate (CkManager *manager,
442 DBusGMethodInvocation *context);
444 -gboolean ck_manager_can_stop (CkManager *manager,
445 - DBusGMethodInvocation *context);
446 -gboolean ck_manager_can_restart (CkManager *manager,
447 +gboolean ck_manager_hybrid_sleep (CkManager *manager,
448 DBusGMethodInvocation *context);
450 -gboolean ck_manager_can_suspend (CkManager *manager,
451 - DBusGMethodInvocation *context);
452 -gboolean ck_manager_can_hibernate (CkManager *manager,
453 +gboolean ck_manager_can_stop (CkManager *manager,
454 + DBusGMethodInvocation *context);
455 +gboolean ck_manager_can_restart (CkManager *manager,
456 DBusGMethodInvocation *context);
458 gboolean ck_manager_get_available_operating_systems (CkManager *manager,
459 @@ -105,10 +103,14 @@
460 gboolean ck_manager_restart_with_parameters (CkManager *manager,
461 const gchar *parameters,
462 DBusGMethodInvocation *context);
463 -gboolean ck_manager_auth_suspend (CkManager *manager,
465 +gboolean ck_manager_can_suspend (CkManager *manager,
466 DBusGMethodInvocation *context);
467 -gboolean ck_manager_auth_hibernate (CkManager *manager,
468 +gboolean ck_manager_can_hibernate (CkManager *manager,
469 + DBusGMethodInvocation *context);
470 +gboolean ck_manager_can_hybrid_sleep (CkManager *manager,
471 DBusGMethodInvocation *context);
473 gboolean ck_manager_inhibit (CkManager *manager,
476 diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c
477 index 63cb6e0..9d26380 100644
478 --- a/src/ck-sysdeps-solaris.c
479 +++ b/src/ck-sysdeps-solaris.c
480 @@ -543,3 +543,10 @@ ck_system_can_hibernate (void)
481 /* TODO: not implemented */
486 +ck_system_can_hybrid_sleep (void)
488 + /* TODO: not implemented */
491 diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h
492 index 73c2608..cf677bc 100644
493 --- a/src/ck-sysdeps.h
494 +++ b/src/ck-sysdeps.h
495 @@ -75,6 +75,7 @@ gboolean ck_wait_for_active_console_num (int console_fd,
497 gboolean ck_system_can_suspend (void);
498 gboolean ck_system_can_hibernate (void);
499 +gboolean ck_system_can_hybrid_sleep (void);
501 #ifdef HAVE_SYS_VT_SIGNAL
502 gint ck_get_vt_signal_fd (void);
503 diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml
504 index 18957c2..1732e0a 100644
505 --- a/src/org.freedesktop.ConsoleKit.Manager.xml
506 +++ b/src/org.freedesktop.ConsoleKit.Manager.xml
509 <method name="CanSuspend">
510 <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
511 - <arg name="can_suspend" type="b" direction="out"/>
512 + <arg name="can_suspend" type="s" direction="out"/>
515 - <doc:para>This method returns whether the computer system is capable of suspending.</doc:para>
516 + <doc:para>This method emulates the logind implementation.
517 + Returns whether the system supports suspending and whether the calling user is eligible to hibernate the system.
518 + Returns one of "na", "yes", "no" or "challenge".
519 + If "na" is returned suspending is not available because of hardware support.
520 + If "yes" is returned suspending is supported and the user may suspend without further authentication.
521 + If "no" is returned suspending is available but the user is not allowed to suspend.
522 + If "challenge" is returned suspending is available, but only after authorization.</doc:para>
527 - <method name="AuthSuspend">
528 + <method name="Hibernate">
529 <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
530 - <arg name="auth_suspend" type="b" direction="out"/>
533 - <doc:para>This method returns whether the user is authorized to suspend the computer system.</doc:para>
534 + <doc:para>This method initiates a request to hibernate the computer system.</doc:para>
539 - <method name="Hibernate">
540 + <method name="CanHibernate">
541 <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
542 + <arg name="can_hibernate" type="s" direction="out"/>
545 - <doc:para>This method initiates a request to hibernate the computer system.</doc:para>
546 + <doc:para>This method emulates the logind implementation.
547 + Returns whether the system supports hibernation and whether the calling user is eligible to hibernate the system.
548 + Returns one of "na", "yes", "no" or "challenge".
549 + If "na" is returned hibernation is not available because of hardware support.
550 + If "yes" is returned hibernation is supported and the user may hibernate without further authentication.
551 + If "no" is returned hibernation is available but the user is not allowed to hibernate.
552 + If "challenge" is returned hibernation is available, but only after authorization.</doc:para>
557 - <method name="CanHibernate">
558 + <method name="HybridSleep">
559 <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
560 - <arg name="can_hibernate" type="b" direction="out"/>
563 - <doc:para>This method returns whether the computer system is capable of hibernating.</doc:para>
564 + <doc:para>This method initiates a request to hybrid sleep (suspend + hibernate) the computer system.</doc:para>
569 - <method name="AuthHibernate">
570 + <method name="CanHybridSleep">
571 <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
572 - <arg name="auth_hibernate" type="b" direction="out"/>
573 + <arg name="can_suspend" type="s" direction="out"/>
576 - <doc:para>This method returns whether the user is authorized to hibernate the computer system.</doc:para>
577 + <doc:para>This method emulates the logind implementation.
578 + Returns whether the system supports hybrid sleep (suspend + hibernate) and whether the calling user is eligible to hybrid sleep the system.
579 + Returns one of "na", "yes", "no" or "challenge".
580 + If "na" is returned hybrid sleeping is not available because of hardware support.
581 + If "yes" is returned hybrid sleeping is supported and the user may hybrid sleep without further authentication.
582 + If "no" is returned hybrid sleeping is available but the user is not allowed to hybrid sleep.
583 + If "challenge" is returned hybrid sleeping is available, but only after authorization.</doc:para>
587 diff --git a/tools/solaris/Makefile.am b/tools/solaris/Makefile.am
588 index 50b9b27..85a7166 100644
589 --- a/tools/solaris/Makefile.am
590 +++ b/tools/solaris/Makefile.am
591 @@ -12,6 +12,7 @@ script_SCRIPTS = \
594 ck-system-hibernate \
595 + ck-system-hybridsleep \
599 diff --git a/tools/solaris/ck-system-hybridsleep b/tools/solaris/ck-system-hybridsleep
601 index 0000000..5f31342
603 +++ b/tools/solaris/ck-system-hybridsleep
607 +# FIXME: Implement this