timedatectl.c revision e5609878d8802e2469c433be418bcbcf55fbe63b
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt This file is part of systemd.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Copyright 2012 Lennart Poettering
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Copyright 2013 Kay Sievers
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is free software; you can redistribute it and/or modify it
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt under the terms of the GNU Lesser General Public License as published by
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt the Free Software Foundation; either version 2.1 of the License, or
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt (at your option) any later version.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is distributed in the hope that it will be useful, but
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Lesser General Public License for more details.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt You should have received a copy of the GNU Lesser General Public License
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic bool arg_adjust_system_clock = false;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic bool arg_no_pager = false;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic bool arg_ask_password = true;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flyktstatic void pager_open_if_enabled(void) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic void polkit_agent_open_if_enabled(void) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt /* Open the polkit agent as a child process if necessary */
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykttypedef struct StatusInfo {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic const char *jump_str(int delta_minutes, char *s, size_t size) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt return "one hour forward";
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return "one hour backwards";
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt snprintf(s, size, "%i minutes backwards", -delta_minutes);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt snprintf(s, size, "%i minutes forward", delta_minutes);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt /* Enforce the values of /etc/localtime */
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt fprintf(stderr, "Warning: ignoring the TZ variable, reading the system's timezone setting only.\n\n");
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (i->rtc_time > 0) {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt rtc_sec = (time_t)(i->rtc_time / USEC_PER_SEC);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", gmtime_r(&rtc_sec, &tm)) > 0);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt assert_se(strftime(a, sizeof(a), "%Z, %z", localtime_r(&sec, &tm)) > 0);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt " NTP enabled: %s\n"
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt "NTP synchronized: %s\n"
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt " RTC in local TZ: %s\n",
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm)) > 0);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm)) > 0);
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt printf(" Next DST change: DST %s (the clock jumps %s) at\n"
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt is_dstn ? "begins" : "ends", jump_str(dn, s, sizeof(s)), a, b);
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt "Warning: The RTC is configured to maintain time in the local timezone. This\n"
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt " mode is not fully supported and will create various problems with time\n"
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt " zone changes and daylight saving adjustments. If at all possible use\n"
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt " RTC in UTC, by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
947527f8326d3591f252c48fee5426a563f03544Patrik Flyktstatic int get_timedate_property_bool(sd_bus *bus, const char *name, bool *target) {
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (r < 0) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt log_error("Failed to get property: %s %s", name, bus_error_message(&error, -r));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flyktstatic int get_timedate_property_usec(sd_bus *bus, const char *name, usec_t *target) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (r < 0) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt log_error("Failed to get property: %s %s", name, bus_error_message(&error, -r));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flyktstatic int show_status(sd_bus *bus, char **args, unsigned n) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (r < 0) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt log_error("Failed to get property: Timezone %s", bus_error_message(&error, -r));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = sd_bus_message_read(reply, "s", &info.timezone);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = get_timedate_property_bool(bus, "LocalRTC", &info.rtc_local);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = get_timedate_property_bool(bus, "NTP", &info.ntp_enabled);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = get_timedate_property_bool(bus, "CanNTP", &info.ntp_capable);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = get_timedate_property_bool(bus, "NTPSynchronized", &info.ntp_synced);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = get_timedate_property_usec(bus, "TimeUSec", &info.time);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = get_timedate_property_usec(bus, "RTCTimeUSec", &info.rtc_time);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flyktstatic int set_time(sd_bus *bus, char **args, unsigned n) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt bool relative = false, interactive = arg_ask_password;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt if (r < 0) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_error("Failed to parse time specification: %s", args[1]);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_error("Failed to set time: %s", bus_error_message(&error, -r));
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flyktstatic int set_timezone(sd_bus *bus, char **args, unsigned n) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt "SetTimezone",
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt log_error("Failed to set timezone: %s", bus_error_message(&error, -r));
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flyktstatic int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt if (b < 0) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_error("Failed to parse local RTC setting: %s", args[1]);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt "SetLocalRTC",
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt "bbb", b, arg_adjust_system_clock, arg_ask_password);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_error("Failed to set local RTC: %s", bus_error_message(&error, -r));
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flyktstatic int set_ntp(sd_bus *bus, char **args, unsigned n) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt if (b < 0) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_error("Failed to parse NTP setting: %s", args[1]);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_error("Failed to set ntp: %s", bus_error_message(&error, -r));
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flyktstatic int list_timezones(sd_bus *bus, char **args, unsigned n) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt f = fopen("/usr/share/zoneinfo/zone.tab", "re");
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_error("Failed to open timezone database: %m");
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt char l[LINE_MAX], *p, **z, *w;
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt if (!fgets(l, sizeof(l), f)) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_error("Failed to read timezone database: %m");
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt /* Skip over country code */
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt /* Skip over coordinates */
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt /* Found timezone name */
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt z = realloc(zones, sizeof(char*) * (n_zones + 2));
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flyktstatic int help(void) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt "Query or change system time and date settings.\n\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " -h --help Show this help\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " --version Show package version\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " --adjust-system-clock\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " Adjust system clock when changing local RTC mode\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " --no-pager Do not pipe output into a pager\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " --no-ask-password Do not prompt for password\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " -H --host=[USER@]HOST Operate on remote host\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " -M --machine=CONTAINER Operate on local container\n\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt "Commands:\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " status Show current time settings\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " set-time TIME Set system time\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " set-timezone ZONE Set system timezone\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " list-timezones Show known timezones\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " set-local-rtc BOOL Control whether RTC is in local time\n"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt " set-ntp BOOL Control whether NTP is enabled\n",
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt { "no-pager", no_argument, NULL, ARG_NO_PAGER },
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt switch (c) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt static const struct {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt const char* verb;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt const enum {
} verbs[] = {
int left;
if (left <= 0)
help();
return -EINVAL;
case EQUAL:
return -EINVAL;
case MORE:
return -EINVAL;
case LESS:
return -EINVAL;
log_open();
goto finish;
goto finish;
goto finish;
pager_close();
return ret;