[BACK]Return to time.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / bind / dist / lib / dns

Annotation of src/external/mpl/bind/dist/lib/dns/time.c, Revision 1.4

1.2       christos    1: /*     $NetBSD: time.c,v 1.1.1.11 2018/04/07 21:44:07 christos Exp $   */
1.1       christos    2:
                      3: /*
                      4:  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
                      5:  *
                      6:  * This Source Code Form is subject to the terms of the Mozilla Public
                      7:  * License, v. 2.0. If a copy of the MPL was not distributed with this
                      8:  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
                      9:  *
                     10:  * See the COPYRIGHT file distributed with this work for additional
                     11:  * information regarding copyright ownership.
                     12:  */
                     13:
                     14: /*! \file */
                     15:
1.4     ! christos   16: #include <ctype.h>
        !            17: #include <inttypes.h>
1.1       christos   18: #include <stdio.h>
                     19: #include <time.h>
                     20:
                     21: #include <isc/print.h>
                     22: #include <isc/region.h>
                     23: #include <isc/serial.h>
                     24: #include <isc/stdtime.h>
1.4     ! christos   25: #include <isc/string.h> /* Required for HP/UX (and others?) */
1.1       christos   26: #include <isc/util.h>
                     27:
                     28: #include <dns/result.h>
                     29: #include <dns/time.h>
                     30:
                     31: static const int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
                     32:
                     33: isc_result_t
1.3       christos   34: dns_time64_totext(int64_t t, isc_buffer_t *target) {
1.1       christos   35:        struct tm tm;
1.4     ! christos   36:        char buf[sizeof("!!!!!!YYYY!!!!!!!!MM!!!!!!!!DD!!!!!!!!HH!!!!!!!!MM!!!!"
        !            37:                        "!!!!SS")];
1.1       christos   38:        int secs;
                     39:        unsigned int l;
                     40:        isc_region_t region;
                     41:
                     42: /*
                     43:  * Warning. Do NOT use arguments with side effects with these macros.
                     44:  */
1.4     ! christos   45: #define is_leap(y)      ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
        !            46: #define year_secs(y)    ((is_leap(y) ? 366 : 365) * 86400)
        !            47: #define month_secs(m, y) ((days[m] + ((m == 1 && is_leap(y)) ? 1 : 0)) * 86400)
1.1       christos   48:
                     49:        tm.tm_year = 70;
                     50:        while (t < 0) {
1.4     ! christos   51:                if (tm.tm_year == 0) {
1.1       christos   52:                        return (ISC_R_RANGE);
1.4     ! christos   53:                }
1.1       christos   54:                tm.tm_year--;
                     55:                secs = year_secs(tm.tm_year + 1900);
                     56:                t += secs;
                     57:        }
                     58:        while ((secs = year_secs(tm.tm_year + 1900)) <= t) {
                     59:                t -= secs;
                     60:                tm.tm_year++;
1.4     ! christos   61:                if (tm.tm_year + 1900 > 9999) {
1.1       christos   62:                        return (ISC_R_RANGE);
1.4     ! christos   63:                }
1.1       christos   64:        }
                     65:        tm.tm_mon = 0;
                     66:        while ((secs = month_secs(tm.tm_mon, tm.tm_year + 1900)) <= t) {
                     67:                t -= secs;
                     68:                tm.tm_mon++;
                     69:        }
                     70:        tm.tm_mday = 1;
                     71:        while (86400 <= t) {
                     72:                t -= 86400;
                     73:                tm.tm_mday++;
                     74:        }
                     75:        tm.tm_hour = 0;
                     76:        while (3600 <= t) {
                     77:                t -= 3600;
                     78:                tm.tm_hour++;
                     79:        }
                     80:        tm.tm_min = 0;
                     81:        while (60 <= t) {
                     82:                t -= 60;
                     83:                tm.tm_min++;
                     84:        }
                     85:        tm.tm_sec = (int)t;
1.4     ! christos   86:        /* yyyy  mm  dd  HH  MM  SS */
1.1       christos   87:        snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02d",
1.4     ! christos   88:                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
        !            89:                 tm.tm_min, tm.tm_sec);
1.1       christos   90:
                     91:        isc_buffer_availableregion(target, &region);
                     92:        l = strlen(buf);
                     93:
1.4     ! christos   94:        if (l > region.length) {
1.1       christos   95:                return (ISC_R_NOSPACE);
1.4     ! christos   96:        }
1.1       christos   97:
                     98:        memmove(region.base, buf, l);
                     99:        isc_buffer_add(target, l);
                    100:        return (ISC_R_SUCCESS);
                    101: }
                    102:
