Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/lib/isc/unix/time.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2004-2008, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
3
 * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
4
 *
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
 * PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
/* $Id$ */
19
20
/*! \file */
21
22
#include <config.h>
23
24
#include <errno.h>
25
#include <limits.h>
26
#include <syslog.h>
27
#include <time.h>
28
29
#include <sys/time.h> /* Required for struct timeval on some platforms. */
30
31
#include <isc/log.h>
32
#include <isc/print.h>
33
#include <isc/strerror.h>
34
#include <isc/string.h>
35
#include <isc/time.h>
36
#include <isc/util.h>
37
38
0
#define NS_PER_S  1000000000  /*%< Nanoseconds per second. */
39
0
#define NS_PER_US 1000    /*%< Nanoseconds per microsecond. */
40
0
#define US_PER_S  1000000    /*%< Microseconds per second. */
41
42
/*
43
 * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
44
 * consistency checking of the type. In lieu of magic numbers, it
45
 * is the best we've got.  The check is only performed on functions which
46
 * need an initialized type.
47
 */
48
49
#ifndef ISC_FIX_TV_USEC
50
#define ISC_FIX_TV_USEC 1
51
#endif
52
53
/*%
54
 *** Intervals
55
 ***/
56
57
static isc_interval_t zero_interval = { 0, 0 };
58
isc_interval_t *isc_interval_zero = &zero_interval;
59
60
#if ISC_FIX_TV_USEC
61
static inline void
62
0
fix_tv_usec(struct timeval *tv) {
63
0
  isc_boolean_t fixed = ISC_FALSE;
64
65
0
  if (tv->tv_usec < 0) {
66
0
    fixed = ISC_TRUE;
67
0
    do {
68
0
      tv->tv_sec -= 1;
69
0
      tv->tv_usec += US_PER_S;
70
0
    } while (tv->tv_usec < 0);
71
0
  } else if (tv->tv_usec >= US_PER_S) {
72
0
    fixed = ISC_TRUE;
73
0
    do {
74
0
      tv->tv_sec += 1;
75
0
      tv->tv_usec -= US_PER_S;
76
0
    } while (tv->tv_usec >=US_PER_S);
77
0
  }
78
  /*
79
   * Call syslog directly as was are called from the logging functions.
80
   */
81
0
  if (fixed)
82
0
    (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
83
0
}
84
#endif
85
86
void
87
isc_interval_set(isc_interval_t *i,
88
     unsigned int seconds, unsigned int nanoseconds)
89
0
{
90
0
  REQUIRE(i != NULL);
91
0
  REQUIRE(nanoseconds < NS_PER_S);
92
93
0
  i->seconds = seconds;
94
0
  i->nanoseconds = nanoseconds;
95
0
}
96
97
isc_boolean_t
98
0
isc_interval_iszero(const isc_interval_t *i) {
99
0
  REQUIRE(i != NULL);
100
0
  INSIST(i->nanoseconds < NS_PER_S);
101
102
0
  if (i->seconds == 0 && i->nanoseconds == 0)
103
0
    return (ISC_TRUE);
104
105
0
  return (ISC_FALSE);
106
0
}
107
108
109
/***
110
 *** Absolute Times
111
 ***/
112
113
static isc_time_t epoch = { 0, 0 };
114
isc_time_t *isc_time_epoch = &epoch;
115
116
void
117
0
isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
118
0
  REQUIRE(t != NULL);
119
0
  REQUIRE(nanoseconds < NS_PER_S);
120
121
0
  t->seconds = seconds;
122
0
  t->nanoseconds = nanoseconds;
123
0
}
124
125
void
126
0
isc_time_settoepoch(isc_time_t *t) {
127
0
  REQUIRE(t != NULL);
128
129
0
  t->seconds = 0;
130
0
  t->nanoseconds = 0;
131
0
}
132
133
isc_boolean_t
134
0
isc_time_isepoch(const isc_time_t *t) {
135
0
  REQUIRE(t != NULL);
136
0
  INSIST(t->nanoseconds < NS_PER_S);
137
138
0
  if (t->seconds == 0 && t->nanoseconds == 0)
139
0
    return (ISC_TRUE);
140
141
0
  return (ISC_FALSE);
142
0
}
143
144
145
isc_result_t
146
0
isc_time_now(isc_time_t *t) {
147
0
  struct timeval tv;
148
0
  char strbuf[ISC_STRERRORSIZE];
149
150
0
  REQUIRE(t != NULL);
151
152
0
  if (gettimeofday(&tv, NULL) == -1) {
153
0
    isc__strerror(errno, strbuf, sizeof(strbuf));
154
0
    UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
155
0
    return (ISC_R_UNEXPECTED);
156
0
  }
157
158
  /*
159
   * Does POSIX guarantee the signedness of tv_sec and tv_usec?  If not,
160
   * then this test will generate warnings for platforms on which it is
161
   * unsigned.  In any event, the chances of any of these problems
162
   * happening are pretty much zero, but since the libisc library ensures
163
   * certain things to be true ...
164
   */
165
0
#if ISC_FIX_TV_USEC
166
0
  fix_tv_usec(&tv);
167
0
  if (tv.tv_sec < 0)
168
0
    return (ISC_R_UNEXPECTED);
169
#else
170
  if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
171
    return (ISC_R_UNEXPECTED);
172
#endif
173
174
  /*
175
   * Ensure the tv_sec value fits in t->seconds.
176
   */
177
0
  if (sizeof(tv.tv_sec) > sizeof(t->seconds) &&
178
0
      ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U)
179
0
    return (ISC_R_RANGE);
180
181
0
  t->seconds = tv.tv_sec;
182
0
  t->nanoseconds = tv.tv_usec * NS_PER_US;
183
184
0
  return (ISC_R_SUCCESS);
185
0
}
186
187
isc_result_t
188
0
isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
189
0
  struct timeval tv;
