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>