Implement Swapspace's Start() and Stop() method
authorDavid Zeuthen <davidz@redhat.com>
Wed, 30 Mar 2011 19:02:46 +0000 (15:02 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Wed, 30 Mar 2011 19:02:46 +0000 (15:02 -0400)
Signed-off-by: David Zeuthen <davidz@redhat.com>
policy/org.freedesktop.udisks2.policy.in
src/udiskslinuxblock.c

index 39b51f2..06dc743 100644 (file)
     </defaults>
   </action>
 
+  <action id="org.freedesktop.udisks2.swap">
+    <_description>Configure swap devices</_description>
+    <_message>Authentication is required to configure swap devices</_message>
+    <defaults>
+      <allow_any>auth_admin</allow_any>
+      <allow_inactive>auth_admin</allow_inactive>
+      <allow_active>auth_admin_keep</allow_active>
+    </defaults>
+  </action>
+
 </policyconfig>
index 3a7ae90..604df44 100644 (file)
@@ -824,6 +824,158 @@ filesystem_update (UDisksLinuxBlock  *block,
 /* ---------------------------------------------------------------------------------------------------- */
 /* org.freedesktop.UDisks.Swapspace */
 
+static void
+swapspace_start_on_job_completed (UDisksJob   *job,
+                                  gboolean     success,
+                                  const gchar *message,
+                                  gpointer     user_data)
+{
+  GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
+  UDisksSwapspace *swapspace;
+  swapspace = UDISKS_SWAPSPACE (g_dbus_method_invocation_get_user_data (invocation));
+  if (success)
+    udisks_swapspace_complete_start (swapspace, invocation);
+  else
+    g_dbus_method_invocation_return_error (invocation,
+                                           UDISKS_ERROR,
+                                           UDISKS_ERROR_FAILED,
+                                           "Error activating swap: %s",
+                                           message);
+}
+
+static gboolean
+swapspace_handle_start (UDisksSwapspace        *swapspace,
+                        GDBusMethodInvocation  *invocation,
+                        const gchar* const     *options,
+                        gpointer                user_data)
+{
+  GDBusObject *object;
+  UDisksDaemon *daemon;
+  UDisksBlockDevice *block;
+  gboolean auth_no_user_interaction;
+  guint n;
+  UDisksBaseJob *job;
+
+  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace));
+  daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
+  block = UDISKS_PEEK_BLOCK_DEVICE (object);
+
+  auth_no_user_interaction = FALSE;
+  for (n = 0; options != NULL && options[n] != NULL; n++)
+    {
+      const gchar *option = options[n];
+      if (g_strcmp0 (option, "auth_no_user_interaction") == 0)
+        {
+          auth_no_user_interaction = TRUE;
+          continue;
+        }
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_OPTION_NOT_PERMITTED,
+                                             "Option `%s' is not allowed",
+                                             option);
+      goto out;
+    }
+
+  if (!udisks_daemon_util_check_authorization_sync (daemon,
+                                                    object,
+                                                    "org.freedesktop.udisks2.swap",
+                                                    auth_no_user_interaction,
+                                                    N_("Authentication is required to activate swapspace on $(udisks2.device)"),
+                                                    invocation))
+    goto out;
+
+  job = udisks_daemon_launch_spawned_job (daemon,
+                                          NULL, /* cancellable */
+                                          NULL, /* input_string */
+                                          "swapon %s",
+                                          udisks_block_device_get_device (block));
+  g_signal_connect (job,
+                    "completed",
+                    G_CALLBACK (swapspace_start_on_job_completed),
+                    invocation);
+
+ out:
+  return TRUE;
+}
+
+static void
+swapspace_stop_on_job_completed (UDisksJob   *job,
+                                 gboolean     success,
+                                 const gchar *message,
+                                  gpointer     user_data)
+{
+  GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
+  UDisksSwapspace *swapspace;
+  swapspace = UDISKS_SWAPSPACE (g_dbus_method_invocation_get_user_data (invocation));
+  if (success)
+    udisks_swapspace_complete_start (swapspace, invocation);
+  else
+    g_dbus_method_invocation_return_error (invocation,
+                                           UDISKS_ERROR,
+                                           UDISKS_ERROR_FAILED,
+                                           "Error deactivating swap: %s",
+                                           message);
+}
+
+static gboolean
+swapspace_handle_stop (UDisksSwapspace        *swapspace,
+                       GDBusMethodInvocation  *invocation,
+                       const gchar* const     *options,
+                       gpointer                user_data)
+{
+  GDBusObject *object;
+  UDisksDaemon *daemon;
+  UDisksBlockDevice *block;
+  gboolean auth_no_user_interaction;
+  guint n;
+  UDisksBaseJob *job;
+
+  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace));
+  daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
+  block = UDISKS_PEEK_BLOCK_DEVICE (object);
+
+  auth_no_user_interaction = FALSE;
+  for (n = 0; options != NULL && options[n] != NULL; n++)
+    {
+      const gchar *option = options[n];
+      if (g_strcmp0 (option, "auth_no_user_interaction") == 0)
+        {
+          auth_no_user_interaction = TRUE;
+          continue;
+        }
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_OPTION_NOT_PERMITTED,
+                                             "Option `%s' is not allowed",
+                                             option);
+      goto out;
+    }
+
+  if (!udisks_daemon_util_check_authorization_sync (daemon,
+                                                    object,
+                                                    "org.freedesktop.udisks2.swap",
+                                                    auth_no_user_interaction,
+                                                    N_("Authentication is required to deactivate swapspace on $(udisks2.device)"),
+                                                    invocation))
+    goto out;
+
+  job = udisks_daemon_launch_spawned_job (daemon,
+                                          NULL, /* cancellable */
+                                          NULL, /* input_string */
+                                          "swapoff %s",
+                                          udisks_block_device_get_device (block));
+  g_signal_connect (job,
+                    "completed",
+                    G_CALLBACK (swapspace_stop_on_job_completed),
+                    invocation);
+
+ out:
+  return TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 static gboolean
 swapspace_check (UDisksLinuxBlock *block)
 {
@@ -843,6 +995,22 @@ swapspace_check (UDisksLinuxBlock *block)
 }
 
 static void
