Annotation of embedaddon/ntp/lib/isc/unix/time.c, revision 1.1.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>