Annotation of embedaddon/ntp/lib/isc/unix/time.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
! 3: * Copyright (C) 1998-2001, 2003 Internet Software Consortium.
! 4: *
! 5: * Permission to use, copy, modify, and/or distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
! 15: * PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: /* $Id: time.c,v 1.56 2008/02/15 23:46:51 tbox Exp $ */
! 19:
! 20: /*! \file */
! 21:
! 22: #include <config.h>
! 23:
! 24: #include <errno.h>
! 25: #include <limits.h>
! 26: #include <syslog.h>
! 27: #include <time.h>
! 28:
! 29: #include <sys/time.h> /* Required for struct timeval on some platforms. */
! 30:
! 31: #include <isc/log.h>
! 32: #include <isc/print.h>
! 33: #include <isc/strerror.h>
! 34: #include <isc/string.h>
! 35: #include <isc/time.h>
! 36: #include <isc/util.h>
! 37:
! 38: #define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
! 39: #define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
! 40: #define US_PER_S 1000000 /*%< Microseconds per second. */
! 41:
! 42: /*
! 43: * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
! 44: * consistency checking of the type. In lieu of magic numbers, it
! 45: * is the best we've got. The check is only performed on functions which
! 46: * need an initialized type.
! 47: */
! 48:
! 49: #ifndef ISC_FIX_TV_USEC
! 50: #define ISC_FIX_TV_USEC 1
! 51: #endif
! 52:
! 53: /*%
! 54: *** Intervals
! 55: ***/
! 56:
! 57: static isc_interval_t zero_interval = { 0, 0 };
! 58: isc_interval_t *isc_interval_zero = &zero_interval;
! 59:
! 60: #if ISC_FIX_TV_USEC
! 61: static inline void
! 62: fix_tv_usec(struct timeval *tv) {
! 63: isc_boolean_t fixed = ISC_FALSE;
! 64:
! 65: if (tv->tv_usec < 0) {
! 66: fixed = ISC_TRUE;
! 67: do {
! 68: tv->tv_sec -= 1;
! 69: tv->tv_usec += US_PER_S;
! 70: } while (tv->tv_usec < 0);
! 71: } else if (tv->tv_usec >= US_PER_S) {
! 72: fixed = ISC_TRUE;
! 73: do {
! 74: tv->tv_sec += 1;
! 75: tv->tv_usec -= US_PER_S;
! 76: } while (tv->tv_usec >=US_PER_S);
! 77: }
! 78: /*
! 79: * Call syslog directly as was are called from the logging functions.
! 80: */
! 81: if (fixed)
! 82: (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
! 83: }
! 84: #endif
! 85:
! 86: void
! 87: isc_interval_set(isc_interval_t *i,
! 88: unsigned int seconds, unsigned int nanoseconds)
! 89: {
! 90: REQUIRE(i != NULL);
! 91: REQUIRE(nanoseconds < NS_PER_S);
! 92:
! 93: i->seconds = seconds;
! 94: i->nanoseconds = nanoseconds;
! 95: }
! 96:
! 97: isc_boolean_t
! 98: isc_interval_iszero(const isc_interval_t *i) {
! 99: REQUIRE(i != NULL);
! 100: INSIST(i->nanoseconds < NS_PER_S);
! 101:
! 102: if (i->seconds == 0 && i->nanoseconds == 0)
! 103: return (ISC_TRUE);
! 104:
! 105: return (ISC_FALSE);
! 106: }
! 107:
! 108:
! 109: /***
! 110: *** Absolute Times
! 111: ***/
! 112:
! 113: static isc_time_t epoch = { 0, 0 };
! 114: isc_time_t *isc_time_epoch = &epoch;
! 115:
! 116: void
! 117: isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
! 118: REQUIRE(t != NULL);
! 119: REQUIRE(nanoseconds < NS_PER_S);
! 120:
! 121: t->seconds = seconds;
! 122: t->nanoseconds = nanoseconds;
! 123: }
! 124:
! 125: void
! 126: isc_time_settoepoch(isc_time_t *t) {
! 127: REQUIRE(t != NULL);
! 128:
! 129: t->seconds = 0;
! 130: t->nanoseconds = 0;
! 131: }
! 132:
! 133: isc_boolean_t
! 134: isc_time_isepoch(const isc_time_t *t) {
! 135: REQUIRE(t != NULL);
! 136: INSIST(t->nanoseconds < NS_PER_S);
! 137:
! 138: if (t->seconds == 0 && t->nanoseconds == 0)
! 139: return (ISC_TRUE);
! 140:
! 141: return (ISC_FALSE);
! 142: }
! 143:
! 144:
! 145: isc_result_t
! 146: isc_time_now(isc_time_t *t) {
! 147: struct timeval tv;
! 148: char strbuf[ISC_STRERRORSIZE];
! 149:
! 150: REQUIRE(t != NULL);
! 151:
! 152: if (gettimeofday(&tv, NULL) == -1) {
! 153: isc__strerror(errno, strbuf, sizeof(strbuf));
! 154: UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
! 155: return (ISC_R_UNEXPECTED);
! 156: }
! 157:
! 158: /*
! 159: * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
! 160: * then this test will generate warnings for platforms on which it is
! 161: * unsigned. In any event, the chances of any of these problems
! 162: * happening are pretty much zero, but since the libisc library ensures
! 163: * certain things to be true ...
! 164: */
! 165: #if ISC_FIX_TV_USEC
! 166: fix_tv_usec(&tv);
! 167: if (tv.tv_sec < 0)
! 168: return (ISC_R_UNEXPECTED);
! 169: #else
! 170: if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
! 171: return (ISC_R_UNEXPECTED);
! 172: #endif
! 173:
! 174: /*
! 175: * Ensure the tv_sec value fits in t->seconds.
! 176: */
! 177: if (sizeof(tv.tv_sec) > sizeof(t->seconds) &&
! 178: ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U)
! 179: return (ISC_R_RANGE);
! 180:
! 181: t->seconds = tv.tv_sec;
! 182: t->nanoseconds = tv.tv_usec * NS_PER_US;
! 183:
! 184: return (ISC_R_SUCCESS);
! 185: }
! 186:
! 187: isc_result_t
! 188: isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
! 189: struct timeval tv;
! 190: char strbuf[ISC_STRERRORSIZE];
! 191:
! 192: REQUIRE(t != NULL);
! 193: REQUIRE(i != NULL);
! 194: INSIST(i->nanoseconds < NS_PER_S);
! 195:
! 196: if (gettimeofday(&tv, NULL) == -1) {
! 197: isc__strerror(errno, strbuf, sizeof(strbuf));
! 198: UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
! 199: return (ISC_R_UNEXPECTED);
! 200: }
! 201:
! 202: /*
! 203: * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
! 204: * then this test will generate warnings for platforms on which it is
! 205: * unsigned. In any event, the chances of any of these problems
! 206: * happening are pretty much zero, but since the libisc library ensures
! 207: * certain things to be true ...
! 208: */
! 209: #if ISC_FIX_TV_USEC
! 210: fix_tv_usec(&tv);
! 211: if (tv.tv_sec < 0)
! 212: return (ISC_R_UNEXPECTED);
! 213: #else
! 214: if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
! 215: return (ISC_R_UNEXPECTED);
! 216: #endif
! 217:
! 218: /*
! 219: * Ensure the resulting seconds value fits in the size of an
! 220: * unsigned int. (It is written this way as a slight optimization;
! 221: * note that even if both values == INT_MAX, then when added
! 222: * and getting another 1 added below the result is UINT_MAX.)
! 223: */
! 224: if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
! 225: ((long long)tv.tv_sec + i->seconds > UINT_MAX))
! 226: return (ISC_R_RANGE);
! 227:
! 228: t->seconds = tv.tv_sec + i->seconds;
! 229: t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
! 230: if (t->nanoseconds >= NS_PER_S) {
! 231: t->seconds++;
! 232: t->nanoseconds -= NS_PER_S;
! 233: }
! 234:
! 235: return (ISC_R_SUCCESS);
! 236: }
! 237:
! 238: int
! 239: isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
! 240: REQUIRE(t1 != NULL && t2 != NULL);
! 241: INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
! 242:
! 243: if (t1->seconds < t2->seconds)
! 244: return (-1);
! 245: if (t1->seconds > t2->seconds)
! 246: return (1);
! 247: if (t1->nanoseconds < t2->nanoseconds)
! 248: return (-1);
! 249: if (t1->nanoseconds > t2->nanoseconds)
! 250: return (1);
! 251: return (0);
! 252: }
! 253:
! 254: isc_result_t
! 255: isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
! 256: {
! 257: REQUIRE(t != NULL && i != NULL && result != NULL);
! 258: INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
! 259:
! 260: /*
! 261: * Ensure the resulting seconds value fits in the size of an
! 262: * unsigned int. (It is written this way as a slight optimization;
! 263: * note that even if both values == INT_MAX, then when added
! 264: * and getting another 1 added below the result is UINT_MAX.)
! 265: */
! 266: if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
! 267: ((long long)t->seconds + i->seconds > UINT_MAX))
! 268: return (ISC_R_RANGE);
! 269:
! 270: result->seconds = t->seconds + i->seconds;
! 271: result->nanoseconds = t->nanoseconds + i->nanoseconds;
! 272: if (result->nanoseconds >= NS_PER_S) {
! 273: result->seconds++;
! 274: result->nanoseconds -= NS_PER_S;
! 275: }
! 276:
! 277: return (ISC_R_SUCCESS);
! 278: }
! 279:
! 280: isc_result_t
! 281: isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
! 282: isc_time_t *result)
! 283: {
! 284: REQUIRE(t != NULL && i != NULL && result != NULL);
! 285: INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
! 286:
! 287: if ((unsigned int)t->seconds < i->seconds ||
! 288: ((unsigned int)t->seconds == i->seconds &&
! 289: t->nanoseconds < i->nanoseconds))
! 290: return (ISC_R_RANGE);
! 291:
! 292: result->seconds = t->seconds - i->seconds;
! 293: if (t->nanoseconds >= i->nanoseconds)
! 294: result->nanoseconds = t->nanoseconds - i->nanoseconds;
! 295: else {
! 296: result->nanoseconds = NS_PER_S - i->nanoseconds +
! 297: t->nanoseconds;
! 298: result->seconds--;
! 299: }
! 300:
! 301: return (ISC_R_SUCCESS);
! 302: }
! 303:
! 304: isc_uint64_t
! 305: isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
! 306: isc_uint64_t i1, i2, i3;
! 307:
! 308: REQUIRE(t1 != NULL && t2 != NULL);
! 309: INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
! 310:
! 311: i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
! 312: i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
! 313:
! 314: if (i1 <= i2)
! 315: return (0);
! 316:
! 317: i3 = i1 - i2;
! 318:
! 319: /*
! 320: * Convert to microseconds.
! 321: */
! 322: i3 = (i1 - i2) / NS_PER_US;
! 323:
! 324: return (i3);
! 325: }
! 326:
! 327: isc_uint32_t
! 328: isc_time_seconds(const isc_time_t *t) {
! 329: REQUIRE(t != NULL);
! 330: INSIST(t->nanoseconds < NS_PER_S);
! 331:
! 332: return ((isc_uint32_t)t->seconds);
! 333: }
! 334:
! 335: isc_result_t
! 336: isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
! 337: isc_uint64_t i;
! 338: time_t seconds;
! 339:
! 340: REQUIRE(t != NULL);
! 341: INSIST(t->nanoseconds < NS_PER_S);
! 342:
! 343: /*
! 344: * Ensure that the number of seconds represented by t->seconds
! 345: * can be represented by a time_t. Since t->seconds is an unsigned
! 346: * int and since time_t is mostly opaque, this is trickier than
! 347: * it seems. (This standardized opaqueness of time_t is *very*
! 348: * frustrating; time_t is not even limited to being an integral
! 349: * type.)
! 350: *
! 351: * The mission, then, is to avoid generating any kind of warning
! 352: * about "signed versus unsigned" while trying to determine if the
! 353: * the unsigned int t->seconds is out range for tv_sec, which is
! 354: * pretty much only true if time_t is a signed integer of the same
! 355: * size as the return value of isc_time_seconds.
! 356: *
! 357: * The use of the 64 bit integer ``i'' takes advantage of C's
! 358: * conversion rules to either zero fill or sign extend the widened
! 359: * type.
! 360: *
! 361: * Solaris 5.6 gives this warning about the left shift:
! 362: * warning: integer overflow detected: op "<<"
! 363: * if the U(nsigned) qualifier is not on the 1.
! 364: */
! 365: seconds = (time_t)t->seconds;
! 366:
! 367: INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
! 368: INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
! 369:
! 370: if (sizeof(time_t) == sizeof(isc_uint32_t) && /* Same size. */
! 371: (time_t)0.5 != 0.5 && /* Not a floating point type. */
! 372: (i = (time_t)-1) != 4294967295u && /* Is signed. */
! 373: (seconds &
! 374: (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0U) { /* Negative. */
! 375: /*
! 376: * This UNUSED() is here to shut up the IRIX compiler:
! 377: * variable "i" was set but never used
! 378: * when the value of i *was* used in the third test.
! 379: * (Let's hope the compiler got the actual test right.)
! 380: */
! 381: UNUSED(i);
! 382: return (ISC_R_RANGE);
! 383: }
! 384:
! 385: *secondsp = seconds;
! 386:
! 387: return (ISC_R_SUCCESS);
! 388: }
! 389:
! 390: isc_uint32_t
! 391: isc_time_nanoseconds(const isc_time_t *t) {
! 392: REQUIRE(t != NULL);
! 393:
! 394: ENSURE(t->nanoseconds < NS_PER_S);
! 395:
! 396: return ((isc_uint32_t)t->nanoseconds);
! 397: }
! 398:
! 399: void
! 400: isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
! 401: time_t now;
! 402: unsigned int flen;
! 403:
! 404: REQUIRE(len > 0);
! 405:
! 406: now = (time_t) t->seconds;
! 407: flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now));
! 408: INSIST(flen < len);
! 409: if (flen != 0)
! 410: snprintf(buf + flen, len - flen,
! 411: ".%03u", t->nanoseconds / 1000000);
! 412: else
! 413: snprintf(buf, len, "99-Bad-9999 99:99:99.999");
! 414: }
! 415:
! 416: void
! 417: isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
! 418: time_t now;
! 419: unsigned int flen;
! 420:
! 421: REQUIRE(len > 0);
! 422:
! 423: now = (time_t)t->seconds;
! 424: flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
! 425: INSIST(flen < len);
! 426: }
! 427:
! 428: void
! 429: isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
! 430: time_t now;
! 431: unsigned int flen;
! 432:
! 433: REQUIRE(len > 0);
! 434:
! 435: now = (time_t)t->seconds;
! 436: flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
! 437: INSIST(flen < len);
! 438: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>