|
|
@ -27,159 +27,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include "slack-timedate.h"
|
|
|
|
#include "slack-timedate.h"
|
|
|
|
|
|
|
|
|
|
|
|
static void slack_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) {
|
|
|
|
static void slack_method_call(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& sender,
|
|
|
|
gchar *timezone, *response;
|
|
|
|
const Glib::ustring& object_path, const Glib::ustring& interface_name, const Glib::ustring& method_name,
|
|
|
|
gboolean user_interaction, relative, is_localtime, use_ntp;
|
|
|
|
const Glib::VariantContainerBase& parameters, const Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation) {
|
|
|
|
gint64 usec_utc;
|
|
|
|
gchar *timezone;
|
|
|
|
auto timedate1 = reinterpret_cast<dlackware::timedate::timedate1 *>(user_data);
|
|
|
|
gboolean user_interaction, relative, is_localtime, use_ntp;
|
|
|
|
|
|
|
|
gint64 usec_utc;
|
|
|
|
|
|
|
|
auto parameters_copy = parameters.gobj_copy();
|
|
|
|
|
|
|
|
|
|
|
|
// Set time zone
|
|
|
|
// Set time zone
|
|
|
|
if (g_strcmp0(method_name, "SetTimezone") == 0)
|
|
|
|
if (method_name == "SetTimezone")
|
|
|
|
{
|
|
|
|
{
|
|
|
|
g_variant_get(parameters, "(&sb)", &timezone, &user_interaction);
|
|
|
|
g_variant_get(parameters_copy, "(&sb)", &timezone, &user_interaction);
|
|
|
|
std::error_code error_code;
|
|
|
|
std::error_code error_code;
|
|
|
|
|
|
|
|
|
|
|
|
if (timedate1->set_timezone(timezone, error_code))
|
|
|
|
if (dlackware::timedate::set_timezone(timezone, error_code))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
|
|
g_dbus_method_invocation_return_value(invocation->gobj(), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_error(invocation, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
|
|
|
|
"Set time zone: %s",
|
|
|
|
|
|
|
|
error_code ? error_code.message().c_str() : "Zone info is not a regular file");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (timezone);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (g_strcmp0(method_name, "SetTime") == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_variant_get (parameters, "(xbb)", &usec_utc, &relative, &user_interaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set time
|
|
|
|
|
|
|
|
//if (!slack_set_time (usec_utc, slack_get_is_localtime ())) {
|
|
|
|
|
|
|
|
if (slack_set_time(usec_utc, relative))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_error(invocation, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
|
|
|
|
"Failed to set system clock");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (g_strcmp0(method_name, "SetNTP") == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_variant_get (parameters, "(bb)", &use_ntp, &user_interaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Enable NTP
|
|
|
|
|
|
|
|
if (slack_set_ntp (use_ntp))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation,
|
|
|
|
g_dbus_method_invocation_return_error(invocation->gobj(), G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
G_IO_ERROR,
|
|
|
|
"Set time zone: %s",
|
|
|
|
G_IO_ERROR_FAILED,
|
|
|
|
error_code ? error_code.message().c_str() : "Zone info is not a regular file");
|
|
|
|
"Error enabling NTP");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_free (timezone);
|
|
|
|
else if (g_strcmp0(method_name, "ListTimezones") == 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (method_name == "SetTime")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_variant_get(parameters_copy, "(xbb)", &usec_utc, &relative, &user_interaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set time
|
|
|
|
|
|
|
|
//if (!slack_set_time (usec_utc, slack_get_is_localtime ())) {
|
|
|
|
|
|
|
|
if (slack_set_time(usec_utc, relative))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_value(invocation->gobj(), NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_error(invocation->gobj(), G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
|
|
|
|
"Failed to set system clock");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (method_name == "SetNTP")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_variant_get(parameters_copy, "(bb)", &use_ntp, &user_interaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Enable NTP
|
|
|
|
|
|
|
|
if (slack_set_ntp (use_ntp))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_value(invocation->gobj(), NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_error(invocation->gobj(),
|
|
|
|
|
|
|
|
G_IO_ERROR,
|
|
|
|
|
|
|
|
G_IO_ERROR_FAILED,
|
|
|
|
|
|
|
|
"Error enabling NTP");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (method_name == "ListTimezones")
|
|
|
|
{
|
|
|
|
{
|
|
|
|
try
|
|
|
|
try
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto return_tuple = Glib::Variant<std::vector<Glib::ustring>>::create_tuple({
|
|
|
|
auto return_tuple = Glib::Variant<std::vector<Glib::ustring>>::create_tuple({
|
|
|
|
timedate1->list_timezones()
|
|
|
|
dlackware::timedate::list_timezones()
|
|
|
|
});
|
|
|
|
});
|
|
|
|
g_dbus_method_invocation_return_value(invocation, return_tuple.gobj());
|
|
|
|
g_dbus_method_invocation_return_value(invocation->gobj(), return_tuple.gobj());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const std::exception& exception)
|
|
|
|
catch (const std::exception& exception)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error(invocation, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
g_dbus_method_invocation_return_error(invocation->gobj(), G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"List time zones: %s", exception.what());
|
|
|
|
"List time zones: %s", exception.what());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(parameters_copy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static GVariant *slack_get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *prop_name, GError **slack_err, gpointer user_data) {
|
|
|
|
static void slack_get_property(Glib::VariantBase& result, const Glib::RefPtr<Gio::DBus::Connection>& connection,
|
|
|
|
auto timedate1 = reinterpret_cast<dlackware::timedate::timedate1 *>(user_data);
|
|
|
|
const Glib::ustring& sender, const Glib::ustring& object_path, const Glib::ustring& interface_name,
|
|
|
|
|
|
|
|
const Glib::ustring& prop_name)
|
|
|
|
if (g_strcmp0 ("Timezone", prop_name) == 0) {
|
|
|
|
{
|
|
|
|
return Glib::Variant<Glib::ustring>::create(timedate1->timezone()).gobj_copy();
|
|
|
|
if (prop_name == "Timezone")
|
|
|
|
} if (g_strcmp0 ("LocalRTC", prop_name) == 0) {
|
|
|
|
{
|
|
|
|
return g_variant_new_boolean (slack_get_is_localtime ());
|
|
|
|
result = Glib::Variant<Glib::ustring>::create(dlackware::timedate::timezone());
|
|
|
|
} if (g_strcmp0 ("NTP", prop_name) == 0) {
|
|
|
|
}
|
|
|
|
return g_variant_new_boolean (slack_get_ntp ());
|
|
|
|
else if (prop_name == "LocalRTC")
|
|
|
|
}
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
result = Glib::Variant<bool>::create(slack_get_is_localtime());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (prop_name == "NTP")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
result = Glib::Variant<bool>::create(slack_get_ntp());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_timedate_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) {
|
|
|
|
gboolean timeout_callback(Glib::RefPtr<Glib::MainLoop> loop2quit)
|
|
|
|
guint registration_id;
|
|
|
|
{
|
|
|
|
GDBusNodeInfo *introspection_data;
|
|
|
|
loop2quit->quit();
|
|
|
|
GError *slack_err;
|
|
|
|
return false;
|
|
|
|
const GDBusInterfaceVTable interface_vtable = {
|
|
|
|
|
|
|
|
slack_method_call,
|
|
|
|
|
|
|
|
slack_get_property,
|
|
|
|
|
|
|
|
NULL
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
slack_err = NULL;
|
|
|
|
|
|
|
|
introspection_data = g_dbus_node_info_new_for_xml (INTROSPECTION_XML, &slack_err);
|
|
|
|
|
|
|
|
if (introspection_data == NULL)
|
|
|
|
|
|
|
|
g_error ("Failed to parse D-Bus introspection XML: %s\n", slack_err->message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
slack_err = NULL;
|
|
|
|
|
|
|
|
registration_id = g_dbus_connection_register_object (connection,
|
|
|
|
|
|
|
|
BUS_PATH,
|
|
|
|
|
|
|
|
introspection_data->interfaces[0],
|
|
|
|
|
|
|
|
&interface_vtable,
|
|
|
|
|
|
|
|
user_data,
|
|
|
|
|
|
|
|
NULL,
|
|
|
|
|
|
|
|
&slack_err);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (registration_id <= 0) {
|
|
|
|
|
|
|
|
g_critical ("Failed to register callbacks for the exported object with the D-Bus interface: %s\n", slack_err->message);
|
|
|
|
|
|
|
|
g_error_free (slack_err);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
g_dbus_node_info_unref (introspection_data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void on_timedate_lost (GDBusConnection *connection, const gchar *name, gpointer user_data) {
|
|
|
|
|
|
|
|
g_warning ("Failed to acquire the service %s.\n", name);
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gboolean timeout_callback (Glib::RefPtr<Glib::MainLoop> loop2quit) {
|
|
|
|
|
|
|
|
loop2quit->quit();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto timedate1 = new dlackware::timedate::timedate1();
|
|
|
|
Gio::init();
|
|
|
|
guint owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
|
|
|
|
auto timedate1 = std::make_unique<dlackware::timedate::timedate1>();
|
|
|
|
BUS_NAME,
|
|
|
|
|
|
|
|
static_cast<GBusNameOwnerFlags>(G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE),
|
|
|
|
guint owner_id = Gio::DBus::own_name(Gio::DBus::BUS_TYPE_SYSTEM, BUS_NAME,
|
|
|
|
on_timedate_acquired,
|
|
|
|
std::bind(&dlackware::timedate::timedate1::on_bus_acquired, timedate1.get(),
|
|
|
|
NULL,
|
|
|
|
std::placeholders::_1, std::placeholders::_2),
|
|
|
|
on_timedate_lost,
|
|
|
|
Gio::DBus::SlotNameAcquired(),
|
|
|
|
timedate1,
|
|
|
|
std::bind(&dlackware::timedate::timedate1::on_name_lost, timedate1.get(),
|
|
|
|
[](void *memory) { delete reinterpret_cast<dlackware::timedate::timedate1 *>(memory); });
|
|
|
|
std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
|
|
|
Gio::DBus::BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | Gio::DBus::BUS_NAME_OWNER_FLAGS_REPLACE);
|
|
|
|
|
|
|
|
|
|
|
|
Glib::RefPtr<Glib::MainLoop> loop = Glib::MainLoop::create(false);
|
|
|
|
Glib::RefPtr<Glib::MainLoop> loop = Glib::MainLoop::create(false);
|
|
|
|
|
|
|
|
|
|
|
|
Glib::signal_timeout().connect_seconds(sigc::bind(&timeout_callback, loop), DEFAULT_EXIT_SEC);
|
|
|
|
Glib::signal_timeout().connect_seconds(sigc::bind(&timeout_callback, loop), DEFAULT_EXIT_SEC);
|
|
|
|
loop->run();
|
|
|
|
loop->run();
|
|
|
|
|
|
|
|
|
|
|
|
g_bus_unown_name (owner_id);
|
|
|
|
Gio::DBus::unown_name(owner_id);
|
|
|
|
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace dlackware::timedate
|
|
|
|
namespace dlackware::timedate
|
|
|
|
{
|
|
|
|
{
|
|
|
|
void timedate1::list_timezones(const std::string& prefix, std::vector<Glib::ustring>& accumulator)
|
|
|
|
timedate1::timedate1()
|
|
|
|
|
|
|
|
: interface_vtable{ &slack_method_call, &slack_get_property }
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void timedate1::on_name_lost(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_warning("Failed to acquire the service %s.\n", name.data());
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void timedate1::on_bus_acquired(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Glib::RefPtr<Gio::DBus::NodeInfo> introspection_data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
introspection_data = Gio::DBus::NodeInfo::create_for_xml(INTROSPECTION_XML);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Glib::Error& slack_err)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_error("Failed to parse D-Bus introspection XML: %s\n", slack_err.what().data());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
guint registration_id = connection->register_object(BUS_PATH,
|
|
|
|
|
|
|
|
introspection_data->lookup_interface(), this->interface_vtable);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Glib::Error& slack_err)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
g_critical("Failed to register callbacks for the exported object with the D-Bus interface: %s\n",
|
|
|
|
|
|
|
|
slack_err.what().data());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void list_timezones(const std::string& prefix, std::vector<Glib::ustring>& accumulator)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto zoneinfo_path = std::filesystem::path(zoneinfo_database) / prefix;
|
|
|
|
auto zoneinfo_path = std::filesystem::path(zoneinfo_database) / prefix;
|
|
|
|
|
|
|
|
|
|
|
@ -199,7 +208,7 @@ namespace dlackware::timedate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Glib::Variant<std::vector<Glib::ustring>> timedate1::list_timezones()
|
|
|
|
Glib::Variant<std::vector<Glib::ustring>> list_timezones()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::vector<Glib::ustring> result;
|
|
|
|
std::vector<Glib::ustring> result;
|
|
|
|
|
|
|
|
|
|
|
@ -207,7 +216,7 @@ namespace dlackware::timedate
|
|
|
|
return Glib::Variant<std::vector<Glib::ustring>>::create(result);
|
|
|
|
return Glib::Variant<std::vector<Glib::ustring>>::create(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Glib::ustring timedate1::timezone()
|
|
|
|
Glib::ustring timezone()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::unique_ptr<gchar[], decltype(&g_free)> zone_copied_from(
|
|
|
|
std::unique_ptr<gchar[], decltype(&g_free)> zone_copied_from(
|
|
|
|
g_file_read_link("/etc/localtime", NULL), &g_free);
|
|
|
|
g_file_read_link("/etc/localtime", NULL), &g_free);
|
|
|
@ -219,7 +228,7 @@ namespace dlackware::timedate
|
|
|
|
return Glib::ustring{ zone_copied_from.get() + strlen(zoneinfo_database) + 1 };
|
|
|
|
return Glib::ustring{ zone_copied_from.get() + strlen(zoneinfo_database) + 1 };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool timedate1::set_timezone(gchar *zone, std::error_code& ec)
|
|
|
|
bool set_timezone(gchar *zone, std::error_code& ec)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ec.clear();
|
|
|
|
ec.clear();
|
|
|
|
auto zone_file = std::filesystem::path("/usr/share/zoneinfo") / zone;
|
|
|
|
auto zone_file = std::filesystem::path("/usr/share/zoneinfo") / zone;
|
|
|
|