timedated.c revision 7fd1b19bc9e9f5574f2877936b8ac267c7706947
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/***
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann This file is part of systemd.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Copyright 2011 Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann systemd is free software; you can redistribute it and/or modify it
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann under the terms of the GNU Lesser General Public License as published by
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann the Free Software Foundation; either version 2.1 of the License, or
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann (at your option) any later version.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann systemd is distributed in the hope that it will be useful, but
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann WITHOUT ANY WARRANTY; without even the implied warranty of
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Lesser General Public License for more details.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann You should have received a copy of the GNU Lesser General Public License
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann along with systemd; If not, see <http://www.gnu.org/licenses/>.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann***/
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include <dbus/dbus.h>
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include <errno.h>
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include <string.h>
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include <unistd.h>
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "systemd/sd-id128.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "systemd/sd-messages.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "util.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "strv.h"
0a6f50c0afdfc434b492493bd9efab20cbee8623Thomas Hindoe Paaboel Andersen#include "dbus-common.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "polkit.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "def.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "hwclock.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "conf-files.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "path-util.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "fileio-label.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "label.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define INTERFACE \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <interface name=\"org.freedesktop.timedate1\">\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <property name=\"Timezone\" type=\"s\" access=\"read\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <property name=\"LocalRTC\" type=\"b\" access=\"read\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <property name=\"CanNTP\" type=\"b\" access=\"read\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <property name=\"NTP\" type=\"b\" access=\"read\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <method name=\"SetTime\">\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"usec_utc\" type=\"x\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"relative\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " </method>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <method name=\"SetTimezone\">\n" \
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering " <arg name=\"timezone\" type=\"s\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " </method>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <method name=\"SetLocalRTC\">\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"local_rtc\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"fix_system\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " </method>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <method name=\"SetNTP\">\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"use_ntp\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann " </method>\n" \
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering " </interface>\n"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define INTROSPECTION \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "<node>\n" \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann INTERFACE \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann BUS_PROPERTIES_INTERFACE \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann BUS_INTROSPECTABLE_INTERFACE \
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann BUS_PEER_INTERFACE \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "</node>\n"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define INTERFACES_LIST \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann BUS_GENERIC_INTERFACES_LIST \
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.timedate1\0"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannconst char timedate_interface[] _introspect_("timedate1") = INTERFACE;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmanntypedef struct TZ {
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann char *zone;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann bool local_rtc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int can_ntp;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann int use_ntp;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann} TZ;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic TZ tz = {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .zone = NULL,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .local_rtc = false,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .can_ntp = -1,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .use_ntp = -1,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann};
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic usec_t remain_until;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic void free_data(void) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(tz.zone);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.zone = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.local_rtc = false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic bool valid_timezone(const char *name) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *p;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char *t;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann bool slash = false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct stat st;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (*name == '/' || *name == 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (p = name; *p; p++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!(*p >= '0' && *p <= '9') &&
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann !(*p >= 'a' && *p <= 'z') &&
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann !(*p >= 'A' && *p <= 'Z') &&
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann !(*p == '-' || *p == '_' || *p == '+' || *p == '/'))
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering return false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (*p == '/') {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (slash)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann slash = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann } else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann slash = false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann if (slash)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann t = strappend("/usr/share/zoneinfo/", name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!t)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = stat(t, &st);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(t);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!S_ISREG(st.st_mode))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int read_data(void) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ char *t = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free_data();
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = readlink_malloc("/etc/localtime", &t);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (r == -EINVAL)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_warning("/etc/localtime should be a symbolic link to a timezone data file in /usr/share/zoneinfo/.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_warning("Failed to get target of /etc/localtime: %s", strerror(-r));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann } else {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *e;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann e = path_startswith(t, "/usr/share/zoneinfo/");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!e)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann e = path_startswith(t, "../usr/share/zoneinfo/");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!e)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_warning("/etc/localtime should be a symbolic link to a timezone data file in /usr/share/zoneinfo/.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.zone = strdup(e);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!tz.zone)
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering return log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto have_timezone;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannhave_timezone:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (isempty(tz.zone)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(tz.zone);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.zone = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.local_rtc = hwclock_is_localtime() > 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int write_data_timezone(void) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ char *p = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!tz.zone) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (unlink("/etc/localtime") < 0 && errno != ENOENT)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -errno;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p = strappend("../usr/share/zoneinfo/", tz.zone);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!p)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = symlink_atomic(p, "/etc/localtime");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int write_data_local_rtc(void) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ char *s = NULL, *w = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = read_full_file("/etc/adjtime", &s, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r != -ENOENT)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!tz.local_rtc)
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann w = strdup(NULL_ADJTIME_LOCAL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!w)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann } else {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char *p, *e;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann size_t a, b;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p = strchr(s, '\n');
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!p)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -EIO;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p = strchr(p+1, '\n');
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!p)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -EIO;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p++;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann e = strchr(p, '\n');
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!e)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -EIO;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering a = p - s;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b = strlen(e);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann w = new(char, a + (tz.local_rtc ? 5 : 3) + b + 1);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!w)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann *(char*) mempcpy(stpcpy(mempcpy(w, s, a), tz.local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (streq(w, NULL_ADJTIME_UTC)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (unlink("/etc/adjtime") < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (errno != ENOENT)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -errno;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann label_init("/etc");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return write_string_file_atomic_label("/etc/adjtime", w);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann}
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmannstatic char** get_ntp_services(void) {
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann _cleanup_strv_free_ char **r = NULL, **files;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann char **i;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann int k;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann k = conf_files_list(&files, ".list", NULL,
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann "/etc/systemd/ntp-units.d",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/run/systemd/ntp-units.d",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/usr/local/lib/systemd/ntp-units.d",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/usr/lib/systemd/ntp-units.d",
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (k < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann STRV_FOREACH(i, files) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_fclose_ FILE *f;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann f = fopen(*i, "re");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!f)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (;;) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char line[PATH_MAX], *l;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!fgets(line, sizeof(line), f)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (ferror(f))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Failed to read NTP units file: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann break;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann l = strstrip(line);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (l[0] == 0 || l[0] == '#')
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (strv_extend(&r, l) < 0) {
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann log_oom();
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return NULL;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann i = r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = NULL; /* avoid cleanup */
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return strv_uniq(i);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmannstatic int read_ntp(DBusConnection *bus) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusMessage *m = NULL, *reply = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusError error;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char **i, **l;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann assert(bus);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_error_init(&error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann l = get_ntp_services();
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering STRV_FOREACH(i, l) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering const char *s;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann m = dbus_message_new_method_call(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.systemd1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/org/freedesktop/systemd1",
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering "org.freedesktop.systemd1.Manager",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "GetUnitFileState");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!m) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = log_oom();
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering goto finish;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering }
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_append_args(m,
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering DBUS_TYPE_STRING, i,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_INVALID)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!reply) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (streq(error.name, "org.freedesktop.DBus.Error.FileNotFound")) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* This implementation does not exist, try next one */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_error_free(&error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering }
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Failed to issue method call: %s", bus_error_message(&error));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -EIO;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_get_args(reply, &error,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_STRING, &s,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_INVALID)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Failed to parse reply: %s", bus_error_message(&error));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -EIO;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.can_ntp = 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.use_ntp =
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann streq(s, "enabled") ||
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann streq(s, "enabled-runtime");
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* NTP is not installed. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.can_ntp = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.use_ntp = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannfinish:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (reply)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(reply);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann strv_free(l);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_error_free(&error);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int start_ntp(DBusConnection *bus, DBusError *error) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusMessage *m = NULL, *reply = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *mode = "replace";
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char **i, **l;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(bus);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann l = get_ntp_services();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann STRV_FOREACH(i, l) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann m = dbus_message_new_method_call(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.systemd1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/org/freedesktop/systemd1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.systemd1.Manager",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.use_ntp ? "StartUnit" : "StopUnit");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!m) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Could not allocate message.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_append_args(m,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_STRING, i,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_STRING, &mode,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_INVALID)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Could not append arguments to message.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
1140e154100f7224fb8bab55ba7fc087409f9d76Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann if (!reply) {
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann if (streq(error->name, "org.freedesktop.DBus.Error.FileNotFound") ||
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann streq(error->name, "org.freedesktop.systemd1.LoadFailed") ||
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann streq(error->name, "org.freedesktop.systemd1.NoSuchUnit")) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* This implementation does not exist, try next one */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_error_free(error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Failed to issue method call: %s", bus_error_message(error));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -EIO;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann /* No implementaiton available... */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -ENOENT;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannfinish:
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (m)
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann dbus_message_unref(m);
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (reply)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(reply);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann strv_free(l);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int enable_ntp(DBusConnection *bus, DBusError *error) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusMessage *m = NULL, *reply = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusMessageIter iter;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t f = FALSE, t = TRUE;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char **i, **l;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann assert(bus);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann l = get_ntp_services();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann STRV_FOREACH(i, l) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char* k[2];
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann m = dbus_message_new_method_call(
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann "org.freedesktop.systemd1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/org/freedesktop/systemd1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.systemd1.Manager",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.use_ntp ? "EnableUnitFiles" : "DisableUnitFiles");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!m) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Could not allocate message.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
1140e154100f7224fb8bab55ba7fc087409f9d76Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_iter_init_append(m, &iter);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann k[0] = *i;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann k[1] = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = bus_append_strv_iter(&iter, k);
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (r < 0) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann log_error("Failed to append unit files.");
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann goto finish;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann }
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann /* send runtime bool */
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &f)) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann log_error("Failed to append runtime boolean.");
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann r = -ENOMEM;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann goto finish;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann }
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (tz.use_ntp) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann /* send force bool */
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &t)) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann log_error("Failed to append force boolean.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!reply) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (streq(error->name, "org.freedesktop.DBus.Error.FileNotFound")) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* This implementation does not exist, try next one */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_error_free(error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann log_error("Failed to issue method call: %s", bus_error_message(error));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -EIO;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann m = dbus_message_new_method_call(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.systemd1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/org/freedesktop/systemd1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.systemd1.Manager",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "Reload");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!m) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Could not allocate message.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto finish;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann }
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann dbus_message_unref(reply);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (!reply) {
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann log_error("Failed to issue method call: %s", bus_error_message(error));
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann r = -EIO;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann goto finish;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann }
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann r = 0;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann goto finish;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = -ENOENT;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannfinish:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (reply)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_message_unref(reply);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann strv_free(l);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int property_append_can_ntp(DBusMessageIter *i, const char *property, void *data) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t db;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(i);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(property);
61adca52f6f0b119e501c523008a454887cdf2b9Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann db = tz.can_ntp > 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
61adca52f6f0b119e501c523008a454887cdf2b9Lennart Poettering return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int property_append_ntp(DBusMessageIter *i, const char *property, void *data) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t db;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(i);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(property);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering db = tz.use_ntp > 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic const BusProperty bus_timedate_properties[] = {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { "Timezone", bus_property_append_string, "s", offsetof(TZ, zone), true },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { "LocalRTC", bus_property_append_bool, "b", offsetof(TZ, local_rtc) },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { "CanNTP", property_append_can_ntp, "b", offsetof(TZ, can_ntp) },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { "NTP", property_append_ntp, "b", offsetof(TZ, use_ntp) },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { NULL, }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann};
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic const BusBoundProperties bps[] = {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { "org.freedesktop.timedate1", bus_timedate_properties, &tz },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { NULL, }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann};
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic DBusHandlerResult timedate_message_handler(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusConnection *connection,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusMessage *message,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann void *userdata) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering DBusMessage *reply = NULL, *changed = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBusError error;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(connection);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(message);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_error_init(&error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetTimezone")) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *z;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t interactive;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_get_args(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann message,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann &error,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_STRING, &z,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_BOOLEAN, &interactive,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_INVALID))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, &error, -EINVAL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!valid_timezone(z))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, NULL, -EINVAL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!streq_ptr(z, tz.zone)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char *t;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-timezone", interactive, NULL, &error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, &error, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann t = strdup(z);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!t)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto oom;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(tz.zone);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.zone = t;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* 1. Write new configuration file */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = write_data_timezone();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Failed to set timezone: %s", strerror(-r));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, NULL, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* 2. Tell the kernel our time zone */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann hwclock_set_timezone(NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (tz.local_rtc) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering struct timespec ts;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct tm *tm;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* 3. Sync RTC from system clock, with the new delta */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert_se(tm = localtime(&ts.tv_sec));
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering hwclock_set_time(tm);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_struct(LOG_INFO,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann MESSAGE_ID(SD_MESSAGE_TIMEZONE_CHANGE),
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "TIMEZONE=%s", tz.zone,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "MESSAGE=Changed timezone to '%s'.", tz.zone,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann changed = bus_properties_changed_new(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/org/freedesktop/timedate1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.timedate1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "Timezone\0");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!changed)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto oom;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering } else if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetLocalRTC")) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t lrtc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t fix_system;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t interactive;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_get_args(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann message,
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering &error,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_BOOLEAN, &lrtc,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_BOOLEAN, &fix_system,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_BOOLEAN, &interactive,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_INVALID))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, &error, -EINVAL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (lrtc != tz.local_rtc) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct timespec ts;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-local-rtc", interactive, NULL, &error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, &error, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tz.local_rtc = lrtc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* 1. Write new configuration file */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = write_data_local_rtc();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Failed to set RTC to local/UTC: %s", strerror(-r));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, NULL, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* 2. Tell the kernel our time zone */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann hwclock_set_timezone(NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* 3. Synchronize clocks */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (fix_system) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct tm tm;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Sync system clock from RTC; first,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * initialize the timezone fields of
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * struct tm. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (tz.local_rtc)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tm = *localtime(&ts.tv_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tm = *gmtime(&ts.tv_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Override the main fields of
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * struct tm, but not the timezone
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * fields */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (hwclock_get_time(&tm) >= 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* And set the system clock
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * with this */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (tz.local_rtc)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann ts.tv_sec = mktime(&tm);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann ts.tv_sec = timegm(&tm);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann clock_settime(CLOCK_REALTIME, &ts);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann } else {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct tm *tm;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Sync RTC from system clock */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (tz.local_rtc)
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering tm = localtime(&ts.tv_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tm = gmtime(&ts.tv_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann hwclock_set_time(tm);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_info("RTC configured to %s time.", tz.local_rtc ? "local" : "UTC");
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann changed = bus_properties_changed_new(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/org/freedesktop/timedate1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.timedate1",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "LocalRTC\0");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!changed)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto oom;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann } else if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetTime")) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int64_t utc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t relative;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dbus_bool_t interactive;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!dbus_message_get_args(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann message,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann &error,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_INT64, &utc,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_BOOLEAN, &relative,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_BOOLEAN, &interactive,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DBUS_TYPE_INVALID))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, &error, -EINVAL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!relative && utc <= 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, NULL, -EINVAL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!relative || utc != 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct timespec ts;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct tm* tm;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (relative) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann usec_t n, x;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = now(CLOCK_REALTIME);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann x = n + utc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if ((utc > 0 && x < n) ||
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann (utc < 0 && x > n))
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering return bus_send_error_reply(connection, message, NULL, -EOVERFLOW);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann timespec_store(&ts, x);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann } else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann timespec_store(&ts, (usec_t) utc);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-time", interactive, NULL, &error);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, &error, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering /* Set system clock */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (clock_settime(CLOCK_REALTIME, &ts) < 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_error("Failed to set local time: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return bus_send_error_reply(connection, message, NULL, -errno);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Sync down to RTC */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (tz.local_rtc)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tm = localtime(&ts.tv_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann tm = gmtime(&ts.tv_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann hwclock_set_time(tm);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_struct(LOG_INFO,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "REALTIME=%llu", (unsigned long long) timespec_load(&ts),
"MESSAGE=Changed local time to %s", ctime(&ts.tv_sec),
NULL);
}
} else if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetNTP")) {
dbus_bool_t ntp;
dbus_bool_t interactive;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_BOOLEAN, &ntp,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
if (ntp != !!tz.use_ntp) {
r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-ntp", interactive, NULL, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
tz.use_ntp = !!ntp;
r = enable_ntp(connection, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
r = start_ntp(connection, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
log_info("Set NTP to %s", tz.use_ntp ? "enabled" : "disabled");
changed = bus_properties_changed_new(
"/org/freedesktop/timedate1",
"org.freedesktop.timedate1",
"NTP\0");
if (!changed)
goto oom;
}
} else
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
if (!bus_maybe_send_reply(connection, message, reply))
goto oom;
dbus_message_unref(reply);
reply = NULL;
if (changed) {
if (!dbus_connection_send(connection, changed, NULL))
goto oom;
dbus_message_unref(changed);
}
return DBUS_HANDLER_RESULT_HANDLED;
oom:
if (reply)
dbus_message_unref(reply);
if (changed)
dbus_message_unref(changed);
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
static int connect_bus(DBusConnection **_bus) {
static const DBusObjectPathVTable timedate_vtable = {
.message_function = timedate_message_handler
};
DBusError error;
DBusConnection *bus = NULL;
int r;
assert(_bus);
dbus_error_init(&error);
bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
if (!bus) {
log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
r = -ECONNREFUSED;
goto fail2;
}
dbus_connection_set_exit_on_disconnect(bus, FALSE);
if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL) ||
!dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
r = log_oom();
goto fail;
}
r = dbus_bus_request_name(bus, "org.freedesktop.timedate1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
if (dbus_error_is_set(&error)) {
log_error("Failed to register name on bus: %s", bus_error_message(&error));
r = -EEXIST;
goto fail;
}
if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
log_error("Failed to acquire name.");
r = -EEXIST;
goto fail;
}
if (_bus)
*_bus = bus;
return 0;
fail:
dbus_connection_close(bus);
dbus_connection_unref(bus);
fail2:
dbus_error_free(&error);
return r;
}
int main(int argc, char *argv[]) {
int r;
DBusConnection *bus = NULL;
bool exiting = false;
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
umask(0022);
if (argc == 2 && streq(argv[1], "--introspect")) {
fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
"<node>\n", stdout);
fputs(timedate_interface, stdout);
fputs("</node>\n", stdout);
return 0;
}
if (argc != 1) {
log_error("This program takes no arguments.");
r = -EINVAL;
goto finish;
}
r = read_data();
if (r < 0) {
log_error("Failed to read timezone data: %s", strerror(-r));
goto finish;
}
r = connect_bus(&bus);
if (r < 0)
goto finish;
r = read_ntp(bus);
if (r < 0) {
log_error("Failed to determine whether NTP is enabled: %s", strerror(-r));
goto finish;
}
remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
for (;;) {
if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
break;
if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
exiting = true;
bus_async_unregister_and_exit(bus, "org.freedesktop.timedated1");
}
}
r = 0;
finish:
free_data();
if (bus) {
dbus_connection_flush(bus);
dbus_connection_close(bus);
dbus_connection_unref(bus);
}
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}