/src/strongswan/src/libstrongswan/utils/utils/time.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2008-2017 Tobias Brunner |
3 | | * Copyright (C) 2005-2008 Martin Willi |
4 | | * |
5 | | * Copyright (C) secunet Security Networks AG |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify it |
8 | | * under the terms of the GNU General Public License as published by the |
9 | | * Free Software Foundation; either version 2 of the License, or (at your |
10 | | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. |
11 | | * |
12 | | * This program is distributed in the hope that it will be useful, but |
13 | | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
14 | | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | | * for more details. |
16 | | */ |
17 | | |
18 | | #ifdef WIN32 |
19 | | /* for GetTickCount64, Windows 7 */ |
20 | | # define _WIN32_WINNT 0x0601 |
21 | | #endif |
22 | | |
23 | | #define _GNU_SOURCE |
24 | | #include <utils/utils.h> |
25 | | |
26 | | #include <inttypes.h> |
27 | | #include <ctype.h> |
28 | | #include <time.h> |
29 | | #include <errno.h> |
30 | | |
31 | | /** |
32 | | * Return monotonic time |
33 | | */ |
34 | | time_t time_monotonic(timeval_t *tv) |
35 | 0 | { |
36 | | #ifdef WIN32 |
37 | | ULONGLONG ms; |
38 | | time_t s; |
39 | | |
40 | | ms = GetTickCount64(); |
41 | | s = ms / 1000; |
42 | | if (tv) |
43 | | { |
44 | | tv->tv_sec = s; |
45 | | tv->tv_usec = (ms - (s * 1000)) * 1000; |
46 | | } |
47 | | return s; |
48 | | #else /* !WIN32 */ |
49 | 0 | #if defined(HAVE_CLOCK_GETTIME) && \ |
50 | 0 | (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \ |
51 | 0 | defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) |
52 | | /* as we use time_monotonic() for condvar operations, we use the |
53 | | * monotonic time source only if it is also supported by pthread. */ |
54 | 0 | timespec_t ts; |
55 | |
|
56 | 0 | if (clock_gettime(TIME_CLOCK_ID, &ts) == 0) |
57 | 0 | { |
58 | 0 | if (tv) |
59 | 0 | { |
60 | 0 | tv->tv_sec = ts.tv_sec; |
61 | 0 | tv->tv_usec = ts.tv_nsec / 1000; |
62 | 0 | } |
63 | 0 | return ts.tv_sec; |
64 | 0 | } |
65 | 0 | #endif /* HAVE_CLOCK_GETTIME && (...) */ |
66 | | /* Fallback to non-monotonic timestamps: |
67 | | * On MAC OS X, creating monotonic timestamps is rather difficult. We |
68 | | * could use mach_absolute_time() and catch sleep/wakeup notifications. |
69 | | * We stick to the simpler (non-monotonic) gettimeofday() for now. |
70 | | * But keep in mind: we need the same time source here as in condvar! */ |
71 | 0 | if (!tv) |
72 | 0 | { |
73 | 0 | return time(NULL); |
74 | 0 | } |
75 | 0 | if (gettimeofday(tv, NULL) != 0) |
76 | 0 | { /* should actually never fail if passed pointers are valid */ |
77 | 0 | return -1; |
78 | 0 | } |
79 | 0 | return tv->tv_sec; |
80 | 0 | #endif /* !WIN32 */ |
81 | 0 | } |
82 | | |
83 | | /* |
84 | | * Described in header |
85 | | */ |
86 | | bool timespan_from_string(char *str, char *defunit, time_t *val) |
87 | 0 | { |
88 | 0 | char *endptr, unit; |
89 | 0 | time_t timeval; |
90 | |
|
91 | 0 | if (str) |
92 | 0 | { |
93 | 0 | errno = 0; |
94 | 0 | timeval = strtoull(str, &endptr, 10); |
95 | 0 | if (endptr == str) |
96 | 0 | { |
97 | 0 | return FALSE; |
98 | 0 | } |
99 | 0 | if (errno == 0) |
100 | 0 | { |
101 | 0 | while (isspace(*endptr)) |
102 | 0 | { |
103 | 0 | endptr++; |
104 | 0 | } |
105 | 0 | unit = *endptr; |
106 | 0 | if (!unit && defunit) |
107 | 0 | { |
108 | 0 | unit = *defunit; |
109 | 0 | } |
110 | 0 | switch (unit) |
111 | 0 | { |
112 | 0 | case 'd': /* time in days */ |
113 | 0 | timeval *= 24 * 3600; |
114 | 0 | break; |
115 | 0 | case 'h': /* time in hours */ |
116 | 0 | timeval *= 3600; |
117 | 0 | break; |
118 | 0 | case 'm': /* time in minutes */ |
119 | 0 | timeval *= 60; |
120 | 0 | break; |
121 | 0 | case 's': /* time in seconds */ |
122 | 0 | case '\0': |
123 | 0 | break; |
124 | 0 | default: |
125 | 0 | return FALSE; |
126 | 0 | } |
127 | 0 | if (val) |
128 | 0 | { |
129 | 0 | *val = timeval; |
130 | 0 | } |
131 | 0 | return TRUE; |
132 | 0 | } |
133 | 0 | } |
134 | 0 | return FALSE; |
135 | 0 | } |
136 | | |
137 | | /* |
138 | | * Described in header |
139 | | */ |
140 | | int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, |
141 | | const void *const *args) |
142 | 0 | { |
143 | 0 | static const char* months[] = { |
144 | 0 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
145 | 0 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
146 | 0 | }; |
147 | 0 | time_t *time = *((time_t**)(args[0])); |
148 | 0 | bool utc = *((int*)(args[1])); |
149 | 0 | struct tm t, *ret = NULL; |
150 | |
|
151 | 0 | if (*time != UNDEFINED_TIME) |
152 | 0 | { |
153 | 0 | if (utc) |
154 | 0 | { |
155 | 0 | ret = gmtime_r(time, &t); |
156 | 0 | } |
157 | 0 | else |
158 | 0 | { |
159 | 0 | ret = localtime_r(time, &t); |
160 | 0 | } |
161 | 0 | } |
162 | 0 | if (ret == NULL) |
163 | 0 | { |
164 | 0 | return print_in_hook(data, "--- -- --:--:--%s----", |
165 | 0 | utc ? " UTC " : " "); |
166 | 0 | } |
167 | 0 | return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d", |
168 | 0 | months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min, |
169 | 0 | t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900); |
170 | 0 | } |
171 | | |
172 | | /* |
173 | | * Described in header |
174 | | */ |
175 | | int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, |
176 | | const void *const *args) |
177 | 0 | { |
178 | 0 | char* unit = "second"; |
179 | 0 | time_t *arg1 = *((time_t**)(args[0])); |
180 | 0 | time_t *arg2 = *((time_t**)(args[1])); |
181 | 0 | uint64_t delta = llabs(*arg1 - *arg2); |
182 | |
|
183 | 0 | if (delta > 2 * 60 * 60 * 24) |
184 | 0 | { |
185 | 0 | delta /= 60 * 60 * 24; |
186 | 0 | unit = "day"; |
187 | 0 | } |
188 | 0 | else if (delta > 2 * 60 * 60) |
189 | 0 | { |
190 | 0 | delta /= 60 * 60; |
191 | 0 | unit = "hour"; |
192 | 0 | } |
193 | 0 | else if (delta > 2 * 60) |
194 | 0 | { |
195 | 0 | delta /= 60; |
196 | 0 | unit = "minute"; |
197 | 0 | } |
198 | 0 | return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit, |
199 | 0 | (delta == 1) ? "" : "s"); |
200 | 0 | } |