time.c revision 33f87146a856eb6c3dfd55a8ee9c173c94f82150
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff * Copyright (C) 1998-2001 Internet Software Consortium.
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 * 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/* $Id: time.c,v 1.39 2001/09/05 17:03:42 gson Exp $ */
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff#include <sys/time.h> /* Required for struct timeval on some platforms. */
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 * 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 *** Intervals
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graffstatic isc_interval_t zero_interval = { 0, 0 };
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graffisc_interval_t *isc_interval_zero = &zero_interval;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffstatic inline void
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff * Call syslog directly as was are called from the logging functions.
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff unsigned int seconds, unsigned int nanoseconds)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff *** Absolute Times
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
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 ...
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * Ensure the tv_sec value fits in t->seconds.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0)
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_nowplusinterval(isc_time_t *t, isc_interval_t *i) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
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 if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
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 if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff ((long long)tv.tv_sec + i->seconds > UINT_MAX))
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graffisc_time_compare(isc_time_t *t1, isc_time_t *t2) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
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 * 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.)
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
da547174e2b7beb6d6119d58197ad0bc85b91179Michael Graff ((long long)t->seconds + i->seconds > UINT_MAX))
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff result->nanoseconds = t->nanoseconds + i->nanoseconds;
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 result->nanoseconds = t->nanoseconds - i->nanoseconds;
910df98b0efcbe8380b952887f4071051cc39a25Michael Graff result->nanoseconds = NS_PER_S - i->nanoseconds +
910df98b0efcbe8380b952887f4071051cc39a25Michael Graffisc_time_microdiff(isc_time_t *t1, isc_time_t *t2) {
efc8a09e19dfcfafa92fd2ad113073a4f5295e9bMichael Graff INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
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 * Convert to microseconds.
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graffisc_time_secondsastimet(isc_time_t *t, time_t *secondsp) {
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 * 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 * 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
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.
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
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 (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0) { /* Negative. */
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.)
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graffisc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff unsigned int flen;
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff strftime(buf, len, "%b %d %X", localtime(&now));