Add FilesystemSetLabel method
authorDavid Zeuthen <davidz@redhat.com>
Sun, 13 Mar 2011 19:56:44 +0000 (15:56 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Sun, 13 Mar 2011 19:56:44 +0000 (15:56 -0400)
Signed-off-by: David Zeuthen <davidz@redhat.com>
data/org.freedesktop.UDisks2.xml
policy/org.freedesktop.udisks2.policy.in
src/udiskslinuxblock.c
udisks/udisksenums.h
udisks/udiskserror.c

index 0efa6b2..5f31596 100644 (file)
     <method name="FilesystemUnmount">
       <arg name="options" direction="in" type="as"/>
     </method>
+    <method name="FilesystemSetLabel">
+      <arg name="label" direction="in" type="ay"/>
+      <arg name="options" direction="in" type="as"/>
+    </method>
 
     <!-- The BlockDevice object that is backing the device ('/' if unknown or not a crypto device)  -->
     <property name="CryptoBackingDevice" type="o" access="read"/>
index 30ab0e4..3930aff 100644 (file)
     </defaults>
   </action>
 
+  <action id="org.freedesktop.udisks2.modify">
+    <_description>Modify a device</_description>
+    <_message>Authentication is required to modify a device</_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 5a24a75..6453077 100644 (file)
@@ -373,6 +373,12 @@ handle_unmount (UDisksBlockDevice      *block,
                 GDBusMethodInvocation  *invocation,
                 const gchar* const     *options);
 
+static gboolean
+handle_set_label (UDisksBlockDevice      *block,
+                  GDBusMethodInvocation  *invocation,
+                  const gchar            *label,
+                  const gchar* const     *options);
+
 static void
 block_device_connect (UDisksLinuxBlock *block)
 {
@@ -384,6 +390,10 @@ block_device_connect (UDisksLinuxBlock *block)
                     "handle-filesystem-unmount",
                     G_CALLBACK (handle_unmount),
                     NULL);
+  g_signal_connect (block->iface_block_device,
+                    "handle-filesystem-set-label",
+                    G_CALLBACK (handle_set_label),
+                    NULL);
 }
 
 static gchar *
@@ -1946,3 +1956,182 @@ handle_unmount (UDisksBlockDevice      *block,
   g_object_unref (object);
   return TRUE;
 }
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_set_label_job_completed (UDisksJob   *job,
+                            gboolean     success,
+                            const gchar *message,
+                            gpointer     user_data)
+{
+  GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
+  UDisksBlockDevice *block;
+
+  block = UDISKS_BLOCK_DEVICE (g_dbus_method_invocation_get_user_data (invocation));
+
+  if (success)
+    udisks_block_device_complete_filesystem_set_label (block, invocation);
+  else
+    g_dbus_method_invocation_return_error (invocation,
+                                           UDISKS_ERROR,
+                                           UDISKS_ERROR_FAILED,
+                                           "Error setting filesystem label: %s",
+                                           message);
+}
+
+/* runs in thread dedicated to handling method call */
+static gboolean
+handle_set_label (UDisksBlockDevice      *block,
+                  GDBusMethodInvocation  *invocation,
+                  const gchar            *label,
+                  const gchar* const     *requested_options)
+{
+  GDBusObject *object;
+  UDisksDaemon *daemon;
+  const gchar *probed_fs_usage;
+  const gchar *probed_fs_type;
+  GError *error;
+  PolkitSubject *auth_subject;
+  const gchar *auth_action_id;
+  PolkitDetails *auth_details;
+  gboolean auth_no_user_interaction;
+  PolkitCheckAuthorizationFlags auth_flags;
+  PolkitAuthorizationResult *auth_result;
+  gboolean supports_online;
+  guint n;
+  UDisksBaseJob *job;
+  gchar *escaped_label;
+
+  object = NULL;
+  daemon = NULL;
+  auth_subject = NULL;
+  auth_details = NULL;
+  auth_result = NULL;
+  auth_no_user_interaction = FALSE;
+  supports_online = FALSE;
+  escaped_label = NULL;
+
+  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (block));
+  daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
+
+  probed_fs_usage = udisks_block_device_get_id_usage (block);
+  probed_fs_type = udisks_block_device_get_id_type (block);
+
+  /* TODO: add support for other fstypes */
+  if (!(g_strcmp0 (probed_fs_usage, "filesystem") == 0 &&
+        (g_strcmp0 (probed_fs_type, "ext2") == 0 ||
+         g_strcmp0 (probed_fs_type, "ext3") == 0 ||
+         g_strcmp0 (probed_fs_type, "ext4") == 0)))
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_NOT_SUPPORTED,
+                                             "Don't know how to change label on device of type %s:%s",
+                                             probed_fs_usage,
+                                             probed_fs_type);
+      goto out;
+    }
+  supports_online = FALSE;
+
+  /* Fail if the device is already mounted and the tools/drivers doesn't
+   * support changing the label in that case
+   */
+  if (!supports_online)
+    {
+      const gchar * const *existing_mount_points;
+      existing_mount_points = udisks_block_device_get_filesystem_mount_points (block);
+      if (existing_mount_points != NULL && g_strv_length ((gchar **) existing_mount_points) > 0)
+        {
+          g_dbus_method_invocation_return_error (invocation,
+                                                 UDISKS_ERROR,
+                                                 UDISKS_ERROR_NOT_SUPPORTED,
+                                                 "Cannot change label on mounted device of type %s:%s.\n",
+                                                 probed_fs_usage,
+                                                 probed_fs_type);
+          goto out;
+        }
+    }
+
+  for (n = 0; requested_options != NULL && requested_options[n] != NULL; n++)
+    {
+      const gchar *option = requested_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;
+    }
+
+  /* now check that the user is actually authorized to change the filesystem label
+   *
+   * (TODO: fill in details and pick the right action_id)
+   */
+  auth_action_id = "org.freedesktop.udisks2.modify",
+  auth_subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation));
+  auth_flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
+  if (!auth_no_user_interaction)
+    auth_flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
+  error = NULL;
+  auth_result = polkit_authority_check_authorization_sync (udisks_daemon_get_authority (daemon),
+                                                           auth_subject,
+                                                           auth_action_id,
+                                                           auth_details,
+                                                           auth_flags,
+                                                           NULL, /* GCancellable* */
+                                                           &error);
+  if (auth_result == NULL)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Error checking authorization: %s (%s, %d)",
+                                             error->message,
+                                             g_quark_to_string (error->domain),
+                                             error->code);
+      g_error_free (error);
+      goto out;
+    }
+  if (!polkit_authorization_result_get_is_authorized (auth_result))
+    {
+      g_dbus_method_invocation_return_error_literal (invocation,
+                                                     UDISKS_ERROR,
+                                                     polkit_authorization_result_get_is_challenge (auth_result) ?
+                                                     UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN :
+                                                     UDISKS_ERROR_NOT_AUTHORIZED,
+                                                     "Not authorized to perform operation");
+      goto out;
+    }
+
+  escaped_label = g_shell_quote (label);
+  job = udisks_daemon_launch_spawned_job (daemon,
+                                          NULL, /* cancellable */
+                                          NULL, /* input_string */
+                                          "e2label %s %s",
+                                          udisks_block_device_get_device (block),
+                                          escaped_label);
+  g_signal_connect (job,
+                    "completed",
+                    G_CALLBACK (on_set_label_job_completed),
+                    invocation);
+
+ out:
+  g_free (escaped_label);
+  if (auth_subject != NULL)
+    g_object_unref (auth_subject);
+  if (auth_details != NULL)
+    g_object_unref (auth_details);
+  if (auth_result != NULL)
+    g_object_unref (auth_result);
+  if (object != NULL)
+    g_object_unref (object);
+
+  return TRUE; /* returning TRUE means that we handled the method invocation */
+}
index f2a5e8d..e0cb524 100644 (file)
@@ -41,6 +41,7 @@ G_BEGIN_DECLS
  * @UDISKS_ERROR_OPTION_NOT_PERMITTED: Not permitted to use the requested option.
  * @UDISKS_ERROR_MOUNTED_BY_OTHER_USER: The device is mounted by another user.
  * @UDISKS_ERROR_ALREADY_UNMOUNTING: The device is already unmounting.
