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