1 /*
2 * Time Functions
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7
8 #include <botan/time.h>
9 #include <botan/exceptn.h>
10 #include <ctime>
11
12 #if defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME)
13 #include <windows.h>
14 #endif
15
16 #if defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY)
17 #include <sys/time.h>
18 #endif
19
20 #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
21
22 #ifndef _POSIX_C_SOURCE
23 #define _POSIX_C_SOURCE 199309
24 #endif
25
26 #include <time.h>
27
28 #ifndef CLOCK_REALTIME
29 #define CLOCK_REALTIME 0
30 #endif
31
32 #endif
33
34 namespace Botan {
35
36 namespace {
37
38 /*
39 * Combine a two time values into a single one
40 */
combine_timers(u32bit seconds,u32bit parts,u32bit parts_hz)41 u64bit combine_timers(u32bit seconds, u32bit parts, u32bit parts_hz)
42 {
43 static const u64bit NANOSECONDS_UNITS = 1000000000;
44
45 u64bit res = seconds * NANOSECONDS_UNITS;
46 res += parts * (NANOSECONDS_UNITS / parts_hz);
47 return res;
48 }
49
do_gmtime(time_t time_val)50 std::tm do_gmtime(time_t time_val)
51 {
52 std::tm tm;
53
54 #if defined(BOTAN_TARGET_OS_HAS_GMTIME_S)
55 gmtime_s(&tm, &time_val); // Windows
56 #elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R)
57 gmtime_r(&time_val, &tm); // Unix/SUSv2
58 #else
59 std::tm* tm_p = std::gmtime(&time_val);
60 if (tm_p == 0)
61 throw Encoding_Error("time_t_to_tm could not convert");
62 tm = *tm_p;
63 #endif
64
65 return tm;
66 }
67
68 }
69
70 /*
71 * Get the system clock
72 */
system_time()73 u64bit system_time()
74 {
75 return static_cast<u64bit>(std::time(0));
76 }
77
78 /*
79 * Convert a time_point to a calendar_point
80 */
calendar_value(u64bit a_time_t)81 calendar_point calendar_value(u64bit a_time_t)
82 {
83 std::tm tm = do_gmtime(static_cast<std::time_t>(a_time_t));
84
85 return calendar_point(tm.tm_year + 1900,
86 tm.tm_mon + 1,
87 tm.tm_mday,
88 tm.tm_hour,
89 tm.tm_min,
90 tm.tm_sec);
91 }
92
get_nanoseconds_clock()93 u64bit get_nanoseconds_clock()
94 {
95 #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
96
97 struct ::timespec tv;
98 ::clock_gettime(CLOCK_REALTIME, &tv);
99 return combine_timers(tv.tv_sec, tv.tv_nsec, 1000000000);
100
101 #elif defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY)
102
103 struct ::timeval tv;
104 ::gettimeofday(&tv, 0);
105 return combine_timers(tv.tv_sec, tv.tv_usec, 1000000);
106
107 #elif defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME)
108
109 // Returns time since January 1, 1601 in 100-ns increments
110 ::FILETIME tv;
111 ::GetSystemTimeAsFileTime(&tv);
112 u64bit tstamp = (static_cast<u64bit>(tv.dwHighDateTime) << 32) |
113 tv.dwLowDateTime;
114
115 return (tstamp * 100); // Scale to 1 nanosecond units
116
117 #else
118
119 return combine_timers(static_cast<u32bit>(std::time(0)),
120 std::clock(), CLOCKS_PER_SEC);
121
122 #endif
123 }
124
125 }
126