]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/timesync/timesyncd.c
src/basic: rename audit.[ch] → audit-util.[ch] and capability.[ch] → capability-util...
[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
687ed123 22#include "sd-daemon.h"
3ffd4af2
LP
23#include "sd-event.h"
24
430f0182 25#include "capability-util.h"
84e51726 26#include "clock-util.h"
3ffd4af2 27#include "fd-util.h"
f4f15635 28#include "fs-util.h"
84e51726 29#include "network-util.h"
24882e06 30#include "signal-util.h"
84e51726 31#include "timesyncd-conf.h"
3ffd4af2 32#include "timesyncd-manager.h"
b1d4f8e1 33#include "user-util.h"
d636d376
KS
34
35static int load_clock_timestamp(uid_t uid, gid_t gid) {
ece6e766 36 _cleanup_close_ int fd = -1;
d636d376
KS
37 usec_t min = TIME_EPOCH * USEC_PER_SEC;
38 usec_t ct;
39 int r;
ece6e766
LP
40
41 /* Let's try to make sure that the clock is always
42 * monotonically increasing, by saving the clock whenever we
43 * have a new NTP time, or when we shut down, and restoring it
44 * when we start again. This is particularly helpful on
45 * systems lacking a battery backed RTC. We also will adjust
46 * the time to at least the build time of systemd. */
47
d636d376
KS
48 fd = open("/var/lib/systemd/clock", O_RDWR|O_CLOEXEC, 0644);
49 if (fd >= 0) {
ece6e766 50 struct stat st;
d636d376
KS
51 usec_t stamp;
52
53 /* check if the recorded time is later than the compiled-in one */
54 r = fstat(fd, &st);
55 if (r >= 0) {
56 stamp = timespec_load(&st.st_mtim);
57 if (stamp > min)
58 min = stamp;
ece6e766
LP
59 }
60
d636d376
KS
61 /* Try to fix the access mode, so that we can still
62 touch the file after dropping priviliges */
ac5b0c13
LP
63 (void) fchmod(fd, 0644);
64 (void) fchown(fd, uid, gid);
d636d376
KS
65
66 } else
67 /* create stamp file with the compiled-in date */
ac5b0c13 68 (void) touch_file("/var/lib/systemd/clock", true, min, uid, gid, 0644);
ece6e766
LP
69
70 ct = now(CLOCK_REALTIME);
d636d376 71 if (ct < min) {
ece6e766 72 struct timespec ts;
d636d376 73 char date[FORMAT_TIMESTAMP_MAX];
ece6e766 74
d636d376
KS
75 log_info("System clock time unset or jumped backwards, restoring from recorded timestamp: %s",
76 format_timestamp(date, sizeof(date), min));
ece6e766 77
d636d376 78 if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, min)) < 0)
56f64d95 79 log_error_errno(errno, "Failed to restore system clock: %m");
ece6e766
LP
80 }
81
82 return 0;
83}
84
687ed123 85int main(int argc, char *argv[]) {
84e51726 86 _cleanup_(manager_freep) Manager *m = NULL;
cedc8c44 87 const char *user = "systemd-timesync";
ece6e766
LP
88 uid_t uid;
89 gid_t gid;
687ed123
KS
90 int r;
91
92 log_set_target(LOG_TARGET_AUTO);
e8af6973 93 log_set_facility(LOG_CRON);
687ed123
KS
94 log_parse_environment();
95 log_open();
96
e8af6973
LP
97 umask(0022);
98
84e51726
LP
99 if (argc != 1) {
100 log_error("This program does not take arguments.");
101 r = -EINVAL;
102 goto finish;
103 }
104
ece6e766
LP
105 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
106 if (r < 0) {
da927ba9 107 log_error_errno(r, "Cannot resolve user name %s: %m", user);
84e51726 108 goto finish;
ece6e766
LP
109 }
110
d636d376 111 r = load_clock_timestamp(uid, gid);
ece6e766 112 if (r < 0)
84e51726 113 goto finish;
ece6e766 114
966bff26 115 r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
a349eb10 116 if (r < 0)
84e51726 117 goto finish;
a349eb10 118
72c0a2c2 119 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
856a5a7d 120
687ed123 121 r = manager_new(&m);
856a5a7d 122 if (r < 0) {
da927ba9 123 log_error_errno(r, "Failed to allocate manager: %m");
84e51726 124 goto finish;
856a5a7d 125 }
687ed123 126
c264aeab
KS
127 if (clock_is_localtime() > 0) {
128 log_info("The system is configured to read the RTC time in the local time zone. "
129 "This mode can not be fully supported. All system time to RTC updates are disabled.");
130 m->rtc_local_time = true;
131 }
132
84e51726
LP
133 r = manager_parse_config_file(m);
134 if (r < 0)
da927ba9 135 log_warning_errno(r, "Failed to parse configuration file: %m");
e0e5ce23 136
aa36007c 137 log_debug("systemd-timesyncd running as pid " PID_FMT, getpid());
af4ec430
LP
138 sd_notify(false,
139 "READY=1\n"
140 "STATUS=Daemon is running");
39594d49 141
e0e5ce23
TG
142 if (network_is_online()) {
143 r = manager_connect(m);
144 if (r < 0)
84e51726 145 goto finish;
e0e5ce23 146 }
678522cf 147
687ed123 148 r = sd_event_loop(m->event);
856a5a7d 149 if (r < 0) {
da927ba9 150 log_error_errno(r, "Failed to run event loop: %m");
84e51726 151 goto finish;
856a5a7d
LP
152 }
153
d636d376
KS
154 /* if we got an authoritative time, store it in the file system */
155 if (m->sync)
ac5b0c13 156 (void) touch("/var/lib/systemd/clock");
687ed123 157
84e51726
LP
158 sd_event_get_exit_code(m->event, &r);
159
160finish:
af4ec430
LP
161 sd_notify(false,
162 "STOPPING=1\n"
163 "STATUS=Shutting down...");
e8af6973 164
687ed123 165 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
bcdbbd7e 166}