]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9120 fix tm2time compat breakage
authorHoward Chu <hyc@openldap.org>
Sun, 19 Jan 2020 19:05:04 +0000 (19:05 +0000)
committerHoward Chu <hyc@openldap.org>
Sun, 19 Jan 2020 19:05:04 +0000 (19:05 +0000)
Add lutil_tm2gtime for Proleptic Gregorian calendar,
revert lutil_tm2time to previous behavior using Unix epoch

include/lutil.h
libraries/liblutil/utils.c
servers/slapd/schema_init.c

index 6cf8aad0c47af7d9365d91264569ed35f7e0fd1e..8b3f391d7182f7a6343a82774bc392a6bc764e00 100644 (file)
@@ -169,8 +169,8 @@ typedef struct lutil_tm {
 } lutil_tm;
 
 typedef struct lutil_timet {
-       unsigned int tt_sec;    /* seconds since 0000 */
-       int tt_gsec;            /* seconds since 0000, high 7 bits, sign-flipped */
+       unsigned int tt_sec;    /* seconds since epoch, 0000 or 1970 */
+       int tt_gsec;            /* seconds since epoch, high 7 bits, maybe sign-flipped */
                                                /* sign flipped to sort properly as unsigned ints */
        unsigned int tt_usec;   /* microseconds */
 } lutil_timet;
@@ -180,11 +180,16 @@ LDAP_LUTIL_F( int )
 lutil_parsetime LDAP_P((
        char *atm, struct lutil_tm * ));
 
-/* Convert structured time to time in seconds since 1900 */
+/* Convert structured time to time in seconds since 1970 (Unix epoch) */
 LDAP_LUTIL_F( int )
 lutil_tm2time LDAP_P((
        struct lutil_tm *, struct lutil_timet * ));
 
+/* Convert structured time to time in seconds since 0000 (Proleptic Gregorian) */
+LDAP_LUTIL_F( int )
+lutil_tm2gtime LDAP_P((
+       struct lutil_tm *, struct lutil_timet * ));
+
 #ifdef _WIN32
 LDAP_LUTIL_F( void )
 lutil_slashpath LDAP_P(( char* path ));
index 94a33ff3180d57c70a8a0be9c0dbbb87ac462ce3..d3a80d18c94c540d429f3ef8ee9da888262c58c6 100644 (file)
@@ -151,14 +151,78 @@ size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta )
        return ret + 4;
 }
 
+int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
+{
+       static int moffset[12] = {
+               0, 31, 59, 90, 120,
+               151, 181, 212, 243,
+               273, 304, 334 };
+       int sec;
+
+       tt->tt_usec = tm->tm_usec;
+
+       /* special case 0000/01/01+00:00:00 is returned as zero */
+       if ( tm->tm_year == -1900 && tm->tm_mon == 0 && tm->tm_mday == 1 &&
+               tm->tm_hour == 0 && tm->tm_min == 0 && tm->tm_sec == 0 ) {
+               tt->tt_sec = 0;
+               tt->tt_gsec = 0;
+               return 0;
+       }
+
+       /* tm->tm_year is years since 1900 */
+       /* calculate days from years since 1970 (epoch) */
+       tt->tt_sec = tm->tm_year - 70;
+       tt->tt_sec *= 365L;
+
+       /* count leap days in preceding years */
+       tt->tt_sec += ((tm->tm_year -69) >> 2);
+
+       /* calculate days from months */
+       tt->tt_sec += moffset[tm->tm_mon];
+
+       /* add in this year's leap day, if any */
+       if (((tm->tm_year & 3) == 0) && (tm->tm_mon > 1)) {
+               tt->tt_sec ++;
+       }
+
+       /* add in days in this month */
+       tt->tt_sec += (tm->tm_mday - 1);
+
+       /* this function can handle a range of about 17408 years... */
+       /* 86400 seconds in a day, divided by 128 = 675 */
+       tt->tt_sec *= 675;
+
+       /* move high 7 bits into tt_gsec */
+       tt->tt_gsec = tt->tt_sec >> 25;
+       tt->tt_sec -= tt->tt_gsec << 25;
+
+       /* get hours */
+       sec = tm->tm_hour;
+
+       /* convert to minutes */
+       sec *= 60L;
+       sec += tm->tm_min;
+
+       /* convert to seconds */
+       sec *= 60L;
+       sec += tm->tm_sec;
+
+       /* add remaining seconds */
+       tt->tt_sec <<= 7;
+       tt->tt_sec += sec;
+
+       /* return success */
+       return 0;
+}
+
 /* Proleptic Gregorian Calendar, 1BCE = year 0 */
 
-int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
+int lutil_tm2gtime( struct lutil_tm *tm, struct lutil_timet *tt )
 {
        static int moffset[12] = {
                0, 31, 59, 90, 120,
                151, 181, 212, 243,
-               273, 304, 334 }; 
+               273, 304, 334 };
        int sec, year;
        long tmp;
 
@@ -169,7 +233,6 @@ int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
        year = tm->tm_year + 1900;
        tmp = year * 365;
 
-
        /* add in leap days */
        sec = (year - 1) / 4;
        tmp += sec;
@@ -181,7 +244,7 @@ int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
        if (year > 0)
                tmp++;
 
-       /* calculate days from months */ 
+       /* calculate days from months */
        tmp += moffset[tm->tm_mon];
 
        /* add in this year's leap day, if any */
index 7f9d8d0f0e7eba823583a9897f681cf036782507..92407391e990b0125235250d203bdd21762eb785 100644 (file)
@@ -5843,7 +5843,7 @@ int generalizedTimeIndexer(
                assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
                /* Use 40 bits of time for key */
                if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
-                       lutil_tm2time( &tm, &tt );
+                       lutil_tm2gtime( &tm, &tt );
                        tmp[0] = tt.tt_gsec & 0xff;
                        tmp[4] = tt.tt_sec & 0xff;
                        tt.tt_sec >>= 8;
@@ -5890,7 +5890,7 @@ int generalizedTimeFilter(
        if ( value->bv_val && value->bv_len >= 10 &&
                lutil_parsetime( value->bv_val, &tm ) == 0 ) {
 
-               lutil_tm2time( &tm, &tt );
+               lutil_tm2gtime( &tm, &tt );
                tmp[0] = tt.tt_gsec & 0xff;
                tmp[4] = tt.tt_sec & 0xff;
                tt.tt_sec >>= 8;