From 9f749a4ea6129c256bb3522291eaa43f63c961c1 Mon Sep 17 00:00:00 2001
From: Marius Vollmer <mvollmer@redhat.com>
Date: Tue, 5 Dec 2017 17:17:40 +0200
Subject: [PATCH] core: Add Encrypted.Resize method
To go with Filesystem.Resize.
---
data/org.freedesktop.UDisks2.xml | 16 ++++
doc/udisks2-sections.txt.in.in | 4 +
src/udiskslinuxencrypted.c | 134 ++++++++++++++++++++++++++++++
udisks/udisksclient.c | 1 +
4 files changed, 155 insertions(+)
diff --git a/data/org.freedesktop.UDisks2.xml b/data/org.freedesktop.UDisks2.xml
index fa53a72..75ec0ea 100644
--- a/data/org.freedesktop.UDisks2.xml
+++ b/data/org.freedesktop.UDisks2.xml
@@ -2059,6 +2059,20 @@
<arg name="options" direction="in" type="a{sv}"/>
</method>
+ <!--
+ Resize:
+ @size: The target cleartext size in bytes, 0 for maximum.
+ @options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
+ @since: 2.7.6
+
+ Resizes the encrypted device. The device must be unlocked.
+ The given size is the target size for the cleartext device.
+ -->
+ <method name="Resize">
+ <arg name="size" direction="in" type="t"/>
+ <arg name="options" direction="in" type="a{sv}"/>
+ </method>
+
</interface>
<!-- ********************************************************************** -->
@@ -2451,6 +2465,8 @@
<listitem><para>Locking encrypted device.</para></listitem></varlistentry>
<varlistentry><term>encrypted-modify</term>
<listitem><para>Modifying encrypted device.</para></listitem></varlistentry>
+ <varlistentry><term>encrypted-resize</term>
+ <listitem><para>Resizing encrypted device.</para></listitem></varlistentry>
<varlistentry><term>swapspace-start</term>
<listitem><para>Starting swapspace.</para></listitem></varlistentry>
<varlistentry><term>swapspace-stop</term>
diff --git a/doc/udisks2-sections.txt.in.in b/doc/udisks2-sections.txt.in.in
index 5860d43..13cf728 100644
--- a/doc/udisks2-sections.txt.in.in
+++ b/doc/udisks2-sections.txt.in.in
@@ -1036,6 +1036,10 @@ udisks_encrypted_call_change_passphrase
udisks_encrypted_call_change_passphrase_finish
udisks_encrypted_call_change_passphrase_sync
udisks_encrypted_complete_change_passphrase
+udisks_encrypted_call_resize
+udisks_encrypted_call_resize_finish
+udisks_encrypted_call_resize_sync
+udisks_encrypted_complete_resize
UDisksEncryptedProxy
UDisksEncryptedProxyClass
udisks_encrypted_proxy_new
diff --git a/src/udiskslinuxencrypted.c b/src/udiskslinuxencrypted.c
index 7b19e84..08e59d1 100644
--- a/src/udiskslinuxencrypted.c
+++ b/src/udiskslinuxencrypted.c
@@ -43,6 +43,7 @@
#include "udiskscrypttabentry.h"
#include "udiskscrypttabmonitor.h"
#include "udisksspawnedjob.h"
+#include "udiskssimplejob.h"
/**
* SECTION:udiskslinuxencrypted
@@ -802,10 +803,143 @@ handle_change_passphrase (UDisksEncrypted *encrypted,
/* ---------------------------------------------------------------------------------------------------- */
+/* runs in thread dedicated to handling method call */
+static gboolean
+handle_resize (UDisksEncrypted *encrypted,
+ GDBusMethodInvocation *invocation,
+ guint64 size,
+ GVariant *options)
+{
+ UDisksObject *object = NULL;
+ UDisksBlock *block;
+ UDisksObject *cleartext_object = NULL;
+ UDisksBlock *cleartext_block;
+ UDisksDaemon *daemon;
+ uid_t caller_uid;
+ const gchar *action_id = NULL;
+ const gchar *message = NULL;
+ GError *error = NULL;
+ UDisksBaseJob *job = NULL;
+
+ object = udisks_daemon_util_dup_object (encrypted, &error);
+ if (object == NULL)
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+
+ block = udisks_object_peek_block (object);
+ daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
+
+ /* Fail if the device is not a LUKS device */
+ if (!(g_strcmp0 (udisks_block_get_id_usage (block), "crypto") == 0 &&
+ g_strcmp0 (udisks_block_get_id_type (block), "crypto_LUKS") == 0))
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Device %s does not appear to be a LUKS device",
+ udisks_block_get_device (block));
+ goto out;
+ }
+
+ error = NULL;
+ if (!udisks_daemon_util_get_caller_uid_sync (daemon, invocation, NULL /* GCancellable */, &caller_uid, NULL, NULL, &error))
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_clear_error (&error);
+ goto out;
+ }
+
+ /* Fail if device is not unlocked */
+ cleartext_object = udisks_daemon_wait_for_object_sync (daemon,
+ wait_for_cleartext_object,
+ g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object))),
+ g_free,
+ 0, /* timeout_seconds */
+ NULL); /* error */
+ if (cleartext_object == NULL)
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Device %s is not unlocked",
+ udisks_block_get_device (block));
+ goto out;
+ }
+ cleartext_block = udisks_object_peek_block (cleartext_object);
+
+ action_id = "org.freedesktop.udisks2.modify-device";
+ /* Translators: Shown in authentication dialog when the user
+ * requests resizing a encrypted block device.
+ *
+ * Do not translate $(drive), it's a placeholder and
+ * will be replaced by the name of the drive/device in question
+ */
+ message = N_("Authentication is required to resize the encrypted device $(drive)");
+ if (! udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
+ {
+ if (udisks_block_get_hint_system (block))
+ {
+ action_id = "org.freedesktop.udisks2.modify-device-system";
+ }
+ else if (! udisks_daemon_util_on_user_seat (daemon, UDISKS_OBJECT (object), caller_uid))
+ {
+ action_id = "org.freedesktop.udisks2.modify-device-other-seat";
+ }
+ }
+
+ /* Check that the user is actually authorized to resize the device. */
+ if (! udisks_daemon_util_check_authorization_sync (daemon,
+ object,
+ action_id,
+ options,
+ message,
+ invocation))
+ goto out;
+
+ job = udisks_daemon_launch_simple_job (daemon,
+ UDISKS_OBJECT (object),
+ "encrypted-resize",
+ caller_uid,
+ NULL);
+ if (job == NULL)
+ {
+ g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
+ "Failed to create a job object");
+ goto out;
+ }
+
+ /* TODO: implement progress parsing for udisks_job_set_progress(_valid) */
+ if (! bd_crypto_luks_resize (udisks_block_get_device (cleartext_block), size / 512, &error))
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Error resizing encrypted device %s: %s",
+ udisks_block_get_device (cleartext_block),
+ error->message);
+ udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), FALSE, error->message);
+ goto out;
+ }
+
+ udisks_encrypted_complete_resize (encrypted, invocation);
+ udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), TRUE, NULL);
+
+ out:
+ g_clear_object (&cleartext_object);
+ g_clear_object (&object);
+ g_clear_error (&error);
+ return TRUE; /* returning TRUE means that we handled the method invocation */
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
encrypted_iface_init (UDisksEncryptedIface *iface)
{
iface->handle_unlock = handle_unlock;
iface->handle_lock = handle_lock;
iface->handle_change_passphrase = handle_change_passphrase;
+ iface->handle_resize = handle_resize;
}
diff --git a/udisks/udisksclient.c b/udisks/udisksclient.c
index 7bd5684..980c941 100644
--- a/udisks/udisksclient.c
+++ b/udisks/udisksclient.c
@@ -2487,6 +2487,7 @@ udisks_client_get_job_description (UDisksClient *client,
g_hash_table_insert (hash, (gpointer) "encrypted-unlock", (gpointer) C_("job", "Unlocking Device"));
g_hash_table_insert (hash, (gpointer) "encrypted-lock", (gpointer) C_("job", "Locking Device"));
g_hash_table_insert (hash, (gpointer) "encrypted-modify", (gpointer) C_("job", "Modifying Encrypted Device"));
+ g_hash_table_insert (hash, (gpointer) "encrypted-resize", (gpointer) C_("job", "Resizing Encrypted Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-start", (gpointer) C_("job", "Starting Swap Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-stop", (gpointer) C_("job", "Stopping Swap Device"));
g_hash_table_insert (hash, (gpointer) "filesystem-check", (gpointer) C_("job", "Checking Filesystem"));
--
1.8.3.1