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