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