Coverage Report

Created: 2024-02-29 06:05

/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
}