/* ------------------------------------------------------------------ */ int32_t leapsec_daystolive( uint32_t when, const time_t * tpiv) { const leap_table_t * pt; vint64 limit; pt = leapsec_get_table(FALSE); limit = ntpcal_ntp_to_ntp(when, tpiv); limit = subv64(&pt->head.expire, &limit); return ntpcal_daysplit(&limit).hi; }
/* ------------------------------------------------------------------ */ int32_t leapsec_daystolive( uint32_t when, const time_t * tpiv) { const leap_table_t * pt; time64_t limit; pt = leapsec_get_table(false); limit = ntpcal_ntp_to_ntp(when, tpiv); limit = pt->head.expire - limit; return ntpcal_daysplit(limit).hi; }
/* * calweekstart - get NTP time at midnight of the last monday on or * before the current date. */ u_int32 calweekstart(u_int32 ntptime, const time_t *pivot) { u_int32 ndays; /* elapsed days since NTP starts */ vint64 vlong; ntpcal_split split; vlong = ntpcal_ntp_to_ntp(ntptime, pivot); split = ntpcal_daysplit(&vlong); ndays = ntpcal_weekday_le(split.hi + DAY_NTP_STARTS, CAL_MONDAY) - DAY_NTP_STARTS; return (u_int32)(ndays * SECSPERDAY); }
/* ------------------------------------------------------------------ */ int/*BOOL*/ leapsec_add_dyn( int insert, uint32_t ntpnow, const time_t * pivot ) { leap_table_t * pt; vint64 now64; pt = leapsec_get_table(TRUE); now64 = ntpcal_ntp_to_ntp(ntpnow, pivot); return ( leapsec_add(pt, &now64, (insert != 0)) && leapsec_set_table(pt)); }
/* ------------------------------------------------------------------ */ int/*BOOL*/ leapsec_query_era( leap_era_t * qr , uint32_t ntpts, const time_t * pivot) { const leap_table_t * pt; vint64 ts64; pt = leapsec_get_table(FALSE); ts64 = ntpcal_ntp_to_ntp(ntpts, pivot); fetch_leap_era(qr, pt, &ts64); return TRUE; }
/* ------------------------------------------------------------------ */ bool leapsec_add_dyn( bool insert, uint32_t ntpnow, const time_t * pivot ) { leap_table_t * pt; time64_t now64; pt = leapsec_get_table(true); now64 = ntpcal_ntp_to_ntp(ntpnow, pivot); return ( leapsec_add(pt, now64, insert) && leapsec_set_table(pt)); }
void caljulian( uint32_t ntp, struct calendar * jt ) { vint64 vlong; ntpcal_split split; NTP_INSIST(NULL != jt); /* * Unfold ntp time around current time into NTP domain. Split * into days and seconds, shift days into CE domain and * process the parts. */ vlong = ntpcal_ntp_to_ntp(ntp, NULL); split = ntpcal_daysplit(&vlong); ntpcal_daysplit_to_date(jt, &split, DAY_NTP_STARTS); }
int/*BOOL*/ leapsec_query( leap_result_t * qr , uint32_t ts32 , const time_t * pivot) { leap_table_t * pt; vint64 ts64, last, next; uint32_t due32; int fired; /* preset things we use later on... */ fired = FALSE; ts64 = ntpcal_ntp_to_ntp(ts32, pivot); pt = leapsec_get_table(FALSE); memset(qr, 0, sizeof(leap_result_t)); if (ucmpv64(&ts64, &pt->head.ebase) < 0) { /* Most likely after leap frame reset. Could also be a * backstep of the system clock. Anyway, get the new * leap era frame. */ reload_limits(pt, &ts64); } else if (ucmpv64(&ts64, &pt->head.dtime) >= 0) { /* Boundary crossed in forward direction. This might * indicate a leap transition, so we prepare for that * case. * * Some operations below are actually NOPs in electric * mode, but having only one code path that works for * both modes is easier to maintain. */ last = pt->head.ttime; qr->warped = (int16_t)(last.D_s.lo - pt->head.dtime.D_s.lo); next = addv64i32(&ts64, qr->warped); reload_limits(pt, &next); fired = ucmpv64(&pt->head.ebase, &last) == 0; if (fired) { ts64 = next; ts32 = next.D_s.lo; } else { qr->warped = 0; } } qr->tai_offs = pt->head.this_tai; /* If before the next scheduling alert, we're done. */ if (ucmpv64(&ts64, &pt->head.stime) < 0) return fired; /* now start to collect the remaing data */ due32 = pt->head.dtime.D_s.lo; qr->tai_diff = pt->head.next_tai - pt->head.this_tai; qr->ttime = pt->head.ttime; qr->ddist = due32 - ts32; qr->dynamic = pt->head.dynls; qr->proximity = LSPROX_SCHEDULE; /* if not in the last day before transition, we're done. */ if (!betweenu32(due32 - SECSPERDAY, ts32, due32)) return fired; qr->proximity = LSPROX_ANNOUNCE; if (!betweenu32(due32 - 10, ts32, due32)) return fired; /* The last 10s before the transition. Prepare for action! */ qr->proximity = LSPROX_ALERT; return fired; }
/* ------------------------------------------------------------------ */ int/*BOOL*/ leapsec_autokey_tai( int tai_offset, uint32_t ntpnow , const time_t * pivot ) { leap_table_t * pt; leap_era_t era; vint64 now64; int idx; (void)tai_offset; pt = leapsec_get_table(FALSE); /* Bail out if the basic offset is not zero and the putative * offset is bigger than 10s. That was in 1972 -- we don't want * to go back that far! */ if (pt->head.base_tai != 0 || tai_offset < 10) return FALSE; /* If there's already data in the table, check if an update is * possible. Update is impossible if there are static entries * (since this indicates a valid leapsecond file) or if we're * too close to a leapsecond transition: We do not know on what * side the transition the sender might have been, so we use a * dead zone around the transition. */ /* Check for static entries */ for (idx = 0; idx != pt->head.size; idx++) if ( ! pt->info[idx].dynls) return FALSE; /* get the fulll time stamp and leap era for it */ now64 = ntpcal_ntp_to_ntp(ntpnow, pivot); fetch_leap_era(&era, pt, &now64); /* check the limits with 20s dead band */ era.ebase = addv64i32(&era.ebase, 20); if (ucmpv64(&now64, &era.ebase) < 0) return FALSE; era.ttime = addv64i32(&era.ttime, -20); if (ucmpv64(&now64, &era.ttime) > 0) return FALSE; /* Here we can proceed. Calculate the delta update. */ tai_offset -= era.taiof; /* Shift the header info offsets. */ pt->head.base_tai += tai_offset; pt->head.this_tai += tai_offset; pt->head.next_tai += tai_offset; /* Shift table entry offsets (if any) */ for (idx = 0; idx != pt->head.size; idx++) pt->info[idx].taiof += tai_offset; /* claim success... */ return TRUE; }