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 <stddef.h>
  14. #include <stdlib.h>
  15. #ifdef HAVE_SYS_TIME_H
  16. #include <sys/time.h>
  17. #endif
  18. #ifdef _WIN32
  19. #include <windows.h>
  20. #endif
  21. #ifdef HAVE_SYS_TYPES_H
  22. #include <sys/types.h>
  23. #endif
  24. #ifndef HAVE_GETTIMEOFDAY
  25. #ifdef HAVE_FTIME
  26. #include <sys/timeb.h>
  27. #endif
  28. #endif
  29. /** Set *timeval to the current time of day. On error, log and terminate.
  30. * (Same as gettimeofday(timeval,NULL), but never returns -1.)
  31. */
  32. MOCK_IMPL(void,
  33. tor_gettimeofday, (struct timeval *timeval))
  34. {
  35. #ifdef _WIN32
  36. /* Epoch bias copied from perl: number of units between windows epoch and
  37. * Unix epoch. */
  38. #define EPOCH_BIAS U64_LITERAL(116444736000000000)
  39. #define UNITS_PER_SEC U64_LITERAL(10000000)
  40. #define USEC_PER_SEC U64_LITERAL(1000000)
  41. #define UNITS_PER_USEC U64_LITERAL(10)
  42. union {
  43. uint64_t ft_64;
  44. FILETIME ft_ft;
  45. } ft;
  46. /* number of 100-nsec units since Jan 1, 1601 */
  47. GetSystemTimeAsFileTime(&ft.ft_ft);
  48. if (ft.ft_64 < EPOCH_BIAS) {
  49. /* LCOV_EXCL_START */
  50. log_err(LD_GENERAL,"System time is before 1970; failing.");
  51. exit(1); // exit ok: system clock is broken.
  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. }