190
0
  char strbuf[ISC_STRERRORSIZE];
191
192
0
  REQUIRE(t != NULL);
193
0
  REQUIRE(i != NULL);
194
0
  INSIST(i->nanoseconds < NS_PER_S);
195
196
0
  if (gettimeofday(&tv, NULL) == -1) {
197
0
    isc__strerror(errno, strbuf, sizeof(strbuf));
198
0
    UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
199
0
    return (ISC_R_UNEXPECTED);
200
0
  }
201
202
  /*
203
   * Does POSIX guarantee the signedness of tv_sec and tv_usec?  If not,
204
   * then this test will generate warnings for platforms on which it is
205
   * unsigned.  In any event, the chances of any of these problems
206
   * happening are pretty much zero, but since the libisc library ensures
207
   * certain things to be true ...
208
   */
209
0
#if ISC_FIX_TV_USEC
210
0
  fix_tv_usec(&tv);
211
0
  if (tv.tv_sec < 0)
212
0
    return (ISC_R_UNEXPECTED);
213
#else
214
  if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
215
    return (ISC_R_UNEXPECTED);
216
#endif
217
218
  /*
219
   * Ensure the resulting seconds value fits in the size of an
220
   * unsigned int.  (It is written this way as a slight optimization;
221
   * note that even if both values == INT_MAX, then when added
222
   * and getting another 1 added below the result is UINT_MAX.)
223
   */
224
0
  if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
225
0
      ((long long)tv.tv_sec + i->seconds > UINT_MAX))
226
0
    return (ISC_R_RANGE);
227
228
0
  t->seconds = tv.tv_sec + i->seconds;
229
0
  t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
230
0
  if (t->nanoseconds >= NS_PER_S) {
231
0
    t->seconds++;
232
0
    t->nanoseconds -= NS_PER_S;
233
0
  }
234
235
0
  return (ISC_R_SUCCESS);
236
0
}
237
238
int
239
0
isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
240
0
  REQUIRE(t1 != NULL && t2 != NULL);
241
0
  INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
242
243
0
  if (t1->seconds < t2->seconds)
244
0
    return (-1);
245
0
  if (t1->seconds > t2->seconds)
246
0
    return (1);
247
0
  if (t1->nanoseconds < t2->nanoseconds)
248
0
    return (-1);
249
0
  if (t1->nanoseconds > t2->nanoseconds)
250
0
    return (1);
251
0
  return (0);
252
0
}
253
254
isc_result_t
255
isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
256
0
{
257
0
  REQUIRE(t != NULL && i != NULL && result != NULL);
258
0
  INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
259
260
  /*
261
   * Ensure the resulting seconds value fits in the size of an
262
   * unsigned int.  (It is written this way as a slight optimization;
263
   * note that even if both values == INT_MAX, then when added
264
   * and getting another 1 added below the result is UINT_MAX.)
265
   */
266
0
  if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
267
0
      ((long long)t->seconds + i->seconds > UINT_MAX))
268
0
    return (ISC_R_RANGE);
269
270
0
  result->seconds = t->seconds + i->seconds;
271
0
  result->nanoseconds = t->nanoseconds + i->nanoseconds;
272
0
  if (result->nanoseconds >= NS_PER_S) {
273
0
    result->seconds++;
274
0
    result->nanoseconds -= NS_PER_S;
275
0
  }
