X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=libraries%2Flibldap%2Futil-int.c;h=3510aec93e45550513d96b9076c25c1274a7a35b;hb=2e4580beaa358299ecb6bc8b920e40dfc373e969;hp=c71aa6d73984ec01905383dafe991d5967431cfd;hpb=1adee08e8912c1f47c7b170fe62bebdd9797921f;p=openldap
diff --git a/libraries/libldap/util-int.c b/libraries/libldap/util-int.c
index c71aa6d739..3510aec93e 100644
--- a/libraries/libldap/util-int.c
+++ b/libraries/libldap/util-int.c
@@ -1,7 +1,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 1998-2010 The OpenLDAP Foundation.
+ * Copyright 1998-2012 The OpenLDAP Foundation.
* Portions Copyright 1998 A. Hartgers.
* All rights reserved.
*
@@ -58,6 +58,8 @@ extern int h_errno;
#else
# include
ldap_pvt_thread_mutex_t ldap_int_resolv_mutex;
+ ldap_pvt_thread_mutex_t ldap_int_hostname_mutex;
+ static ldap_pvt_thread_mutex_t ldap_int_gettime_mutex;
# if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \
&& defined( CTIME_R_NARGS )
@@ -66,6 +68,20 @@ extern int h_errno;
static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex;
# endif
+/* USE_GMTIME_R and USE_LOCALTIME_R defined in ldap_pvt.h */
+
+#ifdef LDAP_DEVEL
+ /* to be released with 2.5 */
+#if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R )
+ /* we use the same mutex for gmtime(3) and localtime(3)
+ * because implementations may use the same buffer
+ * for both functions */
+ static ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex;
+#endif
+#else /* ! LDAP_DEVEL */
+ ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex;
+#endif /* ! LDAP_DEVEL */
+
# if defined(HAVE_GETHOSTBYNAME_R) && \
(GETHOSTBYNAME_R_NARGS < 5) || (6 < GETHOSTBYNAME_R_NARGS)
/* Don't know how to handle this version, pretend it's not there */
@@ -93,20 +109,211 @@ char *ldap_pvt_ctime( const time_t *tp, char *buf )
#else
-# ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ldap_int_ctime_mutex );
-# endif
-
+ LDAP_MUTEX_LOCK( &ldap_int_ctime_mutex );
AC_MEMCPY( buf, ctime(tp), 26 );
-
-# ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ldap_int_ctime_mutex );
-# endif
+ LDAP_MUTEX_UNLOCK( &ldap_int_ctime_mutex );
return buf;
#endif
}
+#if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R )
+int
+ldap_pvt_gmtime_lock( void )
+{
+# ifndef LDAP_R_COMPILE
+ return 0;
+# else /* LDAP_R_COMPILE */
+ return ldap_pvt_thread_mutex_lock( &ldap_int_gmtime_mutex );
+# endif /* LDAP_R_COMPILE */
+}
+
+int
+ldap_pvt_gmtime_unlock( void )
+{
+# ifndef LDAP_R_COMPILE
+ return 0;
+# else /* LDAP_R_COMPILE */
+ return ldap_pvt_thread_mutex_unlock( &ldap_int_gmtime_mutex );
+# endif /* LDAP_R_COMPILE */
+}
+#endif /* !USE_GMTIME_R || !USE_LOCALTIME_R */
+
+#ifndef USE_GMTIME_R
+struct tm *
+ldap_pvt_gmtime( const time_t *timep, struct tm *result )
+{
+ struct tm *tm_ptr;
+
+ LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex );
+ tm_ptr = gmtime( timep );
+ if ( tm_ptr == NULL ) {
+ result = NULL;
+
+ } else {
+ *result = *tm_ptr;
+ }
+ LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex );
+
+ return result;
+}
+#endif /* !USE_GMTIME_R */
+
+#ifndef USE_LOCALTIME_R
+struct tm *
+ldap_pvt_localtime( const time_t *timep, struct tm *result )
+{
+ struct tm *tm_ptr;
+
+ LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex );
+ tm_ptr = localtime( timep );
+ if ( tm_ptr == NULL ) {
+ result = NULL;
+
+ } else {
+ *result = *tm_ptr;
+ }
+ LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex );
+
+ return result;
+}
+#endif /* !USE_LOCALTIME_R */
+
+/* return a broken out time, with microseconds
+ */
+#ifdef _WIN32
+/* Windows SYSTEMTIME only has 10 millisecond resolution, so we
+ * also need to use a high resolution timer to get microseconds.
+ * This is pretty clunky.
+ */
+void
+ldap_pvt_gettime( struct lutil_tm *tm )
+{
+ static LARGE_INTEGER cFreq;
+ static LARGE_INTEGER prevCount;
+ static int subs;
+ static int offset;
+ LARGE_INTEGER count;
+ SYSTEMTIME st;
+
+ GetSystemTime( &st );
+ QueryPerformanceCounter( &count );
+
+ /* It shouldn't ever go backwards, but multiple CPUs might
+ * be able to hit in the same tick.
+ */
+ LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex );
+ if ( count.QuadPart <= prevCount.QuadPart ) {
+ subs++;
+ } else {
+ subs = 0;
+ prevCount = count;
+ }
+ LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex );
+
+ /* We assume Windows has at least a vague idea of
+ * when a second begins. So we align our microsecond count
+ * with the Windows millisecond count using this offset.
+ * We retain the submillisecond portion of our own count.
+ *
+ * Note - this also assumes that the relationship between
+ * the PerformanceCouunter and SystemTime stays constant;
+ * that assumption breaks if the SystemTime is adjusted by
+ * an external action.
+ */
+ if ( !cFreq.QuadPart ) {
+ long long t;
+ int usec;
+ QueryPerformanceFrequency( &cFreq );
+
+ /* just get sub-second portion of counter */
+ t = count.QuadPart % cFreq.QuadPart;
+
+ /* convert to microseconds */
+ t *= 1000000;
+ usec = t / cFreq.QuadPart;
+
+ offset = usec - st.wMilliseconds * 1000;
+ }
+
+ tm->tm_usub = subs;
+
+ /* convert to microseconds */
+ count.QuadPart %= cFreq.QuadPart;
+ count.QuadPart *= 1000000;
+ count.QuadPart /= cFreq.QuadPart;
+ count.QuadPart -= offset;
+
+ tm->tm_usec = count.QuadPart % 1000000;
+ if ( tm->tm_usec < 0 )
+ tm->tm_usec += 1000000;
+
+ /* any difference larger than microseconds is
+ * already reflected in st
+ */
+
+ tm->tm_sec = st.wSecond;
+ tm->tm_min = st.wMinute;
+ tm->tm_hour = st.wHour;
+ tm->tm_mday = st.wDay;
+ tm->tm_mon = st.wMonth - 1;
+ tm->tm_year = st.wYear - 1900;
+}
+#else
+void
+ldap_pvt_gettime( struct lutil_tm *ltm )
+{
+ struct timeval tv;
+ static struct timeval prevTv;
+ static int subs;
+
+ struct tm tm;
+ time_t t;
+
+ gettimeofday( &tv, NULL );
+ t = tv.tv_sec;
+
+ LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex );
+ if ( tv.tv_sec < prevTv.tv_sec
+ || ( tv.tv_sec == prevTv.tv_sec && tv.tv_usec <= prevTv.tv_usec )) {
+ subs++;
+ } else {
+ subs = 0;
+ prevTv = tv;
+ }
+ LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex );
+
+ ltm->tm_usub = subs;
+
+ ldap_pvt_gmtime( &t, &tm );
+
+ ltm->tm_sec = tm.tm_sec;
+ ltm->tm_min = tm.tm_min;
+ ltm->tm_hour = tm.tm_hour;
+ ltm->tm_mday = tm.tm_mday;
+ ltm->tm_mon = tm.tm_mon;
+ ltm->tm_year = tm.tm_year;
+ ltm->tm_usec = tv.tv_usec;
+}
+#endif
+
+size_t
+ldap_pvt_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod)
+{
+ struct lutil_tm tm;
+ int n;
+
+ ldap_pvt_gettime( &tm );
+
+ 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 );
+
+ if( n < 0 ) return 0;
+ return ( (size_t) n < len ) ? n : 0;
+}
+
#define BUFSTART (1024-32)
#define BUFMAX (32*1024-32)
@@ -165,7 +372,7 @@ int ldap_pvt_gethostbyname_a(
int retval;
*buf = NULL;
- ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
+ LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex );
he = gethostbyname( name );
@@ -180,7 +387,7 @@ int ldap_pvt_gethostbyname_a(
retval = 0;
}
- ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
+ LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex );
return retval;
#else
@@ -224,13 +431,9 @@ int ldap_pvt_get_hname(
int rc;
#if defined( HAVE_GETNAMEINFO )
-#if defined( LDAP_R_COMPILE )
- ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
-#endif
+ LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex );
rc = getnameinfo( sa, len, name, namelen, NULL, 0, 0 );
-#if defined( LDAP_R_COMPILE )
- ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
-#endif
+ LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex );
if ( rc ) *err = (char *)AC_GAI_STRERROR( rc );
return rc;
@@ -294,9 +497,7 @@ int ldap_pvt_get_hname(
LDAP_FREE(buf);
#else /* HAVE_GETHOSTBYADDR_R */
-#if defined( LDAP_R_COMPILE )
- ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
-#endif
+ LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex );
hp = gethostbyaddr( addr, alen, sa->sa_family );
if (hp) {
strncpy( name, hp->h_name, namelen );
@@ -305,9 +506,7 @@ int ldap_pvt_get_hname(
rc = h_errno;
*err = (char *)HSTRERROR( h_errno );
}
-#if defined( LDAP_R_COMPILE )
- ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
-#endif
+ LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex );
#endif /* !HAVE_GETHOSTBYADDR_R */
return rc;
@@ -362,8 +561,7 @@ int ldap_pvt_gethostbyaddr_a(
int retval;
*buf = NULL;
- ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
-
+ LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex );
he = gethostbyaddr( addr, len, type );
if (he==NULL) {
@@ -376,8 +574,7 @@ int ldap_pvt_gethostbyaddr_a(
*result = resbuf;
retval = 0;
}
-
- ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
+ LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex );
return retval;
@@ -405,9 +602,16 @@ void ldap_int_utils_init( void )
#ifdef LDAP_R_COMPILE
#if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS )
ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex );
+#endif
+#if !defined( USE_GMTIME_R ) && !defined( USE_LOCALTIME_R )
+ ldap_pvt_thread_mutex_init( &ldap_int_gmtime_mutex );
#endif
ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex );
+ ldap_pvt_thread_mutex_init( &ldap_int_hostname_mutex );
+
+ ldap_pvt_thread_mutex_init( &ldap_int_gettime_mutex );
+
#ifdef HAVE_CYRUS_SASL
ldap_pvt_thread_mutex_init( &ldap_int_sasl_mutex );
#endif
@@ -578,7 +782,9 @@ char *ldap_pvt_gai_strerror (int code) {
{ EAI_NONAME, N_("Name or service not known") },
{ EAI_SERVICE, N_("Servname not supported for ai_socktype") },
{ EAI_SOCKTYPE, N_("ai_socktype not supported") },
+#ifdef EAI_SYSTEM
{ EAI_SYSTEM, N_("System error") },
+#endif
{ 0, NULL }
};