time.c revision 33f87146a856eb6c3dfd55a8ee9c173c94f82150
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff/*
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * Copyright (C) 1998-2001 Internet Software Consortium.
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff *
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * Permission to use, copy, modify, and distribute this software for any
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * purpose with or without fee is hereby granted, provided that the above
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * copyright notice and this permission notice appear in all copies.
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff *
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff */
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff/* $Id: time.c,v 1.39 2001/09/05 17:03:42 gson Exp $ */
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <config.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <errno.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <limits.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <syslog.h>
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff#include <time.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <sys/time.h> /* Required for struct timeval on some platforms. */
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <isc/log.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <isc/print.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <isc/strerror.h>
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#include <isc/string.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <isc/time.h>
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <isc/util.h>
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#define NS_PER_S 1000000000 /* Nanoseconds per second. */
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#define NS_PER_US 1000 /* Nanoseconds per microsecond. */
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#define US_PER_S 1000000 /* Microseconds per second. */
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff/*
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * consistency checking of the type. In lieu of magic numbers, it
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * is the best we've got. The check is only performed on functions which
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * need an initialized type.
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff */
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#ifndef ISC_FIX_TV_USEC
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#define ISC_FIX_TV_USEC 1
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#endif
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff/***
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff *** Intervals
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff ***/
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graffstatic isc_interval_t zero_interval = { 0, 0 };
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graffisc_interval_t *isc_interval_zero = &zero_interval;
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#if ISC_FIX_TV_USEC
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffstatic inline void
910df98b0efcbe8380b952887f4071051cc39a25Michael Grafffix_tv_usec(struct timeval *tv) {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff isc_boolean_t fixed = ISC_FALSE;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff if (tv->tv_usec < 0) {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff fixed = ISC_TRUE;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff do {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff tv->tv_sec -= 1;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff tv->tv_usec += US_PER_S;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff } while (tv->tv_usec < 0);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff } else if (tv->tv_usec >= US_PER_S) {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff fixed = ISC_TRUE;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff do {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff tv->tv_sec += 1;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff tv->tv_usec -= US_PER_S;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff } while (tv->tv_usec >=US_PER_S);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff }
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff /*
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * Call syslog directly as was are called from the logging functions.
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff */
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (fixed)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#endif
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffvoid
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_interval_set(isc_interval_t *i,
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff unsigned int seconds, unsigned int nanoseconds)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff{
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(i != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(nanoseconds < NS_PER_S);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff i->seconds = seconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff i->nanoseconds = nanoseconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_boolean_t
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_interval_iszero(isc_interval_t *i) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(i != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(i->nanoseconds < NS_PER_S);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (i->seconds == 0 && i->nanoseconds == 0)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_TRUE);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_FALSE);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff/***
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff *** Absolute Times
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff ***/
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffstatic isc_time_t epoch = { 0, 0 };
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_t *isc_time_epoch = &epoch;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffvoid
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(t != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(nanoseconds < NS_PER_S);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->seconds = seconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->nanoseconds = nanoseconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffvoid
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_settoepoch(isc_time_t *t) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(t != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->seconds = 0;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->nanoseconds = 0;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_boolean_t
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_isepoch(isc_time_t *t) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(t != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(t->nanoseconds < NS_PER_S);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (t->seconds == 0 && t->nanoseconds == 0)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_TRUE);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_FALSE);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_result_t
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_now(isc_time_t *t) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff struct timeval tv;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff char strbuf[ISC_STRERRORSIZE];
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(t != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (gettimeofday(&tv, NULL) == -1) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff isc__strerror(errno, strbuf, sizeof(strbuf));
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_R_UNEXPECTED);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff }
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff /*
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * then this test will generate warnings for platforms on which it is
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * unsigned. In any event, the chances of any of these problems
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * happening are pretty much zero, but since the libisc library ensures
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * certain things to be true ...
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff */
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#if ISC_FIX_TV_USEC
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff fix_tv_usec(&tv);
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff if (tv.tv_sec < 0)
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff return (ISC_R_UNEXPECTED);
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff#else
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff return (ISC_R_UNEXPECTED);
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff#endif
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff /*
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * Ensure the tv_sec value fits in t->seconds.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff */
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff if (sizeof(tv.tv_sec) > sizeof(t->seconds) &&
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0)
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff return (ISC_R_RANGE);
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff t->seconds = tv.tv_sec;
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff t->nanoseconds = tv.tv_usec * NS_PER_US;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_R_SUCCESS);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_result_t
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_nowplusinterval(isc_time_t *t, isc_interval_t *i) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff struct timeval tv;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff char strbuf[ISC_STRERRORSIZE];
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(t != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(i != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(i->nanoseconds < NS_PER_S);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (gettimeofday(&tv, NULL) == -1) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff isc__strerror(errno, strbuf, sizeof(strbuf));
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_R_UNEXPECTED);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff }
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff /*
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * then this test will generate warnings for platforms on which it is
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * unsigned. In any event, the chances of any of these problems
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * happening are pretty much zero, but since the libisc library ensures
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * certain things to be true ...
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff */
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#if ISC_FIX_TV_USEC
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff fix_tv_usec(&tv);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (tv.tv_sec < 0)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_R_UNEXPECTED);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#else
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_R_UNEXPECTED);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff#endif
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff /*
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * Ensure the resulting seconds value fits in the size of an
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * unsigned int. (It is written this way as a slight optimization;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * note that even if both values == INT_MAX, then when added
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * and getting another 1 added below the result is UINT_MAX.)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff */
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff ((long long)tv.tv_sec + i->seconds > UINT_MAX))
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_R_RANGE);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->seconds = tv.tv_sec + i->seconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (t->nanoseconds > NS_PER_S) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->seconds++;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->nanoseconds -= NS_PER_S;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff }
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (ISC_R_SUCCESS);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff}
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffint
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_compare(isc_time_t *t1, isc_time_t *t2) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(t1 != NULL && t2 != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (t1->seconds < t2->seconds)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (-1);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (t1->seconds > t2->seconds)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (1);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (t1->nanoseconds < t2->nanoseconds)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (-1);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff if (t1->nanoseconds > t2->nanoseconds)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff return (1);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff return (0);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff}
da547174e2b7beb6d6119d58197ad0bc85b91179Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_result_t
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_time_add(isc_time_t *t, isc_interval_t *i, isc_time_t *result) {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff REQUIRE(t != NULL && i != NULL && result != NULL);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff /*
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * Ensure the resulting seconds value fits in the size of an
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * unsigned int. (It is written this way as a slight optimization;
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * note that even if both values == INT_MAX, then when added
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff * and getting another 1 added below the result is UINT_MAX.)
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff */
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
da547174e2b7beb6d6119d58197ad0bc85b91179Michael Graff ((long long)t->seconds + i->seconds > UINT_MAX))
da547174e2b7beb6d6119d58197ad0bc85b91179Michael Graff return (ISC_R_RANGE);
da547174e2b7beb6d6119d58197ad0bc85b91179Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff result->seconds = t->seconds + i->seconds;
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff result->nanoseconds = t->nanoseconds + i->nanoseconds;
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff if (result->nanoseconds >= NS_PER_S) {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff result->seconds++;
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff result->nanoseconds -= NS_PER_S;
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff }
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff return (ISC_R_SUCCESS);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff}
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_result_t
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_time_subtract(isc_time_t *t, isc_interval_t *i, isc_time_t *result) {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff REQUIRE(t != NULL && i != NULL && result != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff if ((unsigned int)t->seconds < i->seconds ||
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff ((unsigned int)t->seconds == i->seconds &&
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff t->nanoseconds < i->nanoseconds))
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff return (ISC_R_RANGE);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff result->seconds = t->seconds - i->seconds;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff if (t->nanoseconds >= i->nanoseconds)
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff result->nanoseconds = t->nanoseconds - i->nanoseconds;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff else {
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff result->nanoseconds = NS_PER_S - i->nanoseconds +
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->nanoseconds;
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff result->seconds--;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff }
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff return (ISC_R_SUCCESS);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff}
82a083ceb7ba067448960d5120f4a6d35b573e28Bob Halley
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_uint64_t
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_time_microdiff(isc_time_t *t1, isc_time_t *t2) {
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff isc_uint64_t i1, i2, i3;
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff REQUIRE(t1 != NULL && t2 != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff if (i1 <= i2)
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff return (0);
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff i3 = i1 - i2;
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff /*
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff * Convert to microseconds.
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff */
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff i3 = (i1 - i2) / NS_PER_US;
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff return (i3);
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff}
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graffisc_uint32_t
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_time_seconds(isc_time_t *t) {
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff REQUIRE(t != NULL);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff INSIST(t->nanoseconds < NS_PER_S);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff return ((isc_uint32_t)t->seconds);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff}
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graffisc_result_t
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graffisc_time_secondsastimet(isc_time_t *t, time_t *secondsp) {
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff isc_uint64_t i;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff time_t seconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff REQUIRE(t != NULL);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(t->nanoseconds < NS_PER_S);
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff /*
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * Ensure that the number of seconds represented by t->seconds
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * can be represented by a time_t. Since t->seconds is an unsigned
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * int and since time_t is mostly opaque, this is trickier than
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * it seems. (This standardized opaqueness of time_t is *very*
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * frustrating; time_t is not even limited to being an integral
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * type.)
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff *
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * The mission, then, is to avoid generating any kind of warning
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff * about "signed versus unsigned" while trying to determine if the
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * the unsigned int t->seconds is out range for tv_sec, which is
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff * pretty much only true if time_t is a signed integer of the same
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * size as the return value of isc_time_seconds.
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff *
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * The use of the 64 bit integer ``i'' takes advantage of C's
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff * conversion rules to either zero fill or sign extend the widened
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * type.
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff *
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff * Solaris 5.6 gives this warning about the left shift:
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff * warning: integer overflow detected: op "<<"
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff * if the U(nsigned) qualifier is not on the 1.
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff */
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff seconds = (time_t)t->seconds;
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff if (sizeof(time_t) == sizeof(isc_uint32_t) && /* Same size. */
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff (time_t)0.5 != 0.5 && /* Not a floating point type. */
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff (i = (time_t)-1) != 4294967295u && /* Is signed. */
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff (seconds &
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0) { /* Negative. */
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff /*
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * This UNUSED() is here to shut up the IRIX compiler:
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff * variable "i" was set but never used
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * when the value of i *was* used in the third test.
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * (Let's hope the compiler got the actual test right.)
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff */
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff UNUSED(i);
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff return (ISC_R_RANGE);
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff }
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff *secondsp = seconds;
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff return (ISC_R_SUCCESS);
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff}
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graffisc_uint32_t
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graffisc_time_nanoseconds(isc_time_t *t) {
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff REQUIRE(t != NULL);
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff ENSURE(t->nanoseconds < NS_PER_S);
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff return ((isc_uint32_t)t->nanoseconds);
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff}
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graffvoid
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graffisc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff time_t now;
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff unsigned int flen;
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff REQUIRE(len > 0);
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff now = (time_t) t->seconds;
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff strftime(buf, len, "%b %d %X", localtime(&now));
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff flen = strlen(buf);
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff snprintf(buf + flen, len - flen,
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff ".%03u", t->nanoseconds / 1000000);
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff}
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff