Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
openldap
OpenLDAP
Commits
f3cdcadf
Commit
f3cdcadf
authored
Aug 18, 2009
by
Pierangelo Masarati
Browse files
wrap gmtime for reentrancy (ITS#6262)
parent
959fd984
Changes
26
Hide whitespace changes
Inline
Side-by-side
configure.in
View file @
f3cdcadf
...
...
@@ -1859,6 +1859,7 @@ dnl ----------------------------------------------------------------
dnl Tests for reentrant functions necessary to build -lldap_r
AC_CHECK_FUNCS( \
ctime_r \
gmtime_r localtime_r \
gethostbyname_r gethostbyaddr_r \
)
...
...
contrib/slapd-modules/lastmod/lastmod.c
View file @
f3cdcadf
...
...
@@ -367,7 +367,7 @@ best_guess( Operation *op,
struct
berval
*
bv_modifiersName
,
struct
berval
*
bv_nmodifiersName
)
{
if
(
bv_entryCSN
)
{
char
csnbuf
[
LDAP_
LUTIL
_CSNSTR_BUFSIZE
];
char
csnbuf
[
LDAP_
PVT
_CSNSTR_BUFSIZE
];
struct
berval
entryCSN
;
entryCSN
.
bv_val
=
csnbuf
;
...
...
@@ -836,7 +836,7 @@ lastmod_db_open(
char
buf
[
8192
];
static
char
tmbuf
[
LDAP_LUTIL_GENTIME_BUFSIZE
];
char
csnbuf
[
LDAP_
LUTIL
_CSNSTR_BUFSIZE
];
char
csnbuf
[
LDAP_
PVT
_CSNSTR_BUFSIZE
];
struct
berval
entryCSN
;
struct
berval
timestamp
;
...
...
include/ldap_pvt.h
View file @
f3cdcadf
...
...
@@ -91,6 +91,43 @@ ldap_pvt_ctime LDAP_P((
const
time_t
*
tp
,
char
*
buf
));
# if defined( HAVE_GMTIME_R )
# define USE_GMTIME_R
# define ldap_pvt_gmtime_lock() (0)
# define ldap_pvt_gmtime_unlock() (0)
# define ldap_pvt_gmtime(timep, result) gmtime_r((timep), (result))
# else
LDAP_F
(
int
)
ldap_pvt_gmtime_lock
LDAP_P
((
void
));
LDAP_F
(
int
)
ldap_pvt_gmtime_unlock
LDAP_P
((
void
));
LDAP_F
(
struct
tm
*
)
ldap_pvt_gmtime
LDAP_P
((
LDAP_CONST
time_t
*
timep
,
struct
tm
*
result
));
#endif
# if defined( HAVE_LOCALTIME_R )
# define USE_LOCALTIME_R
# define ldap_pvt_localtime(timep, result) localtime_r((timep), (result))
# else
LDAP_F
(
struct
tm
*
)
ldap_pvt_localtime
LDAP_P
((
LDAP_CONST
time_t
*
timep
,
struct
tm
*
result
));
# endif
/* Get current time as a structured time */
LDAP_F
(
void
)
ldap_pvt_gettime
LDAP_P
((
struct
lutil_tm
*
));
/* use this macro to allocate buffer for ldap_pvt_csnstr */
#define LDAP_PVT_CSNSTR_BUFSIZE 64
LDAP_F
(
size_t
)
ldap_pvt_csnstr
(
char
*
buf
,
size_t
len
,
unsigned
int
replica
,
unsigned
int
mod
);
LDAP_F
(
char
*
)
ldap_pvt_get_fqdn
LDAP_P
((
char
*
));
struct
hostent
;
/* avoid pulling in <netdb.h> */
...
...
include/lutil.h
View file @
f3cdcadf
...
...
@@ -177,10 +177,6 @@ LDAP_LUTIL_F( int )
lutil_tm2time
LDAP_P
((
struct
lutil_tm
*
,
struct
lutil_timet
*
));
/* Get current time as a structured time */
LDAP_LUTIL_F
(
void
)
lutil_gettime
LDAP_P
((
struct
lutil_tm
*
));
#ifdef _WIN32
LDAP_LUTIL_F
(
void
)
lutil_slashpath
LDAP_P
((
char
*
path
));
...
...
@@ -229,12 +225,6 @@ lutil_uuidstr_from_normalized(
char
*
buf
,
size_t
buflen
);
/* csn.c */
/* use this macro to allocate buffer for lutil_csnstr */
#define LDAP_LUTIL_CSNSTR_BUFSIZE 64
LDAP_LUTIL_F
(
size_t
)
lutil_csnstr
(
char
*
buf
,
size_t
len
,
unsigned
int
replica
,
unsigned
int
mod
);
/*
* Sometimes not all declarations in a header file are needed.
* An indicator to this is whether or not the symbol's type has
...
...
libraries/libldap/ldap-int.h
View file @
f3cdcadf
...
...
@@ -25,6 +25,7 @@
#endif
#include
"../liblber/lber-int.h"
#include
"lutil.h"
#ifdef LDAP_R_COMPILE
#include
<ldap_pvt_thread.h>
...
...
libraries/libldap/util-int.c
View file @
f3cdcadf
...
...
@@ -66,6 +66,15 @@ 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 */
#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
# 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 */
...
...
@@ -107,6 +116,204 @@ char *ldap_pvt_ctime( const time_t *tp, char *buf )
#endif
}
#ifndef USE_GMTIME_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 */
}
struct
tm
*
ldap_pvt_gmtime
(
const
time_t
*
timep
,
struct
tm
*
result
)
{
struct
tm
*
tm_ptr
;
# ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock
(
&
ldap_int_gmtime_mutex
);
# endif
/* LDAP_R_COMPILE */
tm_ptr
=
gmtime
(
timep
);
if
(
tm_ptr
!=
NULL
)
{
*
result
=
*
tm_ptr
;
}
# ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock
(
&
ldap_int_gmtime_mutex
);
# endif
/* LDAP_R_COMPILE */
return
tm_ptr
;
}
#endif
/* !USE_GMTIME_R */
#ifndef USE_LOCALTIME_R
struct
tm
*
ldap_pvt_localtime
(
const
time_t
*
timep
,
struct
tm
*
result
)
{
struct
tm
*
tm_ptr
;
# ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock
(
&
ldap_int_gmtime_mutex
);
# endif
/* LDAP_R_COMPILE */
tm_ptr
=
localtime
(
timep
);
if
(
tm_ptr
!=
NULL
)
{
*
result
=
*
tm_ptr
;
}
# ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock
(
&
ldap_int_gmtime_mutex
);
# endif
/* LDAP_R_COMPILE */
return
tm_ptr
;
}
#endif
/* !USE_LOCALTIME_R */
/* 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
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.
*/
if
(
count
.
QuadPart
<=
prevCount
.
QuadPart
)
{
subs
++
;
}
else
{
subs
=
0
;
prevCount
=
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.
*
* 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
;
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
;
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)
...
...
@@ -405,6 +612,9 @@ 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
);
...
...
libraries/liblutil/Makefile.in
View file @
f3cdcadf
...
...
@@ -27,14 +27,14 @@ UNIX_OBJS = detach.o
XLIBS
=
$(LIBRARY)
$(LDAP_LIBLBER_LA)
SRCS
=
base64.c
csn.c
entropy.c sasl.c signal.c hash.c passfile.c
\
SRCS
=
base64.c entropy.c sasl.c signal.c hash.c passfile.c
\
md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c
\
avl.c tavl.c ldif.c fetch.c
\
testavl.c
\
meter.c
\
@LIBSRCS@
$
(
@PLAT@_SRCS
)
OBJS
=
base64.o
csn.o
entropy.o sasl.o signal.o hash.o passfile.o
\
OBJS
=
base64.o entropy.o sasl.o signal.o hash.o passfile.o
\
md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o
\
avl.o tavl.o ldif.o fetch.o
\
meter.o
\
...
...
libraries/liblutil/csn.c
deleted
100644 → 0
View file @
959fd984
/* csn.c - Change Sequence Number routines */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2009 The OpenLDAP Foundation.
* Portions Copyright 2000-2003 Kurt D. Zeilenga.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* Portions Copyright 2000, John E. Schimmel, All rights reserved.
* This software is not subject to any license of Mirapoint, Inc.
*
* This is free software; you can redistribute and use it
* under the same terms as OpenLDAP itself.
*/
/* This work was developed by John E. Schimmel and adapted for
* inclusion in OpenLDAP Software by Kurt D. Zeilenga.
*/
/* This file contains routines to generate a change sequence number.
* Every add, delete, and modification is given a unique identifier
* for use in resolving conflicts during replication operations.
*
* These routines are (loosly) based upon draft-ietf-ldup-model-03.txt,
* A WORK IN PROGRESS. The format will likely change.
*
* The format of a CSN string is: yyyymmddhhmmssz#s#r#c
* where s is a counter of operations within a timeslice, r is
* the replica id (normally zero), and c is a counter of
* modifications within this operation. s, r, and c are
* represented in hex and zero padded to lengths of 6, 3, and
* 6, respectively. (In previous implementations r was only 2 digits.)
*
* Calls to this routine MUST be serialized with other calls
* to gmtime().
*/
#include
"portable.h"
#include
<stdio.h>
#include
<ac/time.h>
#include
<lutil.h>
/* Must be mutex-protected, because lutil_gettime needs mutex protection */
size_t
lutil_csnstr
(
char
*
buf
,
size_t
len
,
unsigned
int
replica
,
unsigned
int
mod
)
{
struct
lutil_tm
tm
;
int
n
;
lutil_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
;
}
#ifdef TEST
int
main
(
int
argc
,
char
**
argv
)
{
char
buf
[
LDAP_LUTIL_CSNSTR_BUFSIZE
];
if
(
!
lutil_csnstr
(
buf
,
(
size_t
)
10
,
0
,
0
)
)
{
fprintf
(
stderr
,
"failed lutil_csnstr
\n
"
);
}
if
(
!
lutil_csnstr
(
buf
,
sizeof
(
buf
),
0
,
0
)
)
{
fprintf
(
stderr
,
"failed lutil_csnstr
\n
"
);
}
}
#endif
libraries/liblutil/utils.c
View file @
f3cdcadf
...
...
@@ -282,128 +282,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
);
/* 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
;
}
/* 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
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.
...
...
servers/slapd/add.c
View file @
f3cdcadf
...
...
@@ -592,7 +592,7 @@ int slap_add_opattrs(
struct
berval
name
,
timestamp
,
csn
=
BER_BVNULL
;
struct
berval
nname
,
tmp
;
char
timebuf
[
LDAP_LUTIL_GENTIME_BUFSIZE
];
char
csnbuf
[
LDAP_
LUTIL
_CSNSTR_BUFSIZE
];
char
csnbuf
[
LDAP_
PVT
_CSNSTR_BUFSIZE
];
Attribute
*
a
;
if
(
SLAP_LASTMOD
(
op
->
o_bd
)
)
{
...
...
servers/slapd/back-bdb/delete.c
View file @
f3cdcadf
...
...
@@ -101,7 +101,7 @@ txnReturn:
/* allocate CSN */
if
(
BER_BVISNULL
(
&
op
->
o_csn
)
)
{
struct
berval
csn
;
char
csnbuf
[
LDAP_
LUTIL
_CSNSTR_BUFSIZE
];
char
csnbuf
[
LDAP_
PVT
_CSNSTR_BUFSIZE
];
csn
.
bv_val
=
csnbuf
;
csn
.
bv_len
=
sizeof
(
csnbuf
);
...
...
servers/slapd/back-ldif/ldif.c
View file @
f3cdcadf
...
...
@@ -1306,7 +1306,7 @@ ldif_back_delete( Operation *op, SlapReply *rs )
if
(
BER_BVISEMPTY
(
&
op
->
o_csn
))
{
struct
berval
csn
;
char
csnbuf
[
LDAP_
LUTIL
_CSNSTR_BUFSIZE
];
char
csnbuf
[
LDAP_
PVT
_CSNSTR_BUFSIZE
];
csn
.
bv_val
=
csnbuf
;
csn
.
bv_len
=
sizeof
(
csnbuf
);
...
...
servers/slapd/back-monitor/conn.c
View file @
f3cdcadf
...
...
@@ -266,72 +266,27 @@ conn_create(
monitor_subsys_t
*
ms
)
{
monitor_entry_t
*
mp
;
struct
tm
*
tm
;
struct
tm
tm
;
char
buf
[
BACKMONITOR_BUFSIZE
];
char
buf2
[
LDAP_LUTIL_GENTIME_BUFSIZE
];
char
buf3
[
LDAP_LUTIL_GENTIME_BUFSIZE
];
struct
berval
bv
,
ctmbv
,
mtmbv
,
bv2
,
bv3
;
struct
berval
bv
,
ctmbv
,
mtmbv
;
struct
berval
bv_unknown
=
BER_BVC
(
"unknown"
);
Entry
*
e
;
#ifdef HACK_LOCAL_TIME
char
ctmbuf
[
LDAP_LUTIL_GENTIME_BUFSIZE
];
char
mtmbuf
[
LDAP_LUTIL_GENTIME_BUFSIZE
];
#endif
#ifdef HAVE_GMTIME_R
struct
tm
tm_buf
;
#endif
/* HAVE_GMTIME_R */
assert
(
c
!=
NULL
);