compat_time.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2016, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file compat_time.c
  7. * \brief Portable wrappers for finding out the current time, running
  8. * timers, etc.
  9. **/
  10. #define COMPAT_PRIVATE
  11. #include "compat.h"
  12. #ifdef _WIN32
  13. #include <winsock2.h>
  14. #include <windows.h>
  15. #endif
  16. #ifdef HAVE_SYS_TYPES_H
  17. #include <sys/types.h>
  18. #endif
  19. #ifdef HAVE_UNISTD_H
  20. #include <unistd.h>
  21. #endif
  22. #ifdef TOR_UNIT_TESTS
  23. #if !defined(HAVE_USLEEP) && defined(HAVE_SYS_SELECT_H)
  24. /* as fallback implementation for tor_sleep_msec */
  25. #include <sys/select.h>
  26. #endif
  27. #endif
  28. #include "torlog.h"
  29. #include "util.h"
  30. #include "container.h"
  31. #ifndef HAVE_GETTIMEOFDAY
  32. #ifdef HAVE_FTIME
  33. #include <sys/timeb.h>
  34. #endif
  35. #endif
  36. #ifdef TOR_UNIT_TESTS
  37. /** Delay for <b>msec</b> milliseconds. Only used in tests. */
  38. void
  39. tor_sleep_msec(int msec)
  40. {
  41. #ifdef _WIN32
  42. Sleep(msec);
  43. #elif defined(HAVE_USLEEP)
  44. sleep(msec / 1000);
  45. /* Some usleep()s hate sleeping more than 1 sec */
  46. usleep((msec % 1000) * 1000);
  47. #elif defined(HAVE_SYS_SELECT_H)
  48. struct timeval tv = { msec / 1000, (msec % 1000) * 1000};
  49. select(0, NULL, NULL, NULL, &tv);
  50. #else
  51. sleep(CEIL_DIV(msec, 1000));
  52. #endif
  53. }
  54. #endif
  55. /** Set *timeval to the current time of day. On error, log and terminate.
  56. * (Same as gettimeofday(timeval,NULL), but never returns -1.)
  57. */
  58. void
  59. tor_gettimeofday(struct timeval *timeval)
  60. {
  61. #ifdef _WIN32
  62. /* Epoch bias copied from perl: number of units between windows epoch and
  63. * Unix epoch. */
  64. #define EPOCH_BIAS U64_LITERAL(116444736000000000)
  65. #define UNITS_PER_SEC U64_LITERAL(10000000)
  66. #define USEC_PER_SEC U64_LITERAL(1000000)
  67. #define UNITS_PER_USEC U64_LITERAL(10)
  68. union {
  69. uint64_t ft_64;
  70. FILETIME ft_ft;
  71. } ft;
  72. /* number of 100-nsec units since Jan 1, 1601 */
  73. GetSystemTimeAsFileTime(&ft.ft_ft);
  74. if (ft.ft_64 < EPOCH_BIAS) {
  75. /* LCOV_EXCL_START */
  76. log_err(LD_GENERAL,"System time is before 1970; failing.");
  77. exit(1);
  78. /* LCOV_EXCL_STOP */
  79. }
  80. ft.ft_64 -= EPOCH_BIAS;
  81. timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
  82. timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
  83. #elif defined(HAVE_GETTIMEOFDAY)
  84. if (gettimeofday(timeval, NULL)) {
  85. /* LCOV_EXCL_START */
  86. log_err(LD_GENERAL,"gettimeofday failed.");
  87. /* If gettimeofday dies, we have either given a bad timezone (we didn't),
  88. or segfaulted.*/
  89. exit(1);
  90. /* LCOV_EXCL_STOP */
  91. }
  92. #elif defined(HAVE_FTIME)
  93. struct timeb tb;
  94. ftime(&tb);
  95. timeval->tv_sec = tb.time;
  96. timeval->tv_usec = tb.millitm * 1000;
  97. #else
  98. #error "No way to get time."
  99. #endif
  100. return;
  101. }