tor_gettimeofday.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, 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. #include "orconfig.h"
  11. #include "lib/err/torerr.h"
  12. #include "lib/wallclock/tor_gettimeofday.h"
  13. #include "lib/cc/torint.h"
  14. #include <stddef.h>
  15. #include <stdlib.h>
  16. #ifdef HAVE_SYS_TIME_H
  17. #include <sys/time.h>
  18. #endif
  19. #ifdef _WIN32
  20. #include <windows.h>
  21. #endif
  22. #ifdef HAVE_SYS_TYPES_H
  23. #include <sys/types.h>
  24. #endif
  25. #ifndef HAVE_GETTIMEOFDAY
  26. #ifdef HAVE_FTIME
  27. #include <sys/timeb.h>
  28. #endif
  29. #endif
  30. /** Set *timeval to the current time of day. On error, log and terminate.
  31. * (Same as gettimeofday(timeval,NULL), but never returns -1.)
  32. */
  33. MOCK_IMPL(void,
  34. tor_gettimeofday, (struct timeval *timeval))
  35. {
  36. #ifdef _WIN32
  37. /* Epoch bias copied from perl: number of units between windows epoch and
  38. * Unix epoch. */
  39. #define EPOCH_BIAS UINT64_C(116444736000000000)
  40. #define UNITS_PER_SEC UINT64_C(10000000)
  41. #define USEC_PER_SEC UINT64_C(1000000)
  42. #define UNITS_PER_USEC UINT64_C(10)
  43. union {
  44. uint64_t ft_64;
  45. FILETIME ft_ft;
  46. } ft;
  47. /* number of 100-nsec units since Jan 1, 1601 */
  48. GetSystemTimeAsFileTime(&ft.ft_ft);
  49. if (ft.ft_64 < EPOCH_BIAS) {
  50. /* LCOV_EXCL_START */
  51. raw_assert_unreached_msg("System time is before 1970; failing.");
  52. /* LCOV_EXCL_STOP */
  53. }
  54. ft.ft_64 -= EPOCH_BIAS;
  55. timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
  56. timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
  57. #elif defined(HAVE_GETTIMEOFDAY)
  58. if (gettimeofday(timeval, NULL)) {
  59. /* LCOV_EXCL_START */
  60. /* If gettimeofday dies, we have either given a bad timezone (we didn't),
  61. or segfaulted.*/
  62. raw_assert_unreached_msg("gettimeofday failed");
  63. /* LCOV_EXCL_STOP */
  64. }
  65. #elif defined(HAVE_FTIME)
  66. struct timeb tb;
  67. ftime(&tb);
  68. timeval->tv_sec = tb.time;
  69. timeval->tv_usec = tb.millitm * 1000;
  70. #else
  71. #error "No way to get time."
  72. #endif /* defined(_WIN32) || ... */
  73. return;
  74. }