From: "Alexandre Restovtsev" <tetromino@gmail.com>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/openrc-settingsd:master commit in: src/
Date: Mon, 6 Feb 2012 10:24:55 +0000 (UTC) [thread overview]
Message-ID: <52f4dc6163ecbc334f9ba949d6436f650ecf138d.tetromino@gentoo> (raw)
commit: 52f4dc6163ecbc334f9ba949d6436f650ecf138d
Author: Alexandre Rostovtsev <tetromino <AT> gentoo <DOT> org>
AuthorDate: Mon Feb 6 10:19:08 2012 +0000
Commit: Alexandre Restovtsev <tetromino <AT> gmail <DOT> com>
CommitDate: Mon Feb 6 10:19:08 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git;a=commit;h=52f4dc61
Check polkit authorization asynchronously
The other alternative (spawning a thread for each authorization
request) seems less elegant, since such requests can take arbitrarily
long to complete.
---
src/bus-utils.c | 137 +++++++++++++++++++++-------
src/bus-utils.h | 13 ++-
src/hostnamed.c | 275 ++++++++++++++++++++++++++++++++++++++-----------------
3 files changed, 302 insertions(+), 123 deletions(-)
diff --git a/src/bus-utils.c b/src/bus-utils.c
index d3bc7b2..aef8037 100644
--- a/src/bus-utils.c
+++ b/src/bus-utils.c
@@ -20,44 +20,115 @@
#include <gio/gio.h>
#include <polkit/polkit.h>
+#include "bus-utils.h"
+
+struct check_polkit_data {
+ const gchar *unique_name;
+ const gchar *action_id;
+ gboolean user_interaction;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+
+ PolkitAuthority *authority;
+ PolkitSubject *subject;
+};
+
+void
+check_polkit_data_free (struct check_polkit_data *data)
+{
+ if (data == NULL)
+ return;
+
+ if (data->subject != NULL)
+ g_object_unref (data->subject);
+ if (data->authority != NULL)
+ g_object_unref (data->authority);
+
+ g_free (data);
+}
+
gboolean
-check_polkit (const gchar *unique_name,
- const gchar *action_id,
- const gboolean user_interaction,
- GError **error)
+check_polkit_finish (GAsyncResult *res,
+ GError **error)
{
- gboolean ret = FALSE;
- GDBusConnection *connection = NULL;
- PolkitAuthority *authority = NULL;
- PolkitSubject *subject = NULL;
- PolkitAuthorizationResult *result = NULL;
-
- if ((authority = polkit_authority_get_sync (NULL, error)) == NULL)
- goto end;
-
- if (unique_name == NULL || action_id == NULL ||
- (subject = polkit_system_bus_name_new (unique_name)) == NULL) {
- g_propagate_error (error,
- g_error_new (POLKIT_ERROR, POLKIT_ERROR_FAILED,
- "Authorizing for '%s': failed sanity check", action_id));
- goto end;
- }
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (res);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ return g_simple_async_result_get_op_res_gboolean (simple);
+}
+
+static void
+check_polkit_authorization_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer _data)
+{
+ struct check_polkit_data *data;
+ PolkitAuthorizationResult *result;
+ GSimpleAsyncResult *simple;
+ GError *err = NULL;
- if ((result = polkit_authority_check_authorization_sync (authority, subject, action_id, NULL, (PolkitCheckAuthorizationFlags) user_interaction, NULL, error)) == NULL)
- goto end;
+ data = (struct check_polkit_data *) _data;
+ if ((result = polkit_authority_check_authorization_finish (data->authority, res, &err)) == NULL) {
+ g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err);
+ goto out;
+ }
- if ((ret = polkit_authorization_result_get_is_authorized (result)) == FALSE) {
- g_propagate_error (error,
- g_error_new (POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED,
- "Authorizing for '%s': not authorized", action_id));
+ if (!polkit_authorization_result_get_is_authorized (result)) {
+ g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED, "Authorizing for '%s': not authorized", data->action_id);
+ goto out;
}
-
- end:
+ simple = g_simple_async_result_new (NULL, data->callback, data->user_data, check_polkit_async);
+ g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+
+ out:
+ check_polkit_data_free (data);
if (result != NULL)
g_object_unref (result);
- if (subject != NULL)
- g_object_unref (subject);
- if (authority != NULL)
- g_object_unref (authority);
- return ret;
+}
+
+static void
+check_polkit_authority_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer _data)
+{
+ struct check_polkit_data *data;
+ GError *err = NULL;
+
+ data = (struct check_polkit_data *) _data;
+ if ((data->authority = polkit_authority_get_finish (res, &err)) == NULL) {
+ g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err);
+ check_polkit_data_free (data);
+ return;
+ }
+ if (data->unique_name == NULL || data->action_id == NULL ||
+ (data->subject = polkit_system_bus_name_new (data->unique_name)) == NULL) {
+ g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_FAILED, "Authorizing for '%s': failed sanity check", data->action_id);
+ check_polkit_data_free (data);
+ return;
+ }
+ polkit_authority_check_authorization (data->authority, data->subject, data->action_id, NULL, (PolkitCheckAuthorizationFlags) data->user_interaction, NULL, check_polkit_authorization_cb, data);
+}
+
+void
+check_polkit_async (const gchar *unique_name,
+ const gchar *action_id,
+ const gboolean user_interaction,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ struct check_polkit_data *data;
+
+ data = g_new0 (struct check_polkit_data, 1);
+ data->unique_name = unique_name;
+ data->action_id = action_id;
+ data->user_interaction = user_interaction;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ polkit_authority_get_async (NULL, check_polkit_authority_cb, data);
}
\ No newline at end of file
diff --git a/src/bus-utils.h b/src/bus-utils.h
index 31a2ef1..f2e80ea 100644
--- a/src/bus-utils.h
+++ b/src/bus-utils.h
@@ -21,10 +21,15 @@
#include <glib.h>
+void
+check_polkit_async (const gchar *unique_name,
+ const gchar *action_id,
+ const gboolean user_interaction,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
gboolean
-check_polkit (const gchar *unique_name,
- const gchar *action_id,
- const gboolean user_interaction,
- GError **error);
+check_polkit_finish (GAsyncResult *res,
+ GError **error);
#endif
\ No newline at end of file
diff --git a/src/hostnamed.c b/src/hostnamed.c
index 4f95d04..c5914bd 100644
--- a/src/hostnamed.c
+++ b/src/hostnamed.c
@@ -36,6 +36,11 @@
#define QUOTE(macro) #macro
#define STR(macro) QUOTE(macro)
+struct invoked_name {
+ GDBusMethodInvocation *invocation;
+ gchar *name; /* newly allocated */
+};
+
guint bus_id = 0;
gboolean read_only = FALSE;
@@ -103,152 +108,250 @@ guess_icon_name ()
icon_name = g_strdup ("computer");
}
-static gboolean
-on_handle_set_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
- GDBusMethodInvocation *invocation,
- const gchar *name,
- const gboolean user_interaction,
- gpointer user_data)
+static void
+on_handle_set_hostname_authorized_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
GError *err = NULL;
-
- if (read_only) {
- g_dbus_method_invocation_return_dbus_error (invocation,
- DBUS_ERROR_NOT_SUPPORTED,
- "openrc-settingsd hostnamed is in read-only mode");
- goto end;
- }
-
- if (!check_polkit (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-hostname", user_interaction, &err)) {
- g_dbus_method_invocation_return_gerror (invocation, err);
- goto end;
+ struct invoked_name *data;
+
+ data = (struct invoked_name *) user_data;
+ if (!check_polkit_finish (res, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto out;
}
G_LOCK (hostname);
/* Don't allow an empty or invalid hostname */
- if (!hostname_is_valid (name)) {
- name = hostname;
- if (!hostname_is_valid (name))
- name = "localhost";
+ if (!hostname_is_valid (data->name)) {
+ if (data->name != NULL)
+ g_free (data->name);
+
+ if (hostname_is_valid (hostname))
+ data->name = g_strdup (hostname);
+ else
+ data->name = g_strdup ("localhost");
}
- if (sethostname (name, strlen(name))) {
+ if (sethostname (data->name, strlen(data->name))) {
int errsv = errno;
- g_dbus_method_invocation_return_dbus_error (invocation,
+ g_dbus_method_invocation_return_dbus_error (data->invocation,
DBUS_ERROR_FAILED,
strerror (errsv));
G_UNLOCK (hostname);
- goto end;
+ goto out;
}
- g_strlcpy (hostname, name, HOST_NAME_MAX + 1);
- openrc_settingsd_hostnamed_hostname1_complete_set_hostname (hostname1, invocation);
+ g_strlcpy (hostname, data->name, HOST_NAME_MAX + 1);
+ openrc_settingsd_hostnamed_hostname1_complete_set_hostname (hostname1, data->invocation);
openrc_settingsd_hostnamed_hostname1_set_hostname (hostname1, hostname);
G_UNLOCK (hostname);
- end:
- return TRUE;
+ out:
+ g_free (data->name);
+ g_free (data);
+ if (err != NULL)
+ g_error_free (err);
}
static gboolean
-on_handle_set_static_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
- GDBusMethodInvocation *invocation,
- const gchar *name,
- const gboolean user_interaction,
- gpointer user_data)
+on_handle_set_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
+ GDBusMethodInvocation *invocation,
+ const gchar *name,
+ const gboolean user_interaction,
+ gpointer user_data)
{
- ShellUtilsTrivial *confd_file = NULL;
- GError *err = NULL;
-
- if (read_only) {
+ if (read_only)
g_dbus_method_invocation_return_dbus_error (invocation,
DBUS_ERROR_NOT_SUPPORTED,
"openrc-settingsd hostnamed is in read-only mode");
- goto end;
+ else {
+ struct invoked_name *data;
+ data = g_new0 (struct invoked_name, 1);
+ data->invocation = invocation;
+ data->name = g_strdup (name);
+ check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-hostname", user_interaction, on_handle_set_hostname_authorized_cb, data);
}
- if (!check_polkit (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-static-hostname", user_interaction, &err)) {
- g_dbus_method_invocation_return_gerror (invocation, err);
- goto end;
+ return TRUE;
+}
+
+static void
+on_handle_set_static_hostname_authorized_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ struct invoked_name *data;
+
+ data = (struct invoked_name *) user_data;
+ if (!check_polkit_finish (res, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto out;
}
G_LOCK (static_hostname);
/* Don't allow an empty or invalid hostname */
- if (!hostname_is_valid (name))
- name = "localhost";
+ if (!hostname_is_valid (data->name)) {
+ if (data->name != NULL)
+ g_free (data->name);
+
+ data->name = g_strdup ("localhost");
+ }
- if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "hostname", "HOSTNAME", name, NULL)) {
- g_dbus_method_invocation_return_gerror (invocation, err);
+ if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "hostname", "HOSTNAME", data->name, NULL)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
G_UNLOCK (static_hostname);
- goto end;
+ goto out;
}
g_free (static_hostname);
- static_hostname = g_strdup (name);
- openrc_settingsd_hostnamed_hostname1_complete_set_static_hostname (hostname1, invocation);
+ static_hostname = data->name; /* data->name is g_strdup-ed already */;
+ openrc_settingsd_hostnamed_hostname1_complete_set_static_hostname (hostname1, data->invocation);
openrc_settingsd_hostnamed_hostname1_set_static_hostname (hostname1, static_hostname);
G_UNLOCK (static_hostname);
- end:
- shell_utils_trivial_free (confd_file);
+ out:
+ g_free (data);
if (err != NULL)
g_error_free (err);
+}
+
+static gboolean
+on_handle_set_static_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
+ GDBusMethodInvocation *invocation,
+ const gchar *name,
+ const gboolean user_interaction,
+ gpointer user_data)
+{
+ if (read_only)
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ DBUS_ERROR_NOT_SUPPORTED,
+ "openrc-settingsd hostnamed is in read-only mode");
+ else {
+ struct invoked_name *data;
+ data = g_new0 (struct invoked_name, 1);
+ data->invocation = invocation;
+ data->name = g_strdup (name);
+ check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-static-hostname", user_interaction, on_handle_set_static_hostname_authorized_cb, data);
+ }
return TRUE; /* Always return TRUE to indicate signal has been handled */
}
-static gboolean
-on_handle_set_machine_info (OpenrcSettingsdHostnamedHostname1 *hostname1,
- GDBusMethodInvocation *invocation,
- const gchar *name,
- const gboolean user_interaction,
- gpointer user_data)
+static void
+on_handle_set_pretty_hostname_authorized_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
- ShellUtilsTrivial *confd_file = NULL;
GError *err = NULL;
- gboolean is_pretty_hostname = GPOINTER_TO_INT(user_data);
+ struct invoked_name *data;
+
+ data = (struct invoked_name *) user_data;
+ if (!check_polkit_finish (res, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto out;
+ }
+
+ G_LOCK (machine_info);
+ /* Don't allow a null pretty hostname */
+ if (data->name == NULL)
+ data->name = g_strdup ("");
- if (read_only) {
+ if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "PRETTY_HOSTNAME", NULL, data->name, NULL)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ G_UNLOCK (machine_info);
+ goto out;
+ }
+
+ g_free (pretty_hostname);
+ pretty_hostname = data->name; /* data->name is g_strdup-ed already */
+ openrc_settingsd_hostnamed_hostname1_complete_set_pretty_hostname (hostname1, data->invocation);
+ openrc_settingsd_hostnamed_hostname1_set_pretty_hostname (hostname1, pretty_hostname);
+ G_UNLOCK (machine_info);
+
+ out:
+ g_free (data);
+ if (err != NULL)
+ g_error_free (err);
+}
+
+static gboolean
+on_handle_set_pretty_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
+ GDBusMethodInvocation *invocation,
+ const gchar *name,
+ const gboolean user_interaction,
+ gpointer user_data)
+{
+ if (read_only)
g_dbus_method_invocation_return_dbus_error (invocation,
DBUS_ERROR_NOT_SUPPORTED,
"openrc-settingsd hostnamed is in read-only mode");
- goto end;
+ else {
+ struct invoked_name *data;
+ data = g_new0 (struct invoked_name, 1);
+ data->invocation = invocation;
+ data->name = g_strdup (name);
+ check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-machine-info", user_interaction, on_handle_set_pretty_hostname_authorized_cb, data);
}
- if (!check_polkit (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-machine-info", user_interaction, &err)) {
- g_dbus_method_invocation_return_gerror (invocation, err);
- goto end;
+ return TRUE; /* Always return TRUE to indicate signal has been handled */
+}
+
+static void
+on_handle_set_icon_name_authorized_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ struct invoked_name *data;
+
+ data = (struct invoked_name *) user_data;
+ if (!check_polkit_finish (res, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto out;
}
G_LOCK (machine_info);
/* Don't allow a null pretty hostname */
- if (name == NULL)
- name = "";
+ if (data->name == NULL)
+ data->name = g_strdup ("");
- if ((is_pretty_hostname &&
- !shell_utils_trivial_set_and_save (machine_info_file, &err, "PRETTY_HOSTNAME", NULL, name, NULL)) ||
- (!is_pretty_hostname &&
- !shell_utils_trivial_set_and_save (machine_info_file, &err, "ICON_NAME", NULL, name, NULL))) {
- g_dbus_method_invocation_return_gerror (invocation, err);
+ if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "ICON_NAME", NULL, data->name, NULL)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
G_UNLOCK (machine_info);
- goto end;
+ goto out;
}
- if (is_pretty_hostname) {
- g_free (pretty_hostname);
- pretty_hostname = g_strdup (name);
- openrc_settingsd_hostnamed_hostname1_complete_set_pretty_hostname (hostname1, invocation);
- openrc_settingsd_hostnamed_hostname1_set_pretty_hostname (hostname1, pretty_hostname);
- } else {
- g_free (icon_name);
- icon_name = g_strdup (name);
- openrc_settingsd_hostnamed_hostname1_complete_set_icon_name (hostname1, invocation);
- openrc_settingsd_hostnamed_hostname1_set_icon_name (hostname1, icon_name);
- }
+ g_free (icon_name);
+ icon_name = data->name; /* data->name is g_strdup-ed already */
+ openrc_settingsd_hostnamed_hostname1_complete_set_icon_name (hostname1, data->invocation);
+ openrc_settingsd_hostnamed_hostname1_set_icon_name (hostname1, icon_name);
G_UNLOCK (machine_info);
- end:
- shell_utils_trivial_free (confd_file);
+ out:
+ g_free (data);
if (err != NULL)
g_error_free (err);
+}
+
+static gboolean
+on_handle_set_icon_name (OpenrcSettingsdHostnamedHostname1 *hostname1,
+ GDBusMethodInvocation *invocation,
+ const gchar *name,
+ const gboolean user_interaction,
+ gpointer user_data)
+{
+ if (read_only)
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ DBUS_ERROR_NOT_SUPPORTED,
+ "openrc-settingsd hostnamed is in read-only mode");
+ else {
+ struct invoked_name *data;
+ data = g_new0 (struct invoked_name, 1);
+ data->invocation = invocation;
+ data->name = g_strdup (name);
+ check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-machine-info", user_interaction, on_handle_set_icon_name_authorized_cb, data);
+ }
return TRUE; /* Always return TRUE to indicate signal has been handled */
}
@@ -272,8 +375,8 @@ on_bus_acquired (GDBusConnection *connection,
g_signal_connect (hostname1, "handle-set-hostname", G_CALLBACK (on_handle_set_hostname), NULL);
g_signal_connect (hostname1, "handle-set-static-hostname", G_CALLBACK (on_handle_set_static_hostname), NULL);
- g_signal_connect (hostname1, "handle-set-pretty-hostname", G_CALLBACK (on_handle_set_machine_info), GINT_TO_POINTER(TRUE));
- g_signal_connect (hostname1, "handle-set-icon-name", G_CALLBACK (on_handle_set_machine_info), GINT_TO_POINTER(FALSE));
+ g_signal_connect (hostname1, "handle-set-pretty-hostname", G_CALLBACK (on_handle_set_pretty_hostname), NULL);
+ g_signal_connect (hostname1, "handle-set-icon-name", G_CALLBACK (on_handle_set_icon_name), NULL);
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (hostname1),
connection,
next reply other threads:[~2012-02-06 10:25 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-06 10:24 Alexandre Restovtsev [this message]
-- strict thread matches above, loose matches on Subject: below --
2012-09-09 3:47 [gentoo-commits] proj/openrc-settingsd:master commit in: src/ Alexandre Rostovtsev
2012-09-08 0:20 Alexandre Restovtsev
2012-09-05 23:46 Alexandre Restovtsev
2012-09-05 21:19 Alexandre Restovtsev
2012-09-05 21:19 Alexandre Restovtsev
2012-09-05 21:19 Alexandre Restovtsev
2012-09-05 16:54 Alexandre Restovtsev
2012-03-19 3:03 Alexandre Restovtsev
2012-03-19 2:05 Alexandre Restovtsev
2012-03-18 11:02 Alexandre Restovtsev
2012-02-08 6:53 Alexandre Restovtsev
2012-02-08 5:57 Alexandre Restovtsev
2012-02-08 5:01 Alexandre Restovtsev
2012-02-05 7:52 Alexandre Restovtsev
2012-02-05 0:20 Alexandre Restovtsev
2012-01-29 23:22 Alexandre Restovtsev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52f4dc6163ecbc334f9ba949d6436f650ecf138d.tetromino@gentoo \
--to=tetromino@gmail.com \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox