PageRenderTime 17ms CodeModel.GetById 11ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/libntp/clocktime.c

https://bitbucket.org/freebsd/freebsd-head/
C | 132 lines | 71 code | 12 blank | 49 comment | 13 complexity | 4e6c16d0c0fcd850dc04ac1bc74ecc4c MD5 | raw file
  1/*
  2 * clocktime - compute the NTP date from a day of year, hour, minute
  3 *	       and second.
  4 */
  5#include "ntp_fp.h"
  6#include "ntp_unixtime.h"
  7#include "ntp_stdlib.h"
  8
  9/*
 10 * Hacks to avoid excercising the multiplier.  I have no pride.
 11 */
 12#define	MULBY10(x)	(((x)<<3) + ((x)<<1))
 13#define	MULBY60(x)	(((x)<<6) - ((x)<<2))	/* watch overflow */
 14#define	MULBY24(x)	(((x)<<4) + ((x)<<3))
 15
 16/*
 17 * Two days, in seconds.
 18 */
 19#define	TWODAYS		(2*24*60*60)
 20
 21/*
 22 * We demand that the time be within CLOSETIME seconds of the receive
 23 * time stamp.  This is about 4 hours, which hopefully should be
 24 * wide enough to collect most data, while close enough to keep things
 25 * from getting confused.
 26 */
 27#define	CLOSETIME	(4*60*60)
 28
 29
 30int
 31clocktime(
 32	int yday,
 33	int hour,
 34	int minute,
 35	int second,
 36	int tzoff,
 37	u_long rec_ui,
 38	u_long *yearstart,
 39	u_int32 *ts_ui
 40	)
 41{
 42	register long tmp;
 43	register u_long date;
 44	register u_long yst;
 45
 46	/*
 47	 * Compute the offset into the year in seconds.  Note that
 48	 * this could come out to be a negative number.
 49	 */
 50	tmp = (long)(MULBY24((yday-1)) + hour + tzoff);
 51	tmp = MULBY60(tmp) + (long)minute;
 52	tmp = MULBY60(tmp) + (long)second;
 53
 54	/*
 55	 * Initialize yearstart, if necessary.
 56	 */
 57	yst = *yearstart;
 58	if (yst == 0) {
 59		yst = calyearstart(rec_ui);
 60		*yearstart = yst;
 61	}
 62
 63	/*
 64	 * Now the fun begins.  We demand that the received clock time
 65	 * be within CLOSETIME of the receive timestamp, but
 66	 * there is uncertainty about the year the timestamp is in.
 67	 * Use the current year start for the first check, this should
 68	 * work most of the time.
 69	 */
 70	date = (u_long)(tmp + (long)yst);
 71	if (date < (rec_ui + CLOSETIME) &&
 72	    date > (rec_ui - CLOSETIME)) {
 73		*ts_ui = date;
 74		return 1;
 75	}
 76
 77	/*
 78	 * Trouble.  Next check is to see if the year rolled over and, if
 79	 * so, try again with the new year's start.
 80	 */
 81	yst = calyearstart(rec_ui);
 82	if (yst != *yearstart) {
 83		date = (u_long)((long)yst + tmp);
 84		*ts_ui = date;
 85		if (date < (rec_ui + CLOSETIME) &&
 86		    date > (rec_ui - CLOSETIME)) {
 87			*yearstart = yst;
 88			return 1;
 89		}
 90	}
 91
 92	/*
 93	 * Here we know the year start matches the current system
 94	 * time.  One remaining possibility is that the time code
 95	 * is in the year previous to that of the system time.  This
 96	 * is only worth checking if the receive timestamp is less
 97	 * than a couple of days into the new year.
 98	 */
 99	if ((rec_ui - yst) < TWODAYS) {
100		yst = calyearstart(yst - TWODAYS);
101		if (yst != *yearstart) {
102			date = (u_long)(tmp + (long)yst);
103			if (date < (rec_ui + CLOSETIME) &&
104			    date > (rec_ui - CLOSETIME)) {
105				*yearstart = yst;
106				*ts_ui = date;
107				return 1;
108			}
109		}
110	}
111
112	/*
113	 * One last possibility is that the time stamp is in the year
114	 * following the year the system is in.  Try this one before
115	 * giving up.
116	 */
117	yst = calyearstart(rec_ui + TWODAYS);
118	if (yst != *yearstart) {
119		date = (u_long)((long)yst + tmp);
120		if (date < (rec_ui + CLOSETIME) &&
121		    date > (rec_ui - CLOSETIME)) {
122			*yearstart = yst;
123			*ts_ui = date;
124			return 1;
125		}
126	}
127
128	/*
129	 * Give it up.
130	 */
131	return 0;
132}