+swapspace_connect (UDisksLinuxBlock *block)
+{
+  /* indicate that we want to handle the method invocations in a thread */
+  g_dbus_interface_stub_set_flags (G_DBUS_INTERFACE_STUB (block->iface_swapspace),
+                                   G_DBUS_INTERFACE_STUB_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
+  g_signal_connect (block->iface_swapspace,
+                    "handle-start",
+                    UDISKS_SWAPSPACE_HANDLE_START_CALLBACK (swapspace_handle_start, gpointer),
+                    NULL);
+  g_signal_connect (block->iface_swapspace,
+                    "handle-stop",
+                    UDISKS_SWAPSPACE_HANDLE_START_CALLBACK (swapspace_handle_stop, gpointer),
+                    NULL);
+}
+
+static void
 swapspace_update (UDisksLinuxBlock  *block,
                   const gchar       *uevent_action,
                   GDBusInterface    *_iface)
@@ -892,7 +1060,7 @@ udisks_linux_block_uevent (UDisksLinuxBlock *block,
   update_iface (block, action, filesystem_check, NULL, filesystem_update,
                 UDISKS_TYPE_LINUX_FILESYSTEM, &block->iface_filesystem);
   /* TODO: need to hook up Start() and Stop() methods */
-  update_iface (block, action, swapspace_check, NULL, swapspace_update,
+  update_iface (block, action, swapspace_check, swapspace_connect, swapspace_update,
                 UDISKS_TYPE_SWAPSPACE_STUB, &block->iface_swapspace);
 }