1*ab19a69eSdjm /*
2*ab19a69eSdjm * Copyright (c) 2021 Yubico AB. All rights reserved.
3*ab19a69eSdjm * Use of this source code is governed by a BSD-style
4*ab19a69eSdjm * license that can be found in the LICENSE file.
5*ab19a69eSdjm */
6*ab19a69eSdjm
7*ab19a69eSdjm #include <errno.h>
8*ab19a69eSdjm #include "fido.h"
9*ab19a69eSdjm
10*ab19a69eSdjm static int
timespec_to_ms(const struct timespec * ts)11*ab19a69eSdjm timespec_to_ms(const struct timespec *ts)
12*ab19a69eSdjm {
13*ab19a69eSdjm int64_t x, y;
14*ab19a69eSdjm
15*ab19a69eSdjm if (ts->tv_sec < 0 || ts->tv_nsec < 0 ||
16*ab19a69eSdjm ts->tv_nsec >= 1000000000LL)
17*ab19a69eSdjm return -1;
18*ab19a69eSdjm
19*ab19a69eSdjm if ((uint64_t)ts->tv_sec >= INT64_MAX / 1000LL)
20*ab19a69eSdjm return -1;
21*ab19a69eSdjm
22*ab19a69eSdjm x = ts->tv_sec * 1000LL;
23*ab19a69eSdjm y = ts->tv_nsec / 1000000LL;
24*ab19a69eSdjm
25*ab19a69eSdjm if (INT64_MAX - x < y || x + y > INT_MAX)
26*ab19a69eSdjm return -1;
27*ab19a69eSdjm
28*ab19a69eSdjm return (int)(x + y);
29*ab19a69eSdjm }
30*ab19a69eSdjm
31*ab19a69eSdjm int
fido_time_now(struct timespec * ts_now)32*ab19a69eSdjm fido_time_now(struct timespec *ts_now)
33*ab19a69eSdjm {
34*ab19a69eSdjm if (clock_gettime(CLOCK_MONOTONIC, ts_now) != 0) {
35*ab19a69eSdjm fido_log_error(errno, "%s: clock_gettime", __func__);
36*ab19a69eSdjm return -1;
37*ab19a69eSdjm }
38*ab19a69eSdjm
39*ab19a69eSdjm return 0;
40*ab19a69eSdjm }
41*ab19a69eSdjm
42*ab19a69eSdjm int
fido_time_delta(const struct timespec * ts_start,int * ms_remain)43*ab19a69eSdjm fido_time_delta(const struct timespec *ts_start, int *ms_remain)
44*ab19a69eSdjm {
45*ab19a69eSdjm struct timespec ts_end, ts_delta;
46*ab19a69eSdjm int ms;
47*ab19a69eSdjm
48*ab19a69eSdjm if (*ms_remain < 0)
49*ab19a69eSdjm return 0;
50*ab19a69eSdjm
51*ab19a69eSdjm if (clock_gettime(CLOCK_MONOTONIC, &ts_end) != 0) {
52*ab19a69eSdjm fido_log_error(errno, "%s: clock_gettime", __func__);
53*ab19a69eSdjm return -1;
54*ab19a69eSdjm }
55*ab19a69eSdjm
56*ab19a69eSdjm if (timespeccmp(&ts_end, ts_start, <)) {
57*ab19a69eSdjm fido_log_debug("%s: timespeccmp", __func__);
58*ab19a69eSdjm return -1;
59*ab19a69eSdjm }
60*ab19a69eSdjm
61*ab19a69eSdjm timespecsub(&ts_end, ts_start, &ts_delta);
62*ab19a69eSdjm
63*ab19a69eSdjm if ((ms = timespec_to_ms(&ts_delta)) < 0) {
64*ab19a69eSdjm fido_log_debug("%s: timespec_to_ms", __func__);
65*ab19a69eSdjm return -1;
66*ab19a69eSdjm }
67*ab19a69eSdjm
68*ab19a69eSdjm if (ms > *ms_remain)
69*ab19a69eSdjm ms = *ms_remain;
70*ab19a69eSdjm
71*ab19a69eSdjm *ms_remain -= ms;
72*ab19a69eSdjm
73*ab19a69eSdjm return 0;
74*ab19a69eSdjm }
75