/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2005 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;
{
while (atm && tm) {
char *ptr = atm;
- int i, fracs;
+ 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;
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 */
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.
#endif
}
#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
+ */
+void *
+lutil_memrchr(const void *b, int c, size_t n)
+{
+ if (n != 0) {
+ const unsigned char *s, *bb = b, cc = c;
+
+ for ( s = bb + n; s > bb; ) {
+ if ( *--s == cc ) {
+ return (void *) s;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+int
+lutil_atoix( int *v, const char *s, int x )
+{
+ char *next;
+ long i;
+
+ assert( s != NULL );
+ assert( v != NULL );
+
+ i = strtol( s, &next, x );
+ if ( next == s || next[ 0 ] != '\0' ) {
+ return -1;
+ }
+
+ if ( (long)(int)i != i ) {
+ return 1;
+ }
+
+ *v = (int)i;
+
+ return 0;
+}
+
+int
+lutil_atoux( unsigned *v, const char *s, int x )
+{
+ char *next;
+ unsigned long u;
+
+ 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;
+ }
+
+ if ( (unsigned long)(unsigned)u != u ) {
+ return 1;
+ }
+
+ *v = u;
+
+ return 0;
+}
+
+int
+lutil_atolx( long *v, const char *s, int x )
+{
+ char *next;
+ long l;
+
+ assert( s != NULL );
+ assert( v != NULL );
+
+ l = strtol( s, &next, x );
+ if ( next == s || next[ 0 ] != '\0' ) {
+ return -1;
+ }
+
+ *v = l;
+
+ return 0;
+}
+
+int
+lutil_atoulx( unsigned long *v, const char *s, int x )
+{
+ char *next;
+ unsigned long ul;
+
+ 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;
+ }
+
+ *v = ul;
+
+ return 0;
+}
+
+static char time_unit[] = "dhms";
+
+/* Used to parse and unparse time intervals, not timestamps */
+int
+lutil_parse_time(
+ const char *in,
+ unsigned long *tp )
+{
+ unsigned long t = 0;
+ char *s,
+ *next;
+ int sofar = -1,
+ scale[] = { 86400, 3600, 60, 1 };
+
+ *tp = 0;
+
+ for ( s = (char *)in; s[ 0 ] != '\0'; ) {
+ 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;
+ }
+
+ if ( next[ 0 ] == '\0' ) {
+ /* assume seconds */
+ t += u;
+ break;
+ }
+
+ what = strchr( time_unit, next[ 0 ] );
+ if ( what == NULL ) {
+ return -1;
+ }
+
+ if ( what - time_unit <= sofar ) {
+ return -1;
+ }
+
+ sofar = what - time_unit;
+ t += u * scale[ sofar ];
+
+ s = &next[ 1 ];
+ }
+
+ *tp = t;
+ return 0;
+}
+
+int
+lutil_unparse_time(
+ char *buf,
+ size_t buflen,
+ unsigned long t )
+{
+ int len, i;
+ unsigned long v[ 4 ];
+ char *ptr = buf;
+
+ v[ 0 ] = t/86400;
+ v[ 1 ] = (t%86400)/3600;
+ v[ 2 ] = (t%3600)/60;
+ v[ 3 ] = t%60;
+
+ for ( i = 0; i < 4; i++ ) {
+ if ( v[i] > 0 || ( i == 3 && ptr == buf ) ) {
+ len = snprintf( ptr, buflen, "%lu%c", v[ i ], time_unit[ i ] );
+ if ( len < 0 || (unsigned)len >= buflen ) {
+ return -1;
+ }
+ buflen -= len;
+ ptr += len;
+ }
+ }
+
+ return 0;
+}
+