1.3       christos  103: int64_t
                    104: dns_time64_from32(uint32_t value) {
1.1       christos  105:        isc_stdtime_t now;
1.3       christos  106:        int64_t start;
                    107:        int64_t t;
1.1       christos  108:
                    109:        /*
                    110:         * Adjust the time to the closest epoch.  This should be changed
                    111:         * to use a 64-bit counterpart to isc_stdtime_get() if one ever
                    112:         * is defined, but even the current code is good until the year
                    113:         * 2106.
                    114:         */
                    115:        isc_stdtime_get(&now);
1.4     ! christos  116:        start = (int64_t)now;
        !           117:        if (isc_serial_gt(value, now)) {
1.1       christos  118:                t = start + (value - now);
1.4     ! christos  119:        } else {
1.1       christos  120:                t = start - (now - value);
1.4     ! christos  121:        }
1.1       christos  122:
                    123:        return (t);
                    124: }
                    125:
                    126: isc_result_t
1.3       christos  127: dns_time32_totext(uint32_t value, isc_buffer_t *target) {
1.1       christos  128:        return (dns_time64_totext(dns_time64_from32(value), target));
                    129: }
                    130:
                    131: isc_result_t
1.3       christos  132: dns_time64_fromtext(const char *source, int64_t *target) {
1.1       christos  133:        int year, month, day, hour, minute, second;
1.3       christos  134:        int64_t value;
1.1       christos  135:        int secs;
                    136:        int i;
                    137:
1.4     ! christos  138: #define RANGE(min, max, value)                      \
        !           139:        do {                                        \
1.1       christos  140:                if (value < (min) || value > (max)) \
1.4     ! christos  141:                        return ((ISC_R_RANGE));     \
1.2       christos  142:        } while (/*CONSTCOND*/0)
1.1       christos  143:
1.4     ! christos  144:        if (strlen(source) != 14U) {
1.1       christos  145:                return (DNS_R_SYNTAX);
1.4     ! christos  146:        }
1.1       christos  147:        /*
                    148:         * Confirm the source only consists digits.  sscanf() allows some
                    149:         * minor exceptions.
                    150:         */
                    151:        for (i = 0; i < 14; i++) {
1.4     ! christos  152:                if (!isdigit((unsigned char)source[i])) {
1.1       christos  153:                        return (DNS_R_SYNTAX);
1.4     ! christos  154:                }
1.1       christos  155:        }
1.4     ! christos  156:        if (sscanf(source, "%4d%2d%2d%2d%2d%2d", &year, &month, &day, &hour,
        !           157:                   &minute, &second) != 6)
        !           158:        {
1.1       christos  159:                return (DNS_R_SYNTAX);
1.4     ! christos  160:        }
1.1       christos  161:
                    162:        RANGE(0, 9999, year);
                    163:        RANGE(1, 12, month);
1.4     ! christos  164:        RANGE(1, days[month - 1] + ((month == 2 && is_leap(year)) ? 1 : 0),
        !           165:              day);
1.1       christos  166: #ifdef __COVERITY__
                    167:        /*
                    168:         * Use a simplified range to silence Coverity warning (in
                    169:         * arithmetic with day below).
                    170:         */
                    171:        RANGE(1, 31, day);
                    172: #endif /* __COVERITY__ */
                    173:
                    174:        RANGE(0, 23, hour);
                    175:        RANGE(0, 59, minute);
1.4     ! christos  176:        RANGE(0, 60, second); /* 60 == leap second. */
1.1       christos  177:
                    178:        /*
                    179:         * Calculate seconds from epoch.
                    180:         * Note: this uses a idealized calendar.
                    181:         */
                    182:        value = second + (60 * minute) + (3600 * hour) + ((day - 1) * 86400);
1.4     ! christos  183:        for (i = 0; i < (month - 1); i++) {
1.1       christos  184:                value += days[i] * 86400;
1.4     ! christos  185:        }
        !           186:        if (is_leap(year) && month > 2) {
1.1       christos  187:                value += 86400;
1.4     ! christos  188:        }
1.1       christos  189:        if (year < 1970) {
                    190:                for (i = 1969; i >= year; i--) {
                    191:                        secs = (is_leap(i) ? 366 : 365) * 86400;
                    192:                        value -= secs;
                    193:                }
                    194:        } else {
                    195:                for (i = 1970; i < year; i++) {
                    196:                        secs = (is_leap(i) ? 366 : 365) * 86400;
                    197:                        value += secs;
                    198:                }
                    199:        }
                    200:
                    201:        *target = value;
                    202:        return (ISC_R_SUCCESS);
                    203: }
                    204:
                    205: isc_result_t
1.3       christos  206: dns_time32_fromtext(const char *source, uint32_t *target) {
                    207:        int64_t value64;
1.1       christos  208:        isc_result_t result;
                    209:        result = dns_time64_fromtext(source, &value64);
1.4     ! christos  210:        if (result != ISC_R_SUCCESS) {
1.1       christos  211:                return (result);
1.4     ! christos  212:        }
1.3       christos  213:        *target = (uint32_t)value64;
1.1       christos  214:
                    215:        return (ISC_R_SUCCESS);
                    216: }

CVSweb <webmaster@jp.NetBSD.org>