diff --git a/src/slack-timedate.cpp b/src/slack-timedate.cpp index 391c4dc..223ce78 100644 --- a/src/slack-timedate.cpp +++ b/src/slack-timedate.cpp @@ -35,18 +35,18 @@ static void slack_method_call(const Glib::RefPtr& connect if (method_name == "SetTimezone") { Glib::Variant timezone; - std::error_code error_code; + Glib::Variant user_interaction; parameters.get_child(timezone, 0); - if (dlackware::timedate::set_timezone(timezone.get(), error_code)) + parameters.get_child(user_interaction, 1); + try { + dlackware::timedate::set_timezone(timezone.get(), user_interaction.get()); invocation->return_value(Glib::VariantContainerBase()); } - else + catch (const std::filesystem::filesystem_error& filesystem_error) { - Gio::DBus::Error error{ Gio::DBus::Error::FAILED, - error_code ? error_code.message().c_str() : "Zone info is not a regular file" }; - invocation->return_error(error); + invocation->return_error(Gio::DBus::Error{ Gio::DBus::Error::FAILED, filesystem_error.what() }); } } else if (method_name == "SetTime") @@ -70,26 +70,28 @@ static void slack_method_call(const Glib::RefPtr& connect else if (method_name == "SetNTP") { Glib::Variant use_ntp; + Glib::Variant user_interaction; parameters.get_child(use_ntp, 0); + parameters.get_child(user_interaction, 1); // Enable NTP - if (slack_set_ntp(use_ntp.get())) + try { + dlackware::timedate::set_ntp(use_ntp.get(), user_interaction.get()); invocation->return_value(Glib::VariantContainerBase()); } - else + catch (const std::filesystem::filesystem_error& filesystem_error) { - Gio::DBus::Error error{ Gio::DBus::Error::FAILED, "Error enabling NTP" }; - invocation->return_error(error); + invocation->return_error(Gio::DBus::Error{ Gio::DBus::Error::FAILED, filesystem_error.what() }); } } else if (method_name == "ListTimezones") { try { - auto return_tuple = Glib::Variant>::create_tuple({ - dlackware::timedate::list_timezones() + auto return_tuple = Glib::VariantContainerBase::create_tuple({ + Glib::Variant>::create(dlackware::timedate::list_timezones()) }); invocation->return_value(return_tuple); } @@ -111,11 +113,11 @@ static void slack_get_property(Glib::VariantBase& result, const Glib::RefPtr::create(slack_get_is_localtime()); + result = Glib::Variant::create(dlackware::timedate::local_rtc()); } else if (prop_name == "NTP") { - result = Glib::Variant::create(slack_get_ntp()); + result = Glib::Variant::create(dlackware::timedate::ntp()); } } @@ -185,7 +187,7 @@ namespace dlackware::timedate } } - void list_timezones(const std::string& prefix, std::vector& accumulator) + static void list_timezones(const std::string& prefix, std::vector& accumulator) { auto zoneinfo_path = std::filesystem::path(zoneinfo_database) / prefix; @@ -205,12 +207,12 @@ namespace dlackware::timedate } } - Glib::Variant> list_timezones() + std::vector list_timezones() { std::vector result; list_timezones("", result); - return Glib::Variant>::create(result); + return result; } Glib::ustring timezone() @@ -225,21 +227,69 @@ namespace dlackware::timedate return Glib::ustring{ zone_copied_from.get() + strlen(zoneinfo_database) + 1 }; } - bool set_timezone(const Glib::ustring& zone, std::error_code& ec) + void set_timezone(const Glib::ustring& zone, bool) { - ec.clear(); auto zone_file = std::filesystem::path("/usr/share/zoneinfo") / zone.data(); + std::error_code ec{}; - if (!std::filesystem::is_regular_file(zone_file, ec) || ec) + if (!std::filesystem::is_regular_file(zone_file, ec)) { - return false; + throw std::filesystem::filesystem_error("Zone info is not a regular file", zone_file, ec); } std::filesystem::path etc_localtime = "/etc/localtime"; std::filesystem::remove(etc_localtime); - std::filesystem::create_symlink(zone_file, etc_localtime, ec); + std::filesystem::create_symlink(zone_file, etc_localtime); + } - return !ec; + void set_ntp(bool use_ntp, bool) + { + std::filesystem::perms rc_mode = std::filesystem::perms::owner_read | std::filesystem::perms::owner_write + | std::filesystem::perms::group_read | std::filesystem::perms::others_read; + + if (use_ntp) + { + rc_mode |= std::filesystem::perms::owner_exec + | std::filesystem::perms::group_exec | std::filesystem::perms::others_exec; + } + std::error_code ec; + const std::filesystem::path service_path{ "/etc/rc.d/rc.ntpd" }; + + if (std::filesystem::is_regular_file(service_path, ec)) + { + std::filesystem::permissions("/etc/rc.d/rc.ntpd", rc_mode); + } + else + { + throw std::filesystem::filesystem_error("The NTP daemon isn't installed", service_path, ec); + } + } + + bool local_rtc() + { + std::ifstream fh{ "/etc/hardwareclock", std::ios::in }; + if (!fh.is_open()) + { + return false; + } + std::array time_str; // "localtime" is longer than "UTC" and has 9 letters + \0 + + while (fh.good()) + { + fh.getline(time_str.data(), time_str.size()); + fh.clear(fh.rdstate() & (~std::ios_base::failbit)); + + if (std::strncmp(time_str.data(), "localtime", time_str.size()) == 0) + { + return true; + } + } + return false; + } + + bool ntp() + { + return Glib::file_test("/etc/rc.d/rc.ntpd", Glib::FileTest::FILE_TEST_IS_EXECUTABLE); } } @@ -269,59 +319,3 @@ gboolean slack_set_time(gint64 seconds_since_epoch, gboolean relative) } return clock_settime (CLOCK_REALTIME, &ts) == 0; } - -gboolean slack_get_is_localtime() -{ - std::ifstream fh{ "/etc/hardwareclock", std::ios::in }; - if (!fh.is_open()) - { - return false; - } - std::array time_str; // "localtime" is longer than "UTC" and has 9 letters + \0 - - while (fh.good()) - { - fh.getline(time_str.data(), time_str.size()); - fh.clear(fh.rdstate() & (~std::ios_base::failbit)); - - if (std::strncmp(time_str.data(), "localtime", time_str.size()) == 0) - { - return true; - } - } - return false; -} - -gboolean slack_get_ntp() -{ - return Glib::file_test("/etc/rc.d/rc.ntpd", Glib::FileTest::FILE_TEST_IS_EXECUTABLE); -} - -gboolean slack_set_ntp(gboolean xntp) -{ - std::filesystem::perms rc_mode = std::filesystem::perms::owner_read | std::filesystem::perms::owner_write - | std::filesystem::perms::group_read | std::filesystem::perms::others_read; - - if (xntp) - { - rc_mode |= std::filesystem::perms::owner_exec - | std::filesystem::perms::group_exec | std::filesystem::perms::others_exec; - g_message("Please don't forget to configure the NTP daemon"); - - /* It doesn't matter if fails. - * The ntpdate command is considered obsolete, but "orthodox" ntpd -g - * will fail if your system clock is off for more than half an hour. */ - g_spawn_command_line_async("/usr/sbin/ntpdate pool.ntp.org", NULL); - } - if (Glib::file_test("/etc/rc.d/rc.ntpd", Glib::FileTest::FILE_TEST_IS_REGULAR)) - { - std::error_code ec; - std::filesystem::permissions("/etc/rc.d/rc.ntpd", rc_mode, ec); - return !ec; - } - else - { - g_error("The NTP daemon isn't installed"); - return false; - } -} diff --git a/src/slack-timedate.h b/src/slack-timedate.h index 2d4ffd3..a687ab0 100644 --- a/src/slack-timedate.h +++ b/src/slack-timedate.h @@ -64,16 +64,24 @@ namespace dlackware::timedate { constexpr const char *zoneinfo_database = "/usr/share/zoneinfo"; - // Returns the timezones available on the system. - Glib::Variant> list_timezones(); - void list_timezones(const std::string& prefix, std::vector& accumulator); - // Returns the system time zone. Glib::ustring timezone(); + // Returns if the hardware clock is set to local time or not + bool local_rtc(); + + // Returns if NTP is enabled + bool ntp(); + + // Returns the timezones available on the system. + std::vector list_timezones(); + // Sets the system time zone to the one passed by the argument // Returns true on success, false otherwise - bool set_timezone(const Glib::ustring& zone, std::error_code& ec); + void set_timezone(const Glib::ustring& zone, bool user_interaction); + + // Sets NTP + void set_ntp(bool use_ntp, bool user_interaction); class timedate1 { @@ -91,12 +99,3 @@ namespace dlackware::timedate // Takes the amount of seconds since UNIX epoche and // Returns true on success, false otherwise gboolean slack_set_time(gint64 seconds_since_epoch, gboolean relative); - -// Returns if the hardware clock is set to local time or not -gboolean slack_get_is_localtime (); - -// Returns if NTP is enabled -gboolean slack_get_ntp (); - -// Sets NTP -gboolean slack_set_ntp (gboolean);