diff --git a/chrony.texi.in b/chrony.texi.in index 2e477bc..a25b2c4 100644 --- a/chrony.texi.in +++ b/chrony.texi.in @@ -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 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 diff --git a/chronyd.8.in b/chronyd.8.in index 8974d50..4c40c65 100644 --- a/chronyd.8.in +++ b/chronyd.8.in @@ -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 e559813..46a6073 100644 --- 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;