+ * @UDISKS_ERROR_NOT_SUPPORTED: The operation is not supported due to missing driver/tool support.
  *
  * Error codes for the #UDISKS_ERROR error domain and the
  * corresponding D-Bus error names.
@@ -56,10 +57,11 @@ typedef enum
   UDISKS_ERROR_NOT_MOUNTED,                /* org.freedesktop.UDisks.Error.NotMounted */
   UDISKS_ERROR_OPTION_NOT_PERMITTED,       /* org.freedesktop.UDisks.Error.OptionNotPermitted */
   UDISKS_ERROR_MOUNTED_BY_OTHER_USER,      /* org.freedesktop.UDisks.Error.MountedByOtherUser */
-  UDISKS_ERROR_ALREADY_UNMOUNTING          /* org.freedesktop.UDisks.Error.AlreadyUnmounting */
+  UDISKS_ERROR_ALREADY_UNMOUNTING,         /* org.freedesktop.UDisks.Error.AlreadyUnmounting */
+  UDISKS_ERROR_NOT_SUPPORTED               /* org.freedesktop.UDisks.Error.NotSupported */
 } UDisksError;
 
-#define UDISKS_ERROR_NUM_ENTRIES  (UDISKS_ERROR_ALREADY_UNMOUNTING + 1)
+#define UDISKS_ERROR_NUM_ENTRIES  (UDISKS_ERROR_NOT_SUPPORTED + 1)
 
 G_END_DECLS
 
index adb4109..0ce803d 100644 (file)
@@ -41,7 +41,8 @@ static const GDBusErrorEntry dbus_error_entries[] =
   {UDISKS_ERROR_NOT_MOUNTED,                  "org.freedesktop.UDisks.Error.NotMounted"},
   {UDISKS_ERROR_OPTION_NOT_PERMITTED,         "org.freedesktop.UDisks.Error.OptionNotPermitted"},
   {UDISKS_ERROR_MOUNTED_BY_OTHER_USER,        "org.freedesktop.UDisks.Error.MountedByOtherUser"},
-  {UDISKS_ERROR_ALREADY_UNMOUNTING,           "org.freedesktop.UDisks.Error.AlreadyUnmounting"}
+  {UDISKS_ERROR_ALREADY_UNMOUNTING,           "org.freedesktop.UDisks.Error.AlreadyUnmounting"},
+  {UDISKS_ERROR_NOT_SUPPORTED,                "org.freedesktop.UDisks.Error.NotSupported"}
 };
 
 GQuark