276
277
0
  return (ISC_R_SUCCESS);
278
0
}
279
280
isc_result_t
281
isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
282
      isc_time_t *result)
283
0
{
284
0
  REQUIRE(t != NULL && i != NULL && result != NULL);
285
0
  INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
286
287
0
  if ((unsigned int)t->seconds < i->seconds ||
288
0
      ((unsigned int)t->seconds == i->seconds &&
289
0
       t->nanoseconds < i->nanoseconds))
290
0
      return (ISC_R_RANGE);
291
292
0
  result->seconds = t->seconds - i->seconds;
293
0
  if (t->nanoseconds >= i->nanoseconds)
294
0
    result->nanoseconds = t->nanoseconds - i->nanoseconds;
295
0
  else {
296
0
    result->nanoseconds = NS_PER_S - i->nanoseconds +
297
0
      t->nanoseconds;
298
0
    result->seconds--;
299
0
  }
300
301
0
  return (ISC_R_SUCCESS);
302
0
}
303
304
isc_uint64_t
305
0
isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
306
0
  isc_uint64_t i1, i2, i3;
307
308
0
  REQUIRE(t1 != NULL && t2 != NULL);
309
0
  INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
310
311
0
  i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
312
0
  i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
313
314
0
  if (i1 <= i2)
315
0
    return (0);
316
317
0
  i3 = i1 - i2;
318
319
  /*
320
   * Convert to microseconds.
321
   */
322
0
  i3 /= NS_PER_US;
323
324
0
  return (i3);
325
0
}
326
327
isc_uint32_t
328
0
isc_time_seconds(const isc_time_t *t) {
329
0
  REQUIRE(t != NULL);
330
0
  INSIST(t->nanoseconds < NS_PER_S);
331
332
0
  return ((isc_uint32_t)t->seconds);
333
0
}
334
335
isc_result_t
336
0
isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
337
0
  time_t seconds;
338
339
0
  REQUIRE(t != NULL);
340
0
  INSIST(t->nanoseconds < NS_PER_S);
341
342
  /*
343
   * Ensure that the number of seconds represented by t->seconds
344
   * can be represented by a time_t.  Since t->seconds is an unsigned
345
   * int and since time_t is mostly opaque, this is trickier than
346
   * it seems.  (This standardized opaqueness of time_t is *very*
347
   * frustrating; time_t is not even limited to being an integral
348
   * type.)
349
   *
350
   * The mission, then, is to avoid generating any kind of warning
351
   * about "signed versus unsigned" while trying to determine if the
352
   * the unsigned int t->seconds is out range for tv_sec, which is
353
   * pretty much only true if time_t is a signed integer of the same
354
   * size as the return value of isc_time_seconds.
355
   *
356
   * If the paradox in the if clause below is true, t->seconds is out
357
   * of range for time_t.
358
   */
359
0
  seconds = (time_t)t->seconds;
360
361
0
  INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
362
0
  INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
363
364
0
  if (t->seconds > (~0U>>1) && seconds <= (time_t)(~0U>>1))
365
0
    return (ISC_R_RANGE);
366
367
0
  *secondsp = seconds;
368
369
0
  return (ISC_R_SUCCESS);
370
0
}
371
372
isc_uint32_t
373
0
isc_time_nanoseconds(const isc_time_t *t) {
374
0
  REQUIRE(t != NULL);
375
376
0
  ENSURE(t->nanoseconds < NS_PER_S);
377
378
0
  return ((isc_uint32_t)t->nanoseconds);
379
0
}
380
381
void
382
0
isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
383
0
  time_t now;
384
0
  unsigned int flen;
385
386
0
  REQUIRE(len > 0);
387
388
0
  now = (time_t) t->seconds;
389
0
  flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now));
390
0
  INSIST(flen < len);
391
0
  if (flen != 0)
392
0
    snprintf(buf + flen, len - flen,
393
0
       ".%03u", t->nanoseconds / 1000000);
394
0
  else
395
0
    snprintf(buf, len, "99-Bad-9999 99:99:99.999");
396
0
}
397
398
void
399
0
isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
400
0
  time_t now;
401
0
  unsigned int flen;
402
403
0
  REQUIRE(len > 0);
404
405
0
  now = (time_t)t->seconds;
406
0
  flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
407
0
  INSIST(flen < len);
408
0
}
409
410
void
411
0
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
412
0
  time_t now;
413
0
  unsigned int flen;
414
415
0
  REQUIRE(len > 0);
416
417
0
  now = (time_t)t->seconds;
418
0
  flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
419
0
  INSIST(flen < len);
420
0
}