aboutsummaryrefslogtreecommitdiff
path: root/src/timezone-file.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/timezone-file.cpp')
-rw-r--r--src/timezone-file.cpp199
1 files changed, 108 insertions, 91 deletions
diff --git a/src/timezone-file.cpp b/src/timezone-file.cpp
index 3c73913..15e4f61 100644
--- a/src/timezone-file.cpp
+++ b/src/timezone-file.cpp
@@ -36,10 +36,11 @@ class FileTimezone::Impl
{
public:
- Impl(FileTimezone& owner, const std::string& filename):
- m_owner(owner)
+ Impl(FileTimezone& owner):
+ m_owner(owner),
+ m_loop(g_main_loop_new(nullptr, FALSE))
{
- set_filename(filename);
+ monitor_timezone_property();
}
~Impl()
@@ -51,113 +52,128 @@ private:
void clear()
{
- if (m_monitor_handler_id)
- g_signal_handler_disconnect(m_monitor, m_monitor_handler_id);
-
- g_clear_object (&m_monitor);
-
- m_filename.clear();
- }
-
- void set_filename(const std::string& filename)
- {
- clear();
-
- auto tmp = realpath(filename.c_str(), nullptr);
- if(tmp != nullptr)
+ if (m_bus_watch_id)
{
- m_filename = tmp;
- free(tmp);
- }
- else
- {
- g_warning("Unable to resolve path '%s': %s", filename.c_str(), g_strerror(errno));
- m_filename = filename; // better than nothing?
+ g_bus_unwatch_name (m_bus_watch_id);
+ m_bus_watch_id = 0;
}
- auto file = g_file_new_for_path(m_filename.c_str());
- GError * err = nullptr;
- m_monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, nullptr, &err);
- g_object_unref(file);
- if (err)
- {
- g_warning("%s Unable to monitor timezone file '%s': %s", G_STRLOC, TIMEZONE_FILE, err->message);
- g_error_free(err);
- }
- else
+ if (m_properties_changed_id)
{
- m_monitor_handler_id = g_signal_connect_swapped(m_monitor, "changed", G_CALLBACK(on_file_changed), this);
- g_debug("%s Monitoring timezone file '%s'", G_STRLOC, m_filename.c_str());
+ g_signal_handler_disconnect(m_proxy, m_properties_changed_id);
+ m_properties_changed_id = 0;
}
- reload();
+ g_clear_object(&m_proxy);
+ g_clear_pointer(&m_loop, g_main_loop_unref);
}
- static void on_file_changed(gpointer gself)
+ static void on_properties_changed(GDBusProxy *proxy G_GNUC_UNUSED,
+ GVariant *changed_properties /* a{sv} */,
+ GStrv invalidated_properties G_GNUC_UNUSED,
+ gpointer gself)
{
- static_cast<Impl*>(gself)->reload();
+ auto self = static_cast<Impl*>(gself);
+ char *tz;
+
+ if (g_variant_lookup(changed_properties, "Timezone", "s", &tz, NULL))
+ {
+ g_debug("on_properties_changed: got timezone '%s'", tz);
+ self->notify_timezone(tz);
+ g_free (tz);
+ }
}
- void reload()
+ static void on_proxy_ready(GObject *object G_GNUC_UNUSED,
+ GAsyncResult *res,
+ gpointer gself)
{
- const auto new_timezone = get_timezone_from_file(m_filename);
+ auto self = static_cast<Impl*>(gself);
+ GError *error = nullptr;
+ self->m_proxy = g_dbus_proxy_new_finish(res, &error);
- if (!new_timezone.empty())
- m_owner.timezone.set(new_timezone);
- }
+ if (error)
+ {
+ g_warning ("Couldn't create proxy to read timezone: %s", error->message);
+ goto out;
+ }
- /***
- ****
- ***/
+ /* Read the property */
+ GVariant *prop;
+ prop = g_dbus_proxy_get_cached_property(self->m_proxy, "Timezone");
- std::string get_timezone_from_file(const std::string& filename)
- {
- GError * error;
- GIOChannel * io_channel;
- std::string ret;
-
- // read through filename line-by-line until we fine a nonempty non-comment line
- error = nullptr;
- io_channel = g_io_channel_new_file(filename.c_str(), "r", &error);
- if (error == nullptr)
+ if (!prop || !g_variant_is_of_type(prop, G_VARIANT_TYPE_STRING))
{
- auto line = g_string_new(nullptr);
-
- while(ret.empty())
- {
- const auto io_status = g_io_channel_read_line_string(io_channel, line, nullptr, &error);
- if ((io_status == G_IO_STATUS_EOF) || (io_status == G_IO_STATUS_ERROR))
- break;
- if (error != nullptr)
- break;
+ g_warning("Couldn't read the Timezone property, defaulting to Etc/Utc");
+ self->notify_timezone("Etc/Utc");
+ goto out;
+ }
- g_strstrip(line->str);
+ const gchar *tz;
+ tz = g_variant_get_string(prop, nullptr);
- if (!line->len) // skip empty lines
- continue;
+ self->notify_timezone(tz);
- if (*line->str=='#') // skip comments
- continue;
+ self->m_properties_changed_id = g_signal_connect(self->m_proxy,
+ "g-properties-changed",
+ (GCallback) on_properties_changed,
+ gself);
- ret = line->str;
- }
+out:
+ g_clear_pointer(&error, g_error_free);
+ g_clear_pointer(&prop, g_variant_unref);
+ if (self->m_loop && g_main_loop_is_running(self->m_loop))
+ g_main_loop_quit(self->m_loop);
+ }
- g_string_free(line, true);
- }
+ static void on_name_appeared(GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner G_GNUC_UNUSED,
+ gpointer gself G_GNUC_UNUSED)
+ {
+ g_debug ("timedate1 appeared");
+ g_dbus_proxy_new(connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ name,
+ "/org/freedesktop/timedate1",
+ "org.freedesktop.timedate1",
+ nullptr,
+ on_proxy_ready,
+ gself);
+ }
- if (io_channel != nullptr)
- {
- g_io_channel_shutdown(io_channel, false, nullptr);
- g_io_channel_unref(io_channel);
- }
+ static void on_name_vanished(GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *name G_GNUC_UNUSED,
+ gpointer gself)
+ {
+ auto self = static_cast<Impl*>(gself);
+ g_debug ("timedate1 vanished");
+
+ g_signal_handler_disconnect(self->m_proxy,
+ self->m_properties_changed_id);
+ self->m_properties_changed_id = 0;
+ g_clear_object(&self->m_proxy);
+ g_clear_pointer(&self->m_proxy, g_main_loop_unref);
+ }
- if (error != nullptr)
- {
- g_warning("%s Unable to read timezone file '%s': %s", G_STRLOC, filename.c_str(), error->message);
- g_error_free(error);
- }
+ void monitor_timezone_property()
+ {
+ m_bus_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+ "org.freedesktop.timedate1",
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ on_name_appeared,
+ on_name_vanished,
+ this,
+ nullptr);
+
+ g_main_loop_run(m_loop);
+ }
- return ret;
+ void notify_timezone(std::string new_timezone)
+ {
+ if (!new_timezone.empty())
+ m_owner.timezone.set(new_timezone);
}
/***
@@ -165,17 +181,18 @@ private:
***/
FileTimezone & m_owner;
- std::string m_filename;
- GFileMonitor * m_monitor = nullptr;
- unsigned long m_monitor_handler_id = 0;
+ unsigned long m_properties_changed_id = 0;
+ unsigned long m_bus_watch_id = 0;
+ GDBusProxy *m_proxy = nullptr;
+ GMainLoop *m_loop = nullptr;
};
/***
****
***/
-FileTimezone::FileTimezone(const std::string& filename):
- impl(new Impl{*this, filename})
+FileTimezone::FileTimezone():
+ impl(new Impl{*this})
{
}