/* --------------------------------------------------------------------- * Dump a table in human-readable format. Use 'fprintf' and a FILE * pointer if you want to get it printed into a stream. */ void leapsec_dump( const leap_table_t * pt , leapsec_dumper func, void * farg) { int idx; vint64 ts; struct calendar atb, ttb; ntpcal_ntp64_to_date(&ttb, &pt->head.expire); (*func)(farg, "leap table (%u entries) expires at %04u-%02u-%02u:\n", pt->head.size, ttb.year, ttb.month, ttb.monthday); idx = pt->head.size; while (idx-- != 0) { ts = pt->info[idx].ttime; ntpcal_ntp64_to_date(&ttb, &ts); ts = subv64u32(&ts, pt->info[idx].stime); ntpcal_ntp64_to_date(&atb, &ts); (*func)(farg, "%04u-%02u-%02u [%c] (%04u-%02u-%02u) - %d\n", ttb.year, ttb.month, ttb.monthday, "-*"[pt->info[idx].dynls != 0], atb.year, atb.month, atb.monthday, pt->info[idx].taiof); } }
/* [internal] Given a time stamp for a leap insertion (the exact begin * of the new leap era), create new leap frame and put it into the * table. This is the work horse for reading a leap file and getting a * leap second update via authenticated network packet. */ int/*BOOL*/ leapsec_raw( leap_table_t * pt, const vint64 * ttime, int taiof, int dynls) { vint64 stime; struct calendar fts; leap_info_t li; /* Check that we only extend the table. Paranoia rulez! */ if (pt->head.size && ucmpv64(ttime, &pt->info[0].ttime) <= 0) { errno = ERANGE; return FALSE; } ntpcal_ntp64_to_date(&fts, ttime); /* If this does not match the exact month start, bail out. */ if (fts.monthday != 1 || fts.hour || fts.minute || fts.second) { errno = EINVAL; return FALSE; } fts.month--; /* was in range 1..12, no overflow here! */ stime = ntpcal_date_to_ntp64(&fts); li.ttime = *ttime; li.stime = ttime->D_s.lo - stime.D_s.lo; li.taiof = (int16_t)taiof; li.dynls = (dynls != 0); return add_range(pt, &li); }
/* [internal] Given a time stamp for a leap insertion (the exact begin * of the new leap era), create new leap frame and put it into the * table. This is the work horse for reading a leap file and getting a * leap second update via authenticated network packet. */ bool leapsec_raw( leap_table_t * pt, const time64_t ttime, int taiof, int dynls) { time64_t starttime; struct calendar fts; leap_info_t li; /* Check that we only extend the table. Paranoia rulez! */ if (pt->head.size && (ttime <= pt->info[0].ttime)) { errno = ERANGE; return false; } ntpcal_ntp64_to_date(&fts, ttime); /* If this does not match the exact month start, bail out. */ if (fts.monthday != 1 || fts.hour || fts.minute || fts.second) { errno = EINVAL; return false; } fts.month--; /* was in range 1..12, no overflow here! */ starttime = ntpcal_date_to_ntp64(&fts); li.ttime = ttime; li.stime = time64lo(ttime) - time64lo(starttime); li.taiof = (int16_t)taiof; li.dynls = (dynls != 0); return add_range(pt, &li); }
/* * lstostr - prettyprint NTP seconds */ static char * lstostr( const vint64 * ts) { char * buf; struct calendar tm; LIB_GETBUF(buf); ntpcal_ntp64_to_date(&tm, ts); snprintf(buf, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02dZ", tm.year, tm.month, tm.monthday, tm.hour, tm.minute); return buf; }
/* [internal] Take a time stamp and create a leap second frame for * it. This will schedule a leap second for the beginning of the next * month, midnight UTC. The 'insert' argument tells if a leap second is * added (!=0) or removed (==0). We do not handle multiple inserts * (yet?) * * Returns 1 if the insert worked, 0 otherwise. (It's not possible to * insert a leap second into the current history -- only appending * towards the future is allowed!) */ static int/*BOOL*/ leapsec_add( leap_table_t* pt , const vint64 * now64 , int insert) { vint64 ttime, stime; struct calendar fts; leap_info_t li; /* Check against the table expiration and the lates available * leap entry. Do not permit inserts, only appends, and only if * the extend the table beyond the expiration! */ if ( ucmpv64(now64, &pt->head.expire) < 0 || (pt->head.size && ucmpv64(now64, &pt->info[0].ttime) <= 0)) { errno = ERANGE; return FALSE; } ntpcal_ntp64_to_date(&fts, now64); /* To guard against dangling leap flags: do not accept leap * second request on the 1st hour of the 1st day of the month. */ if (fts.monthday == 1 && fts.hour == 0) { errno = EINVAL; return FALSE; } /* Ok, do the remaining calculations */ fts.monthday = 1; fts.hour = 0; fts.minute = 0; fts.second = 0; stime = ntpcal_date_to_ntp64(&fts); fts.month++; ttime = ntpcal_date_to_ntp64(&fts); li.ttime = ttime; li.stime = ttime.D_s.lo - stime.D_s.lo; li.taiof = (pt->head.size ? pt->info[0].taiof : pt->head.base_tai) + (insert ? 1 : -1); li.dynls = 1; return add_range(pt, &li); }
/* * lstostr - prettyprint NTP seconds */ static const char * lstostr( const vint64 * ts) { char * buf; struct calendar tm; LIB_GETBUF(buf); if ( ! (ts->d_s.hi >= 0 && ntpcal_ntp64_to_date(&tm, ts) >= 0)) snprintf(buf, LIB_BUFLENGTH, "%s", "9999-12-31T23:59:59Z"); else snprintf(buf, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02d:%02dZ", tm.year, tm.month, tm.monthday, tm.hour, tm.minute, tm.second); return buf; }
/* [internal] Given a time stamp for a leap insertion (the exact begin * of the new leap era), create new leap frame and put it into the * table. This is the work horse for reading a leap file and getting a * leap second update via authenticated network packet. */ int/*BOOL*/ leapsec_raw( leap_table_t * pt, const vint64 * ttime, int taiof, int dynls) { vint64 starttime; struct calendar fts; leap_info_t li; /* Check that we either extend the table or get a duplicate of * the latest entry. The latter is a benevolent overwrite with * identical data and could happen if we get an autokey message * that extends the lifetime of the current leapsecond table. * Otherwise paranoia rulez! */ if (pt->head.size) { int cmp = ucmpv64(ttime, &pt->info[0].ttime); if (cmp == 0) cmp -= (taiof != pt->info[0].taiof); if (cmp < 0) { errno = ERANGE; return FALSE; } if (cmp == 0) return TRUE; } ntpcal_ntp64_to_date(&fts, ttime); /* If this does not match the exact month start, bail out. */ if (fts.monthday != 1 || fts.hour || fts.minute || fts.second) { errno = EINVAL; return FALSE; } fts.month--; /* was in range 1..12, no overflow here! */ starttime = ntpcal_date_to_ntp64(&fts); li.ttime = *ttime; li.stime = ttime->D_s.lo - starttime.D_s.lo; li.taiof = (int16_t)taiof; li.dynls = (dynls != 0); return add_range(pt, &li); }