]> git.sur5r.net Git - openldap/blobdiff - libraries/liblutil/utils.c
ITS#5129 fix alock_close with Quick mode
[openldap] / libraries / liblutil / utils.c
index 77baee98c65b847caf69e2bff2dc641df84f1fd5..2cd105ed92cf6dd4ddbb4f1c6ea1a7713b24a0dc 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2007 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
 
-#include <lutil.h>
-#include <ldap_defaults.h>
+#include "lutil.h"
+#include "ldap_defaults.h"
+#include "ldap_pvt.h"
 
 #ifdef HAVE_EBCDIC
 int _trans_argv = 1;
@@ -207,7 +211,7 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
                unsigned i, fracs;
 
                /* Is the stamp reasonably long? */
-               for (i=0; isdigit(atm[i]); i++);
+               for (i=0; isdigit((unsigned char) atm[i]); i++);
                if (i < sizeof("00000101000000")-1)
                        break;
 
@@ -247,14 +251,17 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
                if (tm->tm_sec < 0 || tm->tm_sec > 61) break;
 
                /* Fractions of seconds */
-               for (i = 0, fracs = 0;isdigit(*ptr);) {
-                       i*=10; i+= *ptr++ - '0';
-                       fracs++;
-               }
-               tm->tm_usec = i;
-               if (i) {
-                       for (i = fracs; i<6; i++)
-                               tm->tm_usec *= 10;
+               if ( *ptr == '.' ) {
+                       ptr++;
+                       for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) {
+                               i*=10; i+= *ptr++ - '0';
+                               fracs++;
+                       }
+                       tm->tm_usec = i;
+                       if (i) {
+                               for (i = fracs; i<6; i++)
+                                       tm->tm_usec *= 10;
+                       }
                }
 
                /* Must be UTC */
@@ -265,6 +272,117 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
        return -1;
 }
 
+/* return a broken out time, with microseconds
+ * Must be mutex-protected.
+ */
+#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
+lutil_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 );
+
+       /* 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.
+        */
+       if ( !cFreq.QuadPart ) {
+               long long t;
+               int usec;
+               QueryPerformanceFrequency( &cFreq );
+
+               t = count.QuadPart * 1000000;
+               t /= cFreq.QuadPart;
+               usec = t % 10000000;
+               usec /= 1000;
+               offset = ( usec - st.wMilliseconds ) * 1000;
+       }
+
+       /* It shouldn't ever go backwards, but multiple CPUs might
+        * be able to hit in the same tick.
+        */
+       if ( count.QuadPart <= prevCount.QuadPart ) {
+               subs++;
+       } else {
+               subs = 0;
+               prevCount = count;
+       }
+
+       tm->tm_usub = subs;
+
+       /* convert to microseconds */
+       count.QuadPart *= 1000000;
+       count.QuadPart /= cFreq.QuadPart;
+       count.QuadPart -= offset;
+
+       tm->tm_usec = count.QuadPart % 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
+lutil_gettime( struct lutil_tm *ltm )
+{
+       struct timeval tv;
+       static struct timeval prevTv;
+       static int subs;
+
+#ifdef HAVE_GMTIME_R
+       struct tm tm_buf;
+#endif
+       struct tm *tm;
+       time_t t;
+
+       gettimeofday( &tv, NULL );
+       t = tv.tv_sec;
+
+       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;
+       }
+
+       ltm->tm_usub = subs;
+
+#ifdef HAVE_GMTIME_R
+       tm = gmtime_r( &t, &tm_buf );
+#else
+       tm = gmtime( &t );
+#endif
+
+       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
+
 /* strcopy is like strcpy except it returns a pointer to the trailing NUL of
  * the result string. This allows fast construction of catenated strings
  * without the overhead of strlen/strcat.
@@ -311,6 +429,66 @@ int mkstemp( char * template )
 }
 #endif
 
+#ifdef _MSC_VER
+struct dirent {
+       char *d_name;
+};
+typedef struct DIR {
+       HANDLE dir;
+       struct dirent data;
+       int first;
+       char buf[MAX_PATH+1];
+} DIR;
+DIR *opendir( char *path )
+{
+       char tmp[32768];
+       int len = strlen(path);
+       DIR *d;
+       HANDLE h;
+       WIN32_FIND_DATA data;
+       
+       if (len+3 >= sizeof(tmp))
+               return NULL;
+
+       strcpy(tmp, path);
+       tmp[len++] = '\\';
+       tmp[len++] = '*';
+       tmp[len] = '\0';
+
+       h = FindFirstFile( tmp, &data );
+       
+       if ( h == INVALID_HANDLE_VALUE )
+               return NULL;
+
+       d = ber_memalloc( sizeof(DIR) );
+       if ( !d )
+               return NULL;
+       d->dir = h;
+       d->data.d_name = d->buf;
+       d->first = 1;
+       strcpy(d->data.d_name, data.cFileName);
+       return d;
+}
+struct dirent *readdir(DIR *dir)
+{
+       WIN32_FIND_DATA data;
+
+       if (dir->first) {
+               dir->first = 0;
+       } else {
+               if (!FindNextFile(dir->dir, &data))
+                       return NULL;
+               strcpy(dir->data.d_name, data.cFileName);
+       }
+       return &dir->data;
+}
+void closedir(DIR *dir)
+{
+       FindClose(dir->dir);
+       ber_memfree(dir);
+}
+#endif
+
 /*
  * Memory Reverse Search
  */
@@ -362,6 +540,11 @@ lutil_atoux( unsigned *v, const char *s, int x )
        assert( s != NULL );
        assert( v != NULL );
 
+       /* strtoul() has an odd interface */
+       if ( s[ 0 ] == '-' ) {
+               return -1;
+       }
+
        u = strtoul( s, &next, x );
        if ( next == s || next[ 0 ] != '\0' ) {
                return -1;
@@ -404,6 +587,11 @@ lutil_atoulx( unsigned long *v, const char *s, int x )
        assert( s != NULL );
        assert( v != NULL );
 
+       /* strtoul() has an odd interface */
+       if ( s[ 0 ] == '-' ) {
+               return -1;
+       }
+
        ul = strtoul( s, &next, x );
        if ( next == s || next[ 0 ] != '\0' ) {
                return -1;
@@ -416,6 +604,7 @@ lutil_atoulx( unsigned long *v, const char *s, int x )
 
 static char            time_unit[] = "dhms";
 
+/* Used to parse and unparse time intervals, not timestamps */
 int
 lutil_parse_time(
        const char      *in,
@@ -433,6 +622,11 @@ lutil_parse_time(
                unsigned long   u;
                char            *what;
 
+               /* strtoul() has an odd interface */
+               if ( s[ 0 ] == '-' ) {
+                       return -1;
+               }
+
                u = strtoul( s, &next, 10 );
                if ( next == s ) {
                        return -1;