timedated.c revision 403ed0e5c914f2a0a683403d8ba7eaf96e3ffcdf
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering This file is part of systemd.
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering Copyright 2011 Lennart Poettering
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering systemd is free software; you can redistribute it and/or modify it
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering under the terms of the GNU Lesser General Public License as published by
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering (at your option) any later version.
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering systemd is distributed in the hope that it will be useful, but
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering Lesser General Public License for more details.
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering You should have received a copy of the GNU Lesser General Public License
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poettering#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poettering#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
2e3c585472540d69a1f4f2023bc5ed67bad8bdb2Susant Sahanistatic BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map timedated_errors[] = {
2e3c585472540d69a1f4f2023bc5ed67bad8bdb2Susant Sahani SD_BUS_ERROR_MAP("org.freedesktop.timedate1.NoNTPSupport", EOPNOTSUPP),
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poetteringtypedef struct Context {
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poettering bus_verify_polkit_async_registry_free(c->polkit_registry);
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poetteringstatic int context_read_data(Context *c) {
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/.");
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering else if (r < 0)
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering log_warning_errno(r, "Failed to get target of /etc/localtime: %m");
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poetteringstatic int context_write_data_timezone(Context *c) {
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poettering if (unlink("/etc/localtime") < 0 && errno != ENOENT)
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poettering p = strappend("../usr/share/zoneinfo/", c->zone);
assert(c);
if (r != -ENOENT)
if (!c->local_rtc)
return -ENOMEM;
size_t a, b;
return -EIO;
return -EIO;
return -EIO;
b = strlen(e);
return -ENOMEM;
return -errno;
assert(c);
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&error,
&reply,
"systemd-timesyncd.service");
c->can_ntp = true;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
NULL,
"systemd-timesyncd.service",
return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported.");
if (enabled)
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
NULL,
"systemd-timesyncd.service",
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
NULL,
"systemd-timesyncd.service",
return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported.");
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
NULL,
NULL);
static int property_get_rtc_time(
const char *path,
const char *interface,
const char *property,
void *userdata,
usec_t t;
if (r == -EBUSY) {
log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp.");
} else if (r == -ENOENT) {
static int property_get_time(
const char *path,
const char *interface,
const char *property,
void *userdata,
static int property_get_ntp_sync(
const char *path,
const char *interface,
const char *property,
void *userdata,
int interactive;
assert(m);
assert(c);
if (!timezone_is_valid(z))
"org.freedesktop.timedate1.set-timezone",
NULL,
&c->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
t = strdup(z);
return -ENOMEM;
c->zone = t;
r = context_write_data_timezone(c);
if (c->local_rtc) {
NULL);
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone", NULL);
assert(m);
assert(c);
"org.freedesktop.timedate1.set-local-rtc",
NULL,
&c->polkit_registry,
error);
r = context_write_data_local_rtc(c);
if (fix_system) {
if (c->local_rtc)
if (c->local_rtc)
if (c->local_rtc)
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "LocalRTC", NULL);
assert(m);
assert(c);
if (c->use_ntp)
return sd_bus_error_setf(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled");
if (relative) {
usec_t n, x;
x = n + utc;
if ((utc > 0 && x < n) ||
(utc < 0 && x > n))
"org.freedesktop.timedate1.set-time",
NULL,
&c->polkit_registry,
error);
if (r < 0 && r != -ENODATA)
if (c->local_rtc)
NULL);
assert(m);
assert(c);
"org.freedesktop.timedate1.set-ntp",
NULL,
&c->polkit_registry,
error);
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("LocalRTC", "b", bus_property_get_bool, offsetof(Context, local_rtc), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("NTP", "b", bus_property_get_bool, offsetof(Context, use_ntp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
assert(c);
r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c);
log_open();
r = -EINVAL;
goto finish;
goto finish;
goto finish;
goto finish;
goto finish;
r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC, NULL, NULL);
goto finish;