]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/timesync/timesyncd.c
treewide: use log_*_errno whenever %m is in the format string
[thirdparty/systemd.git] / src / timesync / timesyncd.c
CommitLineData
bcdbbd7e
KS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
e8af6973 6 Copyright 2014 Kay Sievers, Lennart Poettering
bcdbbd7e
KS
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
bcdbbd7e 22#include "sd-event.h"
687ed123 23#include "sd-daemon.h"
ece6e766 24#include "mkdir.h"
84e51726
LP
25#include "capability.h"
26#include "clock-util.h"
27#include "network-util.h"
d636d376 28
84e51726
LP
29#include "timesyncd-manager.h"
30#include "timesyncd-conf.h"
d636d376
KS
31
32static int load_clock_timestamp(uid_t uid, gid_t gid) {
ece6e766 33 _cleanup_close_ int fd = -1;
d636d376
KS
34 usec_t min = TIME_EPOCH * USEC_PER_SEC;
35 usec_t ct;
36 int r;
ece6e766
LP
37
38 /* Let's try to make sure that the clock is always
39 * monotonically increasing, by saving the clock whenever we
40 * have a new NTP time, or when we shut down, and restoring it
41 * when we start again. This is particularly helpful on
42 * systems lacking a battery backed RTC. We also will adjust
43 * the time to at least the build time of systemd. */
44
d636d376
KS
45 fd = open("/var/lib/systemd/clock", O_RDWR|O_CLOEXEC, 0644);
46 if (fd >= 0) {
ece6e766 47 struct stat st;
d636d376
KS
48 usec_t stamp;
49
50 /* check if the recorded time is later than the compiled-in one */
51 r = fstat(fd, &st);
52 if (r >= 0) {
53 stamp = timespec_load(&st.st_mtim);
54 if (stamp > min)
55 min = stamp;
ece6e766
LP
56 }
57
d636d376
KS
58 /* Try to fix the access mode, so that we can still
59 touch the file after dropping priviliges */
60 fchmod(fd, 0644);
61 fchown(fd, uid, gid);
62
63 } else
64 /* create stamp file with the compiled-in date */
65 touch_file("/var/lib/systemd/clock", true, min, uid, gid, 0644);
ece6e766
LP
66
67 ct = now(CLOCK_REALTIME);
d636d376 68 if (ct < min) {
ece6e766 69 struct timespec ts;
d636d376 70 char date[FORMAT_TIMESTAMP_MAX];
ece6e766 71
d636d376
KS
72 log_info("System clock time unset or jumped backwards, restoring from recorded timestamp: %s",
73 format_timestamp(date, sizeof(date), min));
ece6e766 74
d636d376 75 if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, min)) < 0)
56f64d95 76 log_error_errno(errno, "Failed to restore system clock: %m");
ece6e766
LP
77 }
78
79 return 0;
80}
81
687ed123 82int main(int argc, char *argv[]) {
84e51726 83 _cleanup_(manager_freep) Manager *m = NULL;
cedc8c44 84 const char *user = "systemd-timesync";
ece6e766
LP
85 uid_t uid;
86 gid_t gid;
687ed123
KS
87 int r;
88
89 log_set_target(LOG_TARGET_AUTO);
e8af6973 90 log_set_facility(LOG_CRON);
687ed123
KS
91 log_parse_environment();
92 log_open();
93
e8af6973
LP
94 umask(0022);
95
84e51726
LP
96 if (argc != 1) {
97 log_error("This program does not take arguments.");
98 r = -EINVAL;
99 goto finish;
100 }
101
ece6e766
LP
102 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
103 if (r < 0) {
da927ba9 104 log_error_errno(r, "Cannot resolve user name %s: %m", user);
84e51726 105 goto finish;
ece6e766
LP
106 }
107
d636d376 108 r = load_clock_timestamp(uid, gid);
ece6e766 109 if (r < 0)
84e51726 110 goto finish;
ece6e766 111
966bff26 112 r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
a349eb10 113 if (r < 0)
84e51726 114 goto finish;
a349eb10 115
856a5a7d
LP
116 assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
117
687ed123 118 r = manager_new(&m);
856a5a7d 119 if (r < 0) {
da927ba9 120 log_error_errno(r, "Failed to allocate manager: %m");
84e51726 121 goto finish;
856a5a7d 122 }
687ed123 123
c264aeab
KS
124 if (clock_is_localtime() > 0) {
125 log_info("The system is configured to read the RTC time in the local time zone. "
126 "This mode can not be fully supported. All system time to RTC updates are disabled.");
127 m->rtc_local_time = true;
128 }
129
84e51726
LP
130 r = manager_parse_config_file(m);
131 if (r < 0)
da927ba9 132 log_warning_errno(r, "Failed to parse configuration file: %m");
e0e5ce23 133
e8af6973 134 log_debug("systemd-timesyncd running as pid %lu", (unsigned long) getpid());
af4ec430
LP
135 sd_notify(false,
136 "READY=1\n"
137 "STATUS=Daemon is running");
39594d49 138
e0e5ce23
TG
139 if (network_is_online()) {
140 r = manager_connect(m);
141 if (r < 0)
84e51726 142 goto finish;
e0e5ce23 143 }
678522cf 144
687ed123 145 r = sd_event_loop(m->event);
856a5a7d 146 if (r < 0) {
da927ba9 147 log_error_errno(r, "Failed to run event loop: %m");
84e51726 148 goto finish;
856a5a7d
LP
149 }
150
d636d376
KS
151 /* if we got an authoritative time, store it in the file system */
152 if (m->sync)
153 touch("/var/lib/systemd/clock");
687ed123 154
84e51726
LP
155 sd_event_get_exit_code(m->event, &r);
156
157finish:
af4ec430
LP
158 sd_notify(false,
159 "STOPPING=1\n"
160 "STATUS=Shutting down...");
e8af6973 161
687ed123 162 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
bcdbbd7e 163}