Line data Source code
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 11125 : 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 11125 : 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 11125 : return; 82 : }