static Boolean setTime (ClockDriver *self, TimeInternal *time, Boolean force) { GET_CONFIG_CLOCKDRIVER(self, myConfig, unix); TimeInternal oldTime, delta; getTime(self, &oldTime); subTime(&delta, &oldTime, time); if(self->config.readOnly) { return FALSE; } if(force) { self->lockedUp = FALSE; } if(!force && !self->config.negativeStep && isTimeNegative(&delta)) { CRITICAL(THIS_COMPONENT"Cannot step Unix clock %s backwards\n", self->name); CRITICAL(THIS_COMPONENT"Manual intervention required or SIGUSR1 to force %s clock step\n", self->name); self->lockedUp = TRUE; self->setState(self, CS_NEGSTEP); return FALSE; } #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) struct timespec tp; tp.tv_sec = time->seconds; tp.tv_nsec = time->nanoseconds; if(tp.tv_sec == 0) { ERROR(THIS_COMPONENT"Unix clock driver %s: cannot set time to zero seconds\n", self->name); return FALSE; } if(tp.tv_sec <= 0) { ERROR(THIS_COMPONENT"Unic clock driver %s: cannot set time to a negative value %d\n", self->name, tp.tv_sec); return FALSE; } #else struct timeval tv; tv.tv_sec = time->seconds; tv.tv_usec = time->nanoseconds / 1000; if(tv.tv_sec == 0) { ERROR(THIS_COMPONENT"Unix clock %s: cannot set time to zero seconds\n", self->name); return FALSE; } if(tv.tv_sec < 0) { ERROR(THIS_COMPONENT"Unic clock %s: cannot set time to a negative value %d\n", self->name, tv.tv_sec); return FALSE; } #endif /* _POSIX_TIMERS */ #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) if (clock_settime(CLOCK_REALTIME, &tp) < 0) { PERROR(THIS_COMPONENT"Could not set system time"); return FALSE; } addTime(&_stepAccumulator, &_stepAccumulator, &delta); #else settimeofday(&tv, 0); addTime(&_stepAccumulator, &_stepAccumulator, &delta); #endif /* _POSIX_TIMERS */ if(oldTime.seconds != time->seconds) { updateXtmp_unix(oldTime, *time); if(myConfig->setRtc) { setRtc(self, time); } } self->_stepped = TRUE; struct timespec tmpTs = { time->seconds,0 }; char timeStr[MAXTIMESTR]; strftime(timeStr, MAXTIMESTR, "%x %X", localtime(&tmpTs.tv_sec)); NOTICE(THIS_COMPONENT"Unix clock %s: stepped the system clock to: %s.%d\n", self->name, timeStr, time->nanoseconds); self->setState(self, CS_FREERUN); return TRUE; }
static Boolean stepTime (ClockDriver *self, TimeInternal *delta, Boolean force) { GET_CONFIG_CLOCKDRIVER(self, myConfig, unix); if(isTimeZero(delta)) { return TRUE; } struct timespec nts; TimeInternal oldTime,newTime; getTime(self, &oldTime); addTime(&newTime, &oldTime, delta); if(self->config.readOnly) { return FALSE; } if(force) { self->lockedUp = FALSE; } if(!force && !self->config.negativeStep && isTimeNegative(delta)) { CRITICAL(THIS_COMPONENT"Cannot step Unix clock %s backwards\n", self->name); CRITICAL(THIS_COMPONENT"Manual intervention required or SIGUSR1 to force %s clock step\n", self->name); self->lockedUp = TRUE; self->setState(self, CS_NEGSTEP); return FALSE; } #ifdef ADJ_SETOFFSET struct timex tmx; memset(&tmx, 0, sizeof(tmx)); tmx.modes = ADJ_SETOFFSET | ADJ_NANO; tmx.time.tv_sec = delta->seconds; tmx.time.tv_usec = delta->nanoseconds; getTime(self, &newTime); addTime(&newTime, &newTime, delta); nts.tv_sec = newTime.seconds; if(nts.tv_sec == 0) { ERROR(THIS_COMPONENT"Unix clock %s: cannot step time to zero seconds\n", self->name); return FALSE; } if(nts.tv_sec < 0) { ERROR(THIS_COMPONENT"Unix clock %s: cannot step time to a negative value %d\n", self->name, nts.tv_sec); return FALSE; } if(adjtimex(&tmx) < 0) { DBG("Could not set clock offset of Unix clock %s\n", self->name); return setTime(self, &newTime, force); } NOTICE(THIS_COMPONENT"Unix clock %s: stepped clock by %s%d.%09d seconds\n", self->name, (delta->seconds <0 || delta->nanoseconds <0) ? "-":"", delta->seconds, delta->nanoseconds); addTime(&_stepAccumulator, &_stepAccumulator, delta); self->_stepped = TRUE; self->setState(self, CS_FREERUN); if(oldTime.seconds != newTime.seconds) { updateXtmp_unix(oldTime, newTime); if(myConfig->setRtc) { setRtc(self, &newTime); } } return TRUE; #else return setTime(self, &newTime, force); #endif }
void servo_perform_clock_step(RunTimeOpts * rtOpts, PtpClock * ptpClock) { if(rtOpts->noAdjust){ WARNING("Could not step clock - clock adjustment disabled\n"); return; } TimeInternal oldTime, newTime; /*No need to reset the frequency offset: if we're far off, it will quickly get back to a high value */ getTime(&oldTime); subTime(&newTime, &oldTime, &ptpClock->offsetFromMaster); setTime(&newTime); #ifdef HAVE_LINUX_RTC_H if(rtOpts->setRtc) { setRtc(&newTime); } #endif /* HAVE_LINUX_RTC_H */ initClock(rtOpts, ptpClock); #ifdef HAVE_SYS_TIMEX_H if(ptpClock->clockQuality.clockClass > 127) restoreDrift(ptpClock, rtOpts, TRUE); #endif /* HAVE_SYS_TIMEX_H */ ptpClock->servo.runningMaxOutput = FALSE; toState(PTP_FAULTY, rtOpts, ptpClock); /* make a full protocol reset */ /* Major time change - need to inform utmp / wtmp */ if(oldTime.seconds != newTime.seconds) { /* Add the old time entry to utmp/wtmp */ /* About as long as the ntpd implementation, but not any less ugly */ #ifdef HAVE_UTMPX_H struct utmpx utx; memset(&utx, 0, sizeof(utx)); strncpy(utx.ut_user, "date", sizeof(utx.ut_user)); #ifndef OTIME_MSG strncpy(utx.ut_line, "|", sizeof(utx.ut_line)); #else strncpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); #endif /* OTIME_MSG */ #ifdef OLD_TIME utx.ut_tv.tv_sec = oldTime.seconds; utx.ut_tv.tv_usec = oldTime.nanoseconds / 1000; utx.ut_type = OLD_TIME; #else /* no ut_type */ utx.ut_time = oldTime.seconds; #endif /* OLD_TIME */ /* ======== BEGIN OLD TIME EVENT - UTMPX / WTMPX =========== */ #ifdef HAVE_UTMPXNAME utmpxname("/var/log/utmp"); #endif /* HAVE_UTMPXNAME */ setutxent(); pututxline(&utx); endutxent(); #ifdef HAVE_UPDWTMPX updwtmpx("/var/log/wtmp", &utx); #endif /* HAVE_IPDWTMPX */ /* ======== END OLD TIME EVENT - UTMPX / WTMPX =========== */ #else /* NO UTMPX_H */ #ifdef HAVE_UTMP_H struct utmp ut; memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_name, "date", sizeof(ut.ut_name)); #ifndef OTIME_MSG strncpy(ut.ut_line, "|", sizeof(ut.ut_line)); #else strncpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); #endif /* OTIME_MSG */ #ifdef OLD_TIME ut.ut_tv.tv_sec = oldTime.seconds; ut.ut_tv.tv_usec = oldTime.nanoseconds / 1000; ut.ut_type = OLD_TIME; #else /* no ut_type */ ut.ut_time = oldTime.seconds; #endif /* OLD_TIME */ /* ======== BEGIN OLD TIME EVENT - UTMP / WTMP =========== */ #ifdef HAVE_UTMPNAME utmpname(UTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ #ifdef HAVE_UTMPNAME utmpname(WTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ /* ======== END OLD TIME EVENT - UTMP / WTMP =========== */ #endif /* HAVE_UTMP_H */ #endif /* HAVE_UTMPX_H */ /* Add the new time entry to utmp/wtmp */ #ifdef HAVE_UTMPX_H memset(&utx, 0, sizeof(utx)); strncpy(utx.ut_user, "date", sizeof(utx.ut_user)); #ifndef NTIME_MSG strncpy(utx.ut_line, "}", sizeof(utx.ut_line)); #else strncpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); #endif /* NTIME_MSG */ #ifdef NEW_TIME utx.ut_tv.tv_sec = newTime.seconds; utx.ut_tv.tv_usec = newTime.nanoseconds / 1000; utx.ut_type = NEW_TIME; #else /* no ut_type */ utx.ut_time = newTime.seconds; #endif /* NEW_TIME */ /* ======== BEGIN NEW TIME EVENT - UTMPX / WTMPX =========== */ #ifdef HAVE_UTMPXNAME utmpxname("/var/log/utmp"); #endif /* HAVE_UTMPXNAME */ setutxent(); pututxline(&utx); endutxent(); #ifdef HAVE_UPDWTMPX updwtmpx("/var/log/wtmp", &utx); #endif /* HAVE_UPDWTMPX */ /* ======== END NEW TIME EVENT - UTMPX / WTMPX =========== */ #else /* NO UTMPX_H */ #ifdef HAVE_UTMP_H memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_name, "date", sizeof(ut.ut_name)); #ifndef NTIME_MSG strncpy(ut.ut_line, "}", sizeof(ut.ut_line)); #else strncpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); #endif /* NTIME_MSG */ #ifdef NEW_TIME ut.ut_tv.tv_sec = newTime.seconds; ut.ut_tv.tv_usec = newTime.nanoseconds / 1000; ut.ut_type = NEW_TIME; #else /* no ut_type */ ut.ut_time = newTime.seconds; #endif /* NEW_TIME */ /* ======== BEGIN NEW TIME EVENT - UTMP / WTMP =========== */ #ifdef HAVE_UTMPNAME utmpname(UTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ #ifdef HAVE_UTMPNAME utmpname(WTMP_FILE); #endif /* HAVE_UTMPNAME */ #ifdef HAVE_SETUTENT setutent(); #endif /* HAVE_SETUTENT */ #ifdef HAVE_PUTUTLINE pututline(&ut); #endif /* HAVE_PUTUTLINE */ #ifdef HAVE_ENDUTENT endutent(); #endif /* HAVE_ENDUTENT */ /* ======== END NEW TIME EVENT - UTMP / WTMP =========== */ #endif /* HAVE_UTMP_H */ #endif /* HAVE_UTMPX_H */ } }