X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblutil%2Futils.c;h=51f35701e0466bbc9e37479ce80e78e26cad9a29;hb=6adee8cd44f016b90183685d9db84a67c47992bc;hp=63b0f3802a2b58db4c0be5e1450eb7fe61f34c9a;hpb=168a9dc22d80b2ee671d72b4da1aa2defa1aaa60;p=openldap
diff --git a/libraries/liblutil/utils.c b/libraries/liblutil/utils.c
index 63b0f3802a..51f35701e0 100644
--- a/libraries/liblutil/utils.c
+++ b/libraries/liblutil/utils.c
@@ -1,7 +1,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 1998-2008 The OpenLDAP Foundation.
+ * Copyright 1998-2011 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,6 +15,7 @@
#include "portable.h"
+#include
#include
#include
#include
@@ -147,7 +148,7 @@ size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta )
snprintf( p, smax - 15, "%02ld%02ld", delta / 3600,
( delta % 3600 ) / 60 );
- return ret + 5;
+ return ret + 4;
}
int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
@@ -282,117 +283,6 @@ 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.
@@ -428,6 +318,21 @@ lutil_strncopy(
return a-1;
}
+/* memcopy is like memcpy except it returns a pointer to the byte past
+ * the end of the result buffer, set to NULL. This allows fast construction
+ * of catenated buffers. Provided for API consistency with lutil_str*copy().
+ */
+char *
+lutil_memcopy(
+ char *a,
+ const char *b,
+ size_t n
+)
+{
+ AC_MEMCPY(a, b, n);
+ return a + n;
+}
+
#ifndef HAVE_MKSTEMP
int mkstemp( char * template )
{
@@ -440,6 +345,40 @@ int mkstemp( char * template )
#endif
#ifdef _MSC_VER
+/* Equivalent of MS CRT's _dosmaperr().
+ * @param lastError[in] Result of GetLastError().
+ */
+static errno_t win2errno(DWORD lastError)
+{
+ const struct {
+ DWORD windows_code;
+ errno_t errno_code;
+ } WIN2ERRNO_TABLE[] = {
+ { ERROR_SUCCESS, 0 },
+ { ERROR_FILE_NOT_FOUND, ENOENT },
+ { ERROR_PATH_NOT_FOUND, ENOENT },
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE },
+ { ERROR_ACCESS_DENIED, EACCES },
+ { ERROR_INVALID_HANDLE, EBADF },
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
+ { ERROR_LOCK_VIOLATION, EACCES },
+ { ERROR_FILE_EXISTS, EEXIST },
+ { ERROR_INVALID_PARAMETER, EINVAL },
+ { ERROR_FILENAME_EXCED_RANGE, ENAMETOOLONG },
+ };
+ const unsigned int WIN2ERRNO_TABLE_SIZE = sizeof(WIN2ERRNO_TABLE) /
+sizeof(WIN2ERRNO_TABLE[0]);
+ const errno_t DEFAULT_ERRNO_ERROR = -1;
+ unsigned int i;
+
+ for (i = 0; i < WIN2ERRNO_TABLE_SIZE; ++i) {
+ if (WIN2ERRNO_TABLE[i].windows_code == lastError) {
+ return WIN2ERRNO_TABLE[i].errno_code;
+ }
+ }
+ return DEFAULT_ERRNO_ERROR;
+}
+
struct dirent {
char *d_name;
};
@@ -457,8 +396,10 @@ DIR *opendir( char *path )
HANDLE h;
WIN32_FIND_DATA data;
- if (len+3 >= sizeof(tmp))
+ if (len+3 >= sizeof(tmp)) {
+ errno = ENAMETOOLONG;
return NULL;
+ }
strcpy(tmp, path);
tmp[len++] = '\\';
@@ -466,9 +407,11 @@ DIR *opendir( char *path )
tmp[len] = '\0';
h = FindFirstFile( tmp, &data );
-
- if ( h == INVALID_HANDLE_VALUE )
+
+ if ( h == INVALID_HANDLE_VALUE ) {
+ errno = win2errno( GetLastError());
return NULL;
+ }
d = ber_memalloc( sizeof(DIR) );
if ( !d )
@@ -492,7 +435,7 @@ struct dirent *readdir(DIR *dir)
}
return &dir->data;
}
-void closedir(DIR *dir)
+int closedir(DIR *dir)
{
FindClose(dir->dir);
ber_memfree(dir);
@@ -503,7 +446,7 @@ void closedir(DIR *dir)
* Memory Reverse Search
*/
void *
-lutil_memrchr(const void *b, int c, size_t n)
+(lutil_memrchr)(const void *b, int c, size_t n)
{
if (n != 0) {
const unsigned char *s, *bb = b, cc = c;
@@ -572,17 +515,28 @@ lutil_atoux( unsigned *v, const char *s, int x )
int
lutil_atolx( long *v, const char *s, int x )
{
- char *next;
- long l;
+ char *next;
+ long l;
+ int save_errno;
assert( s != NULL );
assert( v != NULL );
+ if ( isspace( s[ 0 ] ) ) {
+ return -1;
+ }
+
+ errno = 0;
l = strtol( s, &next, x );
+ save_errno = errno;
if ( next == s || next[ 0 ] != '\0' ) {
return -1;
}
+ if ( ( l == LONG_MIN || l == LONG_MAX ) && save_errno != 0 ) {
+ return -1;
+ }
+
*v = l;
return 0;
@@ -591,27 +545,115 @@ lutil_atolx( long *v, const char *s, int x )
int
lutil_atoulx( unsigned long *v, const char *s, int x )
{
- char *next;
- unsigned long ul;
+ char *next;
+ unsigned long ul;
+ int save_errno;
assert( s != NULL );
assert( v != NULL );
/* strtoul() has an odd interface */
- if ( s[ 0 ] == '-' ) {
+ if ( s[ 0 ] == '-' || isspace( s[ 0 ] ) ) {
return -1;
}
+ errno = 0;
ul = strtoul( s, &next, x );
+ save_errno = errno;
if ( next == s || next[ 0 ] != '\0' ) {
return -1;
}
+ if ( ( ul == 0 || ul == ULONG_MAX ) && save_errno != 0 ) {
+ return -1;
+ }
+
*v = ul;
return 0;
}
+#ifdef HAVE_LONG_LONG
+#if defined(HAVE_STRTOLL) || defined(HAVE_STRTOQ)
+int
+lutil_atollx( long long *v, const char *s, int x )
+{
+ char *next;
+ long long ll;
+ int save_errno;
+
+ assert( s != NULL );
+ assert( v != NULL );
+
+ if ( isspace( s[ 0 ] ) ) {
+ return -1;
+ }
+
+ errno = 0;
+#ifdef HAVE_STRTOLL
+ ll = strtoll( s, &next, x );
+#else /* HAVE_STRTOQ */
+ ll = (unsigned long long)strtoq( s, &next, x );
+#endif /* HAVE_STRTOQ */
+ save_errno = errno;
+ if ( next == s || next[ 0 ] != '\0' ) {
+ return -1;
+ }
+
+ /* LLONG_MIN, LLONG_MAX are C99 only */
+#if defined (LLONG_MIN) && defined(LLONG_MAX)
+ if ( ( ll == LLONG_MIN || ll == LLONG_MAX ) && save_errno != 0 ) {
+ return -1;
+ }
+#endif /* LLONG_MIN && LLONG_MAX */
+
+ *v = ll;
+
+ return 0;
+}
+#endif /* HAVE_STRTOLL || HAVE_STRTOQ */
+
+#if defined(HAVE_STRTOULL) || defined(HAVE_STRTOUQ)
+int
+lutil_atoullx( unsigned long long *v, const char *s, int x )
+{
+ char *next;
+ unsigned long long ull;
+ int save_errno;
+
+ assert( s != NULL );
+ assert( v != NULL );
+
+ /* strtoull() has an odd interface */
+ if ( s[ 0 ] == '-' || isspace( s[ 0 ] ) ) {
+ return -1;
+ }
+
+ errno = 0;
+#ifdef HAVE_STRTOULL
+ ull = strtoull( s, &next, x );
+#else /* HAVE_STRTOUQ */
+ ull = (unsigned long long)strtouq( s, &next, x );
+#endif /* HAVE_STRTOUQ */
+ save_errno = errno;
+ if ( next == s || next[ 0 ] != '\0' ) {
+ return -1;
+ }
+
+ /* ULLONG_MAX is C99 only */
+#if defined(ULLONG_MAX)
+ if ( ( ull == 0 || ull == ULLONG_MAX ) && save_errno != 0 ) {
+ return -1;
+ }
+#endif /* ULLONG_MAX */
+
+ *v = ull;
+
+ return 0;
+}
+#endif /* HAVE_STRTOULL || HAVE_STRTOUQ */
+#endif /* HAVE_LONG_LONG */
+
/* Multiply an integer by 100000000 and add new */
typedef struct lutil_int_decnum {
unsigned char *buf;
@@ -684,7 +726,6 @@ lutil_str2bin( struct berval *in, struct berval *out, void *ctx )
{
char *pin, *pout, ctmp;
char *end;
- long l;
int i, chunk, len, rc = 0, hex = 0;
if ( !out || !out->bv_val || out->bv_len < in->bv_len )
return -1;
@@ -707,38 +748,40 @@ lutil_str2bin( struct berval *in, struct berval *out, void *ctx )
}
if ( hex ) {
#define HEXMAX (2 * sizeof(long))
+ unsigned long l;
/* Convert a longword at a time, but handle leading
* odd bytes first
*/
- chunk = len & (HEXMAX-1);
+ chunk = len % HEXMAX;
if ( !chunk )
chunk = HEXMAX;
while ( len ) {
+ int ochunk;
ctmp = pin[chunk];
pin[chunk] = '\0';
errno = 0;
- l = strtol( pin, &end, 16 );
+ l = strtoul( pin, &end, 16 );
pin[chunk] = ctmp;
if ( errno )
return -1;
- chunk++;
- chunk >>= 1;
- for ( i = chunk; i>=0; i-- ) {
+ ochunk = (chunk + 1)/2;
+ for ( i = ochunk - 1; i >= 0; i-- ) {
pout[i] = l & 0xff;
l >>= 8;
}
pin += chunk;
- pout += sizeof(long);
+ pout += ochunk;
len -= chunk;
chunk = HEXMAX;
}
- out->bv_len = pout + len - out->bv_val;
+ out->bv_len = pout - out->bv_val;
} else {
/* Decimal */
char tmpbuf[64], *tmp;
lutil_int_decnum num;
int neg = 0;
+ long l;
len = in->bv_len;
pin = in->bv_val;
@@ -928,7 +971,7 @@ lutil_snprintf( char *buf, ber_len_t bufsize, char **next, ber_len_t *len, LDAP_
*len = ret;
}
- if ( ret >= bufsize ) {
+ if ( (unsigned) ret >= bufsize ) {
if ( next ) {
*next = &buf[ bufsize - 1 ];
}