diff --git a/configure.ac b/configure.ac index 458e0209ba..cb94e150cc 100644 --- a/configure.ac +++ b/configure.ac @@ -2371,6 +2371,7 @@ fi AC_CHECK_FUNCS( \ bcopy \ + clock_gettime \ closesocket \ chroot \ endgrent \ diff --git a/contrib/slapd-modules/smbk5pwd/smbk5pwd.c b/contrib/slapd-modules/smbk5pwd/smbk5pwd.c index de5745b598..7dc25621e0 100644 --- a/contrib/slapd-modules/smbk5pwd/smbk5pwd.c +++ b/contrib/slapd-modules/smbk5pwd/smbk5pwd.c @@ -289,7 +289,7 @@ static int k5key_chk( struct lutil_tm tm; struct lutil_timet tt; if ( lutil_parsetime( a->a_vals[0].bv_val, &tm ) == 0 && - lutil_tm2time( &tm, &tt ) == 0 && tt.tt_usec < op->o_time ) { + lutil_tm2time( &tm, &tt ) == 0 && tt.tt_sec < op->o_time ) { /* Account is expired */ rc = LUTIL_PASSWD_ERR; break; diff --git a/include/ac/time.h b/include/ac/time.h index fe618e126b..05ffb0cadd 100644 --- a/include/ac/time.h +++ b/include/ac/time.h @@ -29,4 +29,11 @@ # include #endif +#if defined(_WIN32) && !defined(HAVE_CLOCK_GETTIME) + struct timespec { + time_t tv_sec; + int tv_nsec; + }; +#endif + #endif /* _AC_TIME_H */ diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index 3e8ad8e976..8d32701a5e 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -131,6 +131,13 @@ ldap_pvt_gettime LDAP_P(( struct lutil_tm * )); struct timeval; LDAP_F( int ) ldap_pvt_gettimeofday LDAP_P(( struct timeval *tv, void *unused )); +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif +#define clock_gettime(clkid,tv) ldap_pvt_clock_gettime(clkid,tv) +struct timespec; +LDAP_F( int ) +ldap_pvt_clock_gettime LDAP_P(( int clkid, struct timespec *tv )); #endif /* use this macro to allocate buffer for ldap_pvt_csnstr */ diff --git a/include/lutil.h b/include/lutil.h index 8d6406bd83..cdbdbb21dd 100644 --- a/include/lutil.h +++ b/include/lutil.h @@ -172,7 +172,7 @@ typedef struct lutil_tm { int tm_mday; /* day 1-31 */ int tm_mon; /* month 0-11 */ int tm_year; /* year - 1900 */ - int tm_usec; /* microseconds */ + int tm_nsec; /* nanoseconds */ int tm_usub; /* submicro */ } lutil_tm; @@ -180,7 +180,7 @@ typedef struct lutil_timet { 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 */ + unsigned int tt_nsec; /* nanoseconds */ } lutil_timet; /* Parse a timestamp string into a structure */ diff --git a/libraries/libldap/util-int.c b/libraries/libldap/util-int.c index 7161a76948..aa69f70913 100644 --- a/libraries/libldap/util-int.c +++ b/libraries/libldap/util-int.c @@ -178,7 +178,7 @@ static int _ldap_pvt_gt_subs; #ifdef _WIN32 /* Windows SYSTEMTIME only has 10 millisecond resolution, so we - * also need to use a high resolution timer to get microseconds. + * also need to use a high resolution timer to get nanoseconds. * This is pretty clunky. */ static LARGE_INTEGER _ldap_pvt_gt_freq; @@ -187,9 +187,10 @@ static int _ldap_pvt_gt_offset; #define SEC_TO_UNIX_EPOCH 11644473600LL #define TICKS_PER_SECOND 10000000 +#define BILLION 1000000000L static int -ldap_pvt_gettimeusec(int *sec) +ldap_pvt_gettimensec(int *sec) { LARGE_INTEGER count; @@ -200,7 +201,7 @@ ldap_pvt_gettimeusec(int *sec) */ LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex ); /* We assume Windows has at least a vague idea of - * when a second begins. So we align our microsecond count + * when a second begins. So we align our nanosecond count * with the Windows millisecond count using this offset. * We retain the submillisecond portion of our own count. * @@ -214,7 +215,7 @@ ldap_pvt_gettimeusec(int *sec) ULARGE_INTEGER ut; FILETIME ft0, ft1; long long t; - int usec; + int nsec; /* Initialize our offset */ QueryPerformanceFrequency( &_ldap_pvt_gt_freq ); @@ -232,13 +233,13 @@ ldap_pvt_gettimeusec(int *sec) /* get second and fraction portion of counter */ t = c2.QuadPart % (_ldap_pvt_gt_freq.QuadPart*10); - /* convert to microseconds */ - t *= 1000000; - usec = t / _ldap_pvt_gt_freq.QuadPart; + /* convert to nanoseconds */ + t *= BILLION; + nsec = t / _ldap_pvt_gt_freq.QuadPart; ut.QuadPart /= 10; - ut.QuadPart %= 10000000; - _ldap_pvt_gt_offset = usec - ut.QuadPart; + ut.QuadPart %= (10 * BILLION); + _ldap_pvt_gt_offset = nsec - ut.QuadPart; count = c2; } if ( count.QuadPart <= _ldap_pvt_gt_prev.QuadPart ) { @@ -249,28 +250,28 @@ ldap_pvt_gettimeusec(int *sec) } LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex ); - /* convert to microseconds */ + /* convert to nanoseconds */ count.QuadPart %= _ldap_pvt_gt_freq.QuadPart*10; - count.QuadPart *= 1000000; + count.QuadPart *= BILLION; count.QuadPart /= _ldap_pvt_gt_freq.QuadPart; count.QuadPart -= _ldap_pvt_gt_offset; - /* We've extracted the 1s and microseconds. - * The 1sec digit is used to detect wraparound in microsecnds. + /* We've extracted the 1s and nanoseconds. + * The 1sec digit is used to detect wraparound in nanosecnds. */ if (count.QuadPart < 0) - count.QuadPart += 10000000; - else if (count.QuadPart >= 10000000) - count.QuadPart -= 10000000; + count.QuadPart += (10 * BILLION); + else if (count.QuadPart >= (10 * BILLION)) + count.QuadPart -= (10 * BILLION); - *sec = count.QuadPart / 1000000; - return count.QuadPart % 1000000; + *sec = count.QuadPart / BILLION; + return count.QuadPart % BILLION; } -/* emulate POSIX gettimeofday */ +/* emulate POSIX clock_gettime */ int -ldap_pvt_gettimeofday( struct timeval *tv, void *unused ) +ldap_pvt_clock_gettime( int clk_id, struct timespec *tv ) { FILETIME ft; ULARGE_INTEGER ut; @@ -280,11 +281,11 @@ ldap_pvt_gettimeofday( struct timeval *tv, void *unused ) ut.LowPart = ft.dwLowDateTime; ut.HighPart = ft.dwHighDateTime; - /* convert to usec */ - ut.QuadPart /= (TICKS_PER_SECOND / 1000000); + /* convert to sec */ + ut.QuadPart /= TICKS_PER_SECOND; - tv->tv_usec = ldap_pvt_gettimeusec(&sec); - tv->tv_sec = ut.QuadPart / 1000000 - SEC_TO_UNIX_EPOCH; + tv->tv_nsec = ldap_pvt_gettimensec(&sec); + tv->tv_sec = ut.QuadPart - SEC_TO_UNIX_EPOCH; /* check for carry from microseconds */ sec0 = tv->tv_sec % 10; @@ -294,7 +295,20 @@ ldap_pvt_gettimeofday( struct timeval *tv, void *unused ) return 0; } -/* return a broken out time, with microseconds +/* emulate POSIX gettimeofday */ +int +ldap_pvt_gettimeofday( struct timeval *tv, void *unused ) +int +{ + struct timespec ts; + ldap_pvt_clock_gettime( 0, &ts ); + tv->tv_sec = ts.tv_spec; + tv->tv_usec = ts.tv_nsec / 1000; + return 0; +} + + +/* return a broken out time, with nanoseconds */ void ldap_pvt_gettime( struct lutil_tm *tm ) @@ -305,10 +319,10 @@ ldap_pvt_gettime( struct lutil_tm *tm ) 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; GetSystemTime( &st ); - tm->tm_usec = ldap_pvt_gettimeusec(&sec); + tm->tm_nsec = ldap_pvt_gettimensec(&sec); tm->tm_usub = _ldap_pvt_gt_subs; - /* any difference larger than microseconds is + /* any difference larger than nanoseconds is * already reflected in st */ tm->tm_sec = st.wSecond; @@ -318,7 +332,7 @@ ldap_pvt_gettime( struct lutil_tm *tm ) tm->tm_mon = st.wMonth - 1; tm->tm_year = st.wYear - 1900; - /* check for carry from microseconds */ + /* check for carry from nanoseconds */ sec0 = tm->tm_sec % 10; if (sec0 < sec || (sec0 == 9 && !sec)) { tm->tm_sec++; @@ -357,23 +371,36 @@ ldap_pvt_gettime( struct lutil_tm *tm ) } #else +#ifdef HAVE_CLOCK_GETTIME +static struct timespec _ldap_pvt_gt_prevTv; +#else static struct timeval _ldap_pvt_gt_prevTv; +#endif void ldap_pvt_gettime( struct lutil_tm *ltm ) { - struct timeval tv; - struct tm tm; time_t t; +#ifdef HAVE_CLOCK_GETTIME +#define FRAC tv_nsec +#define NSECS(x) x + struct timespec tv; + + clock_gettime( CLOCK_REALTIME, &tv ); +#else +#define FRAC tv_usec +#define NSECS(x) x * 1000 + struct timeval tv; gettimeofday( &tv, NULL ); +#endif t = tv.tv_sec; LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex ); if ( tv.tv_sec < _ldap_pvt_gt_prevTv.tv_sec || ( tv.tv_sec == _ldap_pvt_gt_prevTv.tv_sec - && tv.tv_usec <= _ldap_pvt_gt_prevTv.tv_usec )) { + && tv.FRAC <= _ldap_pvt_gt_prevTv.FRAC )) { _ldap_pvt_gt_subs++; } else { _ldap_pvt_gt_subs = 0; @@ -391,7 +418,7 @@ ldap_pvt_gettime( struct lutil_tm *ltm ) ltm->tm_mday = tm.tm_mday; ltm->tm_mon = tm.tm_mon; ltm->tm_year = tm.tm_year; - ltm->tm_usec = tv.tv_usec; + ltm->tm_nsec = NSECS(tv.FRAC); } #endif @@ -406,7 +433,7 @@ ldap_pvt_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod) n = snprintf( buf, len, "%4d%02d%02d%02d%02d%02d.%06dZ#%06x#%03x#%06x", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, - tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_usub, replica, mod ); + tm.tm_min, tm.tm_sec, tm.tm_nsec / 1000, tm.tm_usub, replica, mod ); if( n < 0 ) return 0; return ( (size_t) n < len ) ? n : 0; diff --git a/libraries/liblutil/utils.c b/libraries/liblutil/utils.c index df9f7a2e91..229fa7b502 100644 --- a/libraries/liblutil/utils.c +++ b/libraries/liblutil/utils.c @@ -159,7 +159,7 @@ int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt ) 273, 304, 334 }; int sec; - tt->tt_usec = tm->tm_usec; + tt->tt_nsec = tm->tm_nsec; /* 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 && @@ -226,7 +226,7 @@ int lutil_tm2gtime( struct lutil_tm *tm, struct lutil_timet *tt ) int sec, year; long tmp; - tt->tt_usec = tm->tm_usec; + tt->tt_nsec = tm->tm_nsec; /* tm->tm_year is years since 1900 */ /* calculate days from 0000 */ @@ -350,13 +350,13 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm ) i*=10; i+= *ptr++ - '0'; fracs++; } - tm->tm_usec = i; + tm->tm_nsec = i; if (i) { - for (i = fracs; i<6; i++) - tm->tm_usec *= 10; + for (i = fracs; i<9; i++) + tm->tm_nsec *= 10; } } else { - tm->tm_usec = 0; + tm->tm_nsec = 0; } tm->tm_usub = 0; diff --git a/servers/slapd/main.c b/servers/slapd/main.c index 98a67247d7..d8be4082b9 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -382,12 +382,21 @@ static BER_logger *ber_logger; static void debug_print( const char *data ) { char buf[4136]; /* 4096 + 40 */ +#ifdef HAVE_CLOCK_GETTIME + struct timespec tv; +#define TS "%08x" +#define Tfrac tv.tv_nsec + clock_gettime( CLOCK_REALTIME, &tv ); +#else struct timeval tv; - +#define TS "%05x" +#define Tfrac tv.tv_usec gettimeofday( &tv, NULL ); +#endif + buf[sizeof(buf)-1] = '\0'; - snprintf( buf, sizeof(buf)-1, "%lx.%05x %p %s", - (long)tv.tv_sec, tv.tv_usec, (void *)ldap_pvt_thread_self(), data ); + snprintf( buf, sizeof(buf)-1, "%lx." TS " %p %s", + (long)tv.tv_sec, Tfrac, (void *)ldap_pvt_thread_self(), data ); ber_logger( buf ); } diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c index 49863a7c6c..6f56752a59 100644 --- a/servers/slapd/overlays/ppolicy.c +++ b/servers/slapd/overlays/ppolicy.c @@ -1500,7 +1500,7 @@ ppolicy_bind_response( Operation *op, SlapReply *rs ) strcpy(nowstr_usec, nowstr); timestamp_usec.bv_val = nowstr_usec; timestamp_usec.bv_len = timestamp.bv_len; - snprintf( timestamp_usec.bv_val + timestamp_usec.bv_len-1, sizeof(".123456Z"), ".%06dZ", now_usec.tt_usec ); + snprintf( timestamp_usec.bv_val + timestamp_usec.bv_len-1, sizeof(".123456Z"), ".%06dZ", now_usec.tt_nsec / 1000 ); timestamp_usec.bv_len += STRLENOF(".123456"); if ( rs->sr_err == LDAP_INVALID_CREDENTIALS && ppb->pp.pwdMaxRecordedFailure ) { diff --git a/tests/progs/slapd-watcher.c b/tests/progs/slapd-watcher.c index 6dbb6e3be8..3cfc0fe743 100644 --- a/tests/progs/slapd-watcher.c +++ b/tests/progs/slapd-watcher.c @@ -425,7 +425,7 @@ void get_csns( if (j < numservers) { ber_bvreplace( &c->vals[j], &bvs[i] ); lutil_parsetime(bvs[i].bv_val, &tm); - c->tvs[j].tv_usec = tm.tm_usec; + c->tvs[j].tv_usec = tm.tm_nsec / 1000; lutil_tm2time( &tm, &tt ); c->tvs[j].tv_sec = tt.tt_sec; }