summaryrefslogtreecommitdiff
path: root/plugins/datetime/msd-datetime-mechanism.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/datetime/msd-datetime-mechanism.c')
-rw-r--r--plugins/datetime/msd-datetime-mechanism.c970
1 files changed, 591 insertions, 379 deletions
diff --git a/plugins/datetime/msd-datetime-mechanism.c b/plugins/datetime/msd-datetime-mechanism.c
index 4dd569c..3d4bf6b 100644
--- a/plugins/datetime/msd-datetime-mechanism.c
+++ b/plugins/datetime/msd-datetime-mechanism.c
@@ -1,6 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set ts=8 sts=8 sw=8 expandtab:
*
* Copyright (C) 2007 David Zeuthen <[email protected]>
+ * Copyright (C) 2012-2021 MATE Developers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,27 +35,87 @@
#include <glib.h>
#include <glib-object.h>
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
#include <polkit/polkit.h>
#include "system-timezone.h"
-
#include "msd-datetime-mechanism.h"
-#include "msd-datetime-mechanism-glue.h"
+#include "msd-datetime-generated.h"
+
+#define MSD_DATETIME_DBUS_NAME "org.mate.SettingsDaemon.DateTimeMechanism"
+#define MSD_DATETIME_DBUS_PATH "/"
+
+enum {
+ PROP_0,
+ PROP_LOOP,
+ LAST_PROP
+};
+
+struct MsdDatetimeMechanismPrivate
+{
+ MateSettingsDateTimeMechanism *skeleton;
+ guint bus_name_id;
+ GMainLoop *loop;
+ PolkitAuthority *auth;
+};
+
+static GParamSpec *properties[LAST_PROP] = { NULL };
+
+static void msd_datetime_mechanism_dispose (GObject *object);
+static gboolean msd_datetime_mechanism_can_set_timezone_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data);
+static gboolean msd_datetime_mechanism_get_timezone_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data);
+static gboolean msd_datetime_mechanism_set_timezone_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_zonefile,
+ gpointer user_data);
+
+static gboolean msd_datetime_mechanism_adjust_time_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gint64 arg_seconds_to_add,
+ gpointer user_data);
+static gboolean msd_datetime_mechanism_can_set_time_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data);
+static gboolean msd_datetime_mechanism_get_hardware_clock_using_utc_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data);
+static gboolean msd_datetime_mechanism_set_hardware_clock_using_utc_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gboolean arg_is_using_utc,
+ gpointer user_data);
+static gboolean msd_datetime_mechanism_set_time_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gint64 arg_seconds_since_epoch,
+ gpointer user_data);
+static gboolean _set_time (MsdDatetimeMechanism *mechanism,
+ const struct timeval *tv,
+ GError **error);
+static gboolean _check_polkit_for_action (MsdDatetimeMechanism *mechanism,
+ const char *action,
+ const char *sender,
+ GError **error);
+static gboolean _rh_update_etc_sysconfig_clock (const char *key,
+ const char *value,
+ GError **error);
+
+G_DEFINE_TYPE_WITH_PRIVATE (MsdDatetimeMechanism, msd_datetime_mechanism, G_TYPE_OBJECT)
static gboolean
do_exit (gpointer user_data)
{
+ GMainLoop *loop;
+
+ loop = (GMainLoop*)user_data;
g_debug ("Exiting due to inactivity");
- exit (1);
+ g_main_loop_quit (loop);
return FALSE;
}
static void
-reset_killtimer (void)
+reset_killtimer (GMainLoop *loop)
{
static guint timer_id = 0;
@@ -61,20 +123,9 @@ reset_killtimer (void)
g_source_remove (timer_id);
}
g_debug ("Setting killtimer to 30 seconds...");
- timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+ timer_id = g_timeout_add_seconds (30, do_exit, loop);
}
-struct MsdDatetimeMechanismPrivate
-{
- DBusGConnection *system_bus_connection;
- DBusGProxy *system_bus_proxy;
- PolkitAuthority *auth;
-};
-
-static void msd_datetime_mechanism_finalize (GObject *object);
-
-G_DEFINE_TYPE_WITH_PRIVATE (MsdDatetimeMechanism, msd_datetime_mechanism, G_TYPE_OBJECT)
-
GQuark
msd_datetime_mechanism_error_quark (void)
{
@@ -87,7 +138,6 @@ msd_datetime_mechanism_error_quark (void)
return ret;
}
-
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
@@ -113,180 +163,235 @@ msd_datetime_mechanism_error_get_type (void)
return etype;
}
-
-static GObject *
-msd_datetime_mechanism_constructor (GType type,
- guint n_construct_properties,
- GObjectConstructParam *construct_properties)
-{
- MsdDatetimeMechanism *mechanism;
-
- mechanism = MSD_DATETIME_MECHANISM (G_OBJECT_CLASS (msd_datetime_mechanism_parent_class)->constructor (
- type,
- n_construct_properties,
- construct_properties));
-
- return G_OBJECT (mechanism);
-}
-
-static void
-msd_datetime_mechanism_class_init (MsdDatetimeMechanismClass *klass)
+static gboolean
+msd_datetime_mechanism_adjust_time_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gint64 seconds_to_add,
+ gpointer user_data)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ struct timeval tv;
+ gboolean ret = FALSE;
+ GError *error = NULL;
+ MsdDatetimeMechanism *mechanism;
- object_class->constructor = msd_datetime_mechanism_constructor;
- object_class->finalize = msd_datetime_mechanism_finalize;
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
- dbus_g_object_type_install_info (MSD_DATETIME_TYPE_MECHANISM, &dbus_glib_msd_datetime_mechanism_object_info);
+ reset_killtimer (mechanism->priv->loop);
+ g_debug ("AdjustTime(%ld) called", seconds_to_add);
- dbus_g_error_domain_register (MSD_DATETIME_MECHANISM_ERROR, NULL, MSD_DATETIME_MECHANISM_TYPE_ERROR);
+ if (gettimeofday (&tv, NULL) != 0) {
+ error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error calling gettimeofday(): %s", strerror (errno));
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ return FALSE;
+ }
-}
+ if (!_check_polkit_for_action (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.settime",
+ g_dbus_method_invocation_get_sender (invocation),
+ &error)) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ return FALSE;
+ }
-static void
-msd_datetime_mechanism_init (MsdDatetimeMechanism *mechanism)
-{
- mechanism->priv = msd_datetime_mechanism_get_instance_private (mechanism);
+ tv.tv_sec += (time_t) seconds_to_add;
+ ret = _set_time (mechanism, &tv, &error);
+ if (!ret) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ } else {
+ mate_settings_date_time_mechanism_complete_adjust_time (object, invocation);
+ }
+ return ret;
}
-static void
-msd_datetime_mechanism_finalize (GObject *object)
+static gint
+check_can_do (MsdDatetimeMechanism *mechanism,
+ const char *action,
+ const char *sender,
+ GError **error)
{
- MsdDatetimeMechanism *mechanism;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (MSD_DATETIME_IS_MECHANISM (object));
+ gint value = -1;
+ PolkitSubject *subject;
+ PolkitAuthorizationResult *result;
- mechanism = MSD_DATETIME_MECHANISM (object);
+ /* Check that caller is privileged */
+ subject = polkit_system_bus_name_new (sender);
+ result = polkit_authority_check_authorization_sync (mechanism->priv->auth,
+ subject,
+ action,
+ NULL,
+ 0,
+ NULL,
+ error);
+ g_object_unref (subject);
- g_return_if_fail (mechanism->priv != NULL);
+ if (*error != NULL) {
+ return value;
+ }
- g_object_unref (mechanism->priv->system_bus_proxy);
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ value = 2;
+ }
+ else if (polkit_authorization_result_get_is_challenge (result)) {
+ value = 1;
+ }
+ else {
+ value = 0;
+ }
- G_OBJECT_CLASS (msd_datetime_mechanism_parent_class)->finalize (object);
+ g_object_unref (result);
+ return value;
}
+
static gboolean
-register_mechanism (MsdDatetimeMechanism *mechanism)
+msd_datetime_mechanism_can_set_time_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
{
+ gboolean ret = FALSE;
+ gint value;
GError *error = NULL;
+ MsdDatetimeMechanism *mechanism;
- mechanism->priv->auth = polkit_authority_get_sync (NULL, &error);
- if (mechanism->priv->auth == NULL) {
- if (error != NULL) {
- g_critical ("error getting system bus: %s", error->message);
- g_error_free (error);
- }
- goto error;
- }
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
- mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
- if (mechanism->priv->system_bus_connection == NULL) {
- if (error != NULL) {
- g_critical ("error getting system bus: %s", error->message);
- g_error_free (error);
- }
- goto error;
+ value = check_can_do (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.settime",
+ g_dbus_method_invocation_get_sender (invocation),
+ &error);
+ if (error != NULL) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ ret = FALSE;
+ } else {
+ mate_settings_date_time_mechanism_complete_can_set_time (object, invocation, value);
+ ret = TRUE;
}
- dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
- G_OBJECT (mechanism));
-
- mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-
- reset_killtimer ();
-
- return TRUE;
-
-error:
- return FALSE;
+ return ret;
}
-
-MsdDatetimeMechanism *
-msd_datetime_mechanism_new (void)
+static gboolean
+msd_datetime_mechanism_can_set_timezone_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
{
- GObject *object;
- gboolean res;
-
- object = g_object_new (MSD_DATETIME_TYPE_MECHANISM, NULL);
+ gboolean ret = FALSE;
+ gint value;
+ GError *error = NULL;
+ MsdDatetimeMechanism *mechanism;
- res = register_mechanism (MSD_DATETIME_MECHANISM (object));
- if (! res) {
- g_object_unref (object);
- return NULL;
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
+ value = check_can_do (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.settimezone",
+ g_dbus_method_invocation_get_sender (invocation),
+ &error);
+ if (error != NULL) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ ret = FALSE;
+ } else {
+ mate_settings_date_time_mechanism_complete_can_set_timezone (object, invocation, value);
+ ret = TRUE;
}
- return MSD_DATETIME_MECHANISM (object);
+ return ret;
}
static gboolean
-_check_polkit_for_action (MsdDatetimeMechanism *mechanism, DBusGMethodInvocation *context, const char *action)
+msd_datetime_mechanism_get_hardware_clock_using_utc_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data G_GNUC_UNUSED)
{
- const char *sender;
- GError *error;
- PolkitSubject *subject;
- PolkitAuthorizationResult *result;
-
- error = NULL;
+ char **lines;
+ char *data;
+ gsize len;
+ gboolean is_utc;
+ GError *error = NULL;
- /* Check that caller is privileged */
- sender = dbus_g_method_get_sender (context);
- subject = polkit_system_bus_name_new (sender);
+ if (!g_file_get_contents ("/etc/adjtime", &data, &len, &error)) {
+ GError *error2;
+ error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error reading /etc/adjtime file: %s", error->message);
+ g_error_free (error);
+ g_dbus_method_invocation_return_gerror (invocation, error2);
+ g_error_free (error2);
+ return FALSE;
+ }
- result = polkit_authority_check_authorization_sync (mechanism->priv->auth,
- subject,
- action,
- NULL,
- POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
- NULL, &error);
- g_object_unref (subject);
+ lines = g_strsplit (data, "\n", 0);
+ g_free (data);
- if (error) {
- dbus_g_method_return_error (context, error);
+ if (g_strv_length (lines) < 3) {
+ error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Cannot parse /etc/adjtime");
+ g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
-
+ g_strfreev (lines);
return FALSE;
}
- if (!polkit_authorization_result_get_is_authorized (result)) {
+ if (strcmp (lines[2], "UTC") == 0) {
+ is_utc = TRUE;
+ } else if (strcmp (lines[2], "LOCAL") == 0) {
+ is_utc = FALSE;
+ } else {
error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED,
- "Not Authorized for action %s", action);
- dbus_g_method_return_error (context, error);
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Expected UTC or LOCAL at line 3 of /etc/adjtime; found '%s'",
+ lines[2]);
+ g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
- g_object_unref (result);
-
+ g_strfreev (lines);
return FALSE;
}
+ g_strfreev (lines);
+ mate_settings_date_time_mechanism_complete_get_hardware_clock_using_utc (object, invocation, is_utc);
+ return TRUE;
+}
- g_object_unref (result);
+static gboolean
+msd_datetime_mechanism_get_timezone_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data G_GNUC_UNUSED)
+{
+ gchar *tz;
+ MsdDatetimeMechanism *mechanism;
+
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
+
+ reset_killtimer (mechanism->priv->loop);
+
+ tz = system_timezone_find ();
+
+ mate_settings_date_time_mechanism_complete_get_timezone (object, invocation, tz);
return TRUE;
}
-
static gboolean
-_set_time (MsdDatetimeMechanism *mechanism,
- const struct timeval *tv,
- DBusGMethodInvocation *context)
+msd_datetime_mechanism_set_hardware_clock_using_utc_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gboolean using_utc,
+ gpointer user_data)
{
- GError *error;
-
- if (!_check_polkit_for_action (mechanism, context, "org.mate.settingsdaemon.datetimemechanism.settime"))
- return FALSE;
+ GError *error = NULL;
+ MsdDatetimeMechanism *mechanism;
- if (settimeofday (tv, NULL) != 0) {
- error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Error calling settimeofday({%ld,%ld}): %s",
- (gint64) tv->tv_sec, (gint64) tv->tv_usec,
- strerror (errno));
- dbus_g_method_return_error (context, error);
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
+ if (!_check_polkit_for_action (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.configurehwclock",
+ g_dbus_method_invocation_get_sender (invocation),
+ &error)) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
return FALSE;
}
@@ -294,153 +399,101 @@ _set_time (MsdDatetimeMechanism *mechanism,
if (g_file_test ("/sbin/hwclock",
G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE)) {
int exit_status;
- if (!g_spawn_command_line_sync ("/sbin/hwclock --systohc", NULL, NULL, &exit_status, &error)) {
+ char *cmd;
+ cmd = g_strdup_printf ("/sbin/hwclock %s --systohc", using_utc ? "--utc" : "--localtime");
+ if (!g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
MSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /sbin/hwclock: %s", error->message);
g_error_free (error);
- dbus_g_method_return_error (context, error2);
+ g_dbus_method_invocation_return_gerror (invocation, error2);
g_error_free (error2);
+ g_free (cmd);
return FALSE;
}
+ g_free (cmd);
if (WEXITSTATUS (exit_status) != 0) {
error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
MSD_DATETIME_MECHANISM_ERROR_GENERAL,
"/sbin/hwclock returned %d", exit_status);
- dbus_g_method_return_error (context, error);
+ g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
return FALSE;
}
- }
-
- dbus_g_method_return (context);
- return TRUE;
-}
-static gboolean
-_rh_update_etc_sysconfig_clock (DBusGMethodInvocation *context, const char *key, const char *value)
-{
- /* On Red Hat / Fedora, the /etc/sysconfig/clock file needs to be kept in sync */
- if (g_file_test ("/etc/sysconfig/clock", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
- char **lines;
- int n;
- gboolean replaced;
- char *data;
- gsize len;
- GError *error;
-
- error = NULL;
-
- if (!g_file_get_contents ("/etc/sysconfig/clock", &data, &len, &error)) {
- GError *error2;
- error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Error reading /etc/sysconfig/clock file: %s", error->message);
+ if (!_rh_update_etc_sysconfig_clock ("UTC=", using_utc ? "true" : "false", &error)) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
return FALSE;
}
- replaced = FALSE;
- lines = g_strsplit (data, "\n", 0);
- g_free (data);
-
- for (n = 0; lines[n] != NULL; n++) {
- if (g_str_has_prefix (lines[n], key)) {
- g_free (lines[n]);
- lines[n] = g_strdup_printf ("%s%s", key, value);
- replaced = TRUE;
- }
- }
- if (replaced) {
- GString *str;
- str = g_string_new (NULL);
- for (n = 0; lines[n] != NULL; n++) {
- g_string_append (str, lines[n]);
- if (lines[n + 1] != NULL)
- g_string_append_c (str, '\n');
- }
- data = g_string_free (str, FALSE);
- len = strlen (data);
- if (!g_file_set_contents ("/etc/sysconfig/clock", data, len, &error)) {
- GError *error2;
- error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Error updating /etc/sysconfig/clock: %s", error->message);
- g_error_free (error);
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
- g_free (data);
- return FALSE;
- }
- g_free (data);
- }
- g_strfreev (lines);
}
-
+ mate_settings_date_time_mechanism_complete_set_hardware_clock_using_utc (object, invocation);
return TRUE;
}
-/* exported methods */
-
-gboolean
-msd_datetime_mechanism_set_time (MsdDatetimeMechanism *mechanism,
- gint64 seconds_since_epoch,
- DBusGMethodInvocation *context)
+static gboolean
+msd_datetime_mechanism_set_time_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ gint64 arg_seconds_since_epoch,
+ gpointer user_data)
{
+ gboolean ret = FALSE;
struct timeval tv;
+ GError *error = NULL;
+ MsdDatetimeMechanism *mechanism;
- reset_killtimer ();
- g_debug ("SetTime(%ld) called", seconds_since_epoch);
-
- tv.tv_sec = (time_t) seconds_since_epoch;
- tv.tv_usec = 0;
- return _set_time (mechanism, &tv, context);
-}
-
-gboolean
-msd_datetime_mechanism_adjust_time (MsdDatetimeMechanism *mechanism,
- gint64 seconds_to_add,
- DBusGMethodInvocation *context)
-{
- struct timeval tv;
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
- reset_killtimer ();
- g_debug ("AdjustTime(%ld) called", seconds_to_add);
+ reset_killtimer (mechanism->priv->loop);
+ g_debug ("SetTime(%ld) called", arg_seconds_since_epoch);
- if (gettimeofday (&tv, NULL) != 0) {
- GError *error;
- error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Error calling gettimeofday(): %s", strerror (errno));
- dbus_g_method_return_error (context, error);
+ if (!_check_polkit_for_action (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.settime",
+ g_dbus_method_invocation_get_sender (invocation),
+ &error)) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
return FALSE;
}
- tv.tv_sec += (time_t) seconds_to_add;
- return _set_time (mechanism, &tv, context);
-}
+ tv.tv_sec = (time_t) arg_seconds_since_epoch;
+ tv.tv_usec = 0;
+ ret = _set_time (mechanism, &tv, &error);
+ if (ret == FALSE) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ } else {
+ mate_settings_date_time_mechanism_complete_set_time (object, invocation);
+ }
+ return ret;
+}
-gboolean
-msd_datetime_mechanism_set_timezone (MsdDatetimeMechanism *mechanism,
- const char *zone_file,
- DBusGMethodInvocation *context)
+static gboolean
+msd_datetime_mechanism_set_timezone_handler (MateSettingsDateTimeMechanism *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *zonefile,
+ gpointer user_data)
{
- GError *error;
+ GError *error = NULL;
+ MsdDatetimeMechanism *mechanism;
- reset_killtimer ();
- g_debug ("SetTimezone('%s') called", zone_file);
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
+ reset_killtimer (mechanism->priv->loop);
+ g_debug ("SetTimezone('%s') called", zonefile);
- if (!_check_polkit_for_action (mechanism, context, "org.mate.settingsdaemon.datetimemechanism.settimezone"))
+ if (!_check_polkit_for_action (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.settimezone",
+ g_dbus_method_invocation_get_sender (invocation),
+ &error)) {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
return FALSE;
+ }
- error = NULL;
-
- if (!system_timezone_set_from_file (zone_file, &error)) {
+ if (!system_timezone_set_from_file (zonefile, &error)) {
GError *error2;
int code;
@@ -452,197 +505,356 @@ msd_datetime_mechanism_set_timezone (MsdDatetimeMechanism *mechanism,
error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
code, "%s", error->message);
+
g_error_free (error);
- dbus_g_method_return_error (context, error2);
+ g_dbus_method_invocation_return_gerror (invocation, error2);
g_error_free (error2);
-
return FALSE;
}
- dbus_g_method_return (context);
+ mate_settings_date_time_mechanism_complete_set_timezone (object, invocation);
return TRUE;
}
+static void
+bus_acquired_handler_cb (GDBusConnection *connection,
+ const gchar *name G_GNUC_UNUSED,
+ gpointer user_data)
+{
+ MsdDatetimeMechanism *mechanism;
+ GError *error = NULL;
+ gboolean exported;
+
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
+
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-can-set-timezone",
+ G_CALLBACK (msd_datetime_mechanism_can_set_timezone_handler),
+ mechanism);
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-set-timezone",
+ G_CALLBACK (msd_datetime_mechanism_set_timezone_handler),
+ mechanism);
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-get-timezone",
+ G_CALLBACK (msd_datetime_mechanism_get_timezone_handler),
+ mechanism);
+
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-can-set-time",
+ G_CALLBACK (msd_datetime_mechanism_can_set_time_handler),
+ mechanism);
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-set-time",
+ G_CALLBACK (msd_datetime_mechanism_set_time_handler),
+ mechanism);
+
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-adjust-time",
+ G_CALLBACK (msd_datetime_mechanism_adjust_time_handler),
+ mechanism);
+
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-get-hardware-clock-using-utc",
+ G_CALLBACK (msd_datetime_mechanism_get_hardware_clock_using_utc_handler),
+ mechanism);
+ g_signal_connect (mechanism->priv->skeleton,
+ "handle-set-hardware-clock-using-utc",
+ G_CALLBACK (msd_datetime_mechanism_set_hardware_clock_using_utc_handler),
+ mechanism);
+
+ exported = g_dbus_interface_skeleton_export (
+ G_DBUS_INTERFACE_SKELETON (mechanism->priv->skeleton),
+ connection,
+ MSD_DATETIME_DBUS_PATH,
+ &error);
+ if (!exported)
+ {
+ g_warning ("Failed to export interface: %s", error->message);
+ g_error_free (error);
+ g_main_loop_quit (mechanism->priv->loop);
+ }
+}
-gboolean
-msd_datetime_mechanism_get_timezone (MsdDatetimeMechanism *mechism,
- DBusGMethodInvocation *context)
+static void
+name_lost_handler_cb (GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *name G_GNUC_UNUSED,
+ gpointer user_data)
{
- gchar *timezone;
+ MsdDatetimeMechanism *mechanism;
+
+ mechanism = MSD_DATETIME_MECHANISM (user_data);
+ g_debug("bus name lost\n");
+
+ g_main_loop_quit (mechanism->priv->loop);
+}
- reset_killtimer ();
+static void
+msd_datetime_mechanism_constructed (GObject *object)
+{
+ MsdDatetimeMechanism *mechanism;
- timezone = system_timezone_find ();
+ mechanism = MSD_DATETIME_MECHANISM (object);
- dbus_g_method_return (context, timezone);
+ G_OBJECT_CLASS (msd_datetime_mechanism_parent_class)->constructed (object);
- return TRUE;
+ mechanism->priv->bus_name_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
+ MSD_DATETIME_DBUS_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ bus_acquired_handler_cb,
+ NULL,
+ name_lost_handler_cb, mechanism, NULL);
}
-gboolean
-msd_datetime_mechanism_get_hardware_clock_using_utc (MsdDatetimeMechanism *mechanism,
- DBusGMethodInvocation *context)
+static void
+msd_datetime_mechanism_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- char **lines;
- char *data;
- gsize len;
- GError *error;
- gboolean is_utc;
+ MsdDatetimeMechanism *mechanism;
- error = NULL;
+ mechanism = MSD_DATETIME_MECHANISM (object);
- if (!g_file_get_contents ("/etc/adjtime", &data, &len, &error)) {
- GError *error2;
- error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Error reading /etc/adjtime file: %s", error->message);
- g_error_free (error);
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
- return FALSE;
+ switch (prop_id)
+ {
+ case PROP_LOOP:
+ mechanism->priv->loop = g_value_get_pointer (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
}
+ }
- lines = g_strsplit (data, "\n", 0);
- g_free (data);
+static void
+msd_datetime_mechanism_class_init (MsdDatetimeMechanismClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- if (g_strv_length (lines) < 3) {
- error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Cannot parse /etc/adjtime");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- g_strfreev (lines);
- return FALSE;
- }
+ object_class->constructed = msd_datetime_mechanism_constructed;
+ object_class->set_property = msd_datetime_mechanism_set_property;
+ object_class->dispose = msd_datetime_mechanism_dispose;
+
+ properties[PROP_LOOP] =
+ g_param_spec_pointer("loop",
+ "loop",
+ "loop",
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
- if (strcmp (lines[2], "UTC") == 0) {
- is_utc = TRUE;
- } else if (strcmp (lines[2], "LOCAL") == 0) {
- is_utc = FALSE;
- } else {
- error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Expected UTC or LOCAL at line 3 of /etc/adjtime; found '%s'", lines[2]);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- g_strfreev (lines);
- return FALSE;
- }
- g_strfreev (lines);
- dbus_g_method_return (context, is_utc);
- return TRUE;
+static void
+msd_datetime_mechanism_init (MsdDatetimeMechanism *mechanism)
+{
+ mechanism->priv = msd_datetime_mechanism_get_instance_private (mechanism);
+ mechanism->priv->skeleton = mate_settings_date_time_mechanism_skeleton_new ();
}
-gboolean
-msd_datetime_mechanism_set_hardware_clock_using_utc (MsdDatetimeMechanism *mechanism,
- gboolean using_utc,
- DBusGMethodInvocation *context)
+static void
+msd_datetime_mechanism_dispose (GObject *object)
{
- GError *error;
+ MsdDatetimeMechanism *mechanism;
- error = NULL;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (MSD_DATETIME_IS_MECHANISM (object));
- if (!_check_polkit_for_action (mechanism, context,
- "org.mate.settingsdaemon.datetimemechanism.configurehwclock"))
- return FALSE;
+ mechanism = MSD_DATETIME_MECHANISM (object);
- if (g_file_test ("/sbin/hwclock",
- G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE)) {
- int exit_status;
- char *cmd;
- cmd = g_strdup_printf ("/sbin/hwclock %s --systohc", using_utc ? "--utc" : "--localtime");
- if (!g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &error)) {
- GError *error2;
- error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "Error spawning /sbin/hwclock: %s", error->message);
- g_error_free (error);
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
- g_free (cmd);
- return FALSE;
- }
- g_free (cmd);
- if (WEXITSTATUS (exit_status) != 0) {
- error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
- MSD_DATETIME_MECHANISM_ERROR_GENERAL,
- "/sbin/hwclock returned %d", exit_status);
- dbus_g_method_return_error (context, error);
+ g_return_if_fail (mechanism->priv != NULL);
+
+ if (mechanism->priv->skeleton != NULL)
+ {
+ GDBusInterfaceSkeleton *skeleton;
+
+ skeleton = G_DBUS_INTERFACE_SKELETON (mechanism->priv->skeleton);
+ g_dbus_interface_skeleton_unexport (skeleton);
+ g_clear_object (&mechanism->priv->skeleton);
+ }
+
+ if (mechanism->priv->bus_name_id > 0)
+ {
+ g_bus_unown_name (mechanism->priv->bus_name_id);
+ mechanism->priv->bus_name_id = 0;
+ }
+
+
+ G_OBJECT_CLASS (msd_datetime_mechanism_parent_class)->dispose (object);
+}
+
+static gboolean
+register_mechanism (MsdDatetimeMechanism *mechanism)
+{
+ GError *error = NULL;
+
+ mechanism->priv->auth = polkit_authority_get_sync (NULL, &error);
+ if (mechanism->priv->auth == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
g_error_free (error);
- return FALSE;
}
+ goto error;
+ }
- if (!_rh_update_etc_sysconfig_clock (context, "UTC=", using_utc ? "true" : "false"))
- return FALSE;
+ reset_killtimer (mechanism->priv->loop);
- }
- dbus_g_method_return (context);
return TRUE;
+
+error:
+ return FALSE;
}
-static void
-check_can_do (MsdDatetimeMechanism *mechanism,
- const char *action,
- DBusGMethodInvocation *context)
+MsdDatetimeMechanism *
+msd_datetime_mechanism_new (GMainLoop *loop)
+{
+ GObject *object;
+ gboolean res;
+
+ object = g_object_new (MSD_DATETIME_TYPE_MECHANISM, "loop", loop, NULL);
+
+ res = register_mechanism (MSD_DATETIME_MECHANISM (object));
+ if (! res) {
+ g_object_unref (object);
+ return NULL;
+ }
+
+ return MSD_DATETIME_MECHANISM (object);
+}
+
+static gboolean
+_check_polkit_for_action (MsdDatetimeMechanism *mechanism,
+ const char *action,
+ const char *sender,
+ GError **error)
{
- const char *sender;
PolkitSubject *subject;
PolkitAuthorizationResult *result;
- GError *error;
/* Check that caller is privileged */
- sender = dbus_g_method_get_sender (context);
subject = polkit_system_bus_name_new (sender);
-
- error = NULL;
result = polkit_authority_check_authorization_sync (mechanism->priv->auth,
subject,
action,
NULL,
- 0,
- NULL,
- &error);
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ NULL, error);
g_object_unref (subject);
- if (error) {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
+ if (*error != NULL) {
+ return FALSE;
}
- if (polkit_authorization_result_get_is_authorized (result)) {
- dbus_g_method_return (context, 2);
- }
- else if (polkit_authorization_result_get_is_challenge (result)) {
- dbus_g_method_return (context, 1);
- }
- else {
- dbus_g_method_return (context, 0);
+ if (!polkit_authorization_result_get_is_authorized (result)) {
+ *error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED,
+ "Not Authorized for action %s", action);
+ g_object_unref (result);
+
+ return FALSE;
}
g_object_unref (result);
-}
+ return TRUE;
+}
-gboolean
-msd_datetime_mechanism_can_set_time (MsdDatetimeMechanism *mechanism,
- DBusGMethodInvocation *context)
+static gboolean
+_set_time (MsdDatetimeMechanism *mechanism G_GNUC_UNUSED,
+ const struct timeval *tv,
+ GError **error)
{
- check_can_do (mechanism,
- "org.mate.settingsdaemon.datetimemechanism.settime",
- context);
+ if (settimeofday (tv, NULL) != 0) {
+ *error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error calling settimeofday({%ld,%ld}): %s",
+ (gint64) tv->tv_sec, (gint64) tv->tv_usec,
+ strerror (errno));
+ return FALSE;
+ }
+
+ if (g_file_test ("/sbin/hwclock",
+ G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE)) {
+ int exit_status;
+ if (!g_spawn_command_line_sync ("/sbin/hwclock --systohc", NULL, NULL, &exit_status, error)) {
+ GError *error2;
+ error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error spawning /sbin/hwclock: %s", (*error)->message);
+ g_error_free (*error);
+ g_propagate_error (error, error2);
+ return FALSE;
+ }
+ if (WEXITSTATUS (exit_status) != 0) {
+ *error = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "/sbin/hwclock returned %d", exit_status);
+ return FALSE;
+ }
+ }
return TRUE;
}
-gboolean
-msd_datetime_mechanism_can_set_timezone (MsdDatetimeMechanism *mechanism,
- DBusGMethodInvocation *context)
+static gboolean
+_rh_update_etc_sysconfig_clock (const char *key,
+ const char *value,
+ GError **error)
{
- check_can_do (mechanism,
- "org.mate.settingsdaemon.datetimemechanism.settimezone",
- context);
+ /* On Red Hat / Fedora, the /etc/sysconfig/clock file needs to be kept in sync */
+ if (g_file_test ("/etc/sysconfig/clock", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ char **lines;
+ int n;
+ gboolean replaced;
+ char *data;
+ gsize len;
+
+ if (!g_file_get_contents ("/etc/sysconfig/clock", &data, &len, error)) {
+ GError *error2;
+ error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error reading /etc/sysconfig/clock file: %s", (*error)->message);
+ g_error_free (*error);
+ g_propagate_error (error, error2);
+ return FALSE;
+ }
+ replaced = FALSE;
+ lines = g_strsplit (data, "\n", 0);
+ g_free (data);
+
+ for (n = 0; lines[n] != NULL; n++) {
+ if (g_str_has_prefix (lines[n], key)) {
+ g_free (lines[n]);
+ lines[n] = g_strdup_printf ("%s%s", key, value);
+ replaced = TRUE;
+ }
+ }
+ if (replaced) {
+ GString *str;
+
+ str = g_string_new (NULL);
+ for (n = 0; lines[n] != NULL; n++) {
+ g_string_append (str, lines[n]);
+ if (lines[n + 1] != NULL)
+ g_string_append_c (str, '\n');
+ }
+ data = g_string_free (str, FALSE);
+ len = strlen (data);
+ if (!g_file_set_contents ("/etc/sysconfig/clock", data, len, error)) {
+ GError *error2;
+ error2 = g_error_new (MSD_DATETIME_MECHANISM_ERROR,
+ MSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error updating /etc/sysconfig/clock: %s", (*error)->message);
+ g_error_free (*error);
+ g_propagate_error (error, error2);
+ g_free (data);
+ return FALSE;
+ }
+ g_free (data);
+ }
+ g_strfreev (lines);
+ }
return TRUE;
}