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