]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
rtc: set clock to mtime of driftfile when RTC preinit fails
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 18 Aug 2014 16:21:24 +0000 (18:21 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 19 Aug 2014 08:46:35 +0000 (10:46 +0200)
When the RTC preinit function fails, set the system clock to the time of
the last modification of the driftfile if it's in the future. This makes
the -s option somewhat useful on systems where RTC is not supported or
missing.

This is similar to the functionality implemented in the fake-hwclock
script.

chrony.texi.in
chronyd.8.in
rtc.c

index 2e477bcfd305202ccd89d5ea3f8dbfd9d7082132..a25b2c433d3d0d0a6c757c38ae8c3f84e6b65ab3 100644 (file)
@@ -1018,18 +1018,20 @@ Support for real-time clocks is limited at present - the criteria are
 described in the section on the @code{rtcfile} directive (@pxref{rtcfile
 directive}).
 
-If @code{chronyd} cannot support the real time clock on your computer,
-this option cannot be used and a warning message will be logged to the
-syslog.
-
 If used in conjunction with the `-r' flag, @code{chronyd} will attempt
 to preserve the old samples after setting the system clock from the real
-time clock.  This can be used to allow @code{chronyd} to perform long
+time clock (RTC).  This can be used to allow @code{chronyd} to perform long
 term averaging of the gain or loss rate across system reboots, and is
 useful for dial-up systems that are shut down when not in use.  For this
 to work well, it relies on @code{chronyd} having been able to determine
-accurate statistics for the difference between the real time clock and
+accurate statistics for the difference between the RTC and
 system clock last time the computer was on.
+
+If @code{chronyd} doesn't support the RTC on your computer or there is no RTC
+installed, the system clock will be set with this option to the time of the
+last modification of the drift file (specified by the @code{driftfile}
+directive) to restore the system time at which @code{chronyd} was previously
+stopped.
 @item -u <user>
 This option sets the name of the user to which will @code{chronyd} switch to
 drop root privileges if compiled with Linux capabilities support (default
index 8974d50eaa418c366805b554bdacf67f35f4d88c..4c40c655c34cf5cfb647af7e219aafa2432609ae 100644 (file)
@@ -88,19 +88,20 @@ Support for real-time clocks is limited at present - the criteria
 are described in the section on the \fIrtcfile\fR directive in the
 documentation supplied with the distribution.
 
-If \fBchronyd\fR cannot support the real time clock on your computer,
-this option cannot be used and a warning message will be logged to
-the syslog.
-
 If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt
 to preserve the old samples after setting the system clock from
-the real time clock.  This can be used to allow \fBchronyd\fR to
+the real time clock (RTC).  This can be used to allow \fBchronyd\fR to
 perform long term averaging of the gain or loss rate across system
 reboots, and is useful for dial-up systems that are shut down when
 not in use.  For this to work well, it relies on \fBchronyd\fR having
 been able to determine accurate statistics for the difference
-between the real time clock and system clock last time the
-computer was on.
+between the RTC and system clock last time the computer was on.
+
+If \fBchronyd\fR doesn't support the RTC on your computer or there is no RTC
+installed, the system clock will be set with this option to the time of the
+last modification of the drift file (specified by the \fIdriftfile\fR
+directive) to restore the system time at which \fBchronyd\fR was previously
+stopped.
 .TP
 \fB\-u\fR \fIuser\fR
 This option sets the name of the user to which will \fBchronyd\fR switch to
diff --git a/rtc.c b/rtc.c
index e559813f098b8cf55987ce9d11ac930c12859312..46a607331e4008e657732d5ac6701ac6f5cda99a 100644 (file)
--- a/rtc.c
+++ b/rtc.c
@@ -28,6 +28,7 @@
 #include "sysincl.h"
 
 #include "rtc.h"
+#include "local.h"
 #include "logging.h"
 #include "conf.h"
 
@@ -71,6 +72,33 @@ static struct {
 #endif 
 };
      
+/* ================================================== */
+/* Set the system clock to the time of last modification of driftfile
+   if it's in the future */
+
+static void
+fallback_time_init(void)
+{
+  struct timeval now;
+  struct stat buf;
+  char *drift_file;
+
+  drift_file = CNF_GetDriftFile();
+  if (!drift_file)
+    return;
+
+  if (stat(drift_file, &buf))
+    return;
+
+  LCL_ReadCookedTime(&now, NULL);
+
+  if (now.tv_sec < buf.st_mtime) {
+    LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime);
+    LOG(LOGS_INFO, LOGF_Rtc,
+        "System clock set from driftfile %s", drift_file);
+  }
+}
+
 /* ================================================== */
 
 void
@@ -79,9 +107,13 @@ RTC_Initialise(int initial_set)
   char *file_name;
 
   /* Do an initial read of the RTC and set the system time to it.  This
-     is analogous to what /sbin/hwclock -s would do on Linux. */
-  if (initial_set && driver.time_pre_init) {
-    (driver.time_pre_init)();
+     is analogous to what /sbin/hwclock -s would do on Linux.  If that fails
+     or RTC is not supported, set the clock to the time of the last
+     modification of driftfile, so we at least get closer to the truth. */
+  if (initial_set) {
+    if (!driver.time_pre_init || !driver.time_pre_init()) {
+      fallback_time_init();
+    }
   }
 
   driver_initialised = 0;