09b9db3c91786130fc095df5055098964e7cdb83Tinderbox User * Copyright (C) 1998-2001, 2003-2008, 2011, 2012, 2014-2018 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6e3a8256eed85f6704861d269ccfb35bdaeed5ffDavid Lawrence#include <sys/time.h> /* Required for struct timeval on some platforms. */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
bb5d14d7243d71e03d262ff175b355b52873e195Evan Hunt#define NS_PER_MS 1000000 /*%< Nanoseconds per millisecond. */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#define US_PER_S 1000000 /*%< Microseconds per second. */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * consistency checking of the type. In lieu of magic numbers, it
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * is the best we've got. The check is only performed on functions which
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * need an initialized type.
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley *** Intervals
27809a2ee5db141b684e53bf1d94da26e9f92d3aMark Andrewsstatic const isc_interval_t zero_interval = { 0, 0 };
27809a2ee5db141b684e53bf1d94da26e9f92d3aMark Andrewsconst isc_interval_t * const isc_interval_zero = &zero_interval;
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrewsstatic inline void
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews * Call syslog directly as was are called from the logging functions.
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence unsigned int seconds, unsigned int nanoseconds)
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_interval_iszero(const isc_interval_t *i) {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley *** Absolute Times
27809a2ee5db141b684e53bf1d94da26e9f92d3aMark Andrewsconst isc_time_t * const isc_time_epoch = &epoch;
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrenceisc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * then this test will generate warnings for platforms on which it is
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * unsigned. In any event, the chances of any of these problems
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * happening are pretty much zero, but since the libisc library ensures
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * certain things to be true ...
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Ensure the tv_sec value fits in t->seconds.
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (sizeof(tv.tv_sec) > sizeof(t->seconds) &&
5eb91bd90e3ad3426e5e3213031556a737cf3809Mark Andrews ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U)
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * then this test will generate warnings for platforms on which it is
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * unsigned. In any event, the chances of any of these problems
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * happening are pretty much zero, but since the libisc library ensures
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * certain things to be true ...
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Ensure the resulting seconds value fits in the size of an
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * unsigned int. (It is written this way as a slight optimization;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * note that even if both values == INT_MAX, then when added
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * and getting another 1 added below the result is UINT_MAX.)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence ((long long)tv.tv_sec + i->seconds > UINT_MAX))
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley return (-1);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley return (-1);
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley REQUIRE(t != NULL && i != NULL && result != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Ensure the resulting seconds value fits in the size of an
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * unsigned int. (It is written this way as a slight optimization;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * note that even if both values == INT_MAX, then when added
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * and getting another 1 added below the result is UINT_MAX.)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence ((long long)t->seconds + i->seconds > UINT_MAX))
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley result->nanoseconds = t->nanoseconds + i->nanoseconds;
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley REQUIRE(t != NULL && i != NULL && result != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley result->nanoseconds = t->nanoseconds - i->nanoseconds;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence result->nanoseconds = NS_PER_S - i->nanoseconds +
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence * Convert to microseconds.
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Ensure that the number of seconds represented by t->seconds
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * can be represented by a time_t. Since t->seconds is an unsigned
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * int and since time_t is mostly opaque, this is trickier than
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * it seems. (This standardized opaqueness of time_t is *very*
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * frustrating; time_t is not even limited to being an integral
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * The mission, then, is to avoid generating any kind of warning
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * about "signed versus unsigned" while trying to determine if the
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * the unsigned int t->seconds is out range for tv_sec, which is
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * pretty much only true if time_t is a signed integer of the same
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * size as the return value of isc_time_seconds.
269c07173e24d7811e2fd09304023e3104fcbe0bMark Andrews * If the paradox in the if clause below is true, t->seconds is out
269c07173e24d7811e2fd09304023e3104fcbe0bMark Andrews * of range for time_t.
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
5fa46bc91672ef5737aee6f99763161511566c24Tinderbox User if (t->seconds > (~0U>>1) && seconds <= (time_t)(~0U>>1))
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_time_nanoseconds(const isc_time_t *t) {
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafssonisc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews flen = strftime(buf, len, "%d-%b-%Y %X", localtime_r(&now, &tm));
c36f45e354c0d5b6ab9f821bfe315d0ce9d95a29Mark Andrews flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now));
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrewsisc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
591389c7d44e5ca20c357627dd179772cfefaaccEvan Hunt * 5 spaces, 1 comma, 3 GMT, 2 %d, 4 %Y, 8 %H:%M:%S, 3+ %a, 3+ %b (29+)
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT",
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntisc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
a147de10fe5e19e593d42152ffd6879eca69860dEvan Hunt p = isc_tm_strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm);
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrewsisc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm));
96ea71632887c58a9d00f47eb318bf76b35903c3Mark Andrews flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
bb5d14d7243d71e03d262ff175b355b52873e195Evan Huntisc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) {
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm));