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