chiark / gitweb /
Fix a few typos in log messages
[elogind.git] / src / timesync / timesyncd.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2014 Kay Sievers, Lennart Poettering
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
22 #include "sd-event.h"
23 #include "sd-daemon.h"
24 #include "mkdir.h"
25 #include "capability.h"
26 #include "clock-util.h"
27 #include "network-util.h"
28
29 #include "timesyncd-manager.h"
30 #include "timesyncd-conf.h"
31
32 static int load_clock_timestamp(uid_t uid, gid_t gid) {
33         _cleanup_close_ int fd = -1;
34         usec_t min = TIME_EPOCH * USEC_PER_SEC;
35         usec_t ct;
36         int r;
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
45         fd = open("/var/lib/systemd/clock", O_RDWR|O_CLOEXEC, 0644);
46         if (fd >= 0) {
47                 struct stat st;
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;
56                 }
57
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);
66
67         ct = now(CLOCK_REALTIME);
68         if (ct < min) {
69                 struct timespec ts;
70                 char date[FORMAT_TIMESTAMP_MAX];
71
72                 log_info("System clock time unset or jumped backwards, restoring from recorded timestamp: %s",
73                          format_timestamp(date, sizeof(date), min));
74
75                 if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, min)) < 0)
76                         log_error("Failed to restore system clock: %m");
77         }
78
79         return 0;
80 }
81
82 int main(int argc, char *argv[]) {
83         _cleanup_(manager_freep) Manager *m = NULL;
84         const char *user = "systemd-timesync";
85         uid_t uid;
86         gid_t gid;
87         int r;
88
89         log_set_target(LOG_TARGET_AUTO);
90         log_set_facility(LOG_CRON);
91         log_parse_environment();
92         log_open();
93
94         umask(0022);
95
96         if (argc != 1) {
97                 log_error("This program does not take arguments.");
98                 r = -EINVAL;
99                 goto finish;
100         }
101
102         r = get_user_creds(&user, &uid, &gid, NULL, NULL);
103         if (r < 0) {
104                 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
105                 goto finish;
106         }
107
108         r = load_clock_timestamp(uid, gid);
109         if (r < 0)
110                 goto finish;
111
112         r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
113         if (r < 0)
114                 goto finish;
115
116         assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
117
118         r = manager_new(&m);
119         if (r < 0) {
120                 log_error("Failed to allocate manager: %s", strerror(-r));
121                 goto finish;
122         }
123
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
130         r = manager_parse_config_file(m);
131         if (r < 0)
132                 log_warning("Failed to parse configuration file: %s", strerror(-r));
133
134         log_debug("systemd-timesyncd running as pid %lu", (unsigned long) getpid());
135         sd_notify(false,
136                   "READY=1\n"
137                   "STATUS=Daemon is running");
138
139         if (network_is_online()) {
140                 r = manager_connect(m);
141                 if (r < 0)
142                         goto finish;
143         }
144
145         r = sd_event_loop(m->event);
146         if (r < 0) {
147                 log_error("Failed to run event loop: %s", strerror(-r));
148                 goto finish;
149         }
150
151         /* if we got an authoritative time, store it in the file system */
152         if (m->sync)
153                 touch("/var/lib/systemd/clock");
154
155         sd_event_get_exit_code(m->event, &r);
156
157 finish:
158         sd_notify(false,
159                   "STOPPING=1\n"
160                   "STATUS=Shutting down...");
161
162         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
163 }