Changes needs updating for release...
OpenLDAP 2.3.8 Engineering
Fixed slapd undef HAVE_EPOLL issue
+ Documentation
+ Add slapo-valsort(5) man page
OpenLDAP 2.3.7 Release
Updated slapd ManageDIT support
esac
done
for i in $FILES; do
- $MKDEP_CC $MKDEP_CFLAGS $FLAGS $i | egrep '^#.*"' > $TMP.sed
+ $MKDEP_CC $MKDEP_CFLAGS $FLAGS $i | grep '^#.*"' > $TMP.sed
awk '
BEGIN {
file = "'$i'"
noCode;
EOF
if AC_TRY_COMMAND($OL_MKDEP $flag conftest.c) \
- | egrep '^conftest\.'"${ac_objext}" >/dev/null 2>&1
+ | grep '^conftest\.'"${ac_objext}" >/dev/null 2>&1
then
if test ! -f conftest."${ac_object}" ; then
ol_cv_mkdep=$flag
dnl Find old Berkeley DB 1.85/1.86
AC_DEFUN([OL_BERKELEY_COMPAT_DB],
[AC_CHECK_HEADERS(db_185.h db.h)
-if test $ac_cv_header_db_185_h = yes -o $ac_cv_header_db_h = yes; then
+if test $ac_cv_header_db_185_h = yes || test $ac_cv_header_db_h = yes; then
AC_CACHE_CHECK([if Berkeley DB header compatibility], [ol_cv_header_db1],[
AC_EGREP_CPP(__db_version_1,[
#if HAVE_DB_185_H
[AC_REQUIRE([OL_LIB_GDBM])
AC_CHECK_HEADERS(gdbm.h)
AC_CACHE_CHECK(for db, [ol_cv_gdbm], [
- if test $ol_cv_lib_gdbm = no -o $ac_cv_header_gdbm_h = no ; then
+ if test $ol_cv_lib_gdbm = no || test $ac_cv_header_gdbm_h = no ; then
ol_cv_gdbm=no
else
ol_cv_gdbm=yes
[AC_REQUIRE([OL_LIB_MDBM])
AC_CHECK_HEADERS(mdbm.h)
AC_CACHE_CHECK(for db, [ol_cv_mdbm], [
- if test $ol_cv_lib_mdbm = no -o $ac_cv_header_mdbm_h = no ; then
+ if test $ol_cv_lib_mdbm = no || test $ac_cv_header_mdbm_h = no ; then
ol_cv_mdbm=no
else
ol_cv_mdbm=yes
[AC_REQUIRE([OL_LIB_NDBM])
AC_CHECK_HEADERS(ndbm.h)
AC_CACHE_CHECK(for db, [ol_cv_ndbm], [
- if test $ol_cv_lib_ndbm = no -o $ac_cv_header_ndbm_h = no ; then
+ if test $ol_cv_lib_ndbm = no || test $ac_cv_header_ndbm_h = no ; then
ol_cv_ndbm=no
else
ol_cv_ndbm=yes
AC_REQUIRE([OL_HEADER_LINUX_THREADS])
AC_REQUIRE([OL_SYS_LINUX_THREADS])
AC_CACHE_CHECK([for LinuxThreads consistency], [ol_cv_linux_threads], [
- if test $ol_cv_header_linux_threads = yes -a \
- $ol_cv_sys_linux_threads = yes; then
+ if test $ol_cv_header_linux_threads = yes &&
+ test $ol_cv_sys_linux_threads = yes; then
ol_cv_linux_threads=yes
- elif test $ol_cv_header_linux_threads = no -a \
- $ol_cv_sys_linux_threads = no; then
+ elif test $ol_cv_header_linux_threads = no &&
+ test $ol_cv_sys_linux_threads = no; then
ol_cv_linux_threads=no
else
ol_cv_linux_threads=error
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[time_t ti; char *buffer; ctime_r(&ti,buffer);]])],[ol_cv_func_ctime_r_nargs2=yes],[ol_cv_func_ctime_r_nargs2=no])
- if test $ol_cv_func_ctime_r_nargs3 = yes -a \
- $ol_cv_func_ctime_r_nargs2 = no ; then
+ if test $ol_cv_func_ctime_r_nargs3 = yes &&
+ test $ol_cv_func_ctime_r_nargs2 = no ; then
ol_cv_func_ctime_r_nargs=3
- elif test $ol_cv_func_ctime_r_nargs3 = no -a \
- $ol_cv_func_ctime_r_nargs2 = yes ; then
+ elif test $ol_cv_func_ctime_r_nargs3 = no &&
+ test $ol_cv_func_ctime_r_nargs2 = yes ; then
ol_cv_func_ctime_r_nargs=2
(void)gethostbyname_r("localhost", &hent, buffer, bufsize,
&rhent, &h_errno);]])],[ol_cv_func_gethostbyname_r_nargs6=yes],[ol_cv_func_gethostbyname_r_nargs6=no])
- if test $ol_cv_func_gethostbyname_r_nargs5 = yes -a \
- $ol_cv_func_gethostbyname_r_nargs6 = no ; then
+ if test $ol_cv_func_gethostbyname_r_nargs5 = yes &&
+ test $ol_cv_func_gethostbyname_r_nargs6 = no ; then
ol_cv_func_gethostbyname_r_nargs=5
- elif test $ol_cv_func_gethostbyname_r_nargs5 = no -a \
- $ol_cv_func_gethostbyname_r_nargs6 = yes ; then
+ elif test $ol_cv_func_gethostbyname_r_nargs5 = no &&
+ test $ol_cv_func_gethostbyname_r_nargs6 = yes ; then
ol_cv_func_gethostbyname_r_nargs=6
alen, AF_INET, &hent, buffer, bufsize,
&rhent, &h_errno);]])],[ol_cv_func_gethostbyaddr_r_nargs8=yes],[ol_cv_func_gethostbyaddr_r_nargs8=no])
- if test $ol_cv_func_gethostbyaddr_r_nargs7 = yes -a \
- $ol_cv_func_gethostbyaddr_r_nargs8 = no ; then
+ if test $ol_cv_func_gethostbyaddr_r_nargs7 = yes &&
+ test $ol_cv_func_gethostbyaddr_r_nargs8 = no ; then
ol_cv_func_gethostbyaddr_r_nargs=7
- elif test $ol_cv_func_gethostbyaddr_r_nargs7 = no -a \
- $ol_cv_func_gethostbyaddr_r_nargs8 = yes ; then
+ elif test $ol_cv_func_gethostbyaddr_r_nargs7 = no &&
+ test $ol_cv_func_gethostbyaddr_r_nargs8 = yes ; then
ol_cv_func_gethostbyaddr_r_nargs=8
#! /bin/sh
-# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.560.2.13 2005/08/29 18:46:16 kurt Exp .
+# From configure.in OpenLDAP: pkg/ldap/configure.in,v 1.560.2.14 2005/09/01 20:28:09 kurt Exp .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59.
#
{ (exit 1); exit 1; }; }
fi
-if test -f "$ac_aux_dir/shtool" -a ! -d $ac_aux_dir/shtool; then
+if test -f "$ac_aux_dir/shtool" && test ! -d $ac_aux_dir/shtool; then
ac_cv_shtool="$ac_aux_dir/shtool"
else
{ { echo "$as_me:$LINENO: error: no shtool found in $ac_aux_dir" >&5
echo "$as_me: WARNING: LDBM disabled, ignoring --enable-ldbm-type argument" >&2;}
fi
- if test $ol_enable_modules != yes -a \
- $ol_enable_bdb = no -a \
- $ol_enable_dnssrv = no -a \
- $ol_enable_hdb = no -a \
- $ol_enable_ldap = no -a \
- $ol_enable_meta = no -a \
- $ol_enable_monitor = no -a \
- $ol_enable_null = no -a \
- $ol_enable_passwd = no -a \
- $ol_enable_perl = no -a \
- $ol_enable_relay = no -a \
- $ol_enable_shell = no -a \
- $ol_enable_sql = no ; then
+ if test $ol_enable_modules != yes &&
+ test $ol_enable_bdb = no &&
+ test $ol_enable_dnssrv = no &&
+ test $ol_enable_hdb = no &&
+ test $ol_enable_ldap = no &&
+ test $ol_enable_meta = no &&
+ test $ol_enable_monitor = no &&
+ test $ol_enable_null = no &&
+ test $ol_enable_passwd = no &&
+ test $ol_enable_perl = no &&
+ test $ol_enable_relay = no &&
+ test $ol_enable_shell = no &&
+ test $ol_enable_sql = no ; then
if test $ol_enable_slapd = yes ; then
{ { echo "$as_me:$LINENO: error: slapd requires a backend" >&5
ol_enable_ldbm_api=no
ol_enable_ldbm_type=no
- if test $ol_enable_bdb != no -o $ol_enable_hdb != no; then
+ if test $ol_enable_bdb/$ol_enable_hdb != no/no; then
ol_enable_ldbm_api=berkeley
fi
else
- if test $ol_enable_ldbm_api = gdbm -a \
- $ol_enable_ldbm_type = btree ; then
+ if test $ol_enable_ldbm_api = gdbm &&
+ test $ol_enable_ldbm_type = btree ; then
{ { echo "$as_me:$LINENO: error: GDBM only supports LDBM type hash" >&5
echo "$as_me: error: GDBM only supports LDBM type hash" >&2;}
{ (exit 1); exit 1; }; }
fi
- if test $ol_enable_ldbm_api = mdbm -a \
- $ol_enable_ldbm_type = btree ; then
+ if test $ol_enable_ldbm_api = mdbm &&
+ test $ol_enable_ldbm_type = btree ; then
{ { echo "$as_me:$LINENO: error: MDBM only supports LDBM type hash" >&5
echo "$as_me: error: MDBM only supports LDBM type hash" >&2;}
{ (exit 1); exit 1; }; }
fi
- if test $ol_enable_ldbm_api = ndbm -a \
- $ol_enable_ldbm_type = btree ; then
+ if test $ol_enable_ldbm_api = ndbm &&
+ test $ol_enable_ldbm_type = btree ; then
{ { echo "$as_me:$LINENO: error: NDBM only supports LDBM type hash" >&5
echo "$as_me: error: NDBM only supports LDBM type hash" >&2;}
{ (exit 1); exit 1; }; }
fi
- if test $ol_enable_bdb != no -o $ol_enable_hdb != no ; then
+ if test $ol_enable_bdb/$ol_enable_hdb != no/no ; then
if test $ol_enable_ldbm_api = auto ; then
ol_enable_ldbm_api=berkeley
elif test $ol_enable_ldbm_api != berkeley ; then
fi
fi
-if test $ol_enable_meta = yes -a $ol_enable_ldap = no ; then
+if test $ol_enable_meta/$ol_enable_ldap = yes/no ; then
{ { echo "$as_me:$LINENO: error: --enable-meta requires --enable-ldap" >&5
echo "$as_me: error: --enable-meta requires --enable-ldap" >&2;}
{ (exit 1); exit 1; }; }
fi
fi
- if test "${CC}" = "cc_r" -o "${CC}" = "xlc_r" ; then
+ case ${CC} in cc_r | xlc_r)
ol_with_threads=posix
ol_cv_pthread_create=yes
- fi
+ ;;
+ esac
fi
if test -z "${CC}"; then
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5688 "configure"' > conftest.$ac_ext
+ echo '#line 5689 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7668: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7669: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7672: \$? = $ac_status" >&5
+ echo "$as_me:7673: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7930: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7931: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7934: \$? = $ac_status" >&5
+ echo "$as_me:7935: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7992: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7993: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7996: \$? = $ac_status" >&5
+ echo "$as_me:7997: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10232 "configure"
+#line 10233 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10330 "configure"
+#line 10331 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } \
- | egrep '^conftest\.'"${ac_objext}" >/dev/null 2>&1
+ | grep '^conftest\.'"${ac_objext}" >/dev/null 2>&1
then
if test ! -f conftest."${ac_object}" ; then
ol_cv_mkdep=$flag
fi
fi
-if test "$ol_enable_dnssrv" = yes -o "$ol_enable_dnssrv" = mod ; then
+if test "$ol_enable_dnssrv" = yes || test "$ol_enable_dnssrv" = mod ; then
if test "$ol_link_dnssrv" = no ; then
{ { echo "$as_me:$LINENO: error: DNSSRV requires res_query()" >&5
echo "$as_me: error: DNSSRV requires res_query()" >&2;}
ol_link_ipv6=no
-if test $ac_cv_func_getaddrinfo = no -o $ac_cv_func_inet_ntop = no ; then
+if test $ac_cv_func_getaddrinfo = no || test $ac_cv_func_inet_ntop = no ; then
if test $ol_enable_ipv6 = yes ; then
{ { echo "$as_me:$LINENO: error: IPv6 support requires getaddrinfo() and inet_ntop()" >&5
echo "$as_me: error: IPv6 support requires getaddrinfo() and inet_ntop()" >&2;}
echo "$as_me:$LINENO: result: $ol_cv_struct_sockaddr_storage" >&5
echo "${ECHO_T}$ol_cv_struct_sockaddr_storage" >&6
- if test $ol_cv_inet6_addrstrlen = yes \
- -a $ol_cv_struct_sockaddr_storage = yes ; then
+ if test $ol_cv_inet6_addrstrlen = yes &&
+ test $ol_cv_struct_sockaddr_storage = yes ; then
ol_link_ipv6=yes
- elif test $ol_enable_ipv6 = yes \
- -a $ol_cv_inet6_addrstrlen = no ; then
+ elif test $ol_enable_ipv6 = yes &&
+ test $ol_cv_inet6_addrstrlen = no ; then
{ { echo "$as_me:$LINENO: error: IPv6 support requires INET6_ADDRSTRLEN" >&5
echo "$as_me: error: IPv6 support requires INET6_ADDRSTRLEN" >&2;}
{ (exit 1); exit 1; }; }
- elif test $ol_enable_ipv6 = yes \
- -a $ol_cv_struct_sockaddr_storage = no ; then
+ elif test $ol_enable_ipv6 = yes &&
+ test $ol_cv_struct_sockaddr_storage = no ; then
{ { echo "$as_me:$LINENO: error: IPv6 support requires struct sockaddr_storage" >&5
echo "$as_me: error: IPv6 support requires struct sockaddr_storage" >&2;}
{ (exit 1); exit 1; }; }
ol_link_krb5=no
ol_link_krb4=no
-if test $ol_with_kerberos = yes -o $ol_with_kerberos = auto \
- -o $ol_with_kerberos = k5 -o $ol_with_kerberos = k5only \
- -o $ol_with_kerberos = k425 ; then
+case $ol_with_kerberos in yes | auto | k5 | k5only | k425)
for ac_header in krb5.h
fi
fi
-fi
+ ;;
+esac
-if test $ol_link_krb5 = yes -a \( $ol_with_kerberos = yes -o \
- $ol_with_kerberos = auto -o $ol_with_kerberos = k425 \) ; then
+if test $ol_link_krb5 = yes &&
+ { test $ol_with_kerberos = yes ||
+ test $ol_with_kerberos = auto ||
+ test $ol_with_kerberos = k425; }; then
ol_with_kerberos=found
fi
-if test $ol_with_kerberos = yes -o $ol_with_kerberos = auto \
- -o $ol_with_kerberos = k4 -o $ol_with_kerberos = kth ; then
+case $ol_with_kerberos in yes | auto | k4 | kth)
fi
fi
fi
-fi
+ ;;
+esac
-if test $ol_link_krb4 = yes -a $ol_enable_kbind != no ; then
+if test $ol_link_krb4 = yes && test $ol_enable_kbind != no ; then
ol_link_kbind=yes
elif test $ol_enable_kbind = yes ; then
{ (exit 1); exit 1; }; }
fi
-if test $ol_link_krb4 = yes -o $ol_link_krb5 = yes ; then
+if test $ol_link_krb4 = yes || test $ol_link_krb5 = yes ; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_KERBEROS 1
_ACEOF
-elif test $ol_with_kerberos != auto -a $ol_with_kerberos != no ; then
+elif test $ol_with_kerberos != auto && test $ol_with_kerberos != no ; then
{ { echo "$as_me:$LINENO: error: Kerberos detection failed" >&5
echo "$as_me: error: Kerberos detection failed" >&2;}
{ (exit 1); exit 1; }; }
done
- if test $ac_cv_header_openssl_ssl_h = yes \
- -o $ac_cv_header_ssl_h = yes ; then
+ if test $ac_cv_header_openssl_ssl_h = yes ||
+ test $ac_cv_header_ssl_h = yes ; then
echo "$as_me:$LINENO: checking for SSLeay_add_ssl_algorithms in -lssl" >&5
echo $ECHO_N "checking for SSLeay_add_ssl_algorithms in -lssl... $ECHO_C" >&6
if test "${ac_cv_lib_ssl_SSLeay_add_ssl_algorithms+set}" = set; then
ol_link_threads=no
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = nt ; then
+case $ol_with_threads in auto | yes | nt)
echo "$as_me:$LINENO: checking for _beginthread" >&5
echo "$as_me: error: could not locate NT Threads" >&2;}
{ (exit 1); exit 1; }; }
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = posix ; then
+case $ol_with_threads in auto | yes | posix)
for ac_header in pthread.h
done
- if test $ac_cv_func_sched_yield = no -a \
- $ac_cv_func_pthread_yield = no -a \
- $ac_cv_func_thr_yield = no ; then
+ if test $ac_cv_func_sched_yield = no &&
+ test $ac_cv_func_pthread_yield = no &&
+ test $ac_cv_func_thr_yield = no ; then
echo "$as_me:$LINENO: checking for sched_yield in -lrt" >&5
echo $ECHO_N "checking for sched_yield in -lrt... $ECHO_C" >&6
if test "${ac_cv_lib_rt_sched_yield+set}" = set; then
fi
fi
- if test $ac_cv_func_sched_yield = no -a \
- $ac_cv_func_pthread_yield = no -a \
- "$ac_cv_func_thr_yield" = no ; then
+ if test $ac_cv_func_sched_yield = no &&
+ test $ac_cv_func_pthread_yield = no &&
+ test "$ac_cv_func_thr_yield" = no ; then
{ echo "$as_me:$LINENO: WARNING: could not locate sched_yield() or pthread_yield()" >&5
echo "$as_me: WARNING: could not locate sched_yield() or pthread_yield()" >&2;}
fi
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if test $ol_cv_header_linux_threads = yes -a \
- $ol_cv_sys_linux_threads = yes; then
+ if test $ol_cv_header_linux_threads = yes &&
+ test $ol_cv_sys_linux_threads = yes; then
ol_cv_linux_threads=yes
- elif test $ol_cv_header_linux_threads = no -a \
- $ol_cv_sys_linux_threads = no; then
+ elif test $ol_cv_header_linux_threads = no &&
+ test $ol_cv_sys_linux_threads = no; then
ol_cv_linux_threads=no
else
ol_cv_linux_threads=error
echo "$as_me: error: could not locate POSIX Threads" >&2;}
{ (exit 1); exit 1; }; }
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = mach ; then
+case $ol_with_threads in auto | yes | mach)
echo "$as_me: error: could not link with Mach CThreads" >&2;}
{ (exit 1); exit 1; }; }
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = pth ; then
+case $ol_with_threads in auto | yes | pth)
for ac_header in pth.h
fi
fi
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = lwp ; then
+case $ol_with_threads in auto | yes | lwp)
done
- if test $ac_cv_header_thread_h = yes -a $ac_cv_header_synch_h = yes ; then
+ if test $ac_cv_header_thread_h = yes &&
+ test $ac_cv_header_synch_h = yes ; then
echo "$as_me:$LINENO: checking for thr_create in -lthread" >&5
echo $ECHO_N "checking for thr_create in -lthread... $ECHO_C" >&6
if test "${ac_cv_lib_thread_thr_create+set}" = set; then
fi
fi
fi
-fi
+ ;;
+esac
if test $ol_with_yielding_select = yes ; then
fi
-if test $ol_link_threads != no -a $ol_link_threads != nt ; then
+if test $ol_link_threads != no && test $ol_link_threads != nt ; then
cat >>confdefs.h <<\_ACEOF
#define REENTRANT 1
_ACEOF
echo "$as_me:$LINENO: result: $ol_cv_h_errno_thread_specific" >&5
echo "${ECHO_T}$ol_cv_h_errno_thread_specific" >&6
- if test $ol_cv_errno_thread_specific != yes \
- -o $ol_cv_h_errno_thread_specific != yes ; then
+ if test $ol_cv_errno_thread_specific != yes ||
+ test $ol_cv_h_errno_thread_specific != yes ; then
LIBS="$LTHREAD_LIBS $LIBS"
LTHREAD_LIBS=""
fi
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test $ol_cv_func_ctime_r_nargs3 = yes -a \
- $ol_cv_func_ctime_r_nargs2 = no ; then
+ if test $ol_cv_func_ctime_r_nargs3 = yes &&
+ test $ol_cv_func_ctime_r_nargs2 = no ; then
ol_cv_func_ctime_r_nargs=3
- elif test $ol_cv_func_ctime_r_nargs3 = no -a \
- $ol_cv_func_ctime_r_nargs2 = yes ; then
+ elif test $ol_cv_func_ctime_r_nargs3 = no &&
+ test $ol_cv_func_ctime_r_nargs2 = yes ; then
ol_cv_func_ctime_r_nargs=2
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test $ol_cv_func_gethostbyname_r_nargs5 = yes -a \
- $ol_cv_func_gethostbyname_r_nargs6 = no ; then
+ if test $ol_cv_func_gethostbyname_r_nargs5 = yes &&
+ test $ol_cv_func_gethostbyname_r_nargs6 = no ; then
ol_cv_func_gethostbyname_r_nargs=5
- elif test $ol_cv_func_gethostbyname_r_nargs5 = no -a \
- $ol_cv_func_gethostbyname_r_nargs6 = yes ; then
+ elif test $ol_cv_func_gethostbyname_r_nargs5 = no &&
+ test $ol_cv_func_gethostbyname_r_nargs6 = yes ; then
ol_cv_func_gethostbyname_r_nargs=6
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test $ol_cv_func_gethostbyaddr_r_nargs7 = yes -a \
- $ol_cv_func_gethostbyaddr_r_nargs8 = no ; then
+ if test $ol_cv_func_gethostbyaddr_r_nargs7 = yes &&
+ test $ol_cv_func_gethostbyaddr_r_nargs8 = no ; then
ol_cv_func_gethostbyaddr_r_nargs=7
- elif test $ol_cv_func_gethostbyaddr_r_nargs7 = no -a \
- $ol_cv_func_gethostbyaddr_r_nargs8 = yes ; then
+ elif test $ol_cv_func_gethostbyaddr_r_nargs7 = no &&
+ test $ol_cv_func_gethostbyaddr_r_nargs8 = yes ; then
ol_cv_func_gethostbyaddr_r_nargs=8
ol_link_ldbm=no
-if test $ol_enable_ldbm_api = auto \
- -o $ol_enable_ldbm_api = berkeley \
- -o $ol_enable_ldbm_api = bcompat ; then
+case $ol_enable_ldbm_api in auto | berkeley | bcompat)
if test $ol_enable_ldbm_api = bcompat; then \
done
-if test $ac_cv_header_db_185_h = yes -o $ac_cv_header_db_h = yes; then
+if test $ac_cv_header_db_185_h = yes || test $ac_cv_header_db_h = yes; then
echo "$as_me:$LINENO: checking if Berkeley DB header compatibility" >&5
echo $ECHO_N "checking if Berkeley DB header compatibility... $ECHO_C" >&6
if test "${ol_cv_header_db1+set}" = set; then
LDBM_LIBS="$LDBM_LIBS $ol_cv_lib_db"
fi
fi
-fi
+ ;;
+esac
-if test $ol_enable_bdb != no -o $ol_enable_hdb != no; then
+if test $ol_enable_bdb/$ol_enable_hdb != no/no; then
if test $ol_link_ldbm != berkeley ; then
{ { echo "$as_me:$LINENO: error: BDB/HDB: BerkeleyDB not available" >&5
echo "$as_me: error: BDB/HDB: BerkeleyDB not available" >&2;}
fi
fi
-if test $ol_link_ldbm = no -a $ol_enable_ldbm_type = btree ; then
+if test $ol_link_ldbm = no && test $ol_enable_ldbm_type = btree ; then
{ echo "$as_me:$LINENO: WARNING: Could not find LDBM with BTREE support" >&5
echo "$as_me: WARNING: Could not find LDBM with BTREE support" >&2;}
ol_enable_ldbm_api=none
fi
-if test $ol_enable_ldbm_api = auto -o $ol_enable_ldbm_api = mdbm ; then
+if test $ol_enable_ldbm_api = auto || test $ol_enable_ldbm_api = mdbm ; then
echo "$as_me:$LINENO: checking for MDBM library" >&5
echo $ECHO_N "checking for MDBM library... $ECHO_C" >&6
if test "${ol_cv_lib_mdbm+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if test $ol_cv_lib_mdbm = no -o $ac_cv_header_mdbm_h = no ; then
+ if test $ol_cv_lib_mdbm = no || test $ac_cv_header_mdbm_h = no ; then
ol_cv_mdbm=no
else
ol_cv_mdbm=yes
fi
fi
-if test $ol_enable_ldbm_api = auto -o $ol_enable_ldbm_api = gdbm ; then
+if test $ol_enable_ldbm_api = auto || test $ol_enable_ldbm_api = gdbm ; then
echo "$as_me:$LINENO: checking for GDBM library" >&5
echo $ECHO_N "checking for GDBM library... $ECHO_C" >&6
if test "${ol_cv_lib_gdbm+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if test $ol_cv_lib_gdbm = no -o $ac_cv_header_gdbm_h = no ; then
+ if test $ol_cv_lib_gdbm = no || test $ac_cv_header_gdbm_h = no ; then
ol_cv_gdbm=no
else
ol_cv_gdbm=yes
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if test $ol_cv_lib_ndbm = no -o $ac_cv_header_ndbm_h = no ; then
+ if test $ol_cv_lib_ndbm = no || test $ac_cv_header_ndbm_h = no ; then
ol_cv_ndbm=no
else
ol_cv_ndbm=yes
fi
fi
-if test $ol_link_ldbm = no -a $ol_enable_ldbm != no ; then
+if test $ol_link_ldbm = no && test $ol_enable_ldbm != no ; then
{ { echo "$as_me:$LINENO: error: could not find suitable LDBM backend" >&5
echo "$as_me: error: could not find suitable LDBM backend" >&2;}
{ (exit 1); exit 1; }; }
fi
-if test $ol_enable_bdb = yes -o \
- $ol_enable_hdb = yes -o \
- $ol_enable_ldbm = yes ; then
+if test $ol_enable_bdb = yes ||
+ test $ol_enable_hdb = yes ||
+ test $ol_enable_ldbm = yes ; then
SLAPD_LIBS="$SLAPD_LIBS \$(LDBM_LIBS)"
fi
-if test $ol_enable_dynamic = yes -a $enable_shared = yes ; then
+if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then
BUILD_LIBS_DYNAMIC=shared
cat >>confdefs.h <<\_ACEOF
echo "$as_me:$LINENO: result: $ac_cv_func_openlog" >&5
echo "${ECHO_T}$ac_cv_func_openlog" >&6
- if test $ac_cv_func_openlog = no -a $ol_enable_syslog = yes; then
+ if test $ac_cv_func_openlog = no && test $ol_enable_syslog = yes; then
{ { echo "$as_me:$LINENO: error: could not find syslog" >&5
echo "$as_me: error: could not find syslog" >&2;}
{ (exit select appropriate options or disable); exit select appropriate options or disable; }; }
done
- if test $ac_cv_header_sasl_sasl_h = yes -o $ac_cv_header_sasl_h = yes; then
+ if test $ac_cv_header_sasl_sasl_h = yes ||
+ test $ac_cv_header_sasl_h = yes; then
echo "$as_me:$LINENO: checking for sasl_client_init in -lsasl2" >&5
echo $ECHO_N "checking for sasl_client_init in -lsasl2... $ECHO_C" >&6
if test "${ac_cv_lib_sasl2_sasl_client_init+set}" = set; then
fi
fi
-if test $cross_compiling != yes -a "$ac_cv_mingw32" != yes ; then
+if test $cross_compiling != yes && test "$ac_cv_mingw32" != yes ; then
dev=no
if test -r /dev/urandom ; then
dev="/dev/urandom";
ol_have_bn_h=no
ol_have_crypto_h=no
- if test "$ac_cv_header_openssl_bn_h" = "yes" \
- -o "$ac_cv_header_bn_h" = "yes" ; then
+ if test "$ac_cv_header_openssl_bn_h" = "yes" ||
+ test "$ac_cv_header_bn_h" = "yes" ; then
ol_have_bn_h=yes
fi
- if test "$ac_cv_header_openssl_crypto_h" = "yes" \
- -o "$ac_cv_header_crypto_h" = "yes" ; then
+ if test "$ac_cv_header_openssl_crypto_h" = "yes" ||
+ test "$ac_cv_header_crypto_h" = "yes" ; then
ol_have_crypto_h=yes
fi
- if test "$ol_have_bn_h" = "yes" \
- -a "$ol_have_crypto_h" = "yes" ; then
+ if test "$ol_have_bn_h" = "yes" &&
+ test "$ol_have_crypto_h" = "yes" ; then
ol_have_bignum=yes
fi
fi
fi
LIBSRCS="$LIBSRCS getpeereid.c"
fi
-if test "$ac_cv_func_snprintf" != yes -o "$ac_cv_func_vsnprintf" != yes; then
+if test "$ac_cv_func_snprintf" != yes ||
+ test "$ac_cv_func_vsnprintf" != yes; then
if test "$ac_cv_func_snprintf" != yes; then
cat >>confdefs.h <<\_ACEOF
fi
-if test "$ol_link_ldbm" != no -a $ol_enable_ldbm != no; then
+if test "$ol_link_ldbm" != no && test $ol_enable_ldbm != no; then
BUILD_SLAPD=yes
BUILD_LDBM=$ol_enable_ldbm
if test "$ol_enable_ldbm" = mod ; then
fi
-if test "$ol_enable_slurpd" != no -a "$ol_link_threads" != no -a \
- $BUILD_SLAPD = yes ; then
+if test "$ol_enable_slurpd" != no &&
+ test "$ol_link_threads" != no &&
+ test $BUILD_SLAPD = yes ; then
BUILD_SLURPD=yes
fi
AC_MSG_ERROR([could not determine version])
fi
-if test -f "$ac_aux_dir/shtool" -a ! -d $ac_aux_dir/shtool; then
+if test -f "$ac_aux_dir/shtool" && test ! -d $ac_aux_dir/shtool; then
ac_cv_shtool="$ac_aux_dir/shtool"
else
AC_MSG_ERROR([no shtool found in $ac_aux_dir])
AC_MSG_WARN([LDBM disabled, ignoring --enable-ldbm-type argument])
fi
- if test $ol_enable_modules != yes -a \
- $ol_enable_bdb = no -a \
- $ol_enable_dnssrv = no -a \
- $ol_enable_hdb = no -a \
- $ol_enable_ldap = no -a \
- $ol_enable_meta = no -a \
- $ol_enable_monitor = no -a \
- $ol_enable_null = no -a \
- $ol_enable_passwd = no -a \
- $ol_enable_perl = no -a \
- $ol_enable_relay = no -a \
- $ol_enable_shell = no -a \
- $ol_enable_sql = no ; then
+ if test $ol_enable_modules != yes &&
+ test $ol_enable_bdb = no &&
+ test $ol_enable_dnssrv = no &&
+ test $ol_enable_hdb = no &&
+ test $ol_enable_ldap = no &&
+ test $ol_enable_meta = no &&
+ test $ol_enable_monitor = no &&
+ test $ol_enable_null = no &&
+ test $ol_enable_passwd = no &&
+ test $ol_enable_perl = no &&
+ test $ol_enable_relay = no &&
+ test $ol_enable_shell = no &&
+ test $ol_enable_sql = no ; then
if test $ol_enable_slapd = yes ; then
AC_MSG_ERROR([slapd requires a backend])
ol_enable_ldbm_api=no
ol_enable_ldbm_type=no
- if test $ol_enable_bdb != no -o $ol_enable_hdb != no; then
+ if test $ol_enable_bdb/$ol_enable_hdb != no/no; then
ol_enable_ldbm_api=berkeley
fi
else
dnl SLAPD with LDBM
- if test $ol_enable_ldbm_api = gdbm -a \
- $ol_enable_ldbm_type = btree ; then
+ if test $ol_enable_ldbm_api = gdbm &&
+ test $ol_enable_ldbm_type = btree ; then
AC_MSG_ERROR([GDBM only supports LDBM type hash])
fi
- if test $ol_enable_ldbm_api = mdbm -a \
- $ol_enable_ldbm_type = btree ; then
+ if test $ol_enable_ldbm_api = mdbm &&
+ test $ol_enable_ldbm_type = btree ; then
AC_MSG_ERROR([MDBM only supports LDBM type hash])
fi
- if test $ol_enable_ldbm_api = ndbm -a \
- $ol_enable_ldbm_type = btree ; then
+ if test $ol_enable_ldbm_api = ndbm &&
+ test $ol_enable_ldbm_type = btree ; then
AC_MSG_ERROR([NDBM only supports LDBM type hash])
fi
- if test $ol_enable_bdb != no -o $ol_enable_hdb != no ; then
+ if test $ol_enable_bdb/$ol_enable_hdb != no/no ; then
if test $ol_enable_ldbm_api = auto ; then
ol_enable_ldbm_api=berkeley
elif test $ol_enable_ldbm_api != berkeley ; then
fi
fi
-if test $ol_enable_meta = yes -a $ol_enable_ldap = no ; then
+if test $ol_enable_meta/$ol_enable_ldap = yes/no ; then
AC_MSG_ERROR([--enable-meta requires --enable-ldap])
fi
fi
fi
- if test "${CC}" = "cc_r" -o "${CC}" = "xlc_r" ; then
+ case ${CC} in cc_r | xlc_r)
ol_with_threads=posix
ol_cv_pthread_create=yes
- fi
+ ;;
+ esac
fi
if test -z "${CC}"; then
fi
fi
-if test "$ol_enable_dnssrv" = yes -o "$ol_enable_dnssrv" = mod ; then
+if test "$ol_enable_dnssrv" = yes || test "$ol_enable_dnssrv" = mod ; then
if test "$ol_link_dnssrv" = no ; then
AC_MSG_ERROR([DNSSRV requires res_query()])
fi
AC_CHECK_FUNCS( getaddrinfo getnameinfo gai_strerror inet_ntop )
ol_link_ipv6=no
-if test $ac_cv_func_getaddrinfo = no -o $ac_cv_func_inet_ntop = no ; then
+if test $ac_cv_func_getaddrinfo = no || test $ac_cv_func_inet_ntop = no ; then
if test $ol_enable_ipv6 = yes ; then
AC_MSG_ERROR([IPv6 support requires getaddrinfo() and inet_ntop()])
fi
struct sockaddr_storage ss;
]])],[ol_cv_struct_sockaddr_storage=yes],[ol_cv_struct_sockaddr_storage=no])])
- if test $ol_cv_inet6_addrstrlen = yes \
- -a $ol_cv_struct_sockaddr_storage = yes ; then
+ if test $ol_cv_inet6_addrstrlen = yes &&
+ test $ol_cv_struct_sockaddr_storage = yes ; then
ol_link_ipv6=yes
- elif test $ol_enable_ipv6 = yes \
- -a $ol_cv_inet6_addrstrlen = no ; then
+ elif test $ol_enable_ipv6 = yes &&
+ test $ol_cv_inet6_addrstrlen = no ; then
AC_MSG_ERROR([IPv6 support requires INET6_ADDRSTRLEN])
- elif test $ol_enable_ipv6 = yes \
- -a $ol_cv_struct_sockaddr_storage = no ; then
+ elif test $ol_enable_ipv6 = yes &&
+ test $ol_cv_struct_sockaddr_storage = no ; then
AC_MSG_ERROR([IPv6 support requires struct sockaddr_storage])
fi
fi
ol_link_krb5=no
ol_link_krb4=no
-if test $ol_with_kerberos = yes -o $ol_with_kerberos = auto \
- -o $ol_with_kerberos = k5 -o $ol_with_kerberos = k5only \
- -o $ol_with_kerberos = k425 ; then
+case $ol_with_kerberos in yes | auto | k5 | k5only | k425)
AC_CHECK_HEADERS(krb5.h)
fi
fi
-fi
+ ;;
+esac
-if test $ol_link_krb5 = yes -a \( $ol_with_kerberos = yes -o \
- $ol_with_kerberos = auto -o $ol_with_kerberos = k425 \) ; then
+if test $ol_link_krb5 = yes &&
+ { test $ol_with_kerberos = yes ||
+ test $ol_with_kerberos = auto ||
+ test $ol_with_kerberos = k425; }; then
AC_CHECK_HEADERS(kerberosIV/krb.h kerberosIV/des.h)
ol_with_kerberos=found
fi
-if test $ol_with_kerberos = yes -o $ol_with_kerberos = auto \
- -o $ol_with_kerberos = k4 -o $ol_with_kerberos = kth ; then
+case $ol_with_kerberos in yes | auto | k4 | kth)
AC_CHECK_HEADERS(krb.h des.h krb-archaeology.h )
fi
fi
fi
-fi
+ ;;
+esac
-if test $ol_link_krb4 = yes -a $ol_enable_kbind != no ; then
+if test $ol_link_krb4 = yes && test $ol_enable_kbind != no ; then
ol_link_kbind=yes
elif test $ol_enable_kbind = yes ; then
AC_MSG_ERROR([Kerberos IV detection failed])
fi
-if test $ol_link_krb4 = yes -o $ol_link_krb5 = yes ; then
+if test $ol_link_krb4 = yes || test $ol_link_krb5 = yes ; then
AC_DEFINE(HAVE_KERBEROS, 1, [define if you have Kerberos])
-elif test $ol_with_kerberos != auto -a $ol_with_kerberos != no ; then
+elif test $ol_with_kerberos != auto && test $ol_with_kerberos != no ; then
AC_MSG_ERROR([Kerberos detection failed])
fi
if test $ol_with_tls != no ; then
AC_CHECK_HEADERS(openssl/ssl.h ssl.h)
- if test $ac_cv_header_openssl_ssl_h = yes \
- -o $ac_cv_header_ssl_h = yes ; then
+ if test $ac_cv_header_openssl_ssl_h = yes ||
+ test $ac_cv_header_ssl_h = yes ; then
AC_CHECK_LIB(ssl, SSLeay_add_ssl_algorithms,
[have_ssleay=yes
need_rsaref=no],
dnl Threads?
ol_link_threads=no
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = nt ; then
+case $ol_with_threads in auto | yes | nt)
OL_NT_THREADS
if test $ol_with_threads = nt ; then
AC_MSG_ERROR([could not locate NT Threads])
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = posix ; then
+case $ol_with_threads in auto | yes | posix)
AC_CHECK_HEADERS(pthread.h)
dnl check for both, and thr_yield for Solaris
AC_CHECK_FUNCS(sched_yield pthread_yield thr_yield)
- if test $ac_cv_func_sched_yield = no -a \
- $ac_cv_func_pthread_yield = no -a \
- $ac_cv_func_thr_yield = no ; then
+ if test $ac_cv_func_sched_yield = no &&
+ test $ac_cv_func_pthread_yield = no &&
+ test $ac_cv_func_thr_yield = no ; then
dnl Digital UNIX has sched_yield() in -lrt
AC_CHECK_LIB(rt, sched_yield,
[LTHREAD_LIBS="$LTHREAD_LIBS -lrt"
ac_cv_func_sched_yield=yes],
[ac_cv_func_sched_yield=no])
fi
- if test $ac_cv_func_sched_yield = no -a \
- $ac_cv_func_pthread_yield = no -a \
- "$ac_cv_func_thr_yield" = no ; then
+ if test $ac_cv_func_sched_yield = no &&
+ test $ac_cv_func_pthread_yield = no &&
+ test "$ac_cv_func_thr_yield" = no ; then
AC_MSG_WARN([could not locate sched_yield() or pthread_yield()])
fi
if test $ol_with_threads = posix ; then
AC_MSG_ERROR([could not locate POSIX Threads])
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = mach ; then
+case $ol_with_threads in auto | yes | mach)
dnl check for Mach CThreads
AC_CHECK_HEADERS(mach/cthreads.h cthreads.h)
elif test $ol_with_threads = found ; then
AC_MSG_ERROR([could not link with Mach CThreads])
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = pth ; then
+case $ol_with_threads in auto | yes | pth)
AC_CHECK_HEADERS(pth.h)
fi
fi
fi
-fi
+ ;;
+esac
-if test $ol_with_threads = auto -o $ol_with_threads = yes \
- -o $ol_with_threads = lwp ; then
+case $ol_with_threads in auto | yes | lwp)
dnl check for SunOS5 LWP
AC_CHECK_HEADERS(thread.h synch.h)
- if test $ac_cv_header_thread_h = yes -a $ac_cv_header_synch_h = yes ; then
+ if test $ac_cv_header_thread_h = yes &&
+ test $ac_cv_header_synch_h = yes ; then
AC_CHECK_LIB(thread, thr_create, [have_thr=yes], [have_thr=no])
if test $have_thr = yes ; then
fi
fi
fi
-fi
+ ;;
+esac
if test $ol_with_yielding_select = yes ; then
AC_DEFINE(HAVE_YIELDING_SELECT,1,
AC_CHECK_HEADERS(thread.h synch.h)
fi
-if test $ol_link_threads != no -a $ol_link_threads != nt ; then
+if test $ol_link_threads != no && test $ol_link_threads != nt ; then
dnl needed to get reentrant/threadsafe versions
dnl
AC_DEFINE(REENTRANT,1)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <netdb.h>]], [[h_errno = 0;]])],[ol_cv_h_errno_thread_specific=yes],[ol_cv_h_errno_thread_specific=no])
])
- if test $ol_cv_errno_thread_specific != yes \
- -o $ol_cv_h_errno_thread_specific != yes ; then
+ if test $ol_cv_errno_thread_specific != yes ||
+ test $ol_cv_h_errno_thread_specific != yes ; then
LIBS="$LTHREAD_LIBS $LIBS"
LTHREAD_LIBS=""
fi
dnl ----------------------------------------------------------------
ol_link_ldbm=no
-if test $ol_enable_ldbm_api = auto \
- -o $ol_enable_ldbm_api = berkeley \
- -o $ol_enable_ldbm_api = bcompat ; then
+case $ol_enable_ldbm_api in auto | berkeley | bcompat)
if test $ol_enable_ldbm_api = bcompat; then \
OL_BERKELEY_COMPAT_DB
LDBM_LIBS="$LDBM_LIBS $ol_cv_lib_db"
fi
fi
-fi
+ ;;
+esac
-if test $ol_enable_bdb != no -o $ol_enable_hdb != no; then
+if test $ol_enable_bdb/$ol_enable_hdb != no/no; then
if test $ol_link_ldbm != berkeley ; then
AC_MSG_ERROR(BDB/HDB: BerkeleyDB not available)
else
fi
fi
-if test $ol_link_ldbm = no -a $ol_enable_ldbm_type = btree ; then
+if test $ol_link_ldbm = no && test $ol_enable_ldbm_type = btree ; then
AC_MSG_WARN([Could not find LDBM with BTREE support])
ol_enable_ldbm_api=none
fi
-if test $ol_enable_ldbm_api = auto -o $ol_enable_ldbm_api = mdbm ; then
+if test $ol_enable_ldbm_api = auto || test $ol_enable_ldbm_api = mdbm ; then
OL_MDBM
if test $ol_cv_mdbm = yes ; then
fi
fi
-if test $ol_enable_ldbm_api = auto -o $ol_enable_ldbm_api = gdbm ; then
+if test $ol_enable_ldbm_api = auto || test $ol_enable_ldbm_api = gdbm ; then
OL_GDBM
if test $ol_cv_gdbm = yes ; then
fi
fi
-if test $ol_link_ldbm = no -a $ol_enable_ldbm != no ; then
+if test $ol_link_ldbm = no && test $ol_enable_ldbm != no ; then
AC_MSG_ERROR([could not find suitable LDBM backend])
fi
-if test $ol_enable_bdb = yes -o \
- $ol_enable_hdb = yes -o \
- $ol_enable_ldbm = yes ; then
+if test $ol_enable_bdb = yes ||
+ test $ol_enable_hdb = yes ||
+ test $ol_enable_ldbm = yes ; then
SLAPD_LIBS="$SLAPD_LIBS \$(LDBM_LIBS)"
fi
dnl ----------------------------------------------------------------
-if test $ol_enable_dynamic = yes -a $enable_shared = yes ; then
+if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then
BUILD_LIBS_DYNAMIC=shared
AC_DEFINE(LDAP_LIBS_DYNAMIC, 1, [define if LDAP libs are dynamic])
LTSTATIC=""
dnl ----------------------------------------------------------------
if test $ol_enable_syslog != no ; then
AC_CHECK_FUNC(openlog)
- if test $ac_cv_func_openlog = no -a $ol_enable_syslog = yes; then
+ if test $ac_cv_func_openlog = no && test $ol_enable_syslog = yes; then
AC_MSG_ERROR(could not find syslog, select appropriate options or disable)
fi
ol_enable_syslog=$ac_cv_func_openlog
if test $ol_with_cyrus_sasl != no ; then
AC_CHECK_HEADERS(sasl/sasl.h sasl.h)
- if test $ac_cv_header_sasl_sasl_h = yes -o $ac_cv_header_sasl_h = yes; then
+ if test $ac_cv_header_sasl_sasl_h = yes ||
+ test $ac_cv_header_sasl_h = yes; then
AC_CHECK_LIB(sasl2, sasl_client_init,
[ol_link_sasl="-lsasl2"],
[AC_CHECK_LIB(sasl, sasl_client_init,
dnl ----------------------------------------------------------------
dnl Check for entropy sources
-if test $cross_compiling != yes -a "$ac_cv_mingw32" != yes ; then
+if test $cross_compiling != yes && test "$ac_cv_mingw32" != yes ; then
dev=no
if test -r /dev/urandom ; then
dev="/dev/urandom";
ol_have_bn_h=no
ol_have_crypto_h=no
- if test "$ac_cv_header_openssl_bn_h" = "yes" \
- -o "$ac_cv_header_bn_h" = "yes" ; then
+ if test "$ac_cv_header_openssl_bn_h" = "yes" ||
+ test "$ac_cv_header_bn_h" = "yes" ; then
ol_have_bn_h=yes
fi
- if test "$ac_cv_header_openssl_crypto_h" = "yes" \
- -o "$ac_cv_header_crypto_h" = "yes" ; then
+ if test "$ac_cv_header_openssl_crypto_h" = "yes" ||
+ test "$ac_cv_header_crypto_h" = "yes" ; then
ol_have_crypto_h=yes
fi
- if test "$ol_have_bn_h" = "yes" \
- -a "$ol_have_crypto_h" = "yes" ; then
+ if test "$ol_have_bn_h" = "yes" &&
+ test "$ol_have_crypto_h" = "yes" ; then
ol_have_bignum=yes
fi
fi
fi
LIBSRCS="$LIBSRCS getpeereid.c"
fi
-if test "$ac_cv_func_snprintf" != yes -o "$ac_cv_func_vsnprintf" != yes; then
+if test "$ac_cv_func_snprintf" != yes ||
+ test "$ac_cv_func_vsnprintf" != yes; then
if test "$ac_cv_func_snprintf" != yes; then
AC_DEFINE(snprintf, ber_pvt_snprintf, [define to snprintf routine])
fi
AC_DEFINE_UNQUOTED(SLAPD_LDAP,$MFLAG,[define to support LDAP backend])
fi
-if test "$ol_link_ldbm" != no -a $ol_enable_ldbm != no; then
+if test "$ol_link_ldbm" != no && test $ol_enable_ldbm != no; then
BUILD_SLAPD=yes
BUILD_LDBM=$ol_enable_ldbm
if test "$ol_enable_ldbm" = mod ; then
AC_DEFINE_UNQUOTED(SLAPD_OVER_VALSORT,$MFLAG,[define for Value Sorting overlay])
fi
-if test "$ol_enable_slurpd" != no -a "$ol_link_threads" != no -a \
- $BUILD_SLAPD = yes ; then
+if test "$ol_enable_slurpd" != no &&
+ test "$ol_link_threads" != no &&
+ test $BUILD_SLAPD = yes ; then
BUILD_SLURPD=yes
fi
The usual rules for LDIF files apply to the configuration information:
Comment lines beginning with a '{{EX:#}}' character
-are ignored. If a line begins with white space, it is considered a
+are ignored. If a line begins with a single space, it is considered a
continuation of the previous line (even if the previous line is a
-comment). Entries are separated by blank lines.
+comment) and the single leading space is removed. Entries are separated by blank lines.
The general layout of the config LDIF is as follows:
A configuration directive may take arguments. If so, the arguments are
separated by white space. If an argument contains white space,
-the argument should be enclosed in double quotes {{EX:"like this"}}. If
-an argument contains a double quote or a backslash character `{{EX:\}}',
-the character should be preceded by a backslash character `{{EX:\}}'.
+the argument should be enclosed in double quotes {{EX:"like this"}}.
In the descriptions that follow, arguments that should be replaced
by actual text are shown in brackets {{EX:<>}}.
>objectClass: olcSchemaConfig
>cn: test
>olcAttributeTypes: ( 1.1.1
-> NAME 'testAttr'
-> EQUALITY integerMatch
-> SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+> NAME 'testAttr'
+> EQUALITY integerMatch
+> SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
>olcAttributeTypes: ( 1.1.2 NAME 'testTwo' EQUALITY caseIgnoreMatch
-> SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
+> SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
>olcObjectClasses: ( 1.1.3 NAME 'testObject'
-> MAY ( testAttr $ testTwo ) AUXILIARY )
+> MAY ( testAttr $ testTwo ) AUXILIARY )
H3: Backend-specific Directives
struct avlnode {
void* avl_data;
- signed int avl_bf;
- struct avlnode *avl_left;
- struct avlnode *avl_right;
+ struct avlnode *avl_link[2];
+ char avl_bits[2];
+ signed char avl_bf;
};
+#define avl_left avl_link[0]
+#define avl_right avl_link[1]
+#define avl_lbit avl_bits[0]
+#define avl_rbit avl_bits[1]
+
#ifdef AVL_INTERNAL
#define NULLAVL ((Avlnode *) NULL)
#define EH 0
#define RH 1
+/* thread bits */
+#define AVL_THREAD 0
+#define AVL_CHILD 1
+
/* avl routines */
#define avl_getone(x) ((x) == 0 ? 0 : (x)->avl_data)
#define avl_onenode(x) ((x) == 0 || ((x)->avl_left == 0 && (x)->avl_right == 0))
#endif /* AVL_INTERNALS */
+#define avl_child(x,dir) ((x)->avl_bits[dir]) == AVL_CHILD ? \
+ (x)->avl_link[dir] : NULL
+#define avl_lchild(x) avl_child(x,0)
+#define avl_rchild(x) avl_child(x,1)
+
typedef int (*AVL_APPLY) LDAP_P((void *, void*));
typedef int (*AVL_CMP) LDAP_P((const void*, const void*));
typedef int (*AVL_DUP) LDAP_P((void*, void*));
LDAP_AVL_F( int )
avl_prefixapply LDAP_P((Avlnode *, void*, AVL_CMP, void*, AVL_CMP, void*, int));
+LDAP_AVL_F( int )
+tavl_free LDAP_P(( Avlnode *root, AVL_FREE dfree ));
+
+LDAP_AVL_F( int )
+tavl_insert LDAP_P((Avlnode **, void*, AVL_CMP, AVL_DUP));
+
+LDAP_AVL_F( void* )
+tavl_delete LDAP_P((Avlnode **, void*, AVL_CMP));
+
+LDAP_AVL_F( void* )
+tavl_find LDAP_P((Avlnode *, const void*, AVL_CMP));
+
+LDAP_AVL_F( Avlnode* )
+tavl_find2 LDAP_P((Avlnode *, const void*, AVL_CMP));
+
+#define TAVL_DIR_LEFT 0
+#define TAVL_DIR_RIGHT 1
+
+LDAP_AVL_F( Avlnode* )
+tavl_end LDAP_P((Avlnode *, int direction ));
+
+LDAP_AVL_F( Avlnode* )
+tavl_next LDAP_P((Avlnode *, int direction ));
+
/* apply traversal types */
#define AVL_PREORDER 1
#define AVL_INORDER 2
* <http://www.OpenLDAP.org/license.html>.
*/
+
+LDAP_BEGIN_DECL
+
+/* Can be done twice in libldap_r. See libldap_r/ldap_thr_debug.h. */
+LDAP_F(int) ldap_int_thread_initialize LDAP_P(( void ));
+LDAP_F(int) ldap_int_thread_destroy LDAP_P(( void ));
+
+LDAP_END_DECL
+
+
#ifndef _LDAP_INT_THREAD_H
#define _LDAP_INT_THREAD_H
typedef pthread_mutex_t ldap_int_thread_mutex_t;
typedef pthread_cond_t ldap_int_thread_cond_t;
+#define ldap_int_thread_equal(a, b) pthread_equal((a), (b))
+
#if defined( _POSIX_REENTRANT_FUNCTIONS ) || \
defined( _POSIX_THREAD_SAFE_FUNCTIONS ) || \
defined( _POSIX_THREADSAFE_FUNCTIONS )
#if 0 && defined( HAVE_PTHREAD_RWLOCK_DESTROY )
#define LDAP_THREAD_HAVE_RDWR 1
-typedef pthread_rwlock_t ldap_pvt_thread_rdwr_t;
+typedef pthread_rwlock_t ldap_int_thread_rdwr_t;
#endif
LDAP_END_DECL
#if 0
#define LDAP_THREAD_HAVE_RDWR 1
-typedef pth_rwlock_t ldap_pvt_thread_rdwr_t;
+typedef pth_rwlock_t ldap_int_thread_rdwr_t;
#endif
LDAP_END_DECL
LDAP_END_DECL
#elif defined(HAVE_NT_THREADS)
+/*************************************
+ * *
+ * thread definitions for NT threads *
+ * *
+ *************************************/
#include <process.h>
#include <windows.h>
LDAP_END_DECL
#else
-
/***********************************
* *
* thread definitions for no *
#endif /* no threads support */
+
LDAP_BEGIN_DECL
-LDAP_F(int) ldap_int_thread_initialize LDAP_P(( void ));
-LDAP_F(int) ldap_int_thread_destroy LDAP_P(( void ));
+#ifndef ldap_int_thread_equal
+#define ldap_int_thread_equal(a, b) ((a) == (b))
+#endif
+
+#ifndef LDAP_THREAD_HAVE_RDWR
+typedef struct ldap_int_thread_rdwr_s * ldap_int_thread_rdwr_t;
+#endif
+
LDAP_F(int) ldap_int_thread_pool_startup ( void );
LDAP_F(int) ldap_int_thread_pool_shutdown ( void );
LDAP_END_DECL
+
+#if defined(LDAP_THREAD_DEBUG) && !((LDAP_THREAD_DEBUG +0) & 2U)
+#define LDAP_THREAD_DEBUG_WRAP 1
+#endif
+
+#ifdef LDAP_THREAD_DEBUG_WRAP
+/**************************************
+ * *
+ * definitions for type-wrapped debug *
+ * *
+ **************************************/
+
+LDAP_BEGIN_DECL
+
+#ifndef LDAP_UINTPTR_T /* May be configured in CPPFLAGS */
+#define LDAP_UINTPTR_T unsigned long
+#endif
+
+typedef union {
+ unsigned char *ptr;
+ LDAP_UINTPTR_T num;
+} ldap_debug_usage_info_t;
+
+typedef struct {
+ ldap_int_thread_mutex_t wrapped;
+ ldap_debug_usage_info_t usage;
+} ldap_debug_thread_mutex_t;
+
+typedef struct {
+ ldap_int_thread_cond_t wrapped;
+ ldap_debug_usage_info_t usage;
+} ldap_debug_thread_cond_t;
+
+typedef struct {
+ ldap_int_thread_rdwr_t wrapped;
+ ldap_debug_usage_info_t usage;
+} ldap_debug_thread_rdwr_t;
+
+LDAP_END_DECL
+
+#endif /* LDAP_THREAD_DEBUG_WRAP */
+
#endif /* _LDAP_INT_THREAD_H */
*/
#ifndef _LDAP_PVT_THREAD_H
-#define _LDAP_PVT_THREAD_H
+#define _LDAP_PVT_THREAD_H /* libldap_r/ldap_thr_debug.h #undefines this */
#include "ldap_cdefs.h"
#include "ldap_int_thread.h"
LDAP_BEGIN_DECL
-typedef ldap_int_thread_t ldap_pvt_thread_t;
-typedef ldap_int_thread_mutex_t ldap_pvt_thread_mutex_t;
-typedef ldap_int_thread_cond_t ldap_pvt_thread_cond_t;
+#ifndef LDAP_PVT_THREAD_H_DONE
+typedef ldap_int_thread_t ldap_pvt_thread_t;
+#ifdef LDAP_THREAD_DEBUG_WRAP
+typedef ldap_debug_thread_mutex_t ldap_pvt_thread_mutex_t;
+typedef ldap_debug_thread_cond_t ldap_pvt_thread_cond_t;
+typedef ldap_debug_thread_rdwr_t ldap_pvt_thread_rdwr_t;
+#else
+typedef ldap_int_thread_mutex_t ldap_pvt_thread_mutex_t;
+typedef ldap_int_thread_cond_t ldap_pvt_thread_cond_t;
+typedef ldap_int_thread_rdwr_t ldap_pvt_thread_rdwr_t;
+#endif
+#endif /* !LDAP_PVT_THREAD_H_DONE */
+
+#define ldap_pvt_thread_equal ldap_int_thread_equal
LDAP_F( int )
ldap_pvt_thread_initialize LDAP_P(( void ));
#define LDAP_PVT_THREAD_CREATE_JOINABLE 0
#define LDAP_PVT_THREAD_CREATE_DETACHED 1
+#ifndef LDAP_PVT_THREAD_H_DONE
#define LDAP_PVT_THREAD_SET_STACK_SIZE
#ifndef LDAP_PVT_THREAD_STACK_SIZE
/* LARGE stack. Will be twice as large on 64 bit machine. */
#elif LDAP_PVT_THREAD_STACK_SIZE == 0
#undef LDAP_PVT_THREAD_SET_STACK_SIZE
#endif
+#endif /* !LDAP_PVT_THREAD_H_DONE */
LDAP_F( int )
ldap_pvt_thread_create LDAP_P((
LDAP_F( ldap_pvt_thread_t )
ldap_pvt_thread_self LDAP_P(( void ));
-#ifndef LDAP_THREAD_HAVE_RDWR
-typedef struct ldap_int_thread_rdwr_s * ldap_pvt_thread_rdwr_t;
-#endif
-
LDAP_F( int )
ldap_pvt_thread_rdwr_init LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
#define LDAP_PVT_THREAD_EINVAL EINVAL
#define LDAP_PVT_THREAD_EBUSY EINVAL
+#ifndef LDAP_PVT_THREAD_H_DONE
typedef ldap_int_thread_pool_t ldap_pvt_thread_pool_t;
typedef void * (ldap_pvt_thread_start_t) LDAP_P((void *ctx, void *arg));
typedef void (ldap_pvt_thread_pool_keyfree_t) LDAP_P((void *key, void *data));
+#endif /* !LDAP_PVT_THREAD_H_DONE */
LDAP_F( int )
ldap_pvt_thread_pool_init LDAP_P((
LDAP_END_DECL
+#define LDAP_PVT_THREAD_H_DONE
#endif /* _LDAP_THREAD_H */
ber_int_t num,
ber_tag_t tag ));
+#define BER_TOP_BYTE(type) (sizeof(type)-1)
+#define BER_TOP_MASK(type) ((type)0xffU << (BER_TOP_BYTE(type)*8))
static int
ber_calc_taglen( ber_tag_t tag )
{
- int i;
- ber_tag_t mask;
+ int i = BER_TOP_BYTE(ber_tag_t);
+ ber_tag_t mask = BER_TOP_MASK(ber_tag_t);
/* find the first non-all-zero byte in the tag */
- for ( i = sizeof(ber_tag_t) - 1; i > 0; i-- ) {
- mask = ((ber_tag_t)0xffU << (i * 8));
+ for ( ; i > 0; i-- ) {
/* not all zero */
if ( tag & mask ) break;
+ mask >>= 8;
}
return i + 1;
int nosos )
{
int rc;
- int taglen;
+ int taglen;
int i;
unsigned char nettag[sizeof(ber_tag_t)];
taglen = ber_calc_taglen( tag );
- for( i=0; i<taglen; i++ ) {
- nettag[(sizeof(ber_tag_t)-1) - i] = (unsigned char)(tag & 0xffU);
+ for( i=taglen-1; i>=0; i-- ) {
+ nettag[i] = (unsigned char)(tag & 0xffU);
tag >>= 8;
}
- rc = ber_write( ber,
- (char *) &nettag[sizeof(ber_tag_t) - taglen],
- taglen, nosos );
+ rc = ber_write( ber, (char *) nettag, taglen, nosos );
return rc;
}
*/
/* find the first non-all-zero byte */
- for ( i = sizeof(ber_len_t) - 1; i > 0; i-- ) {
- mask = ((ber_len_t)0xffU << (i * 8));
+ i = BER_TOP_BYTE(ber_len_t);
+ mask = BER_TOP_MASK(ber_len_t);
+ for ( ; i > 0; i-- ) {
/* not all zero */
if ( len & mask ) break;
+ mask >>= 8;
}
lenlen = (unsigned char) ++i;
if ( lenlen > 4 ) return -1;
/* write the length of the length */
if ( ber_write( ber, &lenlen, 1, nosos ) != 1 ) return -1;
- for( j=0; j<i; j++) {
- netlen[(sizeof(ber_len_t)-1) - j] = (unsigned char)(len & 0xffU);
+ for( j=i-1; j>=0; j-- ) {
+ netlen[j] = (unsigned char)(len & 0xffU);
len >>= 8;
}
/* write the length itself */
- rc = ber_write( ber,
- (char *) &netlen[sizeof(ber_len_t)-i],
- i, nosos );
+ rc = ber_write( ber, (char *) netlen, i, nosos );
return rc == i ? i+1 : -1;
}
* high bit is set - look for first non-all-one byte
* high bit is clear - look for first non-all-zero byte
*/
- for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) {
- mask = ((ber_uint_t)0xffU << (i * 8));
-
+ i = BER_TOP_BYTE(ber_int_t);
+ mask = BER_TOP_MASK(ber_uint_t);
+ for ( ; i > 0; i-- ) {
if ( sign ) {
/* not all ones */
if ( (unum & mask) != mask ) break;
/* not all zero */
if ( unum & mask ) break;
}
+ mask >>= 8;
}
/*
}
i++;
- for( j=0; j<i; j++ ) {
- netnum[(sizeof(ber_int_t)-1) - j] = (unsigned char)(unum & 0xffU);
+ for( j=i-1; j>=0; j-- ) {
+ netnum[j] = (unsigned char)(unum & 0xffU);
unum >>= 8;
}
- rc = ber_write( ber,
- (char *) &netnum[sizeof(ber_int_t) - i],
- i, 0 );
+ rc = ber_write( ber, (char *) netnum, i, 0 );
/* length of tag + length + contents */
return rc == i ? taglen + lenlen + i : -1;
}
if( lenlen > 1 ) {
- ber_len_t i;
- for( i=0; i < lenlen-1; i++ ) {
- netlen[(sizeof(ber_len_t)-1) - i] =
- (unsigned char)((len >> i*8) & 0xffU);
+ int i;
+ ber_len_t j = len;
+ for( i=lenlen-2; i >= 0; i-- ) {
+ netlen[i] = j & 0xffU;
+ j >>= 8;
}
} else {
- netlen[sizeof(ber_len_t)-1] = (unsigned char)(len & 0x7fU);
+ netlen[0] = (unsigned char)(len & 0x7fU);
}
if ( (next = (*sos)->sos_next) == NULL ) {
}
/* the length itself */
- rc = ber_write( ber,
- (char *) &netlen[sizeof(ber_len_t) - (FOUR_BYTE_LEN-1)],
- FOUR_BYTE_LEN-1, 1 );
+ rc = ber_write( ber, (char *) netlen, FOUR_BYTE_LEN-1, 1 );
if( rc != FOUR_BYTE_LEN - 1 ) {
return -1;
/* the tag */
taglen = ber_calc_taglen( tmptag );
- for( i = 0; i < taglen; i++ ) {
- nettag[(sizeof(ber_tag_t)-1) - i] = (unsigned char)(tmptag & 0xffU);
+ for( i = taglen-1; i >= 0; i-- ) {
+ nettag[i] = (unsigned char)(tmptag & 0xffU);
tmptag >>= 8;
}
- AC_FMEMCPY( (*sos)->sos_first,
- &nettag[sizeof(ber_tag_t) - taglen],
- taglen );
+ AC_FMEMCPY( (*sos)->sos_first, nettag, taglen );
if ( ber->ber_options & LBER_USE_DER ) {
ltag = (lenlen == 1)
if ( ber->ber_options & LBER_USE_DER ) {
if (lenlen > 1) {
/* Write the length itself */
- AC_FMEMCPY( (*sos)->sos_first + 2,
- &netlen[sizeof(ber_len_t) - (lenlen - 1)],
- lenlen - 1 );
+ AC_FMEMCPY( (*sos)->sos_first + 2, netlen, lenlen - 1 );
}
if (lenlen != FOUR_BYTE_LEN) {
/*
} else {
/* the length itself */
AC_FMEMCPY( (*sos)->sos_first + taglen + 1,
- &netlen[sizeof(ber_len_t) - (FOUR_BYTE_LEN - 1)],
- FOUR_BYTE_LEN - 1 );
+ netlen, FOUR_BYTE_LEN - 1 );
}
next->sos_clen += (taglen + lenlen + len);
/* Now look for the length */
if (*ber->ber_ptr & 0x80) { /* multi-byte */
- ber_len_t i;
+ int i;
unsigned char *p = (unsigned char *)ber->ber_ptr;
int llen = *p++ & 0x7f;
if (llen > (int)sizeof(ber_len_t)) {
int async)
{
int rc;
- struct timeval tv, *opt_tv=NULL;
+ struct timeval tv = { 0 },
+ *opt_tv = NULL;
#ifdef LDAP_CONNECTIONLESS
/* We could do a connect() but that would interfere with
return ( 0 );
}
#endif
- if ( (opt_tv = ld->ld_options.ldo_tm_net) != NULL ) {
- tv.tv_usec = opt_tv->tv_usec;
- tv.tv_sec = opt_tv->tv_sec;
+ opt_tv = ld->ld_options.ldo_tm_net;
+ if ( opt_tv != NULL ) {
+ tv = *opt_tv;
}
osip_debug(ld, "ldap_connect_timeout: fd: %d tm: %ld async: %d\n",
ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sa, int async)
{
int rc;
- struct timeval tv, *opt_tv=NULL;
+ struct timeval tv = { 0 },
+ *opt_tv = NULL;
- if ( (opt_tv = ld->ld_options.ldo_tm_net) != NULL ) {
- tv.tv_usec = opt_tv->tv_usec;
- tv.tv_sec = opt_tv->tv_sec;
+ opt_tv = ld->ld_options.ldo_tm_net;
+ if ( opt_tv != NULL ) {
+ tv = *opt_tv;
}
oslocal_debug(ld, "ldap_connect_timeout: fd: %d tm: %ld async: %d\n",
LDAPMessage **result )
{
int rc;
- struct timeval tv, tv0, *tvp;
+ struct timeval tv = { 0 },
+ tv0 = { 0 },
+ *tvp;
time_t start_time = 0;
time_t tmp_time;
LDAPConn *lc, *nextlc;
rc = -2;
while ( rc == -2 ) {
#ifdef LDAP_DEBUG
- Debug( LDAP_DEBUG_TRACE, "wait4msg continue, msgid %d, all %d\n",
- msgid, all, 0 );
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
+ Debug( LDAP_DEBUG_TRACE, "wait4msg continue, msgid %d, all %d\n",
+ msgid, all, 0 );
ldap_dump_connection( ld, ld->ld_conns, 1 );
ldap_dump_requests_and_responses( ld );
}
if ( rc == -2 && tvp != NULL ) {
tmp_time = time( NULL );
- if (( tv0.tv_sec -= ( tmp_time - start_time )) <= 0 ) {
+ tv0.tv_sec -= ( tmp_time - start_time );
+ if ( tv0.tv_sec <= 0 ) {
rc = 0; /* timed out */
ld->ld_errno = LDAP_TIMEOUT;
break;
ldap_msgtype( LDAPMessage *lm )
{
assert( lm != NULL );
- return ( lm != NULL ) ? lm->lm_msgtype : -1;
+ return ( lm != NULL ) ? (int)lm->lm_msgtype : -1;
}
turn.c groupings.c txn.c ppolicy.c
SRCS = threads.c rdwr.c tpool.c rq.c \
thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
- thr_pth.c thr_stub.c
+ thr_pth.c thr_stub.c thr_debug.c
OBJS = threads.lo rdwr.lo tpool.lo rq.lo \
thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \
- thr_pth.lo thr_stub.lo \
+ thr_pth.lo thr_stub.lo thr_debug.lo \
bind.lo open.lo result.lo error.lo compare.lo search.lo \
controls.lo messages.lo references.lo extended.lo cyrus.lo \
modify.lo add.lo modrdn.lo delete.lo abandon.lo \
--- /dev/null
+/* ldap_thr_debug.h - preprocessor magic for LDAP_THREAD_DEBUG */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * 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>.
+ */
+
+#ifdef LDAP_THREAD_DEBUG
+
+/*
+ * libldap_r .c files should include this file after ldap_pvt_thread.h,
+ * with the appropriate LDAP_THREAD*_IMPLEMENTATION macro defined.
+ */
+
+#ifndef _LDAP_PVT_THREAD_H
+#error "ldap_pvt_thread.h" must be included before "ldap_thr_debug.h"
+#endif
+
+/*
+ * Support for thr_debug.c:
+ *
+ * thr_debug.c defines the ldap_pvt_*() as wrappers around
+ * ldap_int_*(), and ldap_debug_*() around ldap_int_*().
+ *
+ * Renames ldap_pvt_thread_* names to ldap_int_thread_*, and a few
+ * ldap_int_*() names to ldap_debug_*(). Includes "ldap_pvt_thread.h"
+ * to declare these renamed functions, and undefines the macros
+ * afterwards when included from thr_debug.c. So,
+ *
+ * libldap_r/<not thr_debug.c> define ldap_int_* instead of ldap_pvt_*.
+ * In thread.c, ldap_pvt_thread_<initialize/destroy>() will call
+ * ldap_debug_*() instead of ldap_int_*().
+ * In tpool.c, ldap_int_thread_pool_shutdown() has thr_debug support
+ * which treats ldap_pvt_thread_pool_destroy() the same way.
+ */
+
+#ifndef LDAP_THREAD_IMPLEMENTATION /* for first part of threads.c */
+#define ldap_int_thread_initialize ldap_debug_thread_initialize
+#define ldap_int_thread_destroy ldap_debug_thread_destroy
+#else /* LDAP_THREAD_IMPLEMENTATION -- for thr_*.c and end of threads.c */
+#undef ldap_int_thread_initialize
+#undef ldap_int_thread_destroy
+#ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */
+#define ldap_pvt_thread_mutex_t ldap_int_thread_mutex_t
+#define ldap_pvt_thread_cond_t ldap_int_thread_cond_t
+#endif
+#define ldap_pvt_thread_sleep ldap_int_thread_sleep
+#define ldap_pvt_thread_get_concurrency ldap_int_thread_get_concurrency
+#define ldap_pvt_thread_set_concurrency ldap_int_thread_set_concurrency
+#define ldap_pvt_thread_create ldap_int_thread_create
+#define ldap_pvt_thread_exit ldap_int_thread_exit
+#define ldap_pvt_thread_join ldap_int_thread_join
+#define ldap_pvt_thread_kill ldap_int_thread_kill
+#define ldap_pvt_thread_yield ldap_int_thread_yield
+#define ldap_pvt_thread_cond_init ldap_int_thread_cond_init
+#define ldap_pvt_thread_cond_destroy ldap_int_thread_cond_destroy
+#define ldap_pvt_thread_cond_signal ldap_int_thread_cond_signal
+#define ldap_pvt_thread_cond_broadcast ldap_int_thread_cond_broadcast
+#define ldap_pvt_thread_cond_wait ldap_int_thread_cond_wait
+#define ldap_pvt_thread_mutex_init ldap_int_thread_mutex_init
+#define ldap_pvt_thread_mutex_destroy ldap_int_thread_mutex_destroy
+#define ldap_pvt_thread_mutex_lock ldap_int_thread_mutex_lock
+#define ldap_pvt_thread_mutex_trylock ldap_int_thread_mutex_trylock
+#define ldap_pvt_thread_mutex_unlock ldap_int_thread_mutex_unlock
+#define ldap_pvt_thread_self ldap_int_thread_self
+#endif /* LDAP_THREAD_IMPLEMENTATION */
+
+#ifdef LDAP_THREAD_RDWR_IMPLEMENTATION /* rdwr.c, thr_debug.c */
+#ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */
+#define ldap_pvt_thread_rdwr_t ldap_int_thread_rdwr_t
+#endif
+#define ldap_pvt_thread_rdwr_init ldap_int_thread_rdwr_init
+#define ldap_pvt_thread_rdwr_destroy ldap_int_thread_rdwr_destroy
+#define ldap_pvt_thread_rdwr_rlock ldap_int_thread_rdwr_rlock
+#define ldap_pvt_thread_rdwr_rtrylock ldap_int_thread_rdwr_rtrylock
+#define ldap_pvt_thread_rdwr_runlock ldap_int_thread_rdwr_runlock
+#define ldap_pvt_thread_rdwr_wlock ldap_int_thread_rdwr_wlock
+#define ldap_pvt_thread_rdwr_wtrylock ldap_int_thread_rdwr_wtrylock
+#define ldap_pvt_thread_rdwr_wunlock ldap_int_thread_rdwr_wunlock
+#define ldap_pvt_thread_rdwr_readers ldap_int_thread_rdwr_readers
+#define ldap_pvt_thread_rdwr_writers ldap_int_thread_rdwr_writers
+#define ldap_pvt_thread_rdwr_active ldap_int_thread_rdwr_active
+#endif /* LDAP_THREAD_RDWR_IMPLEMENTATION */
+
+#ifdef LDAP_THREAD_POOL_IMPLEMENTATION /* tpool.c, thr_stub.c, thr_debug.c */
+#ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */
+#define ldap_pvt_thread_pool_t ldap_int_thread_pool_t
+#endif
+#define ldap_pvt_thread_pool_init ldap_int_thread_pool_init
+#define ldap_pvt_thread_pool_submit ldap_int_thread_pool_submit
+#define ldap_pvt_thread_pool_maxthreads ldap_int_thread_pool_maxthreads
+#define ldap_pvt_thread_pool_backload ldap_int_thread_pool_backload
+#define ldap_pvt_thread_pool_pause ldap_int_thread_pool_pause
+#define ldap_pvt_thread_pool_resume ldap_int_thread_pool_resume
+#define ldap_pvt_thread_pool_destroy ldap_int_thread_pool_destroy
+#define ldap_pvt_thread_pool_getkey ldap_int_thread_pool_getkey
+#define ldap_pvt_thread_pool_setkey ldap_int_thread_pool_setkey
+#define ldap_pvt_thread_pool_purgekey ldap_int_thread_pool_purgekey
+#define ldap_pvt_thread_pool_context ldap_int_thread_pool_context
+#define ldap_pvt_thread_pool_context_reset ldap_int_thread_pool_context_reset
+#endif /* LDAP_THREAD_POOL_IMPLEMENTATION */
+
+#undef _LDAP_PVT_THREAD_H
+#include "ldap_pvt_thread.h"
+
+#ifdef LDAP_THREAD_POOL_IMPLEMENTATION /* tpool.c */
+/*
+ * tpool.c:ldap_int_thread_pool_shutdown() needs this. Could not
+ * use it for ldap_pvt_thread.h above because of its use of LDAP_P().
+ */
+#undef ldap_pvt_thread_pool_destroy
+#define ldap_pvt_thread_pool_destroy(p,r) ldap_int_thread_pool_destroy(p,r)
+#endif
+
+#ifdef LDAP_THREAD_DEBUG_IMPLEMENTATION /* thr_debug.c */
+#undef ldap_pvt_thread_mutex_t
+#undef ldap_pvt_thread_cond_t
+#undef ldap_pvt_thread_sleep
+#undef ldap_pvt_thread_get_concurrency
+#undef ldap_pvt_thread_set_concurrency
+#undef ldap_pvt_thread_create
+#undef ldap_pvt_thread_exit
+#undef ldap_pvt_thread_join
+#undef ldap_pvt_thread_kill
+#undef ldap_pvt_thread_yield
+#undef ldap_pvt_thread_cond_init
+#undef ldap_pvt_thread_cond_destroy
+#undef ldap_pvt_thread_cond_signal
+#undef ldap_pvt_thread_cond_broadcast
+#undef ldap_pvt_thread_cond_wait
+#undef ldap_pvt_thread_mutex_init
+#undef ldap_pvt_thread_mutex_destroy
+#undef ldap_pvt_thread_mutex_lock
+#undef ldap_pvt_thread_mutex_trylock
+#undef ldap_pvt_thread_mutex_unlock
+#undef ldap_pvt_thread_self
+/* LDAP_THREAD_RDWR_IMPLEMENTATION: */
+#undef ldap_pvt_thread_rdwr_t
+#undef ldap_pvt_thread_rdwr_init
+#undef ldap_pvt_thread_rdwr_destroy
+#undef ldap_pvt_thread_rdwr_rlock
+#undef ldap_pvt_thread_rdwr_rtrylock
+#undef ldap_pvt_thread_rdwr_runlock
+#undef ldap_pvt_thread_rdwr_wlock
+#undef ldap_pvt_thread_rdwr_wtrylock
+#undef ldap_pvt_thread_rdwr_wunlock
+#undef ldap_pvt_thread_rdwr_readers
+#undef ldap_pvt_thread_rdwr_writers
+#undef ldap_pvt_thread_rdwr_active
+/* LDAP_THREAD_POOL_IMPLEMENTATION: */
+#undef ldap_pvt_thread_pool_t
+#undef ldap_pvt_thread_pool_init
+#undef ldap_pvt_thread_pool_submit
+#undef ldap_pvt_thread_pool_maxthreads
+#undef ldap_pvt_thread_pool_backload
+#undef ldap_pvt_thread_pool_pause
+#undef ldap_pvt_thread_pool_resume
+#undef ldap_pvt_thread_pool_destroy
+#undef ldap_pvt_thread_pool_getkey
+#undef ldap_pvt_thread_pool_setkey
+#undef ldap_pvt_thread_pool_purgekey
+#undef ldap_pvt_thread_pool_context
+#undef ldap_pvt_thread_pool_context_reset
+#endif /* LDAP_THREAD_DEBUG_IMPLEMENTATION */
+
+#endif /* LDAP_THREAD_DEBUG */
#include <ac/time.h>
#include "ldap-int.h"
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_RDWR_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
/*
* implementations that provide their own compatible
ldap_pvt_thread_rdwr_writers(rwlock));
}
-#endif /* LDAP_DEBUG */
+#endif /* LDAP_RDWR_DEBUG */
#endif /* LDAP_THREAD_HAVE_RDWR */
#include "portable.h"
#if defined( HAVE_MACH_CTHREADS )
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
int
ldap_int_thread_initialize( void )
--- /dev/null
+/* thr_debug.c - wrapper around the chosen thread wrapper, for debugging. */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * 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 file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+/*
+ * This package provides three types of thread operation debugging:
+ *
+ * - Print error messages and abort() when thread operations fail:
+ * Operations on threads, mutexes, condition variables, rdwr locks.
+ * Some thread pool operations are also checked, but not those for
+ * which failure can happen in normal slapd operation.
+ *
+ * - Wrap those types except threads and pools in structs that
+ * contain a state variable or a pointer to dummy allocated memory,
+ * and check that on all operations. The dummy memory variant lets
+ * malloc debuggers see some incorrect use as memory leaks, access
+ * to freed memory, etc.
+ *
+ * - Print a count of leaked thread resources after cleanup.
+ *
+ * Compile-time (./configure) setup: Macros defined in CPPFLAGS.
+ *
+ * LDAP_THREAD_DEBUG or LDAP_THREAD_DEBUG=2
+ * Enables debugging, but value & 2 turns off type wrapping.
+ *
+ * LDAP_UINTPTR_T=integer type to hold pointers, preferably unsigned.
+ * Used by dummy memory option "scramble". Default = unsigned long.
+ *
+ * In addition, you may need to set up an implementation-specific way
+ * to enable whatever error checking your thread library provides.
+ * Currently only implemented for Posix threads (pthreads), where
+ * you may need to define LDAP_INT_THREAD_MUTEXATTR. The default
+ * is PTHREAD_MUTEX_ERRORCHECK, or PTHREAD_MUTEX_ERRORCHECK_NP for
+ * Linux threads. See pthread_mutexattr_settype(3).
+ *
+ * Run-time configuration: Environment variable LDAP_THREAD_DEBUG.
+ *
+ * The variable may contain a comma- or space-separated option list.
+ * Options:
+ * off - Disable this package.
+ * Error checking:
+ * noabort - Do not abort() on errors.
+ * noerror - Do not report errors. Implies noabort.
+ * nocount - Do not report counts of unreleased resources.
+ * State variable/dummy memory, unless type wrapping is disabled:
+ * noalloc - Default. Use a state variable, not dummy memory.
+ * dupinit - Implies noalloc. Check if resources that have
+ * not been destroyed are reinitialized. Tools that
+ * report uninitialized memory access should disable
+ * such warnings about debug_already_initialized().
+ * alloc - Allocate dummy memory and store pointers as-is.
+ * Malloc debuggers might not notice unreleased
+ * resources in global variables as memory leaks.
+ * scramble - Store bitwise complement of dummy memory pointer.
+ * That never escapes memory leak detectors -
+ * but detection while the program is running will
+ * report active resources as leaks. Do not
+ * use this if a garbage collector is in use:-)
+ * adjptr - Point to end of dummy memory.
+ * Purify reports these as "potential leaks" (PLK).
+ * I have not checked other malloc debuggers.
+ * Tracing:
+ * tracethreads - Report create/join/exit/kill of threads.
+ */
+
+#include "portable.h"
+
+#if defined( LDAP_THREAD_DEBUG )
+
+#include <stdio.h>
+#include <ac/errno.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#define LDAP_THREAD_DEBUG_IMPLEMENTATION
+#define LDAP_THREAD_RDWR_IMPLEMENTATION
+#define LDAP_THREAD_POOL_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* Get the underlying implementation */
+
+
+/* Options from environment variable $LDAP_THREAD_DEBUG */
+enum { Count_no = 0, Count_yes, Count_reported, Count_reported_more };
+static int nodebug, noabort, noerror, count = Count_yes, options_done;
+#ifdef LDAP_THREAD_DEBUG_WRAP
+enum { Wrap_noalloc, Wrap_alloc, Wrap_scramble, Wrap_adjptr };
+static int dupinit, wraptype = Wrap_noalloc, wrap_offset, unwrap_offset;
+#endif
+static int tracethreads;
+
+static int threading_enabled;
+
+enum {
+ Idx_unexited_thread, Idx_unjoined_thread, Idx_locked_mutex,
+ Idx_mutex, Idx_cond, Idx_rdwr, Idx_tpool, Idx_max
+};
+static int resource_counts[Idx_max];
+static const char *const resource_names[] = {
+ "unexited threads", "unjoined threads", "locked mutexes",
+ "mutexes", "conds", "rdwrs", "thread pools"
+};
+static ldap_int_thread_mutex_t resource_mutexes[Idx_max];
+
+
+/*
+ * Making ldap_pvt_thread_t a wrapper around ldap_int_thread_t would
+ * slow down ldap_pvt_thread_self(), so keep a list of threads instead.
+ */
+typedef struct ldap_debug_thread_s {
+ ldap_pvt_thread_t wrapped;
+ ldap_debug_usage_info_t usage;
+ int detached;
+ int freeme, idx;
+} ldap_debug_thread_t;
+
+static ldap_debug_thread_t **thread_info;
+static unsigned int thread_info_size, thread_info_used;
+static ldap_int_thread_mutex_t thread_info_mutex;
+
+
+#define WARN(var, msg) (warn (__FILE__, __LINE__, (msg), #var, (var)))
+#define ERROR(var,msg) (error(__FILE__, __LINE__, (msg), #var, (var)))
+#define WARN_IF(rc, msg) {if (rc) warn (__FILE__, __LINE__, (msg), #rc, (rc));}
+#define ERROR_IF(rc,msg) {if (rc) error(__FILE__, __LINE__, (msg), #rc, (rc));}
+
+#if 0
+static void
+warn( const char *file, int line, const char *msg, const char *var, int val )
+{
+ fprintf( stderr, "%s:%d: %s warning: %s is %d\n",
+ file, line, msg, var, val );
+}
+#endif
+
+static void
+error( const char *file, int line, const char *msg, const char *var, int val )
+{
+ if( !noerror ) {
+ fprintf( stderr, "%s:%d: %s error: %s is %d\n",
+ file, line, msg, var, val );
+ if( !noabort )
+ abort();
+ }
+}
+
+static void
+count_resource_leaks( void )
+{
+ int i, j;
+ char errbuf[200], *delim = "Leaked";
+ if( count == Count_yes ) {
+ count = Count_reported;
+#if 0 /* Could break if there are still threads after atexit */
+ for( i = j = 0; i < Idx_max; i++ )
+ j |= ldap_int_thread_mutex_destroy( &resource_mutexes[i] );
+ WARN_IF( j, "ldap_debug_thread_destroy:mutexes" );
+#endif
+ for( i = j = 0; i < Idx_max; i++ ) {
+ if( resource_counts[i] ) {
+ j += sprintf( errbuf + j, "%s %d %s",
+ delim, resource_counts[i], resource_names[i] );
+ delim = ",";
+ }
+ }
+ if( j )
+ fprintf( stderr, "%s:%d: %s.\n", __FILE__, __LINE__, errbuf );
+ }
+}
+
+static void
+get_options( void )
+{
+ static const struct option_info_s {
+ const char *name;
+ int *var, val;
+ } option_info[] = {
+ { "off", &nodebug, 1 },
+ { "noabort", &noabort, 1 },
+ { "noerror", &noerror, 1 },
+ { "nocount", &count, Count_no },
+#ifdef LDAP_THREAD_DEBUG_WRAP
+ { "noalloc", &wraptype, Wrap_noalloc },
+ { "dupinit", &dupinit, 1 },
+ { "alloc", &wraptype, Wrap_alloc },
+ { "adjptr", &wraptype, Wrap_adjptr },
+ { "scramble", &wraptype, Wrap_scramble },
+#endif
+ { "tracethreads", &tracethreads, 1 },
+ { NULL, NULL, 0 }
+ };
+ const char *s = getenv( "LDAP_THREAD_DEBUG" );
+ if( s != NULL ) {
+ while( *(s += strspn( s, ", \t\r\n" )) != '\0' ) {
+ size_t optlen = strcspn( s, ", \t\r\n" );
+ const struct option_info_s *oi;
+ for( oi = option_info; oi->name; oi++ ) {
+ if( strncasecmp( oi->name, s, optlen ) == 0 ) {
+ if( oi->name && oi->name[optlen] == '\0' ) {
+ *oi->var = oi->val;
+ } else {
+ fprintf( stderr, "Unknown $%s option '%.*s'\n",
+ "LDAP_THREAD_DEBUG", (int) optlen, s );
+ }
+ break;
+ }
+ }
+ s += optlen;
+ }
+ }
+ if( nodebug ) {
+ noabort = noerror = 1;
+ tracethreads = dupinit = 0;
+ count = Count_no;
+ }
+#ifdef LDAP_THREAD_DEBUG_WRAP
+ if( nodebug || dupinit ) {
+ wraptype = Wrap_noalloc;
+ } else if( wraptype == Wrap_scramble ) {
+ const unsigned char *dummy = (const unsigned char *)&option_info;
+ if( sizeof(LDAP_UINTPTR_T) < sizeof(void *)
+ || (unsigned char *)~~(LDAP_UINTPTR_T) dummy != dummy
+ || (unsigned char *)~~(LDAP_UINTPTR_T) (unsigned char *)0 )
+ {
+ fprintf( stderr, "Misconfigured for $%s %s. Using %s.\n",
+ "LDAP_THREAD_DEBUG", "scramble", "adjptr" );
+ wraptype = Wrap_adjptr;
+ }
+ }
+ unwrap_offset = -(wrap_offset = (wraptype == Wrap_adjptr));
+#endif
+ options_done = 1;
+}
+
+
+static char *
+thread_name( char *buf, int bufsize, ldap_pvt_thread_t thread )
+{
+ int i;
+ --bufsize;
+ if( bufsize > 2*sizeof(thread) )
+ bufsize = 2*sizeof(thread);
+ for( i = 0; i < bufsize; i += 2 )
+ snprintf( buf+i, 3, "%02x", ((unsigned char *)&thread)[i/2] );
+ return buf;
+}
+
+static void
+exit_thread_message( const ldap_pvt_thread_t thread )
+{
+ if( tracethreads ) {
+ char buf[40];
+ fprintf( stderr, "== Exiting thread %s ==\n",
+ thread_name( buf, sizeof(buf), thread ) );
+ }
+}
+
+
+#ifndef LDAP_THREAD_DEBUG_WRAP
+
+#define WRAPPED(ptr) (ptr)
+#define alloc_usage(ptr, msg) ((void) 0)
+#define check_usage(ptr, msg) ((void) 0)
+#define free_usage(ptr, msg) ((void) 0)
+
+#define with_threads_lock(statement) { statement; }
+#define get_new_thread_info(msg) NULL
+#define update_thread_info(ti, th, det) {}
+#define remove_thread_info(ti, msg) ((void)0)
+#define get_thread_info(thread, msg) NULL
+#define exiting_thread(msg) exit_thread_message(ldap_pvt_thread_self())
+
+#else /* LDAP_THREAD_DEBUG_WRAP */
+
+#define WRAPPED(ptr) (&(ptr)->wrapped)
+
+#define INITED_VALUE 0x12345678UL
+#define INITED_BYTE_VALUE 0xd5
+
+static int
+debug_already_initialized( const LDAP_UINTPTR_T *num )
+{
+ /* Valid programs will access uninitialized memory if dupinit */
+ return dupinit && *num == INITED_VALUE;
+}
+
+static void
+alloc_usage( ldap_debug_usage_info_t *usage, const char *msg )
+{
+ if( !options_done )
+ get_options();
+ if( wraptype == Wrap_noalloc ) {
+ ERROR_IF( debug_already_initialized( &usage->num ), msg );
+ usage->num = INITED_VALUE;
+ } else {
+ unsigned char *dummy = malloc( 1 );
+ assert( dummy != NULL );
+ *dummy = INITED_BYTE_VALUE;
+ if( wraptype == Wrap_scramble ) {
+ usage->num = ~(LDAP_UINTPTR_T) dummy;
+ assert( (unsigned char *)~usage->num == dummy );
+ } else {
+ usage->ptr = dummy + wrap_offset;
+ }
+ }
+}
+
+static void
+check_usage( ldap_debug_usage_info_t *usage, const char *msg )
+{
+ if( wraptype == Wrap_noalloc ) {
+ ERROR_IF( usage->num != INITED_VALUE, msg );
+ } else if( wraptype == Wrap_scramble ) {
+ ERROR_IF( !usage->num, msg );
+ ERROR_IF( *(unsigned char *)~usage->num != INITED_BYTE_VALUE, msg );
+ } else {
+ ERROR_IF( !usage->ptr, msg );
+ ERROR_IF( usage->ptr[unwrap_offset] != INITED_BYTE_VALUE, msg );
+ }
+}
+
+static void
+free_usage( ldap_debug_usage_info_t *usage, const char *msg )
+{
+ if( wraptype == Wrap_noalloc ) {
+ usage->num = ~(LDAP_UINTPTR_T)INITED_VALUE;
+ } else {
+ unsigned char *dummy = (wraptype == Wrap_scramble
+ ? (unsigned char *)~usage->num
+ : usage->ptr + unwrap_offset);
+ *(volatile unsigned char *)dummy = (unsigned char)-1;
+ free( dummy );
+ }
+}
+
+#define with_threads_lock(statement) { \
+ if( !nodebug ) { \
+ int rc_wtl_ = ldap_int_thread_mutex_lock( &thread_info_mutex ); \
+ assert( rc_wtl_ == 0 ); \
+ } \
+ statement; \
+ if( !nodebug ) { \
+ int rc_wtl_ = ldap_int_thread_mutex_unlock( &thread_info_mutex ); \
+ assert( rc_wtl_ == 0 ); \
+ } \
+}
+
+static ldap_debug_thread_t *
+get_new_thread_info( const char *msg )
+{
+ if( nodebug )
+ return NULL;
+ if( thread_info_used >= thread_info_size ) {
+ unsigned int more = thread_info_size + 1; /* debug value. increase. */
+ unsigned int new_size = thread_info_size + more;
+ ldap_debug_thread_t *t = calloc( more, sizeof(ldap_debug_thread_t) );
+ assert( t != NULL );
+ t->freeme = 1;
+ thread_info = realloc( thread_info, new_size * sizeof(*thread_info) );
+ assert( thread_info != NULL );
+ while( thread_info_size < new_size ) {
+ t->idx = thread_info_size;
+ thread_info[thread_info_size++] = t++;
+ }
+ }
+ alloc_usage( &thread_info[thread_info_used]->usage, msg );
+ return thread_info[thread_info_used++];
+}
+
+static void
+update_thread_info(
+ ldap_debug_thread_t *t,
+ const ldap_pvt_thread_t *thread,
+ int detached )
+{
+ if( !nodebug ) {
+ t->wrapped = *thread;
+ t->detached = detached;
+ }
+}
+
+static void
+remove_thread_info( ldap_debug_thread_t *t, const char *msg )
+{
+ if( !nodebug ) {
+ ldap_debug_thread_t *last;
+ int idx;
+ free_usage( &t->usage, msg );
+ idx = t->idx;
+ assert( thread_info[idx] == t );
+ last = thread_info[--thread_info_used];
+ assert( last->idx == thread_info_used );
+ (thread_info[idx] = last)->idx = idx;
+ (thread_info[thread_info_used] = t )->idx = thread_info_used;
+ }
+}
+
+ldap_debug_thread_t *
+get_thread_info( ldap_pvt_thread_t *thread, const char *msg )
+{
+ unsigned int i;
+ ldap_debug_thread_t *t;
+ if( nodebug )
+ return NULL;
+ for( i = 0; i < thread_info_used; i++ ) {
+ if( ldap_pvt_thread_equal( *thread, thread_info[i]->wrapped ) )
+ break;
+ }
+ ERROR_IF( i == thread_info_used, msg );
+ t = thread_info[i];
+ check_usage( &t->usage, msg );
+ return t;
+}
+
+static void
+exiting_thread( const char *msg )
+{
+ if( !nodebug ) {
+ ldap_pvt_thread_t thread;
+ thread = ldap_pvt_thread_self();
+ exit_thread_message( thread );
+ with_threads_lock({
+ ldap_debug_thread_t *t = get_thread_info( &thread, msg );
+ if( t->detached )
+ remove_thread_info( t, msg );
+ });
+ }
+}
+
+#endif /* LDAP_THREAD_DEBUG_WRAP */
+
+
+static void
+adjust_count( int which, int adjust )
+{
+ int rc;
+ switch( count ) {
+ case Count_no:
+ break;
+ case Count_yes:
+ rc = ldap_int_thread_mutex_lock( &resource_mutexes[which] );
+ assert( rc == 0 );
+ resource_counts[which] += adjust;
+ rc = ldap_int_thread_mutex_unlock( &resource_mutexes[which] );
+ assert( rc == 0 );
+ case Count_reported:
+ fputs( "...more ldap_debug_thread activity after exit...\n", stderr );
+ count = Count_reported_more;
+ /* FALL THROUGH */
+ case Count_reported_more:
+ /* Not used, but result might be inspected with debugger */
+ /* (Hopefully threading is disabled by now...) */
+ resource_counts[which] += adjust;
+ break;
+ }
+}
+
+
+/* Wrappers for LDAP_THREAD_IMPLEMENTATION: */
+
+/* Used instead of ldap_int_thread_initialize by ldap_pvt_thread_initialize */
+int
+ldap_debug_thread_initialize( void )
+{
+ int i, rc, rc2;
+ if( !options_done )
+ get_options();
+ ERROR_IF( threading_enabled, "ldap_debug_thread_initialize" );
+ threading_enabled = 1;
+ rc = ldap_int_thread_initialize();
+ if( rc ) {
+ ERROR( rc, "ldap_debug_thread_initialize:threads" );
+ threading_enabled = 0;
+ } else {
+ rc2 = ldap_int_thread_mutex_init( &thread_info_mutex );
+ assert( rc2 == 0 );
+ if( count != Count_no ) {
+ for( i = rc2 = 0; i < Idx_max; i++ )
+ rc2 |= ldap_int_thread_mutex_init( &resource_mutexes[i] );
+ assert( rc2 == 0 );
+ /* FIXME: Only for static libldap_r as in init.c? If so, why? */
+ atexit( count_resource_leaks );
+ }
+ }
+ return rc;
+}
+
+/* Used instead of ldap_int_thread_destroy by ldap_pvt_thread_destroy */
+int
+ldap_debug_thread_destroy( void )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_debug_thread_destroy" );
+ /* sleep(1) -- need to wait for thread pool to finish? */
+ rc = ldap_int_thread_destroy();
+ if( rc ) {
+ ERROR( rc, "ldap_debug_thread_destroy:threads" );
+ } else {
+ threading_enabled = 0;
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_set_concurrency( int n )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_set_concurrency" );
+ rc = ldap_int_thread_set_concurrency( n );
+ ERROR_IF( rc, "ldap_pvt_thread_set_concurrency" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_get_concurrency( void )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_get_concurrency" );
+ rc = ldap_int_thread_get_concurrency();
+ ERROR_IF( rc, "ldap_pvt_thread_get_concurrency" );
+ return rc;
+}
+
+unsigned int
+ldap_pvt_thread_sleep( unsigned int interval )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_sleep" );
+ rc = ldap_int_thread_sleep( interval );
+ ERROR_IF( rc, "ldap_pvt_thread_sleep" );
+ return 0;
+}
+
+int
+ldap_pvt_thread_create(
+ ldap_pvt_thread_t *thread,
+ int detach,
+ void *(*start_routine)( void * ),
+ void *arg )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_create" );
+ if( !options_done )
+ get_options();
+ with_threads_lock({
+ ldap_debug_thread_t *t;
+ t = get_new_thread_info( "ldap_pvt_thread_create" );
+ rc = ldap_int_thread_create( thread, detach, start_routine, arg );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_create" );
+ remove_thread_info( t, "ldap_pvt_thread_init" );
+ } else {
+ update_thread_info( t, thread, detach );
+ }
+ });
+ if( rc == 0 ) {
+ if( tracethreads ) {
+ char buf[40];
+ fprintf( stderr, "== Created thread %s%s ==\n",
+ thread_name( buf, sizeof(buf), *thread ),
+ detach ? " (detached)" : "" );
+ }
+ adjust_count( Idx_unexited_thread, +1 );
+ if( !detach )
+ adjust_count( Idx_unjoined_thread, +1 );
+ }
+ return rc;
+}
+
+void
+ldap_pvt_thread_exit( void *retval )
+{
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_exit" );
+ adjust_count( Idx_unexited_thread, -1 );
+ exiting_thread( "ldap_pvt_thread_exit" );
+ ldap_int_thread_exit( retval );
+}
+
+int
+ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
+{
+ int rc;
+ ldap_debug_thread_t *t;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_join" );
+ if( tracethreads ) {
+ char buf[40];
+ fprintf( stderr, "== Joining thread %s ==\n",
+ thread_name( buf, sizeof(buf), thread ) );
+ }
+ with_threads_lock(
+ t = get_thread_info( &thread, "ldap_pvt_thread_join" ) );
+ rc = ldap_int_thread_join( thread, thread_return );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_join" );
+ } else {
+ with_threads_lock(
+ remove_thread_info( t, "ldap_pvt_thread_join" ) );
+ adjust_count( Idx_unjoined_thread, -1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_kill" );
+ if( tracethreads ) {
+ char buf[40];
+ fprintf( stderr, "== Killing thread %s (sig %i) ==\n",
+ thread_name( buf, sizeof(buf), thread ), signo );
+ }
+ rc = ldap_int_thread_kill( thread, signo );
+ ERROR_IF( rc, "ldap_pvt_thread_kill" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_yield( void )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_yield" );
+ rc = ldap_int_thread_yield();
+ ERROR_IF( rc, "ldap_pvt_thread_yield" );
+ return rc;
+}
+
+ldap_pvt_thread_t
+ldap_pvt_thread_self( void )
+{
+#if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_self" );
+#endif
+ return ldap_int_thread_self();
+}
+
+int
+ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
+{
+ int rc;
+ alloc_usage( &cond->usage, "ldap_pvt_thread_cond_init" );
+ rc = ldap_int_thread_cond_init( WRAPPED( cond ) );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_cond_init" );
+ free_usage( &cond->usage, "ldap_pvt_thread_cond_init" );
+ } else {
+ adjust_count( Idx_cond, +1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
+{
+ int rc;
+ check_usage( &cond->usage, "ldap_pvt_thread_cond_destroy" );
+ rc = ldap_int_thread_cond_destroy( WRAPPED( cond ) );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_cond_destroy" );
+ } else {
+ free_usage( &cond->usage, "ldap_pvt_thread_cond_destroy" );
+ adjust_count( Idx_cond, -1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
+{
+ int rc;
+ check_usage( &cond->usage, "ldap_pvt_thread_cond_signal" );
+ rc = ldap_int_thread_cond_signal( WRAPPED( cond ) );
+ ERROR_IF( rc, "ldap_pvt_thread_cond_signal" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
+{
+ int rc;
+ check_usage( &cond->usage, "ldap_pvt_thread_cond_broadcast" );
+ rc = ldap_int_thread_cond_broadcast( WRAPPED( cond ) );
+ ERROR_IF( rc, "ldap_pvt_thread_cond_broadcast" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_cond_wait(
+ ldap_pvt_thread_cond_t *cond,
+ ldap_pvt_thread_mutex_t *mutex )
+{
+ int rc;
+ check_usage( &cond->usage, "ldap_pvt_thread_cond_wait:cond" );
+ check_usage( &mutex->usage, "ldap_pvt_thread_cond_wait:mutex" );
+ adjust_count( Idx_locked_mutex, -1 );
+ rc = ldap_int_thread_cond_wait( WRAPPED( cond ), WRAPPED( mutex ) );
+ adjust_count( Idx_locked_mutex, +1 );
+ ERROR_IF( rc, "ldap_pvt_thread_cond_wait" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
+{
+ int rc;
+ alloc_usage( &mutex->usage, "ldap_pvt_thread_mutex_init" );
+ rc = ldap_int_thread_mutex_init( WRAPPED( mutex ) );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_mutex_init" );
+ free_usage( &mutex->usage, "ldap_pvt_thread_mutex_init" );
+ } else {
+ adjust_count( Idx_mutex, +1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
+{
+ int rc;
+ check_usage( &mutex->usage, "ldap_pvt_thread_mutex_destroy" );
+ rc = ldap_int_thread_mutex_destroy( WRAPPED( mutex ) );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_mutex_destroy" );
+ } else {
+ free_usage( &mutex->usage, "ldap_pvt_thread_mutex_destroy" );
+ adjust_count( Idx_mutex, -1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
+{
+ int rc;
+ check_usage( &mutex->usage, "ldap_pvt_thread_mutex_lock" );
+ rc = ldap_int_thread_mutex_lock( WRAPPED( mutex ) );
+ if( rc ) {
+ ERROR_IF( rc, "ldap_pvt_thread_mutex_lock" );
+ } else {
+ adjust_count( Idx_locked_mutex, +1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
+{
+ int rc;
+ check_usage( &mutex->usage, "ldap_pvt_thread_mutex_trylock" );
+ rc = ldap_int_thread_mutex_trylock( WRAPPED( mutex ) );
+ if( rc == 0 )
+ adjust_count( Idx_locked_mutex, +1 );
+ return rc;
+}
+
+int
+ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
+{
+ int rc;
+ check_usage( &mutex->usage, "ldap_pvt_thread_mutex_unlock" );
+ rc = ldap_int_thread_mutex_unlock( WRAPPED( mutex ) );
+ if( rc ) {
+ ERROR_IF( rc, "ldap_pvt_thread_mutex_unlock" );
+ } else {
+ adjust_count( Idx_locked_mutex, -1 );
+ }
+ return rc;
+}
+
+
+/* Wrappers for LDAP_THREAD_RDWR_IMPLEMENTATION: */
+
+int
+ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ int rc;
+ alloc_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_init" );
+ rc = ldap_int_thread_rdwr_init( WRAPPED( rwlock ) );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_rdwr_init" );
+ free_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_init" );
+ } else {
+ adjust_count( Idx_rdwr, +1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ int rc;
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_destroy" );
+ rc = ldap_int_thread_rdwr_destroy( WRAPPED( rwlock ) );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_rdwr_destroy" );
+ } else {
+ free_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_destroy" );
+ adjust_count( Idx_rdwr, -1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ int rc;
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_rlock" );
+ rc = ldap_int_thread_rdwr_rlock( WRAPPED( rwlock ) );
+ ERROR_IF( rc, "ldap_pvt_thread_rdwr_rlock" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_rtrylock" );
+ return ldap_int_thread_rdwr_rtrylock( WRAPPED( rwlock ) );
+}
+
+int
+ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ int rc;
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_runlock" );
+ rc = ldap_int_thread_rdwr_runlock( WRAPPED( rwlock ) );
+ ERROR_IF( rc, "ldap_pvt_thread_rdwr_runlock" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ int rc;
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wlock" );
+ rc = ldap_int_thread_rdwr_wlock( WRAPPED( rwlock ) );
+ ERROR_IF( rc, "ldap_pvt_thread_rdwr_wlock" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wtrylock" );
+ return ldap_int_thread_rdwr_wtrylock( WRAPPED( rwlock ) );
+}
+
+int
+ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ int rc;
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wunlock" );
+ rc = ldap_int_thread_rdwr_wunlock( WRAPPED( rwlock ) );
+ ERROR_IF( rc, "ldap_pvt_thread_rdwr_wunlock" );
+ return rc;
+}
+
+#ifdef LDAP_RDWR_DEBUG
+
+int
+ldap_pvt_thread_rdwr_readers( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_readers" );
+ return ldap_int_thread_rdwr_readers( WRAPPED( rwlock ) );
+}
+
+int
+ldap_pvt_thread_rdwr_writers( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_writers" );
+ return ldap_int_thread_rdwr_writers( WRAPPED( rwlock ) );
+}
+
+int
+ldap_pvt_thread_rdwr_active( ldap_pvt_thread_rdwr_t *rwlock )
+{
+ check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_active" );
+ return ldap_int_thread_rdwr_active( WRAPPED( rwlock ) );
+}
+
+#endif /* LDAP_RDWR_DEBUG */
+
+
+/* Some wrappers for LDAP_THREAD_POOL_IMPLEMENTATION: */
+#ifdef LDAP_THREAD_POOL_IMPLEMENTATION
+
+int
+ldap_pvt_thread_pool_init(
+ ldap_pvt_thread_pool_t *tpool,
+ int max_threads,
+ int max_pending )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_init" );
+ rc = ldap_int_thread_pool_init( tpool, max_threads, max_pending );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_pool_init" );
+ } else {
+ adjust_count( Idx_tpool, +1 );
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_pool_submit(
+ ldap_pvt_thread_pool_t *tpool,
+ ldap_pvt_thread_start_t *start_routine, void *arg )
+{
+ int rc, has_pool;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_submit" );
+ has_pool = (tpool != NULL && *tpool != NULL);
+ rc = ldap_int_thread_pool_submit( tpool, start_routine, arg );
+ if( has_pool )
+ ERROR_IF( rc, "ldap_pvt_thread_pool_submit" );
+ return rc;
+}
+
+int
+ldap_pvt_thread_pool_maxthreads(
+ ldap_pvt_thread_pool_t *tpool,
+ int max_threads )
+{
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_maxthreads" );
+ return ldap_int_thread_pool_maxthreads( tpool, max_threads );
+}
+
+int
+ldap_pvt_thread_pool_backload( ldap_pvt_thread_pool_t *tpool )
+{
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_backload" );
+ return ldap_int_thread_pool_backload( tpool );
+}
+
+int
+ldap_pvt_thread_pool_destroy( ldap_pvt_thread_pool_t *tpool, int run_pending )
+{
+ int rc, has_pool;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_destroy" );
+ has_pool = (tpool != NULL && *tpool != NULL);
+ rc = ldap_int_thread_pool_destroy( tpool, run_pending );
+ if( has_pool ) {
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_pool_destroy" );
+ } else {
+ adjust_count( Idx_tpool, -1 );
+ }
+ }
+ return rc;
+}
+
+int
+ldap_pvt_thread_pool_pause( ldap_pvt_thread_pool_t *tpool )
+{
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_pause" );
+ return ldap_int_thread_pool_pause( tpool );
+}
+
+int
+ldap_pvt_thread_pool_resume( ldap_pvt_thread_pool_t *tpool )
+{
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_resume" );
+ return ldap_int_thread_pool_resume( tpool );
+}
+
+int
+ldap_pvt_thread_pool_getkey(
+ void *xctx,
+ void *key,
+ void **data,
+ ldap_pvt_thread_pool_keyfree_t **kfree )
+{
+#if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_getkey" );
+#endif
+ return ldap_int_thread_pool_getkey( xctx, key, data, kfree );
+}
+
+int
+ldap_pvt_thread_pool_setkey(
+ void *xctx,
+ void *key,
+ void *data,
+ ldap_pvt_thread_pool_keyfree_t *kfree )
+{
+ int rc;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_setkey" );
+ rc = ldap_int_thread_pool_setkey( xctx, key, data, kfree );
+ ERROR_IF( rc, "ldap_pvt_thread_pool_setkey" );
+ return rc;
+}
+
+void
+ldap_pvt_thread_pool_purgekey( void *key )
+{
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_purgekey" );
+ ldap_int_thread_pool_purgekey( key );
+}
+
+void *
+ldap_pvt_thread_pool_context( void )
+{
+#if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_context" );
+#endif
+ return ldap_int_thread_pool_context();
+}
+
+void
+ldap_pvt_thread_pool_context_reset( void *vctx )
+{
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_context_reset" );
+ ldap_int_thread_pool_context_reset( vctx );
+}
+
+#endif /* LDAP_THREAD_POOL_IMPLEMENTATION */
+
+#endif /* LDAP_THREAD_DEBUG */
#include "ldap-int.h"
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
#include <lwp/lwp.h>
#include <lwp/stackdep.h>
int
ldap_int_thread_destroy( void )
{
- /* need to destory lwp_scheduler thread and clean up private
+ /* need to destroy lwp_scheduler thread and clean up private
variables */
return 0;
}
int
ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond,
- ldap_int_thread_mutex_t *mutex )
+ ldap_pvt_thread_mutex_t *mutex )
{
if ( ! cond->lcv_created ) {
cv_create( &cond->lcv_cv, *mutex );
#if defined( HAVE_NT_THREADS )
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
typedef struct ldap_int_thread_s {
long tid;
#include <ac/errno.h>
-#include "ldap_pvt_thread.h"
-
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#define LDAP_THREAD_RDWR_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
#if HAVE_PTHREADS < 6
# define LDAP_INT_THREAD_ATTR_DEFAULT pthread_attr_default
#else
# define LDAP_INT_THREAD_ATTR_DEFAULT NULL
# define LDAP_INT_THREAD_CONDATTR_DEFAULT NULL
-# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL
+# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL
#endif
+#ifdef LDAP_THREAD_DEBUG
+# if defined LDAP_INT_THREAD_MUTEXATTR /* May be defined in CPPFLAGS */
+# elif defined HAVE_PTHREAD_KILL_OTHER_THREADS_NP
+ /* LinuxThreads hack */
+# define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK_NP
+# else
+# define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK
+# endif
+static pthread_mutexattr_t mutex_attr;
+# undef LDAP_INT_THREAD_MUTEXATTR_DEFAULT
+# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT &mutex_attr
+#endif
int
ldap_int_thread_initialize( void )
{
+#ifdef LDAP_INT_THREAD_MUTEXATTR
+ pthread_mutexattr_init( &mutex_attr );
+ pthread_mutexattr_settype( &mutex_attr, LDAP_INT_THREAD_MUTEXATTR );
+#endif
return 0;
}
#ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP
/* LinuxThreads: kill clones */
pthread_kill_other_threads_np();
+#endif
+#ifdef LDAP_INT_THREAD_MUTEXATTR
+ pthread_mutexattr_destroy( &mutex_attr );
#endif
return 0;
}
#endif
}
-#endif /* HAVE_PTHREAD_RDLOCK_DESTROY */
+#endif /* HAVE_PTHREAD_RWLOCK_DESTROY */
#endif /* LDAP_THREAD_HAVE_RDWR */
#endif /* HAVE_PTHREADS */
#if defined( HAVE_GNU_PTH )
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#define LDAP_THREAD_RDWR_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
+
#include <errno.h>
/*******************
#if defined( NO_THREADS )
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#define LDAP_THREAD_POOL_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
/***********************************************************************
* *
return(NULL);
}
+void ldap_pvt_thread_pool_context_reset( void *vctx )
+{
+}
+
ldap_pvt_thread_t
ldap_pvt_thread_self( void )
{
#if defined( HAVE_THR )
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#define LDAP_THREAD_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
/*******************
* *
#include <ac/string.h>
#include <ac/unistd.h>
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
+#include "ldap_thr_debug.h" /* May redirect thread initialize/destroy calls */
/*
return ldap_int_thread_destroy();
}
+
+/*
+ * Default implementations of some LDAP thread routines
+ */
+
+#define LDAP_THREAD_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename the symbols defined below */
+
+
#ifndef LDAP_THREAD_HAVE_GETCONCURRENCY
int
ldap_pvt_thread_get_concurrency ( void )
#include <ac/errno.h>
#include "ldap-int.h"
-#include "ldap_pvt_thread.h"
+#include "ldap_pvt_thread.h" /* Get the thread interface */
#include "ldap_queue.h"
+#define LDAP_THREAD_POOL_IMPLEMENTATION
+#include "ldap_thr_debug.h" /* May rename symbols defined below */
#ifndef LDAP_THREAD_HAVE_TPOOL
static ldap_pvt_thread_t tid_zero;
-#ifdef HAVE_PTHREADS
-#define TID_EQ(a,b) pthread_equal((a),(b))
-#else
-#define TID_EQ(a,b) ((a) == (b))
-#endif
static struct {
ldap_pvt_thread_t id;
ldap_int_thread_key_t *ctx;
while ((pool = LDAP_STAILQ_FIRST(&ldap_int_thread_pool_list)) != NULL) {
LDAP_STAILQ_REMOVE_HEAD(&ldap_int_thread_pool_list, ltp_next);
- ldap_pvt_thread_pool_destroy( &pool, 0);
+ (ldap_pvt_thread_pool_destroy)(&pool, 0); /* ignore thr_debug macro */
}
ldap_pvt_thread_mutex_destroy(&ldap_pvt_thread_pool_mutex);
return(0);
*/
TID_HASH(thr, hash);
for (rc = hash & (LDAP_MAXTHR-1);
- !TID_EQ(thread_keys[rc].id, tid_zero);
+ !ldap_pvt_thread_equal(thread_keys[rc].id, tid_zero);
rc = (rc+1) & (LDAP_MAXTHR-1));
thread_keys[rc].id = thr;
} else {
/* store pointer to our keys */
TID_HASH(tid, hash);
- for (i = hash & (LDAP_MAXTHR-1); !TID_EQ(thread_keys[i].id, tid);
+ for (i = hash & (LDAP_MAXTHR-1);
+ !ldap_pvt_thread_equal(thread_keys[i].id, tid);
i = (i+1) & (LDAP_MAXTHR-1));
thread_keys[i].ctx = ltc_key;
keyslot = i;
int i, hash;
tid = ldap_pvt_thread_self();
- if ( TID_EQ( tid, ldap_int_main_tid ))
+ if ( ldap_pvt_thread_equal( tid, ldap_int_main_tid ))
return ldap_int_main_thrctx;
TID_HASH( tid, hash );
- for (i = hash & (LDAP_MAXTHR-1); !TID_EQ(thread_keys[i].id, tid_zero) &&
- !TID_EQ(thread_keys[i].id, tid); i = (i+1) & (LDAP_MAXTHR-1));
+ for (i = hash & (LDAP_MAXTHR-1);
+ !ldap_pvt_thread_equal(thread_keys[i].id, tid_zero) &&
+ !ldap_pvt_thread_equal(thread_keys[i].id, tid);
+ i = (i+1) & (LDAP_MAXTHR-1));
return thread_keys[i].ctx;
}
done
touch .links
-$(XXSRCS) : .links
+$(XXSRCS) $(XXHEADERS) : .links
clean-local: FORCE
@$(RM) *.dat .links $(XXHEADERS) ucgendat
#include "ldap_config.h"
#include <stdio.h>
+#include <ac/ctype.h>
#include <ac/stdlib.h>
#include <ac/string.h>
#include <ac/unistd.h>
*/
for (s = line, i = code = 0; *s != '#' && i < 6; i++, s++) {
- if (isspace(*s)) break;
+ if (isspace((unsigned char)*s)) break;
code <<= 4;
if (*s >= '0' && *s <= '9')
code += *s - '0';
for (i=0; i<num; i++) {
if (first) first = 0;
else fprintf(out, ",");
- fprintf(out, "\n\t0x%08x, 0x%08x, 0x%08x",
- tab[i].key, tab[i].other1, tab[i].other2);
+ fprintf(out, "\n\t0x%08lx, 0x%08lx, 0x%08lx",
+ (unsigned long) tab[i].key, (unsigned long) tab[i].other1,
+ (unsigned long) tab[i].other2);
}
}
FILE *out;
ac_uint4 bytes;
ac_uint4 i, idx, nprops;
+#if !(HARDCODE_DATA)
ac_uint2 casecnt[2];
+#endif
char path[BUFSIZ];
#if HARDCODE_DATA
int j, k;
if (!(k&3)) fprintf(out,"\n\t");
else fprintf(out, " ");
k++;
- fprintf(out, "0x%08x", proptbl[i].ranges[j]);
+ fprintf(out, "0x%08lx", (unsigned long) proptbl[i].ranges[j]);
}
}
}
*****************************************************************/
#if HARDCODE_DATA
- fprintf(out, PREF "ac_uint4 _uccase_size = %d;\n\n",
- upper_used + lower_used + title_used);
+ fprintf(out, PREF "ac_uint4 _uccase_size = %ld;\n\n",
+ (long) (upper_used + lower_used + title_used));
- fprintf(out, PREF "ac_uint2 _uccase_len[2] = {%d, %d};\n\n",
- upper_used, lower_used);
+ fprintf(out, PREF "ac_uint2 _uccase_len[2] = {%ld, %ld};\n\n",
+ (long) upper_used, (long) lower_used);
fprintf(out, PREF "ac_uint4 _uccase_map[] = {");
if (upper_used > 0)
create_comps();
#if HARDCODE_DATA
- fprintf(out, PREF "ac_uint4 _uccomp_size = %d;\n\n",
- comps_used * 4);
+ fprintf(out, PREF "ac_uint4 _uccomp_size = %ld;\n\n",
+ comps_used * 4L);
fprintf(out, PREF "ac_uint4 _uccomp_data[] = {");
if (comps_used > 0) {
for (i=0; i<comps_used; i++) {
if (i) fprintf(out, ",");
- fprintf(out, "\n\t0x%08x, 0x%08x, 0x%08x, 0x%08x",
- comps[i].comp, comps[i].count, comps[i].code1, comps[i].code2);
+ fprintf(out, "\n\t0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx",
+ (unsigned long) comps[i].comp, (unsigned long) comps[i].count,
+ (unsigned long) comps[i].code1, (unsigned long) comps[i].code2);
}
} else {
fprintf(out, "\t0");
expand_decomp();
#if HARDCODE_DATA
- fprintf(out, PREF "ac_uint4 _ucdcmp_size = %d;\n\n",
- decomps_used * 2);
+ fprintf(out, PREF "ac_uint4 _ucdcmp_size = %ld;\n\n",
+ decomps_used * 2L);
fprintf(out, PREF "ac_uint4 _ucdcmp_nodes[] = {");
* Write the list of decomp nodes.
*/
for (i = idx = 0; i < decomps_used; i++) {
- fprintf(out, "\n\t0x%08x, 0x%08x,", decomps[i].code, idx);
+ fprintf(out, "\n\t0x%08lx, 0x%08lx,",
+ (unsigned long) decomps[i].code, (unsigned long) idx);
idx += decomps[i].used;
}
/*
* Write the sentinel index as the last decomp node.
*/
- fprintf(out, "\n\t0x%08x\n};\n\n", idx);
+ fprintf(out, "\n\t0x%08lx\n};\n\n", (unsigned long) idx);
fprintf(out, PREF "ac_uint4 _ucdcmp_decomp[] = {");
/*
if (!(k&3)) fprintf(out,"\n\t");
else fprintf(out, " ");
k++;
- fprintf(out, "0x%08x", decomps[i].decomp[j]);
+ fprintf(out, "0x%08lx", (unsigned long) decomps[i].decomp[j]);
}
fprintf(out, "\n};\n\n");
}
#endif
#ifdef HARDCODE_DATA
- fprintf(out, PREF "ac_uint4 _uckdcmp_size = %d;\n\n",
- kdecomps_used * 2);
+ fprintf(out, PREF "ac_uint4 _uckdcmp_size = %ld;\n\n",
+ kdecomps_used * 2L);
fprintf(out, PREF "ac_uint4 _uckdcmp_nodes[] = {");
* Write the list of kdecomp nodes.
*/
for (i = idx = 0; i < kdecomps_used; i++) {
- fprintf(out, "\n\t0x%08x, 0x%08x,", kdecomps[i].code, idx);
+ fprintf(out, "\n\t0x%08lx, 0x%08lx,",
+ (unsigned long) kdecomps[i].code, (unsigned long) idx);
idx += kdecomps[i].used;
}
/*
* Write the sentinel index as the last decomp node.
*/
- fprintf(out, "\n\t0x%08x\n};\n\n", idx);
+ fprintf(out, "\n\t0x%08lx\n};\n\n", (unsigned long) idx);
fprintf(out, PREF "ac_uint4 _uckdcmp_decomp[] = {");
if (!(k&3)) fprintf(out,"\n\t");
else fprintf(out, " ");
k++;
- fprintf(out, "0x%08x", kdecomps[i].decomp[j]);
+ fprintf(out, "0x%08lx", (unsigned long) kdecomps[i].decomp[j]);
}
fprintf(out, "\n};\n\n");
}
*
*****************************************************************/
#ifdef HARDCODE_DATA
- fprintf(out, PREF "ac_uint4 _uccmcl_size = %d;\n\n", ccl_used);
+ fprintf(out, PREF "ac_uint4 _uccmcl_size = %ld;\n\n", (long) ccl_used);
fprintf(out, PREF "ac_uint4 _uccmcl_nodes[] = {");
if (i) fprintf(out, ",");
if (!(i&3)) fprintf(out, "\n\t");
else fprintf(out, " ");
- fprintf(out, "0x%08x", ccl[i]);
+ fprintf(out, "0x%08lx", (unsigned long) ccl[i]);
}
} else {
fprintf(out, "\t0");
*****************************************************************/
#if HARDCODE_DATA
- fprintf(out, PREF "ac_uint4 _ucnum_size = %d;\n\n", ncodes_used<<1);
+ fprintf(out, PREF "ac_uint4 _ucnum_size = %lu;\n\n",
+ (unsigned long)ncodes_used<<1);
fprintf(out, PREF "ac_uint4 _ucnum_nodes[] = {");
if (i) fprintf(out, ",");
if (!(i&1)) fprintf(out, "\n\t");
else fprintf(out, " ");
- fprintf(out, "0x%08x, 0x%08x", ncodes[i].code, ncodes[i].idx);
+ fprintf(out, "0x%08lx, 0x%08lx",
+ (unsigned long) ncodes[i].code, (unsigned long) ncodes[i].idx);
}
fprintf(out, "\n};\n\n");
SRCS = base64.c csn.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 ldif.c fetch.c \
+ avl.c tavl.c ldif.c fetch.c \
testavl.c \
@LIBSRCS@ $(@PLAT@_SRCS)
OBJS = base64.o csn.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 ldif.o fetch.o \
+ avl.o tavl.o ldif.o fetch.o \
@LIBOBJS@ $(@PLAT@_OBJS)
testavl: $(XLIBS) testavl.o
(LTLINK) -o $@ testavl.o $(LIBS)
+testtavl: $(XLIBS) testtavl.o
+ (LTLINK) -o $@ testtavl.o $(LIBS)
+
# These rules are for a Mingw32 build, specifically.
# It's ok for them to be here because the clean rule is harmless, and
# slapdmsg.res won't get built unless it's declared in OBJS.
* This work was originally developed by the University of Michigan
* (as part of U-MICH LDAP). Additional significant contributors
* include:
+ * Howard Y. Chu
* Hallvard B. Furuseth
* Kurt D. Zeilenga
*/
#define AVL_INTERNAL
#include "avl.h"
-#define ROTATERIGHT(x) { \
- Avlnode *tmp;\
- if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
- (void) fputs("RR error\n", stderr); exit( EXIT_FAILURE ); \
- }\
- tmp = (*(x))->avl_left;\
- (*(x))->avl_left = tmp->avl_right;\
- tmp->avl_right = *(x);\
- *(x) = tmp;\
-}
-#define ROTATELEFT(x) { \
- Avlnode *tmp;\
- if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
- (void) fputs("RL error\n", stderr); exit( EXIT_FAILURE ); \
- }\
- tmp = (*(x))->avl_right;\
- (*(x))->avl_right = tmp->avl_left;\
- tmp->avl_left = *(x);\
- *(x) = tmp;\
-}
-
-/*
- * ravl_insert - called from avl_insert() to do a recursive insert into
- * and balance of an avl tree.
- */
-
-static int
-ravl_insert(
- Avlnode **iroot,
- void* data,
- int *taller,
- AVL_CMP fcmp, /* comparison function */
- AVL_DUP fdup, /* function to call for duplicates */
- int depth
-)
-{
- int rc, cmp, tallersub;
- Avlnode *l, *r;
-
- if ( *iroot == 0 ) {
- if ( (*iroot = (Avlnode *) ber_memalloc( sizeof( Avlnode ) ))
- == NULL ) {
- return( -1 );
- }
- (*iroot)->avl_left = 0;
- (*iroot)->avl_right = 0;
- (*iroot)->avl_bf = 0;
- (*iroot)->avl_data = data;
- *taller = 1;
- return( 0 );
- }
-
- cmp = (*fcmp)( data, (*iroot)->avl_data );
-
- /* equal - duplicate name */
- if ( cmp == 0 ) {
- *taller = 0;
- return( (*fdup)( (*iroot)->avl_data, data ) );
- }
-
- /* go right */
- else if ( cmp > 0 ) {
- rc = ravl_insert( &((*iroot)->avl_right), data, &tallersub,
- fcmp, fdup, depth );
- if ( tallersub )
- switch ( (*iroot)->avl_bf ) {
- case LH : /* left high - balance is restored */
- (*iroot)->avl_bf = EH;
- *taller = 0;
- break;
- case EH : /* equal height - now right heavy */
- (*iroot)->avl_bf = RH;
- *taller = 1;
- break;
- case RH : /* right heavy to start - right balance */
- r = (*iroot)->avl_right;
- switch ( r->avl_bf ) {
- case LH : /* double rotation left */
- l = r->avl_left;
- switch ( l->avl_bf ) {
- case LH : (*iroot)->avl_bf = EH;
- r->avl_bf = RH;
- break;
- case EH : (*iroot)->avl_bf = EH;
- r->avl_bf = EH;
- break;
- case RH : (*iroot)->avl_bf = LH;
- r->avl_bf = EH;
- break;
- }
- l->avl_bf = EH;
- ROTATERIGHT( (&r) )
- (*iroot)->avl_right = r;
- ROTATELEFT( iroot )
- *taller = 0;
- break;
- case EH : /* This should never happen */
- break;
- case RH : /* single rotation left */
- (*iroot)->avl_bf = EH;
- r->avl_bf = EH;
- ROTATELEFT( iroot )
- *taller = 0;
- break;
- }
- break;
- }
- else
- *taller = 0;
- }
-
- /* go left */
- else {
- rc = ravl_insert( &((*iroot)->avl_left), data, &tallersub,
- fcmp, fdup, depth );
- if ( tallersub )
- switch ( (*iroot)->avl_bf ) {
- case LH : /* left high to start - left balance */
- l = (*iroot)->avl_left;
- switch ( l->avl_bf ) {
- case LH : /* single rotation right */
- (*iroot)->avl_bf = EH;
- l->avl_bf = EH;
- ROTATERIGHT( iroot )
- *taller = 0;
- break;
- case EH : /* this should never happen */
- break;
- case RH : /* double rotation right */
- r = l->avl_right;
- switch ( r->avl_bf ) {
- case LH : (*iroot)->avl_bf = RH;
- l->avl_bf = EH;
- break;
- case EH : (*iroot)->avl_bf = EH;
- l->avl_bf = EH;
- break;
- case RH : (*iroot)->avl_bf = EH;
- l->avl_bf = LH;
- break;
- }
- r->avl_bf = EH;
- ROTATELEFT( (&l) )
- (*iroot)->avl_left = l;
- ROTATERIGHT( iroot )
- *taller = 0;
- break;
- }
- break;
- case EH : /* equal height - now left heavy */
- (*iroot)->avl_bf = LH;
- *taller = 1;
- break;
- case RH : /* right high - balance is restored */
- (*iroot)->avl_bf = EH;
- *taller = 0;
- break;
- }
- else
- *taller = 0;
- }
-
- return( rc );
-}
+static const int avl_bfs[] = {LH, RH};
/*
* avl_insert -- insert a node containing data data into the avl tree
*
* NOTE: this routine may malloc memory
*/
-
int
-avl_insert( Avlnode **root, void* data, AVL_CMP fcmp, AVL_DUP fdup )
+avl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup )
{
- int taller;
+ Avlnode *t, *p, *s, *q, *r;
+ int a, cmp, ncmp;
- return( ravl_insert( root, data, &taller, fcmp, fdup, 0 ) );
-}
+ if ( *root == NULL ) {
+ if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
+ return( -1 );
+ }
+ r->avl_link[0] = r->avl_link[1] = NULL;
+ r->avl_data = data;
+ r->avl_bf = EH;
+ *root = r;
-/*
- * right_balance() - called from delete when root's right subtree has
- * been shortened because of a deletion.
- */
+ return( 0 );
+ }
-static int
-right_balance( Avlnode **root )
-{
- int shorter = -1;
- Avlnode *r, *l;
-
- switch( (*root)->avl_bf ) {
- case RH: /* was right high - equal now */
- (*root)->avl_bf = EH;
- shorter = 1;
- break;
- case EH: /* was equal - left high now */
- (*root)->avl_bf = LH;
- shorter = 0;
- break;
- case LH: /* was right high - balance */
- l = (*root)->avl_left;
- switch ( l->avl_bf ) {
- case RH : /* double rotation left */
- r = l->avl_right;
- switch ( r->avl_bf ) {
- case RH :
- (*root)->avl_bf = EH;
- l->avl_bf = LH;
- break;
- case EH :
- (*root)->avl_bf = EH;
- l->avl_bf = EH;
- break;
- case LH :
- (*root)->avl_bf = RH;
- l->avl_bf = EH;
- break;
+ t = NULL;
+ s = p = *root;
+
+ /* find insertion point */
+ while (1) {
+ cmp = fcmp( data, p->avl_data );
+ if ( cmp == 0 )
+ return (*fdup)( p->avl_data, data );
+
+ cmp = (cmp > 0);
+ q = p->avl_link[cmp];
+ if (q == NULL) {
+ /* insert */
+ if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
+ return( -1 );
}
- r->avl_bf = EH;
- ROTATELEFT( (&l) )
- (*root)->avl_left = l;
- ROTATERIGHT( root )
- shorter = 1;
- break;
- case EH : /* right rotation */
- (*root)->avl_bf = LH;
- l->avl_bf = RH;
- ROTATERIGHT( root );
- shorter = 0;
- break;
- case LH : /* single rotation right */
- (*root)->avl_bf = EH;
- l->avl_bf = EH;
- ROTATERIGHT( root )
- shorter = 1;
+ q->avl_link[0] = q->avl_link[1] = NULL;
+ q->avl_data = data;
+ q->avl_bf = EH;
+
+ p->avl_link[cmp] = q;
break;
+ } else if ( q->avl_bf ) {
+ t = p;
+ s = q;
}
- break;
+ p = q;
+ }
+
+ /* adjust balance factors */
+ cmp = fcmp( data, s->avl_data ) > 0;
+ r = p = s->avl_link[cmp];
+ a = avl_bfs[cmp];
+
+ while ( p != q ) {
+ cmp = fcmp( data, p->avl_data ) > 0;
+ p->avl_bf = avl_bfs[cmp];
+ p = p->avl_link[cmp];
}
- return( shorter );
-}
-
-/*
- * left_balance() - called from delete when root's left subtree has
- * been shortened because of a deletion.
- */
-
-static int
-left_balance( Avlnode **root )
-{
- int shorter = -1;
- Avlnode *r, *l;
-
- switch( (*root)->avl_bf ) {
- case LH: /* was left high - equal now */
- (*root)->avl_bf = EH;
- shorter = 1;
- break;
- case EH: /* was equal - right high now */
- (*root)->avl_bf = RH;
- shorter = 0;
- break;
- case RH: /* was right high - balance */
- r = (*root)->avl_right;
- switch ( r->avl_bf ) {
- case LH : /* double rotation left */
- l = r->avl_left;
- switch ( l->avl_bf ) {
- case LH :
- (*root)->avl_bf = EH;
- r->avl_bf = RH;
- break;
- case EH :
- (*root)->avl_bf = EH;
- r->avl_bf = EH;
- break;
- case RH :
- (*root)->avl_bf = LH;
- r->avl_bf = EH;
- break;
+ /* checks and balances */
+
+ if ( s->avl_bf == EH ) {
+ s->avl_bf = a;
+ return 0;
+ } else if ( s->avl_bf == -a ) {
+ s->avl_bf = EH;
+ return 0;
+ } else if ( s->avl_bf == a ) {
+ cmp = (a > 0);
+ ncmp = !cmp;
+ if ( r->avl_bf == a ) {
+ /* single rotation */
+ p = r;
+ s->avl_link[cmp] = r->avl_link[ncmp];
+ r->avl_link[ncmp] = s;
+ s->avl_bf = 0;
+ r->avl_bf = 0;
+ } else if ( r->avl_bf == -a ) {
+ /* double rotation */
+ p = r->avl_link[ncmp];
+ r->avl_link[ncmp] = p->avl_link[cmp];
+ p->avl_link[cmp] = r;
+ s->avl_link[cmp] = p->avl_link[ncmp];
+ p->avl_link[ncmp] = s;
+
+ if ( p->avl_bf == a ) {
+ s->avl_bf = -a;
+ r->avl_bf = 0;
+ } else if ( p->avl_bf == -a ) {
+ s->avl_bf = 0;
+ r->avl_bf = a;
+ } else {
+ s->avl_bf = 0;
+ r->avl_bf = 0;
}
- l->avl_bf = EH;
- ROTATERIGHT( (&r) )
- (*root)->avl_right = r;
- ROTATELEFT( root )
- shorter = 1;
- break;
- case EH : /* single rotation left */
- (*root)->avl_bf = RH;
- r->avl_bf = LH;
- ROTATELEFT( root );
- shorter = 0;
- break;
- case RH : /* single rotation left */
- (*root)->avl_bf = EH;
- r->avl_bf = EH;
- ROTATELEFT( root )
- shorter = 1;
- break;
+ p->avl_bf = 0;
}
- break;
- }
+ /* Update parent */
+ if ( t == NULL )
+ *root = p;
+ else if ( s == t->avl_right )
+ t->avl_right = p;
+ else
+ t->avl_left = p;
+ }
- return( shorter );
+ return 0;
}
-/*
- * ravl_delete() - called from avl_delete to do recursive deletion of a
- * node from an avl tree. It finds the node recursively, deletes it,
- * and returns shorter if the tree is shorter after the deletion and
- * rebalancing.
- */
-
-static void*
-ravl_delete( Avlnode **root, void* data, AVL_CMP fcmp, int *shorter )
+void*
+avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
{
- int shortersubtree = 0;
- int cmp;
- void* savedata;
- Avlnode *minnode, *savenode;
-
- if ( *root == NULLAVL )
- return( 0 );
-
- cmp = (*fcmp)( data, (*root)->avl_data );
+ Avlnode *p, *q, *r, *top;
+ int side, side_bf, shorter, nside;
- /* found it! */
- if ( cmp == 0 ) {
- savenode = *root;
- savedata = savenode->avl_data;
-
- /* simple cases: no left child */
- if ( (*root)->avl_left == 0 ) {
- *root = (*root)->avl_right;
- *shorter = 1;
- ber_memfree( (char *) savenode );
- return( savedata );
- /* no right child */
- } else if ( (*root)->avl_right == 0 ) {
- *root = (*root)->avl_left;
- *shorter = 1;
- ber_memfree( (char *) savenode );
- return( savedata );
- }
-
- /*
- * avl_getmin will return to us the smallest node greater
- * than the one we are trying to delete. deleting this node
- * from the right subtree is guaranteed to end in one of the
- * simple cases above.
- */
+ /* parent stack */
+ Avlnode *pptr[sizeof(void *)*8];
+ unsigned char pdir[sizeof(void *)*8];
+ int depth = 0;
- minnode = (*root)->avl_right;
- while ( minnode->avl_left != NULLAVL )
- minnode = minnode->avl_left;
+ if ( *root == NULL )
+ return NULL;
- /* swap the data */
- (*root)->avl_data = minnode->avl_data;
- minnode->avl_data = savedata;
+ p = *root;
- savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
- &shortersubtree );
+ while (1) {
+ side = fcmp( data, p->avl_data );
+ if ( !side )
+ break;
+ side = ( side > 0 );
+ pdir[depth] = side;
+ pptr[depth++] = p;
- if ( shortersubtree )
- *shorter = right_balance( root );
- else
- *shorter = 0;
- /* go left */
- } else if ( cmp < 0 ) {
- if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp,
- &shortersubtree )) == 0 ) {
- *shorter = 0;
- return( 0 );
+ p = p->avl_link[side];
+ if ( p == NULL )
+ return p;
+ }
+ data = p->avl_data;
+
+ /* If this node has two children, swap so we are deleting a node with
+ * at most one child.
+ */
+ if ( p->avl_link[0] && p->avl_link[1] ) {
+
+ /* find the immediate predecessor <q> */
+ q = p->avl_link[0];
+ side = depth;
+ pdir[depth++] = 0;
+ while (q->avl_link[1]) {
+ pdir[depth] = 1;
+ pptr[depth++] = q;
+ q = q->avl_link[1];
}
-
- /* left subtree shorter? */
- if ( shortersubtree )
- *shorter = left_balance( root );
- else
- *shorter = 0;
- /* go right */
- } else {
- if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
- &shortersubtree )) == 0 ) {
- *shorter = 0;
- return( 0 );
+ /* swap links */
+ r = p->avl_link[0];
+ p->avl_link[0] = q->avl_link[0];
+ q->avl_link[0] = r;
+
+ q->avl_link[1] = p->avl_link[1];
+ p->avl_link[1] = NULL;
+
+ q->avl_bf = p->avl_bf;
+
+ /* fix stack positions: old parent of p points to q */
+ pptr[side] = q;
+ if ( side ) {
+ r = pptr[side-1];
+ r->avl_link[pdir[side-1]] = q;
+ } else {
+ *root = q;
+ }
+ /* new parent of p points to p */
+ if ( depth-side > 1 ) {
+ r = pptr[depth-1];
+ r->avl_link[1] = p;
+ } else {
+ q->avl_link[0] = p;
}
-
- if ( shortersubtree )
- *shorter = right_balance( root );
- else
- *shorter = 0;
}
- return( savedata );
-}
+ /* now <p> has at most one child, get it */
+ q = p->avl_link[0] ? p->avl_link[0] : p->avl_link[1];
-/*
- * avl_delete() - deletes the node containing data (according to fcmp) from
- * the avl tree rooted at root.
- */
+ ber_memfree( p );
-void*
-avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
-{
- int shorter;
+ if ( !depth ) {
+ *root = q;
+ return data;
+ }
+
+ /* set the child into p's parent */
+ depth--;
+ p = pptr[depth];
+ side = pdir[depth];
+ p->avl_link[side] = q;
+
+ top = NULL;
+ shorter = 1;
+
+ while ( shorter ) {
+ p = pptr[depth];
+ side = pdir[depth];
+ nside = !side;
+ side_bf = avl_bfs[side];
+
+ /* case 1: height unchanged */
+ if ( p->avl_bf == EH ) {
+ /* Tree is now heavier on opposite side */
+ p->avl_bf = avl_bfs[nside];
+ shorter = 0;
+
+ } else if ( p->avl_bf == side_bf ) {
+ /* case 2: taller subtree shortened, height reduced */
+ p->avl_bf = EH;
+ } else {
+ /* case 3: shorter subtree shortened */
+ if ( depth )
+ top = pptr[depth-1]; /* p->parent; */
+ else
+ top = NULL;
+ /* set <q> to the taller of the two subtrees of <p> */
+ q = p->avl_link[nside];
+ if ( q->avl_bf == EH ) {
+ /* case 3a: height unchanged, single rotate */
+ p->avl_link[nside] = q->avl_link[side];
+ q->avl_link[side] = p;
+ shorter = 0;
+ q->avl_bf = side_bf;
+ p->avl_bf = (- side_bf);
+
+ } else if ( q->avl_bf == p->avl_bf ) {
+ /* case 3b: height reduced, single rotate */
+ p->avl_link[nside] = q->avl_link[side];
+ q->avl_link[side] = p;
+ shorter = 1;
+ q->avl_bf = EH;
+ p->avl_bf = EH;
+
+ } else {
+ /* case 3c: height reduced, balance factors opposite */
+ r = q->avl_link[side];
+ q->avl_link[side] = r->avl_link[nside];
+ r->avl_link[nside] = q;
+
+ p->avl_link[nside] = r->avl_link[side];
+ r->avl_link[side] = p;
+
+ if ( r->avl_bf == side_bf ) {
+ q->avl_bf = (- side_bf);
+ p->avl_bf = EH;
+ } else if ( r->avl_bf == (- side_bf)) {
+ q->avl_bf = EH;
+ p->avl_bf = side_bf;
+ } else {
+ q->avl_bf = EH;
+ p->avl_bf = EH;
+ }
+ r->avl_bf = EH;
+ q = r;
+ }
+ /* a rotation has caused <q> (or <r> in case 3c) to become
+ * the root. let <p>'s former parent know this.
+ */
+ if ( top == NULL ) {
+ *root = q;
+ } else if (top->avl_link[0] == p) {
+ top->avl_link[0] = q;
+ } else {
+ top->avl_link[1] = q;
+ }
+ /* end case 3 */
+ p = q;
+ }
+ if ( !depth )
+ break;
+ depth--;
+ } /* end while(shorter) */
- return( ravl_delete( root, data, fcmp, &shorter ) );
+ return data;
}
static int
int cmp;
while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
- if ( cmp < 0 )
- root = root->avl_left;
- else
- root = root->avl_right;
+ cmp = cmp > 0;
+ root = root->avl_link[cmp];
}
return root;
}
int cmp;
while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
- if ( cmp < 0 )
- root = root->avl_left;
- else
- root = root->avl_right;
+ cmp = cmp > 0;
+ root = root->avl_link[cmp];
}
return( root ? root->avl_data : 0 );
bv.bv_val = (char *) scheme;
for( pws=pw_schemes; pws; pws=pws->next ) {
- if( bv.bv_len != pws->s.name.bv_len )
- continue;
- if( strncasecmp(bv.bv_val, pws->s.name.bv_val, bv.bv_len ) == 0 ) {
+ if ( ber_bvstrcasecmp(&bv, &pws->s.name ) == 0 ) {
return &(pws->s);
}
}
--- /dev/null
+/* avl.c - routines to implement an avl tree */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * Portions Copyright (c) 2005 by Howard Chu, Symas Corp.
+ * 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>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by Howard Chu for inclusion
+ * in OpenLDAP software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+
+#ifdef CSRIMALLOC
+#define ber_memalloc malloc
+#define ber_memrealloc realloc
+#define ber_memfree free
+#else
+#include "lber.h"
+#endif
+
+#define AVL_INTERNAL
+#include "avl.h"
+
+static const int avl_bfs[] = {LH, RH};
+
+/*
+ * Threaded AVL trees - for fast in-order traversal of nodes.
+ */
+/*
+ * tavl_insert -- insert a node containing data data into the avl tree
+ * with root root. fcmp is a function to call to compare the data portion
+ * of two nodes. it should take two arguments and return <, >, or == 0,
+ * depending on whether its first argument is <, >, or == its second
+ * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
+ * node is inserted. it should return 0, or -1 and its return value
+ * will be the return value from avl_insert in the case of a duplicate node.
+ * the function will be called with the original node's data as its first
+ * argument and with the incoming duplicate node's data as its second
+ * argument. this could be used, for example, to keep a count with each
+ * node.
+ *
+ * NOTE: this routine may malloc memory
+ */
+int
+tavl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup )
+{
+ Avlnode *t, *p, *s, *q, *r;
+ int a, cmp, ncmp;
+
+ if ( *root == NULL ) {
+ if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
+ return( -1 );
+ }
+ r->avl_link[0] = r->avl_link[1] = NULL;
+ r->avl_data = data;
+ r->avl_bf = EH;
+ r->avl_bits[0] = r->avl_bits[1] = AVL_THREAD;
+ *root = r;
+
+ return( 0 );
+ }
+
+ t = NULL;
+ s = p = *root;
+
+ /* find insertion point */
+ while (1) {
+ cmp = fcmp( data, p->avl_data );
+ if ( cmp == 0 )
+ return (*fdup)( p->avl_data, data );
+
+ cmp = (cmp > 0);
+ q = avl_child( p, cmp );
+ if (q == NULL) {
+ /* insert */
+ if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
+ return( -1 );
+ }
+ q->avl_link[cmp] = p->avl_link[cmp];
+ q->avl_link[!cmp] = p;
+ q->avl_data = data;
+ q->avl_bf = EH;
+ q->avl_bits[0] = q->avl_bits[1] = AVL_THREAD;
+
+ p->avl_link[cmp] = q;
+ p->avl_bits[cmp] = AVL_CHILD;
+ break;
+ } else if ( q->avl_bf ) {
+ t = p;
+ s = q;
+ }
+ p = q;
+ }
+
+ /* adjust balance factors */
+ cmp = fcmp( data, s->avl_data ) > 0;
+ r = p = s->avl_link[cmp];
+ a = avl_bfs[cmp];
+
+ while ( p != q ) {
+ cmp = fcmp( data, p->avl_data ) > 0;
+ p->avl_bf = avl_bfs[cmp];
+ p = p->avl_link[cmp];
+ }
+
+ /* checks and balances */
+
+ if ( s->avl_bf == EH ) {
+ s->avl_bf = a;
+ return 0;
+ } else if ( s->avl_bf == -a ) {
+ s->avl_bf = EH;
+ return 0;
+ } else if ( s->avl_bf == a ) {
+ cmp = (a > 0);
+ ncmp = !cmp;
+ if ( r->avl_bf == a ) {
+ /* single rotation */
+ p = r;
+ if ( r->avl_bits[ncmp] == AVL_THREAD ) {
+ r->avl_bits[ncmp] = AVL_CHILD;
+ s->avl_bits[cmp] = AVL_THREAD;
+ } else {
+ s->avl_link[cmp] = r->avl_link[ncmp];
+ r->avl_link[ncmp] = s;
+ }
+ s->avl_bf = 0;
+ r->avl_bf = 0;
+ } else if ( r->avl_bf == -a ) {
+ /* double rotation */
+ p = r->avl_link[ncmp];
+ if ( p->avl_bits[cmp] == AVL_THREAD ) {
+ p->avl_bits[cmp] = AVL_CHILD;
+ r->avl_bits[ncmp] = AVL_THREAD;
+ } else {
+ r->avl_link[ncmp] = p->avl_link[cmp];
+ p->avl_link[cmp] = r;
+ }
+ if ( p->avl_bits[ncmp] == AVL_THREAD ) {
+ p->avl_bits[ncmp] = AVL_CHILD;
+ s->avl_link[cmp] = p;
+ s->avl_bits[cmp] = AVL_THREAD;
+ } else {
+ s->avl_link[cmp] = p->avl_link[ncmp];
+ p->avl_link[ncmp] = s;
+ }
+ if ( p->avl_bf == a ) {
+ s->avl_bf = -a;
+ r->avl_bf = 0;
+ } else if ( p->avl_bf == -a ) {
+ s->avl_bf = 0;
+ r->avl_bf = a;
+ } else {
+ s->avl_bf = 0;
+ r->avl_bf = 0;
+ }
+ p->avl_bf = 0;
+ }
+ /* Update parent */
+ if ( t == NULL )
+ *root = p;
+ else if ( s == t->avl_right )
+ t->avl_right = p;
+ else
+ t->avl_left = p;
+ }
+
+ return 0;
+}
+
+void*
+tavl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
+{
+ Avlnode *p, *q, *r, *top;
+ int side, side_bf, shorter, nside;
+
+ /* parent stack */
+ Avlnode *pptr[sizeof(void *)*8];
+ unsigned char pdir[sizeof(void *)*8];
+ int depth = 0;
+
+ if ( *root == NULL )
+ return NULL;
+
+ p = *root;
+
+ while (1) {
+ side = fcmp( data, p->avl_data );
+ if ( !side )
+ break;
+ side = ( side > 0 );
+ pdir[depth] = side;
+ pptr[depth++] = p;
+
+ if ( p->avl_bits[side] == AVL_THREAD )
+ return NULL;
+ p = p->avl_link[side];
+ }
+ data = p->avl_data;
+
+ /* If this node has two children, swap so we are deleting a node with
+ * at most one child.
+ */
+ if ( p->avl_bits[0] == AVL_CHILD && p->avl_bits[1] == AVL_CHILD &&
+ p->avl_link[0] && p->avl_link[1] ) {
+
+ /* find the immediate predecessor <q> */
+ q = p->avl_link[0];
+ side = depth;
+ pdir[depth++] = 0;
+ while (q->avl_bits[1] == AVL_CHILD && q->avl_link[1]) {
+ pdir[depth] = 1;
+ pptr[depth++] = q;
+ q = q->avl_link[1];
+ }
+ /* swap links */
+ r = p->avl_link[0];
+ p->avl_link[0] = q->avl_link[0];
+ q->avl_link[0] = r;
+
+ q->avl_link[1] = p->avl_link[1];
+ p->avl_link[1] = q;
+
+ p->avl_bits[0] = q->avl_bits[0];
+ p->avl_bits[1] = q->avl_bits[1];
+ q->avl_bits[0] = q->avl_bits[1] = AVL_CHILD;
+
+ q->avl_bf = p->avl_bf;
+
+ /* fix stack positions: old parent of p points to q */
+ pptr[side] = q;
+ if ( side ) {
+ r = pptr[side-1];
+ r->avl_link[pdir[side-1]] = q;
+ } else {
+ *root = q;
+ }
+ /* new parent of p points to p */
+ if ( depth-side > 1 ) {
+ r = pptr[depth-1];
+ r->avl_link[1] = p;
+ } else {
+ q->avl_link[0] = p;
+ }
+
+ /* fix right subtree: successor of p points to q */
+ r = q->avl_link[1];
+ while ( r->avl_bits[0] == AVL_CHILD && r->avl_link[0] )
+ r = r->avl_link[0];
+ r->avl_link[0] = q;
+ }
+
+ /* now <p> has at most one child, get it */
+ if ( p->avl_link[0] && p->avl_bits[0] == AVL_CHILD ) {
+ q = p->avl_link[0];
+ /* Preserve thread continuity */
+ r = p->avl_link[1];
+ nside = 1;
+ } else if ( p->avl_link[1] && p->avl_bits[1] == AVL_CHILD ) {
+ q = p->avl_link[1];
+ r = p->avl_link[0];
+ nside = 0;
+ } else {
+ q = NULL;
+ if ( depth > 0 )
+ r = p->avl_link[pdir[depth-1]];
+ else
+ r = NULL;
+ }
+
+ ber_memfree( p );
+
+ if ( !depth ) {
+ *root = q;
+ return data;
+ }
+
+ /* set the child into p's parent */
+ depth--;
+ p = pptr[depth];
+ side = pdir[depth];
+ p->avl_link[side] = q;
+
+ /* Update child thread */
+ if ( q ) {
+ for ( ; q->avl_bits[nside] == AVL_CHILD && q->avl_link[nside];
+ q = q->avl_link[nside] ) ;
+ q->avl_link[nside] = r;
+ } else {
+ p->avl_bits[side] = AVL_THREAD;
+ p->avl_link[side] = r;
+ }
+
+ top = NULL;
+ shorter = 1;
+
+ while ( shorter ) {
+ p = pptr[depth];
+ side = pdir[depth];
+ nside = !side;
+ side_bf = avl_bfs[side];
+
+ /* case 1: height unchanged */
+ if ( p->avl_bf == EH ) {
+ /* Tree is now heavier on opposite side */
+ p->avl_bf = avl_bfs[nside];
+ shorter = 0;
+
+ } else if ( p->avl_bf == side_bf ) {
+ /* case 2: taller subtree shortened, height reduced */
+ p->avl_bf = EH;
+ } else {
+ /* case 3: shorter subtree shortened */
+ if ( depth )
+ top = pptr[depth-1]; /* p->parent; */
+ else
+ top = NULL;
+ /* set <q> to the taller of the two subtrees of <p> */
+ q = p->avl_link[nside];
+ if ( q->avl_bf == EH ) {
+ /* case 3a: height unchanged, single rotate */
+ if ( q->avl_bits[side] == AVL_THREAD ) {
+ q->avl_bits[side] = AVL_CHILD;
+ p->avl_bits[nside] = AVL_THREAD;
+ } else {
+ p->avl_link[nside] = q->avl_link[side];
+ q->avl_link[side] = p;
+ }
+ shorter = 0;
+ q->avl_bf = side_bf;
+ p->avl_bf = (- side_bf);
+
+ } else if ( q->avl_bf == p->avl_bf ) {
+ /* case 3b: height reduced, single rotate */
+ if ( q->avl_bits[side] == AVL_THREAD ) {
+ q->avl_bits[side] = AVL_CHILD;
+ p->avl_bits[nside] = AVL_THREAD;
+ } else {
+ p->avl_link[nside] = q->avl_link[side];
+ q->avl_link[side] = p;
+ }
+ shorter = 1;
+ q->avl_bf = EH;
+ p->avl_bf = EH;
+
+ } else {
+ /* case 3c: height reduced, balance factors opposite */
+ r = q->avl_link[side];
+ if ( r->avl_bits[nside] == AVL_THREAD ) {
+ r->avl_bits[nside] = AVL_CHILD;
+ q->avl_bits[side] = AVL_THREAD;
+ } else {
+ q->avl_link[side] = r->avl_link[nside];
+ r->avl_link[nside] = q;
+ }
+
+ if ( r->avl_bits[side] == AVL_THREAD ) {
+ r->avl_bits[side] = AVL_CHILD;
+ p->avl_bits[nside] = AVL_THREAD;
+ p->avl_link[nside] = r;
+ } else {
+ p->avl_link[nside] = r->avl_link[side];
+ r->avl_link[side] = p;
+ }
+
+ if ( r->avl_bf == side_bf ) {
+ q->avl_bf = (- side_bf);
+ p->avl_bf = EH;
+ } else if ( r->avl_bf == (- side_bf)) {
+ q->avl_bf = EH;
+ p->avl_bf = side_bf;
+ } else {
+ q->avl_bf = EH;
+ p->avl_bf = EH;
+ }
+ r->avl_bf = EH;
+ q = r;
+ }
+ /* a rotation has caused <q> (or <r> in case 3c) to become
+ * the root. let <p>'s former parent know this.
+ */
+ if ( top == NULL ) {
+ *root = q;
+ } else if (top->avl_link[0] == p) {
+ top->avl_link[0] = q;
+ } else {
+ top->avl_link[1] = q;
+ }
+ /* end case 3 */
+ p = q;
+ }
+ if ( !depth )
+ break;
+ depth--;
+ } /* end while(shorter) */
+
+ return data;
+}
+
+/*
+ * tavl_free -- traverse avltree root, freeing the memory it is using.
+ * the dfree() is called to free the data portion of each node. The
+ * number of items actually freed is returned.
+ */
+
+int
+tavl_free( Avlnode *root, AVL_FREE dfree )
+{
+ int nleft, nright;
+
+ if ( root == 0 )
+ return( 0 );
+
+ nleft = tavl_free( avl_lchild( root ), dfree );
+
+ nright = tavl_free( avl_rchild( root ), dfree );
+
+ if ( dfree )
+ (*dfree)( root->avl_data );
+ ber_memfree( root );
+
+ return( nleft + nright + 1 );
+}
+
+/*
+ * tavl_find -- search avltree root for a node with data data. the function
+ * cmp is used to compare things. it is called with data as its first arg
+ * and the current node data as its second. it should return 0 if they match,
+ * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
+ */
+
+Avlnode *
+tavl_find2( Avlnode *root, const void *data, AVL_CMP fcmp )
+{
+ int cmp;
+
+ while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
+ cmp = cmp > 0;
+ root = avl_child( root, cmp );
+ }
+ return root;
+}
+
+void*
+tavl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
+{
+ int cmp;
+
+ while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
+ cmp = cmp > 0;
+ root = avl_child( root, cmp );
+ }
+
+ return( root ? root->avl_data : 0 );
+}
+
+/* Return the leftmost or rightmost node in the tree */
+Avlnode *
+tavl_end( Avlnode *root, int dir )
+{
+ if ( root ) {
+ while ( root->avl_bits[dir] == AVL_CHILD )
+ root = root->avl_link[dir];
+ }
+ return root;
+}
+
+/* Return the next node in the given direction */
+Avlnode *
+tavl_next( Avlnode *root, int dir )
+{
+ if ( root ) {
+ int c = root->avl_bits[dir];
+
+ root = root->avl_link[dir];
+ if ( c == AVL_CHILD ) {
+ dir ^= 1;
+ while ( root->avl_bits[dir] == AVL_CHILD )
+ root = root->avl_link[dir];
+ }
+ }
+ return root;
+}
{
while (atm && tm) {
char *ptr = atm;
- int i, fracs;
+ unsigned i, fracs;
/* Is the stamp reasonably long? */
for (i=0; isdigit(atm[i]); i++);
if (memcmp(eaddr, zero, sizeof(eaddr)) == 0) {
/* XXX - who knows? */
lutil_entropy( eaddr, sizeof(eaddr) );
- eaddr[0] |= 0x80; /* turn it into a multicast address */
+ eaddr[0] |= 0x01; /* turn it into a multicast address */
}
return eaddr;
session = rewrite_session_find( info, cookie );
if ( session == NULL ) {
session = rewrite_session_init( info, cookie );
+ if ( session == NULL ) {
+ return REWRITE_ERR;
+ }
+
+#ifdef USE_REWRITE_LDAP_PVT_THREADS
+ ldap_pvt_thread_mutex_lock( &session->ls_mutex );
+#endif /* USE_REWRITE_LDAP_PVT_THREADS */
}
#ifdef USE_REWRITE_LDAP_PVT_THREADS
backglue.c backover.c ctxcsn.c ldapsync.c frontend.c \
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
- aci.c \
+ aci.c alock.c \
$(@PLAT@_SRCS)
OBJS = main.o globals.o bconfig.o config.o daemon.o \
backglue.o backover.o ctxcsn.o ldapsync.o frontend.o \
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
slappasswd.o slaptest.o slapauth.o slapacl.o component.o \
- aci.o \
+ aci.o alock.o \
$(@PLAT@_OBJS)
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
done="" ;\
base=`expr "$$i" : "-l\(.*\)"`; \
for p in $$paths ; do \
- for ext in la dll a ; do \
+ for ext in la dll dll.a a ; do \
path=$$p/lib$$base.$$ext; \
test ! -f $$path && continue; \
if test $$ext = la ; then \
test -z "$$obj" && continue; \
;; \
*.la) \
- if test -n "$LTSTATIC"; then \
+ if test -n "$(LTSTATIC)"; then \
base=`expr "$$i" : ".*/\(.*\).la"`; \
path=`expr "$$i" : "\(.*/\).*"`; \
obj=$$path.libs/$$base.a; \
fi; \
;; \
+ *.dll.a) \
+ ;; \
*.o | *.a) \
obj=$$i; \
esac; \
depend-local-srv: FORCE
@for i in $(SUBDIRS); do \
- if test -d $$i -a -f $$i/Makefile ; then \
+ if test -d $$i && test -f $$i/Makefile ; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) depend"; \
( cd $$i; $(MAKE) $(MFLAGS) depend ); \
if test $$? != 0 ; then exit 1; fi ; \
clean-local-srv: FORCE
@for i in $(SUBDIRS); do \
- if test -d $$i -a -f $$i/Makefile ; then \
+ if test -d $$i && test -f $$i/Makefile ; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \
( cd $$i; $(MAKE) $(MFLAGS) clean ); \
if test $$? != 0 ; then exit 1; fi ; \
veryclean-local-srv: FORCE
@for i in $(SUBDIRS); do \
- if test -d $$i -a -f $$i/Makefile ; then \
+ if test -d $$i && test -f $$i/Makefile ; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \
( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \
fi; \
$(LTINSTALL) $(INSTALLFLAGS) $(STRIP) -m 755 \
slapd$(EXEEXT) $(DESTDIR)$(libexecdir)
@for i in $(SUBDIRS); do \
- if test -d $$i -a -f $$i/Makefile ; then \
+ if test -d $$i && test -f $$i/Makefile ; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) install"; \
( cd $$i; $(MAKE) $(MFLAGS) install ); \
if test $$? != 0 ; then exit 1; fi ; \
continue;
} else if ( a->acl_dn_style == ACL_STYLE_ONE ) {
- int rdnlen = -1, sep = 0;
+ ber_len_t rdnlen = 0;
+ int sep = 0;
if ( dnlen <= patlen )
continue;
continue;
} else if ( a->acl_attrval_style == ACL_STYLE_ONE ) {
- int rdnlen = -1;
+ ber_len_t rdnlen = 0;
if ( !DN_SEPARATOR( val->bv_val[vdnlen - patlen - 1] ) )
continue;
}
} else if ( b->a_style == ACL_STYLE_ONE ) {
- int rdnlen = -1;
+ ber_len_t rdnlen = 0;
if ( odnlen <= patlen ) {
goto dn_match_cleanup;
for ( da = b->a_dynacl; da; da = da->da_next ) {
if ( strcasecmp( da->da_name, name ) == 0 ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: dynacl \"%s\" already specified.\n",
fname, lineno, name );
acl_usage();
int e;
regex_t re;
- char buf[512];
- unsigned size;
+ char buf[ SLAP_TEXT_BUFLEN ];
+ unsigned size;
char *sp;
char *dp;
*dp = '\0';
if ( size >= (sizeof(buf) - 1) ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: regular expression \"%s\" too large\n",
fname, lineno, pat );
acl_usage();
}
if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
- char error[512];
+ char error[ SLAP_TEXT_BUFLEN ];
+
regerror(e, &re, error, sizeof(error));
- fprintf( stderr,
- "%s: line %d: regular expression \"%s\" bad because of %s\n",
- fname, lineno, pat, error );
+
+ snprintf( buf, sizeof( buf ),
+ "regular expression \"%s\" bad because of %s",
+ pat, error );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
regfree(&re);
static int
check_scope( BackendDB *be, AccessControl *a )
{
- int patlen;
+ ber_len_t patlen;
struct berval dn;
dn = be->be_nsuffix[0];
* more than one level between the suffix
* and the pattern */
if ( style == ACL_STYLE_ONE ) {
- int rdnlen = -1, sep = 0;
+ ber_len_t rdnlen = 0;
+ int sep = 0;
if ( patlen > 0 ) {
if ( !DN_SEPARATOR( dn.bv_val[dn.bv_len - patlen - 1] )) {
/* to clause - select which entries are protected */
if ( strcasecmp( argv[i], "to" ) == 0 ) {
if ( a != NULL ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"only one to clause allowed in access line\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
a->acl_dn_style != ACL_STYLE_REGEX )
{
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: dn pattern"
" already specified in to clause.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
split( left, '.', &left, &style );
if ( right == NULL ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing \"=\" in \"%s\" in to clause\n",
fname, lineno, left );
acl_usage();
if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
a->acl_dn_style != ACL_STYLE_REGEX )
{
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: dn pattern"
" already specified in to clause.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
}
} else {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"unknown dn style \"%s\" in to clause\n",
fname, lineno, style );
acl_usage();
if ( strcasecmp( left, "filter" ) == 0 ) {
if ( (a->acl_filter = str2filter( right )) == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad filter \"%s\" in to clause\n",
fname, lineno, right );
acl_usage();
} else if ( strcasecmp( left, "attr" ) == 0 /* TOLERATED */
|| strcasecmp( left, "attrs" ) == 0 ) /* DOCUMENTED */
{
+ if ( strcasecmp( left, "attr" ) == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"attr\" "
+ "is deprecated (and undocumented); "
+ "use \"attrs\" instead.\n",
+ fname, lineno, 0 );
+ }
+
a->acl_attrs = str2anlist( a->acl_attrs,
right, "," );
if ( a->acl_attrs == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: unknown attr \"%s\" in to clause\n",
fname, lineno, right );
acl_usage();
char *mr;
if ( !BER_BVISEMPTY( &a->acl_attrval ) ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: attr val already specified in to clause.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
if ( a->acl_attrs == NULL || !BER_BVISEMPTY( &a->acl_attrs[1].an_name ) )
{
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: attr val requires a single attribute.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
a->acl_attrval_mr = mr_find( mr );
if ( a->acl_attrval_mr == NULL ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"invalid matching rule \"%s\".\n",
fname, lineno, mr );
acl_usage();
if( !mr_usable_with_at( a->acl_attrval_mr, a->acl_attrs[ 0 ].an_desc->ad_type ) )
{
- fprintf( stderr, "%s: line %d: "
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
"matching rule \"%s\" use "
- "with attr \"%s\" not appropriate.\n",
- fname, lineno, mr,
- a->acl_attrs[ 0 ].an_name.bv_val );
+ "with attr \"%s\" not appropriate.",
+ mr, a->acl_attrs[ 0 ].an_name.bv_val );
+
+
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
}
int e = regcomp( &a->acl_attrval_re, a->acl_attrval.bv_val,
REG_EXTENDED | REG_ICASE | REG_NOSUB );
if ( e ) {
- char buf[512];
- regerror( e, &a->acl_attrval_re, buf, sizeof(buf) );
- fprintf( stderr, "%s: line %d: "
- "regular expression \"%s\" bad because of %s\n",
- fname, lineno, right, buf );
+ char err[SLAP_TEXT_BUFLEN],
+ buf[ SLAP_TEXT_BUFLEN ];
+
+ regerror( e, &a->acl_attrval_re, err, sizeof( err ) );
+
+ snprintf( buf, sizeof( buf ),
+ "regular expression \"%s\" bad because of %s",
+ right, err );
+
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
a->acl_attrval_style = ACL_STYLE_REGEX;
} else if ( !strcasecmp( style, "children" ) ) {
a->acl_attrval_style = ACL_STYLE_CHILDREN;
} else {
- fprintf( stderr,
- "%s: line %d: unknown val.<style> \"%s\" "
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ /* FIXME: should be an error */
+
+ snprintf( buf, sizeof( buf ),
+ "unknown val.<style> \"%s\" "
"for attributeType \"%s\" with DN syntax; "
- "using \"base\"\n",
- fname, lineno, style,
+ "using \"base\""
+ SLAPD_CONF_UNKNOWN_IGNORED ".",
+ style,
a->acl_attrs[0].an_desc->ad_cname.bv_val );
+
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
+#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
+ acl_usage();
+#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
a->acl_attrval_style = ACL_STYLE_BASE;
}
bv = a->acl_attrval;
rc = dnNormalize( 0, NULL, NULL, &bv, &a->acl_attrval, NULL );
if ( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
- "%s: line %d: unable to normalize DN \"%s\" "
- "for attributeType \"%s\" (%d).\n",
- fname, lineno, bv.bv_val,
- a->acl_attrs[0].an_desc->ad_cname.bv_val, rc );
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "unable to normalize DN \"%s\" "
+ "for attributeType \"%s\" (%d).",
+ bv.bv_val,
+ a->acl_attrs[0].an_desc->ad_cname.bv_val,
+ rc );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
ber_memfree( bv.bv_val );
} else {
- fprintf( stderr,
- "%s: line %d: unknown val.<style> \"%s\" "
- "for attributeType \"%s\"; using \"exact\"\n",
- fname, lineno, style,
- a->acl_attrs[0].an_desc->ad_cname.bv_val );
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ /* FIXME: should be an error */
+
+ snprintf( buf, sizeof( buf ),
+ "unknown val.<style> \"%s\" "
+ "for attributeType \"%s\"; using \"exact\""
+ SLAPD_CONF_UNKNOWN_IGNORED ".",
+ style, a->acl_attrs[0].an_desc->ad_cname.bv_val );
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
+#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
+ acl_usage();
+#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
a->acl_attrval_style = ACL_STYLE_BASE;
}
}
}
if ( a->acl_attrval_mr == NULL ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"attr \"%s\" must have an EQUALITY matching rule.\n",
fname, lineno, a->acl_attrs[ 0 ].an_name.bv_val );
acl_usage();
}
} else {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: expecting <what> got \"%s\"\n",
fname, lineno, left );
acl_usage();
struct berval bv;
rc = dnNormalize( 0, NULL, NULL, &a->acl_dn_pat, &bv, NULL);
if ( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad DN \"%s\" in to DN clause\n",
fname, lineno, a->acl_dn_pat.bv_val );
acl_usage();
int e = regcomp( &a->acl_dn_re, a->acl_dn_pat.bv_val,
REG_EXTENDED | REG_ICASE );
if ( e ) {
- char buf[512];
- regerror( e, &a->acl_dn_re, buf, sizeof(buf) );
- fprintf( stderr, "%s: line %d: "
- "regular expression \"%s\" bad because of %s\n",
- fname, lineno, right, buf );
+ char err[ SLAP_TEXT_BUFLEN ],
+ buf[ SLAP_TEXT_BUFLEN ];
+
+ regerror( e, &a->acl_dn_re, err, sizeof( err ) );
+ snprintf( buf, sizeof( buf ),
+ "regular expression \"%s\" bad because of %s",
+ right, err );
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
}
/* by clause - select who has what access to entries */
} else if ( strcasecmp( argv[i], "by" ) == 0 ) {
if ( a == NULL ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"to clause required before by clause in access line\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
ACL_INVALIDATE( b->a_access_mask );
if ( ++i == argc ) {
- fprintf( stderr,
- "%s: line %d: premature eol: expecting <who>\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: premature EOL: expecting <who>\n",
+ fname, lineno, 0 );
acl_usage();
}
if ( style_level != NULL ) {
char *p = strchr( style_level, '}' );
if ( p == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: premature eol: "
"expecting closing '}' in \"level{n}\"\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
} else if ( p == style_level ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: empty level "
"in \"level{n}\"\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
p[0] = '\0';
level = strtol( style_level, &next, 10 );
if ( next[0] != '\0' ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: unable to parse level "
"in \"level{n}\"\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
} else if ( strcasecmp( style, "path" ) == 0 ) {
sty = ACL_STYLE_PATH;
#ifndef LDAP_PF_LOCAL
- fprintf( stderr, "%s: line %d: "
- "path style modifier is useless without local\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: "
+ "\"path\" style modifier is useless without local"
+ SLAPD_CONF_UNKNOWN_IGNORED ".\n",
+ fname, lineno, 0 );
+#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
+ acl_usage();
+#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
#endif /* LDAP_PF_LOCAL */
} else {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: unknown style \"%s\" in by clause\n",
- fname, lineno, style );
+ fname, lineno, style );
acl_usage();
}
{
switch ( sty ) {
case ACL_STYLE_REGEX:
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"regex\" style implies "
"\"expand\" modifier"
SLAPD_CONF_UNKNOWN_IGNORED ".\n",
- fname, lineno );
+ fname, lineno, 0 );
#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
acl_usage();
#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
break;
case ACL_STYLE_EXPAND:
-#if 0
- /* FIXME: now it's legal... */
- fprintf( stderr, "%s: line %d: "
- "\"expand\" style used "
- "in conjunction with "
- "\"expand\" modifier"
- SLAPD_CONF_UNKNOWN_IGNORED ".\n",
- fname, lineno );
-#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
- acl_usage();
-#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
-#endif
break;
default:
if ( ( sty == ACL_STYLE_EXPAND || expand )
&& a->acl_dn_style != ACL_STYLE_REGEX )
{
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL, "%s: line %d: "
"\"expand\" style or modifier used "
"in conjunction with "
- "a non-regex <what> clause\n",
- fname, lineno );
+ "a non-regex <what> clause"
+ SLAPD_CONF_UNKNOWN_IGNORED ".\n",
+ fname, lineno, 0 );
+#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
+ acl_usage();
+#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
}
if ( strncasecmp( left, "real", STRLENOF( "real" ) ) == 0 ) {
}
} else if ( right == NULL || *right == '\0' ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing \"=\" in (or value after) \"%s\" "
"in by clause\n",
- fname, lineno, left );
+ fname, lineno, left );
acl_usage();
} else {
if ( !BER_BVISNULL( &bv ) ) {
if ( !BER_BVISEMPTY( &bdn->a_pat ) ) {
- fprintf( stderr,
- "%s: line %d: dn pattern already specified.\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: dn pattern already specified.\n",
+ fname, lineno, 0 );
acl_usage();
}
rc = dnNormalize(0, NULL, NULL,
&bv, &bdn->a_pat, NULL);
if ( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad DN \"%s\" in by DN clause\n",
fname, lineno, bv.bv_val );
acl_usage();
}
free( bv.bv_val );
+ if ( sty == ACL_STYLE_BASE
+ && be != NULL
+ && !BER_BVISNULL( &be->be_rootndn )
+ && dn_match( &bdn->a_pat, &be->be_rootndn ) )
+ {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: rootdn is always granted "
+ "unlimited privileges.\n",
+ fname, lineno, 0 );
+ }
} else {
bdn->a_pat = bv;
int gotit = 0;
for ( exp = strchr( bdn->a_pat.bv_val, '$' );
- exp && exp - bdn->a_pat.bv_val < bdn->a_pat.bv_len;
+ exp && (ber_len_t)(exp - bdn->a_pat.bv_val)
+ < bdn->a_pat.bv_len;
exp = strchr( exp, '$' ) )
{
if ( isdigit( exp[ 1 ] ) ) {
bdn->a_expand = expand;
} else {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"expand\" used "
"with no expansions in \"pattern\""
SLAPD_CONF_UNKNOWN_IGNORED ".\n",
- fname, lineno );
+ fname, lineno, 0 );
#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
acl_usage();
#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
} else {
if ( level < 0 ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad negative level \"%d\" "
"in by DN clause\n",
fname, lineno, level );
acl_usage();
} else if ( level == 1 ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"onelevel\" should be used "
"instead of \"level{1}\" in by DN clause\n",
- fname, lineno );
+ fname, lineno, 0 );
} else if ( level == 0 && sty == ACL_STYLE_LEVEL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"base\" should be used "
"instead of \"level{0}\" in by DN clause\n",
- fname, lineno );
+ fname, lineno, 0 );
}
bdn->a_level = level;
if ( strcasecmp( left, "dnattr" ) == 0 ) {
if ( right == NULL || right[0] == '\0' ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing \"=\" in (or value after) \"%s\" "
"in by clause\n",
fname, lineno, left );
}
if( bdn->a_at != NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: dnattr already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
rc = slap_str2ad( right, &bdn->a_at, &text );
if( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
- "%s: line %d: dnattr \"%s\": %s\n",
- fname, lineno, right, text );
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "dnattr \"%s\": %s",
+ right, text );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
!is_at_syntax( bdn->a_at->ad_type,
SLAPD_NAMEUID_SYNTAX ))
{
- fprintf( stderr,
- "%s: line %d: dnattr \"%s\": "
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "dnattr \"%s\": "
"inappropriate syntax: %s\n",
- fname, lineno, right,
+ right,
bdn->a_at->ad_type->sat_syntax_oid );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
if( bdn->a_at->ad_type->sat_equality == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: dnattr \"%s\": "
"inappropriate matching (no EQUALITY)\n",
fname, lineno, right );
switch ( sty ) {
case ACL_STYLE_REGEX:
/* legacy, tolerated */
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: "
"deprecated group style \"regex\"; "
- "use \"expand\" instead\n",
- fname, lineno );
+ "use \"expand\" instead.\n",
+ fname, lineno, 0 );
sty = ACL_STYLE_EXPAND;
break;
default:
/* unknown */
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( right == NULL || right[0] == '\0' ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: "
"missing \"=\" in (or value after) \"%s\" "
- "in by clause\n",
+ "in by clause.\n",
fname, lineno, left );
acl_usage();
}
if ( !BER_BVISEMPTY( &b->a_group_pat ) ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: group pattern already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
rc = dnNormalize( 0, NULL, NULL, &bv,
&b->a_group_pat, NULL );
if ( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
- "%s: line %d: bad DN \"%s\"\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: bad DN \"%s\".\n",
fname, lineno, right );
acl_usage();
}
*--value = '/';
if ( b->a_group_oc == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: group objectclass "
- "\"%s\" unknown\n",
+ "\"%s\" unknown.\n",
fname, lineno, value );
acl_usage();
}
b->a_group_oc = oc_find( SLAPD_GROUP_CLASS );
if( b->a_group_oc == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: group default objectclass "
- "\"%s\" unknown\n",
+ "\"%s\" unknown.\n",
fname, lineno, SLAPD_GROUP_CLASS );
acl_usage();
}
if ( is_object_subclass( slap_schema.si_oc_referral,
b->a_group_oc ) )
{
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: group objectclass \"%s\" "
- "is subclass of referral\n",
+ "is subclass of referral.\n",
fname, lineno, value );
acl_usage();
}
if ( is_object_subclass( slap_schema.si_oc_alias,
b->a_group_oc ) )
{
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: group objectclass \"%s\" "
- "is subclass of alias\n",
+ "is subclass of alias.\n",
fname, lineno, value );
acl_usage();
}
rc = slap_str2ad( name, &b->a_group_at, &text );
if( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
- "%s: line %d: group \"%s\": %s\n",
- fname, lineno, right, text );
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group \"%s\": %s.",
+ right, text );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
*--name = '/';
rc = slap_str2ad( SLAPD_GROUP_ATTR, &b->a_group_at, &text );
if ( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
- "%s: line %d: group \"%s\": %s\n",
- fname, lineno, SLAPD_GROUP_ATTR, text );
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group \"%s\": %s.",
+ SLAPD_GROUP_ATTR, text );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
}
SLAPD_NAMEUID_SYNTAX ) &&
!is_at_subtype( b->a_group_at->ad_type, slap_schema.si_ad_labeledURI->ad_type ) )
{
- fprintf( stderr,
- "%s: line %d: group \"%s\": inappropriate syntax: %s\n",
- fname, lineno, right,
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group \"%s\": inappropriate syntax: %s.",
+ right,
b->a_group_at->ad_type->sat_syntax_oid );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
vals, NULL );
if( rc != 0 ) {
- fprintf( stderr, "%s: line %d: "
- "group: \"%s\" not allowed by \"%s\"\n",
- fname, lineno,
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group: \"%s\" not allowed by \"%s\".",
b->a_group_at->ad_cname.bv_val,
b->a_group_oc->soc_oid );
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
}
break;
default:
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( right == NULL || right[0] == '\0' ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing \"=\" in (or value after) \"%s\" "
- "in by clause\n",
+ "in by clause.\n",
fname, lineno, left );
acl_usage();
}
if ( !BER_BVISEMPTY( &b->a_peername_pat ) ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"peername pattern already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
b->a_peername_addr = inet_addr( addr );
if ( b->a_peername_addr == (unsigned long)(-1) ) {
/* illegal address */
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"illegal peername address \"%s\".\n",
fname, lineno, addr );
acl_usage();
(unsigned long)(-1) )
{
/* illegal mask */
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"illegal peername address mask "
"\"%s\".\n",
fname, lineno, mask );
b->a_peername_port = strtol( port, &end, 10 );
if ( end[0] != '}' ) {
/* illegal port */
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"illegal peername port specification "
"\"{%s}\".\n",
fname, lineno, port );
default:
/* unknown */
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"inappropriate style \"%s\" in by clause\n",
fname, lineno, style );
acl_usage();
}
if ( right == NULL || right[0] == '\0' ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing \"=\" in (or value after) \"%s\" "
"in by clause\n",
fname, lineno, left );
}
if ( !BER_BVISNULL( &b->a_sockname_pat ) ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"sockname pattern already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
case ACL_STYLE_EXPAND:
/* tolerated: means exact,expand */
if ( expand ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: "
"\"expand\" modifier "
- "with \"expand\" style\n",
- fname, lineno );
+ "with \"expand\" style.\n",
+ fname, lineno, 0 );
}
sty = ACL_STYLE_BASE;
expand = 1;
default:
/* unknown */
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( right == NULL || right[0] == '\0' ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing \"=\" in (or value after) \"%s\" "
- "in by clause\n",
+ "in by clause.\n",
fname, lineno, left );
acl_usage();
}
if ( !BER_BVISEMPTY( &b->a_domain_pat ) ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: domain pattern already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
default:
/* unknown */
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( right == NULL || right[0] == '\0' ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing \"=\" in (or value after) \"%s\" "
- "in by clause\n",
+ "in by clause.\n",
fname, lineno, left );
acl_usage();
}
if ( !BER_BVISEMPTY( &b->a_sockurl_pat ) ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: sockurl pattern already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
switch ( sty ) {
/* deprecated */
case ACL_STYLE_REGEX:
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: "
"deprecated set style "
"\"regex\" in <by> clause; "
- "use \"expand\" instead\n",
- fname, lineno );
+ "use \"expand\" instead.\n",
+ fname, lineno, 0 );
sty = ACL_STYLE_EXPAND;
/* FALLTHRU */
break;
default:
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( !BER_BVISEMPTY( &b->a_set_pat ) ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: set attribute already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
if ( right == NULL || *right == '\0' ) {
- fprintf( stderr,
- "%s: line %d: no set is defined\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: no set is defined.\n",
+ fname, lineno, 0 );
acl_usage();
}
if ( name ) {
if ( slap_dynacl_config( fname, lineno, b, name, opts, sty, right ) ) {
- fprintf( stderr, "%s: line %d: "
- "unable to configure dynacl \"%s\"\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "unable to configure dynacl \"%s\".\n",
fname, lineno, name );
acl_usage();
}
#ifdef SLAPD_ACI_ENABLED
if ( strcasecmp( left, "aci" ) == 0 ) {
if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if( b->a_aci_at != NULL ) {
- fprintf( stderr,
- "%s: line %d: aci attribute already specified.\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: ACI attribute already specified.\n",
+ fname, lineno, 0 );
acl_usage();
}
rc = slap_str2ad( right, &b->a_aci_at, &text );
if( rc != LDAP_SUCCESS ) {
- fprintf( stderr,
- "%s: line %d: aci \"%s\": %s\n",
- fname, lineno, right, text );
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "aci \"%s\": %s.",
+ right, text );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
if( !is_at_syntax( b->a_aci_at->ad_type,
SLAPD_ACI_SYNTAX) )
{
- fprintf( stderr, "%s: line %d: "
- "aci \"%s\": inappropriate syntax: %s\n",
- fname, lineno, right,
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "ACI \"%s\": inappropriate syntax: %s.",
+ right,
b->a_aci_at->ad_type->sat_syntax_oid );
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
if ( strcasecmp( left, "ssf" ) == 0 ) {
if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( b->a_authz.sai_ssf ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: ssf attribute already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
if ( right == NULL || *right == '\0' ) {
- fprintf( stderr,
- "%s: line %d: no ssf is defined\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: no ssf is defined.\n",
+ fname, lineno, 0 );
acl_usage();
}
b->a_authz.sai_ssf = strtol( right, &next, 10 );
if ( next == NULL || next[0] != '\0' ) {
- fprintf( stderr,
- "%s: line %d: unable to parse ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: unable to parse ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
if ( !b->a_authz.sai_ssf ) {
- fprintf( stderr,
- "%s: line %d: invalid ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: invalid ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
if ( strcasecmp( left, "transport_ssf" ) == 0 ) {
if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( b->a_authz.sai_transport_ssf ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"transport_ssf attribute already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
if ( right == NULL || *right == '\0' ) {
- fprintf( stderr,
- "%s: line %d: no transport_ssf is defined\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: no transport_ssf is defined.\n",
+ fname, lineno, 0 );
acl_usage();
}
b->a_authz.sai_transport_ssf = strtol( right, &next, 10 );
if ( next == NULL || next[0] != '\0' ) {
- fprintf( stderr, "%s: line %d: "
- "unable to parse transport_ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "unable to parse transport_ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
if ( !b->a_authz.sai_transport_ssf ) {
- fprintf( stderr,
- "%s: line %d: invalid transport_ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: invalid transport_ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
if ( strcasecmp( left, "tls_ssf" ) == 0 ) {
if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( b->a_authz.sai_tls_ssf ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"tls_ssf attribute already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
if ( right == NULL || *right == '\0' ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: no tls_ssf is defined\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
b->a_authz.sai_tls_ssf = strtol( right, &next, 10 );
if ( next == NULL || next[0] != '\0' ) {
- fprintf( stderr, "%s: line %d: "
- "unable to parse tls_ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "unable to parse tls_ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
if ( !b->a_authz.sai_tls_ssf ) {
- fprintf( stderr,
- "%s: line %d: invalid tls_ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: invalid tls_ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
if ( strcasecmp( left, "sasl_ssf" ) == 0 ) {
if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
- fprintf( stderr, "%s: line %d: "
- "inappropriate style \"%s\" in by clause\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
fname, lineno, style );
acl_usage();
}
if ( b->a_authz.sai_sasl_ssf ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"sasl_ssf attribute already specified.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
if ( right == NULL || *right == '\0' ) {
- fprintf( stderr,
- "%s: line %d: no sasl_ssf is defined\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: no sasl_ssf is defined.\n",
+ fname, lineno, 0 );
acl_usage();
}
b->a_authz.sai_sasl_ssf = strtol( right, &next, 10 );
if ( next == NULL || next[0] != '\0' ) {
- fprintf( stderr, "%s: line %d: "
- "unable to parse sasl_ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "unable to parse sasl_ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
if ( !b->a_authz.sai_sasl_ssf ) {
- fprintf( stderr,
- "%s: line %d: invalid sasl_ssf value (%s)\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: invalid sasl_ssf value (%s).\n",
fname, lineno, right );
acl_usage();
}
}
if ( ACL_IS_INVALID( b->a_access_mask ) ) {
- fprintf( stderr,
- "%s: line %d: expecting <access> got \"%s\"\n",
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: expecting <access> got \"%s\".\n",
fname, lineno, left );
acl_usage();
}
access_append( &a->acl_access, b );
} else {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: expecting \"to\" "
"or \"by\" got \"%s\"\n",
fname, lineno, argv[i] );
/* if we have no real access clause, complain and do nothing */
if ( a == NULL ) {
- fprintf( stderr, "%s: line %d: "
- "warning: no access clause(s) specified in access line\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "warning: no access clause(s) "
+ "specified in access line"
+ SLAPD_CONF_UNKNOWN_IGNORED ".\n",
+ fname, lineno, 0 );
+#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
+ acl_usage();
+#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
} else {
#ifdef LDAP_DEBUG
#endif
if ( a->acl_access == NULL ) {
- fprintf( stderr, "%s: line %d: "
- "warning: no by clause(s) specified in access line\n",
- fname, lineno );
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "warning: no by clause(s) "
+ "specified in access line"
+ SLAPD_CONF_UNKNOWN_IGNORED ".\n",
+ fname, lineno, 0 );
+#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
+ acl_usage();
+#endif /* SLAPD_CONF_UNKNOWN_BAILOUT */
}
if ( be != NULL ) {
if ( !BER_BVISNULL( &be->be_nsuffix[ 1 ] ) ) {
- fprintf( stderr, "%s: line %d: warning: "
+ Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
"scope checking only applies to single-valued "
"suffix databases\n",
- fname, lineno );
+ fname, lineno, 0 );
/* go ahead, since checking is not authoritative */
}
switch ( check_scope( be, a ) ) {
case ACL_SCOPE_UNKNOWN:
- fprintf( stderr, "%s: line %d: warning: "
+ Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
"cannot assess the validity of the ACL scope within "
"backend naming context\n",
- fname, lineno );
+ fname, lineno, 0 );
break;
case ACL_SCOPE_WARN:
- fprintf( stderr, "%s: line %d: warning: "
+ Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
"ACL could be out of scope within backend naming context\n",
- fname, lineno );
+ fname, lineno, 0 );
break;
case ACL_SCOPE_PARTIAL:
- fprintf( stderr, "%s: line %d: warning: "
+ Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
"ACL appears to be partially out of scope within "
"backend naming context\n",
- fname, lineno );
+ fname, lineno, 0 );
break;
case ACL_SCOPE_ERR:
- fprintf( stderr, "%s: line %d: warning: "
+ Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
"ACL appears to be out of scope within "
"backend naming context\n",
- fname, lineno );
+ fname, lineno, 0 );
break;
default:
static void
acl_usage( void )
{
- fprintf( stderr, "%s%s%s\n",
+ char *access =
"<access clause> ::= access to <what> "
- "[ by <who> <access> [ <control> ] ]+ \n"
+ "[ by <who> <access> [ <control> ] ]+ \n";
+
+ char *what =
"<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrlist>]\n"
"<attrlist> ::= <attr> [val[/matchingRule][.<attrstyle>]=<value>] | <attr> , <attrlist>\n"
- "<attr> ::= <attrname> | entry | children\n",
+ "<attr> ::= <attrname> | entry | children\n";
+
+ char *who =
"<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
"\t[ realanonymous | realusers | realself | realdn[.<dnstyle>]=<DN> ]\n"
"\t[dnattr=<attrname>]\n"
"\t[group[/<objectclass>[/<attrname>]][.<style>]=<group>]\n"
"\t[peername[.<peernamestyle>]=<peer>] [sockname[.<style>]=<name>]\n"
"\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
-#ifdef SLAPD_ACI_ENABLED
- "\t[aci[=<attrname>]]\n"
-#endif
#ifdef SLAP_DYNACL
"\t[dynacl/<name>[/<options>][.<dynstyle>][=<pattern>]]\n"
-#endif /* SLAP_DYNACL */
- "\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n",
+#else /* ! SLAP_DYNACL */
+#ifdef SLAPD_ACI_ENABLED
+ "\t[aci[=<attrname>]]\n"
+#endif /* SLAPD_ACI_ENABLED */
+#endif /* ! SLAP_DYNACL */
+ "\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n"
"<style> ::= exact | regex | base(Object)\n"
"<dnstyle> ::= base(Object) | one(level) | sub(tree) | children | "
"exact | regex\n"
"<level> ::= none|disclose|auth|compare|search|read|{write|add|delete}|manage\n"
"<priv> ::= {=|+|-}{0|d|x|c|s|r|{w|a|z}|m}+\n"
"<control> ::= [ stop | continue | break ]\n"
- );
+#ifdef SLAP_DYNACL
+#ifdef SLAPD_ACI_ENABLED
+ "dynacl:\n"
+ "\t<name>=ACI\t<pattern>=<attrname>\n"
+#endif /* SLAPD_ACI_ENABLED */
+#endif /* ! SLAP_DYNACL */
+ "";
+
+ Debug( LDAP_DEBUG_ANY, "%s%s%s\n", access, who, what );
exit( EXIT_FAILURE );
}
} else if ( strcasecmp( str, "disclose" ) == 0 ) {
#ifndef SLAP_ACL_HONOR_DISCLOSE
- fprintf( stderr, "str2access: warning, "
- "\"disclose\" privilege disabled.\n" );
+ Debug( LDAP_DEBUG_ACL, "str2access: warning, "
+ "\"disclose\" privilege disabled.\n",
+ 0, 0, 0 );
#endif /* SLAP_ACL_HONOR_DISCLOSE */
return ACL_DISCLOSE;
}
#ifdef LDAP_DEBUG
-
static void
print_acl( Backend *be, AccessControl *a )
{
}
static int
-undef_remove(
+undef_promote(
AttributeType *at,
- char *name )
+ char *name,
+ AttributeType *nat )
{
- AttributeDescription **u_ad;
+ AttributeDescription **u_ad, **n_ad;
+
+ /* Get to last ad on the new type */
+ for ( n_ad = &nat->sat_ad; *n_ad; n_ad = &(*n_ad)->ad_next ) ;
for ( u_ad = &at->sat_ad; *u_ad; ) {
struct berval bv;
*u_ad = (*u_ad)->ad_next;
- ch_free( tmp );
-
+ tmp->ad_next = NULL;
+ *n_ad = tmp;
+ n_ad = &tmp->ad_next;
} else {
u_ad = &(*u_ad)->ad_next;
}
}
int
-slap_ad_undef_remove(
- char *name )
+slap_ad_undef_promote(
+ char *name,
+ AttributeType *at )
{
int rc;
ldap_pvt_thread_mutex_lock( &ad_undef_mutex );
- rc = undef_remove( slap_schema.si_at_undefined, name );
+ rc = undef_promote( slap_schema.si_at_undefined, name, at );
if ( rc == 0 ) {
- rc = undef_remove( slap_schema.si_at_proxied, name );
+ rc = undef_promote( slap_schema.si_at_proxied, name, at );
}
ldap_pvt_thread_mutex_unlock( &ad_undef_mutex );
--- /dev/null
+/* alock.c - access lock library */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * Portions Copyright 2004-2005 Symas Corporation.
+ * 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>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by Matthew Backes at Symas
+ * Corporation for inclusion in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#if SLAPD_BDB || SLAPD_HDB || SLAPD_LDBM
+
+#include "alock.h"
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/errno.h>
+#include <ac/assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+
+#ifdef _WIN32
+#include <stdio.h>
+#include <io.h>
+#include <sys/locking.h>
+#endif
+
+
+static int
+alock_grab_lock ( int fd, int slot )
+{
+ int res;
+
+#if defined( HAVE_LOCKF )
+ res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
+#elif defined( HAVE_FCNTL )
+ struct flock lock_info;
+ (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
+
+ lock_info.l_type = F_WRLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
+ lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
+
+ res = fcntl (fd, F_SETLKW, &lock_info);
+#elif defined( _WIN32 )
+ if( _lseek( fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET ) < 0 )
+ return -1;
+ /*
+ * _lock will try for the lock once per second, returning EDEADLOCK
+ * after ten tries. We just loop until we either get the lock
+ * or some other error is returned.
+ */
+ while((res = _locking( fd, _LK_LOCK, ALOCK_SLOT_SIZE )) < 0 ) {
+ if( errno != EDEADLOCK )
+ break;
+ }
+#else
+# error alock needs lockf, fcntl, or _locking
+#endif
+ if (res == -1) {
+ assert (errno != EDEADLK);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+alock_release_lock ( int fd, int slot )
+{
+ int res;
+
+#if defined( HAVE_LOCKF )
+ res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
+ if (res == -1) return -1;
+#elif defined ( HAVE_FCNTL )
+ struct flock lock_info;
+ (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
+
+ lock_info.l_type = F_UNLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
+ lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
+
+ res = fcntl (fd, F_SETLKW, &lock_info);
+ if (res == -1) return -1;
+#elif defined( _WIN32 )
+ res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
+ if (res == -1) return -1;
+#else
+# error alock needs lockf, fcntl, or _locking
+#endif
+
+ return 0;
+}
+
+static int
+alock_test_lock ( int fd, int slot )
+{
+ int res;
+
+#if defined( HAVE_LOCKF )
+ res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+
+ res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
+ if (res == -1) {
+ if (errno == EACCES || errno == EAGAIN) {
+ return ALOCK_LOCKED;
+ } else {
+ return -1;
+ }
+ }
+#elif defined( HAVE_FCNTL )
+ struct flock lock_info;
+ (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
+
+ lock_info.l_type = F_WRLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
+ lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
+
+ res = fcntl (fd, F_GETLK, &lock_info);
+ if (res == -1) return -1;
+
+ if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
+#elif defined( _WIN32 )
+ res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = _locking( fd, _LK_NBLCK, ALOCK_SLOT_SIZE );
+ _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
+ if (res == -1) {
+ if( errno == EACCES ) {
+ return ALOCK_LOCKED;
+ } else {
+ return -1;
+ }
+ }
+#else
+# error alock needs lockf, fcntl, or _locking
+#endif
+
+ return 0;
+}
+
+/* Read a 64bit LE value */
+static unsigned long int
+alock_read_iattr ( unsigned char * bufptr )
+{
+ unsigned long int val = 0;
+ int count;
+
+ assert (bufptr != NULL);
+
+ bufptr += sizeof (unsigned long int);
+ for (count=0; count <= sizeof (unsigned long int); ++count) {
+ val <<= 8;
+ val += (unsigned long int) *bufptr--;
+ }
+
+ return val;
+}
+
+/* Write a 64bit LE value */
+static void
+alock_write_iattr ( unsigned char * bufptr,
+ unsigned long int val )
+{
+ int count;
+
+ assert (bufptr != NULL);
+
+ for (count=0; count < 8; ++count) {
+ *bufptr++ = (unsigned char) (val & 0xff);
+ val >>= 8;
+ }
+}
+
+static int
+alock_read_slot ( alock_info_t * info,
+ alock_slot_t * slot_data )
+{
+ unsigned char slotbuf [ALOCK_SLOT_SIZE];
+ int res, size, size_total, err;
+
+ assert (info != NULL);
+ assert (slot_data != NULL);
+ assert (info->al_slot > 0);
+
+ res = lseek (info->al_fd,
+ (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
+ SEEK_SET);
+ if (res == -1) return -1;
+
+ size_total = 0;
+ while (size_total < ALOCK_SLOT_SIZE) {
+ size = read (info->al_fd,
+ slotbuf + size_total,
+ ALOCK_SLOT_SIZE - size_total);
+ if (size == 0) return -1;
+ if (size < 0) {
+ err = errno;
+ if (err != EINTR && err != EAGAIN) return -1;
+ } else {
+ size_total += size;
+ }
+ }
+
+ if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
+ return 1;
+ }
+ slot_data->al_lock = alock_read_iattr (slotbuf+8);
+ slot_data->al_stamp = alock_read_iattr (slotbuf+16);
+ slot_data->al_pid = alock_read_iattr (slotbuf+24);
+
+ if (slot_data->al_appname) free (slot_data->al_appname);
+ slot_data->al_appname = calloc (1, ALOCK_MAX_APPNAME);
+ strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
+ (slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
+
+ return 0;
+}
+
+static int
+alock_write_slot ( alock_info_t * info,
+ alock_slot_t * slot_data )
+{
+ unsigned char slotbuf [ALOCK_SLOT_SIZE];
+ int res, size, size_total, err;
+
+ assert (info != NULL);
+ assert (slot_data != NULL);
+ assert (info->al_slot > 0);
+
+ (void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
+
+ alock_write_iattr (slotbuf, ALOCK_MAGIC);
+ assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
+ alock_write_iattr (slotbuf+8, slot_data->al_lock);
+ alock_write_iattr (slotbuf+16, slot_data->al_stamp);
+ alock_write_iattr (slotbuf+24, slot_data->al_pid);
+
+ strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
+ slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
+
+ res = lseek (info->al_fd,
+ (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
+ SEEK_SET);
+ if (res == -1) return -1;
+
+ size_total = 0;
+ while (size_total < ALOCK_SLOT_SIZE) {
+ size = write (info->al_fd,
+ slotbuf + size_total,
+ ALOCK_SLOT_SIZE - size_total);
+ if (size == 0) return -1;
+ if (size < 0) {
+ err = errno;
+ if (err != EINTR && err != EAGAIN) return -1;
+ } else {
+ size_total += size;
+ }
+ }
+
+ return 0;
+}
+
+static int
+alock_query_slot ( alock_info_t * info )
+{
+ int res;
+ alock_slot_t slot_data;
+
+ assert (info != NULL);
+ assert (info->al_slot > 0);
+
+ (void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
+ alock_read_slot (info, &slot_data);
+
+ if (slot_data.al_appname != NULL) free (slot_data.al_appname);
+ slot_data.al_appname = NULL;
+
+ if (slot_data.al_lock == ALOCK_UNLOCKED) return ALOCK_UNLOCKED;
+
+ res = alock_test_lock (info->al_fd, info->al_slot);
+ if (res < 0) return -1;
+ if (res > 0) {
+ if (slot_data.al_lock == ALOCK_UNIQUE) {
+ return ALOCK_UNIQUE;
+ } else {
+ return ALOCK_LOCKED;
+ }
+ }
+
+ return ALOCK_DIRTY;
+}
+
+int
+alock_open ( alock_info_t * info,
+ const char * appname,
+ const char * envdir,
+ int locktype )
+{
+ struct stat statbuf;
+ alock_info_t scan_info;
+ alock_slot_t slot_data;
+ char * filename;
+ int res, max_slot;
+ int dirty_count, live_count;
+
+ assert (info != NULL);
+ assert (appname != NULL);
+ assert (envdir != NULL);
+ assert (locktype >= 1 && locktype <= 2);
+
+ slot_data.al_lock = locktype;
+ slot_data.al_stamp = time(NULL);
+ slot_data.al_pid = getpid();
+ slot_data.al_appname = calloc (1, ALOCK_MAX_APPNAME);
+ strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
+ slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
+
+ filename = calloc (1, strlen (envdir) + strlen ("/alock") + 1);
+ strcpy (filename, envdir);
+ strcat (filename, "/alock");
+ info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
+ free (filename);
+ if (info->al_fd < 0) {
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ info->al_slot = 0;
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = fstat (info->al_fd, &statbuf);
+ if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+
+ max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
+ dirty_count = 0;
+ live_count = 0;
+ scan_info.al_fd = info->al_fd;
+ for (scan_info.al_slot = 1;
+ scan_info.al_slot < max_slot;
+ ++ scan_info.al_slot) {
+ if (scan_info.al_slot != info->al_slot) {
+ res = alock_query_slot (&scan_info);
+
+ if (res == ALOCK_UNLOCKED
+ && info->al_slot == 0) {
+ info->al_slot = scan_info.al_slot;
+
+ } else if (res == ALOCK_LOCKED) {
+ ++live_count;
+
+ } else if (res == ALOCK_UNIQUE
+ && locktype == ALOCK_UNIQUE) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_BUSY;
+
+ } else if (res == ALOCK_DIRTY) {
+ ++dirty_count;
+
+ } else if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+
+ }
+ }
+ }
+
+ if (dirty_count && live_count) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+
+ if (info->al_slot == 0) info->al_slot = max_slot + 1;
+ res = alock_grab_lock (info->al_fd,
+ info->al_slot);
+ if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ res = alock_write_slot (info, &slot_data);
+ free (slot_data.al_appname);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ if (dirty_count) return ALOCK_RECOVER;
+ return ALOCK_CLEAN;
+}
+
+int
+alock_scan ( alock_info_t * info )
+{
+ struct stat statbuf;
+ alock_info_t scan_info;
+ int res, max_slot;
+ int dirty_count, live_count;
+
+ assert (info != NULL);
+
+ scan_info.al_fd = info->al_fd;
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = fstat (info->al_fd, &statbuf);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
+ dirty_count = 0;
+ live_count = 0;
+ for (scan_info.al_slot = 1;
+ scan_info.al_slot < max_slot;
+ ++ scan_info.al_slot) {
+ if (scan_info.al_slot != info->al_slot) {
+ res = alock_query_slot (&scan_info);
+
+ if (res == ALOCK_LOCKED) {
+ ++live_count;
+
+ } else if (res == ALOCK_DIRTY) {
+ ++dirty_count;
+
+ } else if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+
+ }
+ }
+ }
+
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ if (dirty_count) {
+ if (live_count) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ } else {
+ return ALOCK_RECOVER;
+ }
+ }
+
+ return ALOCK_CLEAN;
+}
+
+int
+alock_close ( alock_info_t * info )
+{
+ alock_slot_t slot_data;
+ int res;
+
+ (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ /* mark our slot as clean */
+ res = alock_read_slot (info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ if (slot_data.al_appname != NULL)
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ slot_data.al_lock = ALOCK_UNLOCKED;
+ res = alock_write_slot (info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ if (slot_data.al_appname != NULL)
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ if (slot_data.al_appname != NULL) {
+ free (slot_data.al_appname);
+ slot_data.al_appname = NULL;
+ }
+
+ res = alock_release_lock (info->al_fd, info->al_slot);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = close (info->al_fd);
+ if (res == -1) return ALOCK_UNSTABLE;
+
+ return ALOCK_CLEAN;
+}
+
+int
+alock_recover ( alock_info_t * info )
+{
+ struct stat statbuf;
+ alock_slot_t slot_data;
+ alock_info_t scan_info;
+ int res, max_slot;
+
+ assert (info != NULL);
+
+ scan_info.al_fd = info->al_fd;
+
+ (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = fstat (info->al_fd, &statbuf);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
+ for (scan_info.al_slot = 1;
+ scan_info.al_slot < max_slot;
+ ++ scan_info.al_slot) {
+ if (scan_info.al_slot != info->al_slot) {
+ res = alock_query_slot (&scan_info);
+
+ if (res == ALOCK_LOCKED
+ || res == ALOCK_UNIQUE) {
+ /* recovery attempt on an active db? */
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+
+ } else if (res == ALOCK_DIRTY) {
+ /* mark it clean */
+ res = alock_read_slot (&scan_info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+ slot_data.al_lock = ALOCK_UNLOCKED;
+ res = alock_write_slot (&scan_info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ if (slot_data.al_appname != NULL)
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ if (slot_data.al_appname != NULL) {
+ free (slot_data.al_appname);
+ slot_data.al_appname = NULL;
+ }
+
+ } else if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+
+ }
+ }
+ }
+
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ return ALOCK_CLEAN;
+}
+
+#endif /* SLAPD_BDB || SLAPD_HDB */
--- /dev/null
+/* alock.h - access lock header */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * Portions Copyright 2004-2005 Symas Corporation.
+ * 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>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by Matthew Backes at Symas
+ * Corporation for inclusion in OpenLDAP Software.
+ */
+
+#ifndef _ALOCK_H_
+#define _ALOCK_H_
+
+#include "portable.h"
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+/* environment states (all the slots together) */
+#define ALOCK_CLEAN (0)
+#define ALOCK_RECOVER (1)
+#define ALOCK_BUSY (2)
+#define ALOCK_UNSTABLE (3)
+
+/* lock user types and states */
+#define ALOCK_UNLOCKED (0)
+#define ALOCK_LOCKED (1)
+#define ALOCK_UNIQUE (2)
+#define ALOCK_DIRTY (3)
+
+/* constants */
+#define ALOCK_SLOT_SIZE (1024)
+#define ALOCK_SLOT_IATTRS (4)
+#define ALOCK_MAX_APPNAME (ALOCK_SLOT_SIZE - 8 * ALOCK_SLOT_IATTRS)
+#define ALOCK_MAGIC (0x12345678)
+
+LDAP_BEGIN_DECL
+
+typedef struct alock_info {
+ int al_fd;
+ int al_slot;
+} alock_info_t;
+
+typedef struct alock_slot {
+ unsigned int al_lock;
+ time_t al_stamp;
+ pid_t al_pid;
+ char * al_appname;
+} alock_slot_t;
+
+LDAP_SLAPD_F (int) alock_open LDAP_P(( alock_info_t * info, const char * appname,
+ const char * envdir, int locktype ));
+LDAP_SLAPD_F (int) alock_scan LDAP_P(( alock_info_t * info ));
+LDAP_SLAPD_F (int) alock_close LDAP_P(( alock_info_t * info ));
+LDAP_SLAPD_F (int) alock_recover LDAP_P(( alock_info_t * info ));
+
+LDAP_END_DECL
+
+#endif
}
if ( sat->sat_oid ) {
- slap_ad_undef_remove( sat->sat_oid );
+ slap_ad_undef_promote( sat->sat_oid, sat );
}
names = sat->sat_names;
if ( names ) {
while ( *names ) {
- slap_ad_undef_remove( *names );
+ slap_ad_undef_promote( *names, sat );
names++;
}
}
extended.c referral.c operational.c \
attr.c index.c key.c dbcache.c filterindex.c \
dn2entry.c dn2id.c error.c id2entry.c idl.c \
- nextid.c cache.c trans.c alock.c
+ nextid.c cache.c trans.c
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
extended.lo referral.lo operational.lo \
attr.lo index.lo key.lo dbcache.lo filterindex.lo \
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo \
- nextid.lo cache.lo trans.lo alock.lo
+ nextid.lo cache.lo trans.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
+++ /dev/null
-/* alock.c - access lock library */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * 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>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Matthew Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#include "portable.h"
-#include "alock.h"
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/errno.h>
-#include <ac/assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <fcntl.h>
-
-#ifdef _WIN32
-#include <stdio.h>
-#include <io.h>
-#include <sys/locking.h>
-#endif
-
-
-static int
-alock_grab_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
-#elif defined( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_WRLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_SETLKW, &lock_info);
-#elif defined( _WIN32 )
- if( _lseek( fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET ) < 0 )
- return -1;
- /*
- * _lock will try for the lock once per second, returning EDEADLOCK
- * after ten tries. We just loop until we either get the lock
- * or some other error is returned.
- */
- while((res = _locking( fd, _LK_LOCK, ALOCK_SLOT_SIZE )) < 0 ) {
- if( errno != EDEADLOCK )
- break;
- }
-#else
-# error alock needs lockf, fcntl, or _locking
-#endif
- if (res == -1) {
- assert (errno != EDEADLK);
- return -1;
- }
- return 0;
-}
-
-static int
-alock_release_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
- if (res == -1) return -1;
-#elif defined ( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_UNLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_SETLKW, &lock_info);
- if (res == -1) return -1;
-#elif defined( _WIN32 )
- res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
- if (res == -1) return -1;
-#else
-# error alock needs lockf, fcntl, or _locking
-#endif
-
- return 0;
-}
-
-static int
-alock_test_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
-
- res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
- if (res == -1) {
- if (errno == EACCES || errno == EAGAIN) {
- return ALOCK_LOCKED;
- } else {
- return -1;
- }
- }
-#elif defined( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_WRLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_GETLK, &lock_info);
- if (res == -1) return -1;
-
- if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
-#elif defined( _WIN32 )
- res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = _locking( fd, _LK_NBLCK, ALOCK_SLOT_SIZE );
- _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
- if (res == -1) {
- if( errno == EACCES ) {
- return ALOCK_LOCKED;
- } else {
- return -1;
- }
- }
-#else
-# error alock needs lockf, fcntl, or _locking
-#endif
-
- return 0;
-}
-
-/* Read a 64bit LE value */
-static unsigned long int
-alock_read_iattr ( unsigned char * bufptr )
-{
- unsigned long int val = 0;
- int count;
-
- assert (bufptr != NULL);
-
- bufptr += sizeof (unsigned long int);
- for (count=0; count <= sizeof (unsigned long int); ++count) {
- val <<= 8;
- val += (unsigned long int) *bufptr--;
- }
-
- return val;
-}
-
-/* Write a 64bit LE value */
-static void
-alock_write_iattr ( unsigned char * bufptr,
- unsigned long int val )
-{
- int count;
-
- assert (bufptr != NULL);
-
- for (count=0; count < 8; ++count) {
- *bufptr++ = (unsigned char) (val & 0xff);
- val >>= 8;
- }
-}
-
-static int
-alock_read_slot ( alock_info_t * info,
- alock_slot_t * slot_data )
-{
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
- int res, size, size_total, err;
-
- assert (info != NULL);
- assert (slot_data != NULL);
- assert (info->al_slot > 0);
-
- res = lseek (info->al_fd,
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
- SEEK_SET);
- if (res == -1) return -1;
-
- size_total = 0;
- while (size_total < ALOCK_SLOT_SIZE) {
- size = read (info->al_fd,
- slotbuf + size_total,
- ALOCK_SLOT_SIZE - size_total);
- if (size == 0) return -1;
- if (size < 0) {
- err = errno;
- if (err != EINTR && err != EAGAIN) return -1;
- } else {
- size_total += size;
- }
- }
-
- if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
- return 1;
- }
- slot_data->al_lock = alock_read_iattr (slotbuf+8);
- slot_data->al_stamp = alock_read_iattr (slotbuf+16);
- slot_data->al_pid = alock_read_iattr (slotbuf+24);
-
- if (slot_data->al_appname) free (slot_data->al_appname);
- slot_data->al_appname = calloc (1, ALOCK_MAX_APPNAME);
- strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
- (slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
-
- return 0;
-}
-
-static int
-alock_write_slot ( alock_info_t * info,
- alock_slot_t * slot_data )
-{
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
- int res, size, size_total, err;
-
- assert (info != NULL);
- assert (slot_data != NULL);
- assert (info->al_slot > 0);
-
- (void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
-
- alock_write_iattr (slotbuf, ALOCK_MAGIC);
- assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
- alock_write_iattr (slotbuf+8, slot_data->al_lock);
- alock_write_iattr (slotbuf+16, slot_data->al_stamp);
- alock_write_iattr (slotbuf+24, slot_data->al_pid);
-
- strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
- slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
-
- res = lseek (info->al_fd,
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
- SEEK_SET);
- if (res == -1) return -1;
-
- size_total = 0;
- while (size_total < ALOCK_SLOT_SIZE) {
- size = write (info->al_fd,
- slotbuf + size_total,
- ALOCK_SLOT_SIZE - size_total);
- if (size == 0) return -1;
- if (size < 0) {
- err = errno;
- if (err != EINTR && err != EAGAIN) return -1;
- } else {
- size_total += size;
- }
- }
-
- return 0;
-}
-
-static int
-alock_query_slot ( alock_info_t * info )
-{
- int res;
- alock_slot_t slot_data;
-
- assert (info != NULL);
- assert (info->al_slot > 0);
-
- (void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
- alock_read_slot (info, &slot_data);
-
- if (slot_data.al_appname != NULL) free (slot_data.al_appname);
- slot_data.al_appname = NULL;
-
- if (slot_data.al_lock == ALOCK_UNLOCKED) return ALOCK_UNLOCKED;
-
- res = alock_test_lock (info->al_fd, info->al_slot);
- if (res < 0) return -1;
- if (res > 0) {
- if (slot_data.al_lock == ALOCK_UNIQUE) {
- return ALOCK_UNIQUE;
- } else {
- return ALOCK_LOCKED;
- }
- }
-
- return ALOCK_DIRTY;
-}
-
-int
-alock_open ( alock_info_t * info,
- const char * appname,
- const char * envdir,
- int locktype )
-{
- struct stat statbuf;
- alock_info_t scan_info;
- alock_slot_t slot_data;
- char * filename;
- int res, max_slot;
- int dirty_count, live_count;
-
- assert (info != NULL);
- assert (appname != NULL);
- assert (envdir != NULL);
- assert (locktype >= 1 && locktype <= 2);
-
- slot_data.al_lock = locktype;
- slot_data.al_stamp = time(NULL);
- slot_data.al_pid = getpid();
- slot_data.al_appname = calloc (1, ALOCK_MAX_APPNAME);
- strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
- slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
-
- filename = calloc (1, strlen (envdir) + strlen ("/alock") + 1);
- strcpy (filename, envdir);
- strcat (filename, "/alock");
- info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
- free (filename);
- if (info->al_fd < 0) {
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- info->al_slot = 0;
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- dirty_count = 0;
- live_count = 0;
- scan_info.al_fd = info->al_fd;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res == ALOCK_UNLOCKED
- && info->al_slot == 0) {
- info->al_slot = scan_info.al_slot;
-
- } else if (res == ALOCK_LOCKED) {
- ++live_count;
-
- } else if (res == ALOCK_UNIQUE
- && locktype == ALOCK_UNIQUE) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_BUSY;
-
- } else if (res == ALOCK_DIRTY) {
- ++dirty_count;
-
- } else if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- if (dirty_count && live_count) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- if (info->al_slot == 0) info->al_slot = max_slot + 1;
- res = alock_grab_lock (info->al_fd,
- info->al_slot);
- if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- res = alock_write_slot (info, &slot_data);
- free (slot_data.al_appname);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- if (dirty_count) return ALOCK_RECOVER;
- return ALOCK_CLEAN;
-}
-
-int
-alock_scan ( alock_info_t * info )
-{
- struct stat statbuf;
- alock_info_t scan_info;
- int res, max_slot;
- int dirty_count, live_count;
-
- assert (info != NULL);
-
- scan_info.al_fd = info->al_fd;
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- dirty_count = 0;
- live_count = 0;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res == ALOCK_LOCKED) {
- ++live_count;
-
- } else if (res == ALOCK_DIRTY) {
- ++dirty_count;
-
- } else if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- if (dirty_count) {
- if (live_count) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- } else {
- return ALOCK_RECOVER;
- }
- }
-
- return ALOCK_CLEAN;
-}
-
-int
-alock_close ( alock_info_t * info )
-{
- alock_slot_t slot_data;
- int res;
-
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- /* mark our slot as clean */
- res = alock_read_slot (info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- if (slot_data.al_appname != NULL)
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- slot_data.al_lock = ALOCK_UNLOCKED;
- res = alock_write_slot (info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- if (slot_data.al_appname != NULL)
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- if (slot_data.al_appname != NULL) {
- free (slot_data.al_appname);
- slot_data.al_appname = NULL;
- }
-
- res = alock_release_lock (info->al_fd, info->al_slot);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = close (info->al_fd);
- if (res == -1) return ALOCK_UNSTABLE;
-
- return ALOCK_CLEAN;
-}
-
-int
-alock_recover ( alock_info_t * info )
-{
- struct stat statbuf;
- alock_slot_t slot_data;
- alock_info_t scan_info;
- int res, max_slot;
-
- assert (info != NULL);
-
- scan_info.al_fd = info->al_fd;
-
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res == ALOCK_LOCKED
- || res == ALOCK_UNIQUE) {
- /* recovery attempt on an active db? */
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-
- } else if (res == ALOCK_DIRTY) {
- /* mark it clean */
- res = alock_read_slot (&scan_info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
- slot_data.al_lock = ALOCK_UNLOCKED;
- res = alock_write_slot (&scan_info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- if (slot_data.al_appname != NULL)
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- if (slot_data.al_appname != NULL) {
- free (slot_data.al_appname);
- slot_data.al_appname = NULL;
- }
-
- } else if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- return ALOCK_CLEAN;
-}
+++ /dev/null
-/* alock.h - access lock header */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * 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>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Matthew Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#ifndef _ALOCK_H_
-#define _ALOCK_H_
-
-#include "portable.h"
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-/* environment states (all the slots together) */
-#define ALOCK_CLEAN (0)
-#define ALOCK_RECOVER (1)
-#define ALOCK_BUSY (2)
-#define ALOCK_UNSTABLE (3)
-
-/* lock user types and states */
-#define ALOCK_UNLOCKED (0)
-#define ALOCK_LOCKED (1)
-#define ALOCK_UNIQUE (2)
-#define ALOCK_DIRTY (3)
-
-/* constants */
-#define ALOCK_SLOT_SIZE (1024)
-#define ALOCK_SLOT_IATTRS (4)
-#define ALOCK_MAX_APPNAME (ALOCK_SLOT_SIZE - 8 * ALOCK_SLOT_IATTRS)
-#define ALOCK_MAGIC (0x12345678)
-
-LDAP_BEGIN_DECL
-
-typedef struct alock_info {
- int al_fd;
- int al_slot;
-} alock_info_t;
-
-typedef struct alock_slot {
- unsigned int al_lock;
- time_t al_stamp;
- pid_t al_pid;
- char * al_appname;
-} alock_slot_t;
-
-extern int alock_open LDAP_P(( alock_info_t * info, const char * appname,
- const char * envdir, int locktype ));
-extern int alock_scan LDAP_P(( alock_info_t * info ));
-extern int alock_close LDAP_P(( alock_info_t * info ));
-extern int alock_recover LDAP_P(( alock_info_t * info ));
-
-LDAP_END_DECL
-
-#endif
* that is always zero.
*/
char bei_lockpad;
-
+
short bei_state;
#define CACHE_ENTRY_DELETED 1
#define CACHE_ENTRY_NO_KIDS 2
#define CACHE_ENTRY_NOT_LINKED 4
#define CACHE_ENTRY_NO_GRANDKIDS 8
#define CACHE_ENTRY_LOADING 0x10
+#define CACHE_ENTRY_WALKING 0x20
+#define CACHE_ENTRY_ONELEVEL 0x40
/*
* remaining fields require backend cache lock to access
int c_maxsize;
int c_cursize;
int c_eiused; /* EntryInfo's in use */
+ int c_leaves; /* EntryInfo leaf nodes */
EntryInfo c_dntree;
EntryInfo *c_eifree; /* free list */
Avlnode *c_idtree;
} else {
bdb->bi_cache.c_eiused++;
ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn );
+
+ /* This is a new leaf node. But if parent had no kids, then it was
+ * a leaf and we would be decrementing that. So, only increment if
+ * the parent already has kids.
+ */
+ if ( ei->bei_parent->bei_kids || !ei->bei_parent->bei_id )
+ bdb->bi_cache.c_leaves++;
avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
avl_dup_error );
#ifdef BDB_HIER
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
int rc;
- int addlru = 1;
+ int addlru = 0;
ei.bei_id = id;
ei.bei_kids = NULL;
ein->bei_ckids++;
bdb_cache_entryinfo_unlock( ein );
}
+ addlru = 0;
- if ( !eir ) {
- addlru = 0;
- }
}
+ if ( addlru ) {
+ ldap_pvt_thread_mutex_lock( &bdb->bi_cache.lru_mutex );
+ LRU_ADD( &bdb->bi_cache, ein );
+ ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.lru_mutex );
+ }
+ addlru = 1;
/* If this is the first time, save this node
* to be returned later.
ei2 = &bdb->bi_cache.c_dntree;
}
bdb->bi_cache.c_eiused++;
+ if ( ei2 && ( ei2->bei_kids || !ei2->bei_id ))
+ bdb->bi_cache.c_leaves++;
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
/* Got the parent, link in and we're done. */
*/
if ( bdb_cache_entry_db_lock( bdb->bi_dbenv,
bdb->bi_cache.c_locker, elru, 1, 1, lockp ) == 0 ) {
- int stop = 0;
- /* If there's no entry, or this node is in
- * the process of linking into the cache,
+ int stop = 0, decr = 0;
+
+ /* If this node is in the process of linking into the cache,
* or this node is being deleted, skip it.
*/
- if ( !elru->bei_e || (elru->bei_state &
- ( CACHE_ENTRY_NOT_LINKED | CACHE_ENTRY_DELETED ))) {
+ if ( elru->bei_state &
+ ( CACHE_ENTRY_NOT_LINKED | CACHE_ENTRY_DELETED )) {
bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp );
continue;
}
- LRU_DELETE( &bdb->bi_cache, elru );
- elru->bei_e->e_private = NULL;
+ /* Free entry for this node if it's present */
+ if ( elru->bei_e ) {
+ elru->bei_e->e_private = NULL;
#ifdef SLAP_ZONE_ALLOC
- bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq );
+ bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq );
#else
- bdb_entry_return( elru->bei_e );
+ bdb_entry_return( elru->bei_e );
#endif
- elru->bei_e = NULL;
+ elru->bei_e = NULL;
+ decr = 1;
+ }
+ /* ITS#4010 if we're in slapcat, and this node is a leaf
+ * node, free it.
+ *
+ * FIXME: we need to do this for slapd as well, (which is
+ * why we compute bi_cache.c_leaves now) but at the moment
+ * we can't because it causes unresolvable deadlocks.
+ */
+ if ( slapMode & SLAP_TOOL_READONLY ) {
+ if ( !elru->bei_kids ) {
+ /* This does LRU_DELETE for us */
+ bdb_cache_delete_internal( &bdb->bi_cache, elru, 0 );
+ bdb_cache_delete_cleanup( &bdb->bi_cache, elru );
+ }
+ /* Leave node on LRU list for a future pass */
+ } else {
+ LRU_DELETE( &bdb->bi_cache, elru );
+ }
+ bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp );
+
ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
- --bdb->bi_cache.c_cursize;
+ if ( decr )
+ --bdb->bi_cache.c_cursize;
if (bdb->bi_cache.c_cursize <= bdb->bi_cache.c_maxsize)
stop = 1;
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
- bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp );
if (stop) break;
}
}
/* set lru mutex */
ldap_pvt_thread_mutex_lock( &cache->lru_mutex );
+
+ /* set cache write lock */
+ ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
+
rc = bdb_cache_delete_internal( cache, e->e_private, 1 );
+
+ /* free cache write lock */
+ ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
/* free lru mutex */
ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
{
int rc = 0; /* return code */
- /* set cache write lock */
- ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
-
/* Lock the parent's kids tree */
bdb_cache_entryinfo_lock( e->bei_parent );
{
rc = -1;
}
+ if ( e->bei_parent->bei_kids )
+ cache->c_leaves--;
/* id tree */
if ( avl_delete( &cache->c_idtree, (caddr_t) e, bdb_id_cmp ) == NULL ) {
rc = -1;
}
- if (rc != 0) {
- return rc;
- }
-
- cache->c_eiused--;
+ if ( rc == 0 ){
+ cache->c_eiused--;
- /* lru */
- LRU_DELETE( cache, e );
- if ( e->bei_e ) cache->c_cursize--;
+ /* lru */
+ LRU_DELETE( cache, e );
+ if ( e->bei_e ) cache->c_cursize--;
+ }
- /* free cache write lock */
- ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
bdb_cache_entryinfo_unlock( e->bei_parent );
- return( 0 );
+ return( rc );
}
static void
}
cache->c_cursize = 0;
cache->c_eiused = 0;
+ cache->c_leaves = 0;
cache->c_idtree = NULL;
cache->c_lruhead = NULL;
cache->c_lrutail = NULL;
bdb_locker_id_free( void *key, void *data )
{
DB_ENV *env = key;
- u_int32_t lockid = (u_int32_t) data;
+ u_int32_t lockid = (long)data;
int rc;
rc = XLOCK_ID_FREE( env, lockid );
if ( rc != 0) {
return rc;
}
- data = (void *)lockid;
+ data = (void *)((long)lockid);
if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, env,
data, bdb_locker_id_free ) ) ) {
XLOCK_ID_FREE( env, lockid );
return rc;
}
} else {
- lockid = (u_int32_t) data;
+ lockid = (long)data;
}
*locker = lockid;
return 0;
key.flags = DB_DBT_USERMEM;
BDB_ID2DISK( eip->bei_id, &nid );
- /* Delete parent's IDL cache entry */
- if ( bdb->bi_idl_cache_size ) {
- key.data = &eip->bei_id;
- bdb_idl_cache_del( bdb, db, &key );
- }
key.data = &nid;
/* Need to make dummy root node once. Subsequent attempts
rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
}
+ /* Update all parents' IDL cache entries */
+ if ( rc == 0 && bdb->bi_idl_cache_size ) {
+ ID tmp[2];
+ char *ptr = ((char *)&tmp[1])-1;
+ key.data = ptr;
+ key.size = sizeof(ID)+1;
+ tmp[1] = eip->bei_id;
+ *ptr = DN_ONE_PREFIX;
+ bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
+ *ptr = DN_SUBTREE_PREFIX;
+ for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
+ tmp[1] = eip->bei_id;
+ bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
+ }
+ }
op->o_tmpfree( d, op->o_tmpmemctx );
return rc;
data.dlen = data.size;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
- /* Delete IDL cache entries */
- if ( bdb->bi_idl_cache_size ) {
- /* Ours */
- key.data = &e->e_id;
- bdb_idl_cache_del( bdb, db, &key );
- /* Parent's */
- key.data = &eip->bei_id;
- bdb_idl_cache_del( bdb, db, &key );
- }
key.data = &nid;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
cursor->c_close( cursor );
op->o_tmpfree( d, op->o_tmpmemctx );
+ /* Delete IDL cache entries */
+ if ( rc == 0 && bdb->bi_idl_cache_size ) {
+ ID tmp[2];
+ char *ptr = ((char *)&tmp[1])-1;
+ key.data = ptr;
+ key.size = sizeof(ID)+1;
+ tmp[1] = eip->bei_id;
+ *ptr = DN_ONE_PREFIX;
+ bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
+ *ptr = DN_SUBTREE_PREFIX;
+ for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
+ tmp[1] = eip->bei_id;
+ bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
+ }
+ }
return rc;
}
struct dn2id_cookie {
struct bdb_info *bdb;
- DB *db;
- int prefix;
- int rc;
+ Operation *op;
EntryInfo *ei;
- ID id;
- ID nid;
- ID dbuf;
ID *ids;
- void *ptr;
- ID tmp[BDB_IDL_UM_SIZE];
+ ID *tmp;
ID *buf;
+ DB *db;
+ DBC *dbc;
DBT key;
DBT data;
- DBC *dbc;
- Operation *op;
+ ID dbuf;
+ ID id;
+ ID nid;
+ int rc;
+ int depth;
+ char need_sort;
+ char prefix;
};
static int
{
BDB_IDL_ZERO( cx->tmp );
- if ( !cx->ei ) {
- cx->ei = bdb_cache_find_info( cx->bdb, cx->id );
- if ( !cx->ei ) {
- cx->rc = DB_NOTFOUND;
- goto saveit;
- }
- }
-
if ( cx->bdb->bi_idl_cache_size ) {
- cx->key.data = &cx->id;
- cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
- if ( cx->rc == DB_NOTFOUND ) {
- return cx->rc;
+ char *ptr = ((char *)&cx->id)-1;
+
+ cx->key.data = ptr;
+ cx->key.size = sizeof(ID)+1;
+ if ( cx->prefix == DN_SUBTREE_PREFIX ) {
+ ID *ids = cx->depth ? cx->tmp : cx->ids;
+ *ptr = cx->prefix;
+ cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, ids);
+ if ( cx->rc == LDAP_SUCCESS ) {
+ if ( cx->depth ) {
+ bdb_idl_append( cx->ids, cx->tmp );
+ cx->need_sort = 1;
+ }
+ return cx->rc;
+ }
}
+ *ptr = DN_ONE_PREFIX;
+ cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
if ( cx->rc == LDAP_SUCCESS ) {
goto gotit;
}
+ if ( cx->rc == DB_NOTFOUND ) {
+ return cx->rc;
+ }
}
bdb_cache_entryinfo_lock( cx->ei );
db_recno_t dkids = cx->ei->bei_dkids;
ei.bei_parent = cx->ei;
+ /* Only one thread should load the cache */
+ while ( cx->ei->bei_state & CACHE_ENTRY_ONELEVEL ) {
+ bdb_cache_entryinfo_unlock( cx->ei );
+ ldap_pvt_thread_yield();
+ bdb_cache_entryinfo_lock( cx->ei );
+ if ( cx->ei->bei_ckids+1 == cx->ei->bei_dkids ) {
+ goto synced;
+ }
+ }
+
+ cx->ei->bei_state |= CACHE_ENTRY_ONELEVEL;
+
bdb_cache_entryinfo_unlock( cx->ei );
cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc,
/* The first item holds the parent ID. Ignore it. */
cx->key.data = &cx->nid;
+ cx->key.size = sizeof(ID);
cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET );
if ( cx->rc ) {
cx->dbc->c_close( cx->dbc );
- if ( cx->rc == DB_NOTFOUND ) goto saveit;
return cx->rc;
}
DB_MULTIPLE | DB_NEXT_DUP )) == 0 ) {
u_int8_t *j;
size_t len;
- DB_MULTIPLE_INIT( cx->ptr, &cx->data );
- while (cx->ptr) {
- DB_MULTIPLE_NEXT( cx->ptr, &cx->data, j, len );
+ void *ptr;
+ DB_MULTIPLE_INIT( ptr, &cx->data );
+ while (ptr) {
+ DB_MULTIPLE_NEXT( ptr, &cx->data, j, len );
if (j) {
EntryInfo *ei2;
diskNode *d = (diskNode *)j;
/* The in-memory cache is in sync with the on-disk data.
* do we have any kids?
*/
+synced:
cx->rc = 0;
if ( cx->ei->bei_ckids > 0 ) {
- /* Walk the kids tree; order is irrelevant since bdb_idl_insert
- * will insert in sorted order.
+ /* Walk the kids tree; order is irrelevant since bdb_idl_sort
+ * will sort it later.
*/
avl_apply( cx->ei->bei_kids, apply_func,
cx->tmp, -1, AVL_POSTORDER );
bdb_cache_entryinfo_unlock( cx->ei );
}
-saveit:
+ if ( !BDB_IDL_IS_RANGE( cx->tmp ) && cx->tmp[0] > 3 )
+ bdb_idl_sort( cx->tmp, cx->buf );
if ( cx->bdb->bi_idl_cache_max_size ) {
- cx->key.data = &cx->id;
+ char *ptr = ((char *)&cx->id)-1;
+ cx->key.data = ptr;
+ cx->key.size = sizeof(ID)+1;
+ *ptr = DN_ONE_PREFIX;
bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
}
- ;
+
gotit:
if ( !BDB_IDL_IS_ZERO( cx->tmp )) {
if ( cx->prefix == DN_SUBTREE_PREFIX ) {
bdb_idl_append( cx->ids, cx->tmp );
+ cx->need_sort = 1;
if ( !(cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS)) {
ID *save, idcurs;
EntryInfo *ei = cx->ei;
BDB_IDL_CPY( save, cx->tmp );
idcurs = 0;
+ cx->depth++;
for ( cx->id = bdb_idl_first( save, &idcurs );
cx->id != NOID;
cx->id = bdb_idl_next( save, &idcurs )) {
+ cx->ei = bdb_cache_find_info( cx->bdb, cx->id );
+ if ( !cx->ei ||
+ ( cx->ei->bei_state & CACHE_ENTRY_NO_KIDS ))
+ continue;
+
BDB_ID2DISK( cx->id, &cx->nid );
- cx->ei = NULL;
hdb_dn2idl_internal( cx );
if ( !BDB_IDL_IS_ZERO( cx->tmp ))
nokids = 0;
}
+ cx->depth--;
cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
if ( nokids ) ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
}
cx.prefix = (op->ors_scope == LDAP_SCOPE_ONELEVEL) ?
DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
cx.ids = ids;
- cx.buf = stack;
+ cx.tmp = stack;
+ cx.buf = stack + BDB_IDL_UM_SIZE;
cx.op = op;
+ cx.need_sort = 0;
+ cx.depth = 0;
- BDB_IDL_ZERO( ids );
if ( cx.prefix == DN_SUBTREE_PREFIX ) {
- bdb_idl_insert( ids, cx.id );
+ ids[0] = 1;
+ ids[1] = cx.id;
+ } else {
+ BDB_IDL_ZERO( ids );
}
+ if ( cx.ei->bei_state & CACHE_ENTRY_NO_KIDS )
+ return LDAP_SUCCESS;
DBTzero(&cx.key);
cx.key.ulen = sizeof(ID);
DBTzero(&cx.data);
hdb_dn2idl_internal(&cx);
- if ( !BDB_IDL_IS_ZERO( ids ) && !BDB_IDL_IS_RANGE( ids ))
- bdb_idl_sort( ids );
+ if ( cx.need_sort ) {
+ char *ptr = ((char *)&cx.id)-1;
+ if ( !BDB_IDL_IS_RANGE( cx.ids ) && cx.ids[0] > 3 )
+ bdb_idl_sort( cx.ids, cx.tmp );
+ cx.key.data = ptr;
+ cx.key.size = sizeof(ID)+1;
+ *ptr = cx.prefix;
+ cx.id = e->e_id;
+ bdb_idl_cache_put( cx.bdb, cx.db, &cx.key, cx.ids, cx.rc );
+ }
+
+ if ( cx.rc == DB_NOTFOUND )
+ cx.rc = LDAP_SUCCESS;
return cx.rc;
}
return 0;
}
-#if 0 /* unused */
-static int idl_delete( ID *ids, ID id )
+static int bdb_idl_delete( ID *ids, ID id )
{
unsigned x = bdb_idl_search( ids, id );
return 0;
}
-#endif /* unused */
static char *
bdb_show_key(
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
}
+void
+bdb_idl_cache_add_id(
+ struct bdb_info *bdb,
+ DB *db,
+ DBT *key,
+ ID id )
+{
+ bdb_idl_cache_entry_t *cache_entry, idl_tmp;
+ DBT2bv( key, &idl_tmp.kstr );
+ idl_tmp.db = db;
+ ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
+ cache_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
+ bdb_idl_entry_cmp );
+ if ( cache_entry != NULL ) {
+ if ( !BDB_IDL_IS_RANGE( cache_entry->idl ) &&
+ cache_entry->idl[0] < BDB_IDL_DB_MAX ) {
+ size_t s = BDB_IDL_SIZEOF( cache_entry->idl ) + sizeof(ID);
+ cache_entry->idl = ch_realloc( cache_entry->idl, s );
+ }
+ bdb_idl_insert( cache_entry->idl, id );
+ }
+ ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
+}
+
+void
+bdb_idl_cache_del_id(
+ struct bdb_info *bdb,
+ DB *db,
+ DBT *key,
+ ID id )
+{
+ bdb_idl_cache_entry_t *cache_entry, idl_tmp;
+ DBT2bv( key, &idl_tmp.kstr );
+ idl_tmp.db = db;
+ ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
+ cache_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
+ bdb_idl_entry_cmp );
+ if ( cache_entry != NULL ) {
+ bdb_idl_delete( cache_entry->idl, id );
+ if ( cache_entry->idl[0] == 0 ) {
+ if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) cache_entry,
+ bdb_idl_entry_cmp ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_del: "
+ "AVL delete failed\n",
+ 0, 0, 0 );
+ }
+ --bdb->bi_idl_cache_size;
+ ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
+ IDL_LRU_DELETE( bdb, cache_entry );
+ ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
+ free( cache_entry->kstr.bv_val );
+ if ( cache_entry->idl )
+ free( cache_entry->idl );
+ free( cache_entry );
+ }
+ }
+ ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
+}
+
int
bdb_idl_fetch_key(
BackendDB *be,
return NOID;
}
-/* Add one ID to an unsorted list. We still maintain a lo/hi reference
- * for fast range compaction.
+#ifdef BDB_HIER
+
+/* Add one ID to an unsorted list. We ensure that the first element is the
+ * minimum and the last element is the maximum, for fast range compaction.
+ * this means IDLs up to length 3 are always sorted...
*/
int bdb_idl_append_one( ID *ids, ID id )
{
tmp = ids[1];
ids[1] = id;
id = tmp;
- } else if ( ids[0] > 1 && id > ids[2] ) {
- tmp = ids[2];
- ids[2] = id;
+ }
+ if ( ids[0] > 1 && id < ids[ids[0]] ) {
+ tmp = ids[ids[0]];
+ ids[ids[0]] = id;
id = tmp;
}
}
ids[0]++;
if ( ids[0] >= BDB_IDL_UM_MAX ) {
ids[0] = NOID;
+ ids[2] = id;
} else {
ids[ids[0]] = id;
}
return 0;
}
-/* Append unsorted list b to unsorted list a. Both lists must have their
- * lowest value in slot 1 and highest value in slot 2.
+/* Append sorted list b to sorted list a. The result is unsorted but
+ * a[1] is the min of the result and a[a[0]] is the max.
*/
int bdb_idl_append( ID *a, ID *b )
{
- ID ida, idb;
+ ID ida, idb, tmp;
if ( BDB_IDL_IS_ZERO( b ) ) {
return 0;
return 0;
}
+ ida = BDB_IDL_LAST( a );
+ idb = BDB_IDL_LAST( b );
if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ||
a[0] + b[0] >= BDB_IDL_UM_MAX ) {
- ida = IDL_MIN( a[1], b[1] );
- idb = IDL_MAX( a[2], b[2] );
+ a[2] = IDL_MAX( ida, idb );
+ a[1] = IDL_MIN( a[1], b[1] );
a[0] = NOID;
- a[1] = ida;
- a[2] = idb;
return 0;
}
- if ( b[1] < a[1] ) {
- ida = a[1];
- a[1] = b[1];
- } else {
- ida = b[1];
+ if ( b[0] > 1 && ida > idb ) {
+ a[a[0]] = idb;
+ b[b[0]] = ida;
}
- a[0]++;
- a[a[0]] = ida;
- if ( b[0] > 1 && b[2] > a[2] ) {
- ida = a[2];
- a[2] = b[2];
+ if ( b[1] < a[1] ) {
+ tmp = a[1];
+ a[1] = b[1];
} else {
- ida = b[2];
+ tmp = b[1];
}
a[0]++;
- a[a[0]] = ida;
+ a[a[0]] = tmp;
- if ( b[0] > 2 ) {
- int i = b[0] - 2;
- AC_MEMCPY(a+a[0]+1, b+3, i * sizeof(ID));
+ if ( b[0] > 1 ) {
+ int i = b[0] - 1;
+ AC_MEMCPY(a+a[0]+1, b+2, i * sizeof(ID));
a[0] += i;
}
return 0;
-
}
-/* Sort an IDL using HeapSort */
-static void
-siftDown(ID *ids, int root, int bottom)
+#if 0
+
+/* Quicksort + Insertion sort for small arrays */
+
+#define SMALL 8
+#define SWAP(a,b) itmp=(a);(a)=(b);(b)=itmp
+
+void
+bdb_idl_sort( ID *ids, ID *tmp )
{
- int child;
- ID temp;
+ int *istack = (int *)tmp;
+ int i,j,k,l,ir,jstack;
+ ID a, itmp;
- temp = ids[root];
- while ((child=root*2) <= bottom) {
- if (child < bottom && ids[child] < ids[child + 1])
- child++;
+ if ( BDB_IDL_IS_RANGE( ids ))
+ return;
- if (temp >= ids[child])
- break;
- ids[root] = ids[child];
- root = child;
+ ir = ids[0];
+ l = 1;
+ jstack = 0;
+ for(;;) {
+ if (ir - l < SMALL) { /* Insertion sort */
+ for (j=l+1;j<=ir;j++) {
+ a = ids[j];
+ for (i=j-1;i>=1;i--) {
+ if (ids[i] <= a) break;
+ ids[i+1] = ids[i];
+ }
+ ids[i+1] = a;
+ }
+ if (jstack == 0) break;
+ ir = istack[jstack--];
+ l = istack[jstack--];
+ } else {
+ k = (l + ir) >> 1; /* Choose median of left, center, right */
+ SWAP(ids[k], ids[l+1]);
+ if (ids[l] > ids[ir]) {
+ SWAP(ids[l], ids[ir]);
+ }
+ if (ids[l+1] > ids[ir]) {
+ SWAP(ids[l+1], ids[ir]);
+ }
+ if (ids[l] > ids[l+1]) {
+ SWAP(ids[l], ids[l+1]);
+ }
+ i = l+1;
+ j = ir;
+ a = ids[l+1];
+ for(;;) {
+ do i++; while(ids[i] < a);
+ do j--; while(ids[j] > a);
+ if (j < i) break;
+ SWAP(ids[i],ids[j]);
+ }
+ ids[l+1] = ids[j];
+ ids[j] = a;
+ jstack += 2;
+ if (ir-i+1 >= j-1) {
+ istack[jstack] = ir;
+ istack[jstack-1] = i;
+ ir = j-1;
+ } else {
+ istack[jstack] = j-1;
+ istack[jstack-1] = l;
+ l = i;
+ }
+ }
}
- ids[root] = temp;
}
+#else
+
+/* 8 bit Radix sort + insertion sort
+ *
+ * based on code from http://www.cubic.org/docs/radix.htm
+ * with improvements by mbackes@symas.com and hyc@symas.com
+ *
+ * This code is O(n) but has a relatively high constant factor. For lists
+ * up to ~50 Quicksort is slightly faster; up to ~100 they are even.
+ * Much faster than quicksort for lists longer than ~100. Insertion
+ * sort is actually superior for lists <50.
+ */
+
+#define BUCKETS (1<<8)
+#define SMALL 50
+
void
-bdb_idl_sort( ID *ids )
+bdb_idl_sort( ID *ids, ID *tmp )
{
- int i;
- ID temp;
-
- if ( BDB_IDL_IS_RANGE( ids ))
+ int count, soft_limit, phase = 0, size = ids[0];
+ ID *idls[2];
+ unsigned char *maxv = (unsigned char *)&ids[size];
+
+ if ( BDB_IDL_IS_RANGE( ids ))
+ return;
+
+ /* Use insertion sort for small lists */
+ if ( size <= SMALL ) {
+ int i,j;
+ ID a;
+
+ for (j=1;j<=size;j++) {
+ a = ids[j];
+ for (i=j-1;i>=1;i--) {
+ if (ids[i] <= a) break;
+ ids[i+1] = ids[i];
+ }
+ ids[i+1] = a;
+ }
return;
+ }
- for (i = ids[0] / 2; i >= 1; i--)
- siftDown(ids, i, ids[0]);
+ tmp[0] = size;
+ idls[0] = ids;
+ idls[1] = tmp;
- for (i = ids[0]; i > 1; i--)
- {
- temp = ids[i];
- ids[i] = ids[1];
- ids[1] = temp;
- siftDown(ids, 1, i-1);
+#if BYTE_ORDER == BIG_ENDIAN
+ for (soft_limit = 0; !maxv[soft_limit]; soft_limit++);
+#else
+ for (soft_limit = sizeof(ID)-1; !maxv[soft_limit]; soft_limit--);
+#endif
+
+ for (
+#if BYTE_ORDER == BIG_ENDIAN
+ count = sizeof(ID)-1; count >= soft_limit; --count
+#else
+ count = 0; count <= soft_limit; ++count
+#endif
+ ) {
+ unsigned int num[BUCKETS], * np, n, sum;
+ int i;
+ ID *sp, *source, *dest;
+ unsigned char *bp, *source_start;
+
+ source = idls[phase]+1;
+ dest = idls[phase^1]+1;
+ source_start = ((unsigned char *) source) + count;
+
+ np = num;
+ for ( i = BUCKETS; i > 0; --i ) *np++ = 0;
+
+ /* count occurences of every byte value */
+ bp = source_start;
+ for ( i = size; i > 0; --i, bp += sizeof(ID) )
+ num[*bp]++;
+
+ /* transform count into index by summing elements and storing
+ * into same array
+ */
+ sum = 0;
+ np = num;
+ for ( i = BUCKETS; i > 0; --i ) {
+ n = *np;
+ *np++ = sum;
+ sum += n;
+ }
+
+ /* fill dest with the right values in the right place */
+ bp = source_start;
+ sp = source;
+ for ( i = size; i > 0; --i, bp += sizeof(ID) ) {
+ np = num + *bp;
+ dest[*np] = *sp++;
+ ++(*np);
+ }
+ phase ^= 1;
+ }
+
+ /* copy back from temp if needed */
+ if ( phase ) {
+ ids++; tmp++;
+ for ( count = 0; count < size; ++count )
+ *ids++ = *tmp++;
}
}
+#endif /* Quick vs Radix */
+
+#endif /* BDB_HIER */
/* IDL sizes - likely should be even bigger
* limiting factors: sizeof(ID), thread stack size
*/
-#define BDB_IDL_DB_SIZE (1<<16) /* 64K IDL on disk */
-#define BDB_IDL_UM_SIZE (1<<17) /* 128K IDL in memory */
+#define BDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
+#define BDB_IDL_DB_SIZE (1<<BDB_IDL_LOGN)
+#define BDB_IDL_UM_SIZE (1<<(BDB_IDL_LOGN+1))
#define BDB_IDL_UM_SIZEOF (BDB_IDL_UM_SIZE * sizeof(ID))
#define BDB_IDL_DB_MAX (BDB_IDL_DB_SIZE-1)
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
locker, &lock );
- e = ei->bei_e;
-
if ( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": dn2entry failed (%d)\n",
}
}
+ e = ei->bei_e;
+
/* acquire and lock entry */
/* FIXME: dn2entry() should return non-glue entry */
if (( rs->sr_err == DB_NOTFOUND ) ||
AttributeDescription *entry = slap_schema.si_ad_entry;
struct berval p_dn, p_ndn;
struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
- int isroot = -1;
Entry *e = NULL;
Entry *p = NULL;
EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
}
if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
+#ifdef BDB_MULTIPLE_SUFFIXES
+ /* Allow renaming one suffix entry to another */
p_ndn = slap_empty_bv;
+#else
+ /* There can only be one suffix entry */
+ rs->sr_err = LDAP_NAMING_VIOLATION;
+ rs->sr_text = "cannot rename suffix entry";
+ goto return_results;
+#endif
} else {
dnParent( &e->e_nname, &p_ndn );
}
rs->sr_text = "old entry's parent does not exist";
goto return_results;
}
+ } else {
+ p = (Entry *)&slap_entry_root;
+ }
- /* check parent for "children" acl */
- rs->sr_err = access_allowed( op, p,
- children, NULL,
- op->oq_modrdn.rs_newSup == NULL ?
- ACL_WRITE : ACL_WDEL,
- NULL );
+ /* check parent for "children" acl */
+ rs->sr_err = access_allowed( op, p,
+ children, NULL,
+ op->oq_modrdn.rs_newSup == NULL ?
+ ACL_WRITE : ACL_WDEL,
+ NULL );
- if ( ! rs->sr_err ) {
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
- 0, 0 );
- rs->sr_text = "no write access to old parent's children";
- goto return_results;
- }
+ if ( !p_ndn.bv_len )
+ p = NULL;
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn) ": wr to children "
- "of entry %s OK\n", p_ndn.bv_val, 0, 0 );
-
- if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
- p_dn = slap_empty_bv;
- } else {
- dnParent( &e->e_name, &p_dn );
+ if ( ! rs->sr_err ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
}
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
- p_dn.bv_val, 0, 0 );
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
+ rs->sr_text = "no write access to old parent's children";
+ goto return_results;
+ }
+ Debug( LDAP_DEBUG_TRACE,
+ LDAP_XSTRING(bdb_modrdn) ": wr to children "
+ "of entry %s OK\n", p_ndn.bv_val, 0, 0 );
+
+ if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
+ p_dn = slap_empty_bv;
} else {
- /* no parent, modrdn entry directly under root */
- isroot = be_isroot( op );
- if ( ! isroot ) {
- if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
- || be_shadow_update( op ) ) {
-
- p = (Entry *)&slap_entry_root;
-
- /* check parent for "children" acl */
- rs->sr_err = access_allowed( op, p,
- children, NULL,
- op->oq_modrdn.rs_newSup == NULL ?
- ACL_WRITE : ACL_WDEL,
- NULL );
-
- p = NULL;
-
- if ( ! rs->sr_err ) {
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- Debug( LDAP_DEBUG_TRACE,
- "no access to parent\n",
- 0, 0, 0 );
- rs->sr_text = "no write access to old parent";
- goto return_results;
- }
-
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn)
- ": wr to children of entry \"\" OK\n",
- 0, 0, 0 );
-
- p_dn.bv_val = "";
- p_dn.bv_len = 0;
-
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn)
- ": parent dn=\"\"\n",
- 0, 0, 0 );
-
- } else {
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn)
- ": no parent, not root "
- "& \"\" is not suffix\n",
- 0, 0, 0);
- rs->sr_text = "no write access to old parent";
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- goto return_results;
- }
- }
+ dnParent( &e->e_name, &p_dn );
}
+ Debug( LDAP_DEBUG_TRACE,
+ LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
+ p_dn.bv_val, 0, 0 );
+
new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
if ( op->oq_modrdn.rs_newSup != NULL ) {
}
}
+ /* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
+ * support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
+ * We do not allow modDN
+ * dc=foo,dc=com
+ * newrdn dc=bar
+ * newsup dc=net
+ * and we probably should. But since MULTIPLE_SUFFIXES is deprecated
+ * I'm ignoring this problem for now.
+ */
if ( op->oq_modrdn.rs_newSup != NULL ) {
if ( op->oq_modrdn.rs_newSup->bv_len ) {
np_dn = op->oq_modrdn.rs_newSup;
/* newSuperior == oldParent? - checked above */
/* newSuperior == entry being moved?, if so ==> ERROR */
if ( dnIsSuffix( np_ndn, &e->e_nname )) {
- rs->sr_err = LDAP_NAMING_VIOLATION;
- rs->sr_text = "new superior is invalid";
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ rs->sr_text = "new superior not found";
goto return_results;
}
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
": newSup(ndn=%s) not here!\n",
np_ndn->bv_val, 0, 0);
rs->sr_text = "new superior not found";
- rs->sr_err = LDAP_OTHER;
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
}
}
} else {
- if ( isroot == -1 ) {
- isroot = be_isroot( op );
- }
-
np_dn = NULL;
/* no parent, modrdn entry directly under root */
- if ( ! isroot ) {
- if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
- || be_isupdate( op ) ) {
- np = (Entry *)&slap_entry_root;
-
- /* check parent for "children" acl */
- rs->sr_err = access_allowed( op, np,
- children, NULL, ACL_WADD, NULL );
-
- np = NULL;
-
- if ( ! rs->sr_err ) {
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- Debug( LDAP_DEBUG_TRACE,
- "no access to new superior\n",
- 0, 0, 0 );
- rs->sr_text =
- "no write access to new superior's children";
- goto return_results;
+ if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
+ || be_isupdate( op ) ) {
+ np = (Entry *)&slap_entry_root;
+
+ /* check parent for "children" acl */
+ rs->sr_err = access_allowed( op, np,
+ children, NULL, ACL_WADD, NULL );
+
+ np = NULL;
+
+ if ( ! rs->sr_err ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
}
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn)
- ": wr to children "
- "of entry \"\" OK\n",
- 0, 0, 0 );
-
- } else {
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn)
- ": new superior=\"\", not root "
- "& \"\" is not suffix\n",
- 0, 0, 0 );
- rs->sr_text = "no write access to new superior's children";
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ Debug( LDAP_DEBUG_TRACE,
+ "no access to new superior\n",
+ 0, 0, 0 );
+ rs->sr_text =
+ "no write access to new superior's children";
goto return_results;
}
}
-
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_modrdn)
- ": new superior=\"\"\n",
- 0, 0, 0 );
}
Debug( LDAP_DEBUG_TRACE,
#define bdb_idl_cache_get BDB_SYMBOL(idl_cache_get)
#define bdb_idl_cache_put BDB_SYMBOL(idl_cache_put)
#define bdb_idl_cache_del BDB_SYMBOL(idl_cache_del)
+#define bdb_idl_cache_add_id BDB_SYMBOL(idl_cache_add_id)
+#define bdb_idl_cache_del_id BDB_SYMBOL(idl_cache_del_id)
int bdb_idl_cache_get(
struct bdb_info *bdb,
DB *db,
DBT *key );
+void
+bdb_idl_cache_add_id(
+ struct bdb_info *bdb,
+ DB *db,
+ DBT *key,
+ ID id );
+
+void
+bdb_idl_cache_del_id(
+ struct bdb_info *bdb,
+ DB *db,
+ DBT *key,
+ ID id );
+
#define bdb_idl_first BDB_SYMBOL(idl_first)
#define bdb_idl_next BDB_SYMBOL(idl_next)
#define bdb_idl_search BDB_SYMBOL(idl_search)
ID bdb_idl_first( ID *ids, ID *cursor );
ID bdb_idl_next( ID *ids, ID *cursor );
-void bdb_idl_sort( ID *ids );
+void bdb_idl_sort( ID *ids, ID *tmp );
int bdb_idl_append( ID *a, ID *b );
int bdb_idl_append_one( ID *ids, ID id );
rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;
rs->sr_text = "maximum deref depth exceeded";
- while (BDB_IDL_N(tmp) < op->o_bd->be_max_deref_depth) {
+ for (;;) {
/* Remember the last entry we looked at, so we can
* report broken links
*/
*matched = e;
+ if (BDB_IDL_N(tmp) >= op->o_bd->be_max_deref_depth) {
+ e = NULL;
+ break;
+ }
+
/* If this is part of a subtree or onelevel search,
* have we seen this ID before? If so, quit.
*/
ei = &ei_root;
rs->sr_err = LDAP_SUCCESS;
} else {
+ if ( op->ors_deref & LDAP_DEREF_FINDING ) {
+ BDB_IDL_ZERO(candidates);
+ }
dn2entry_retry:
/* get entry with reader lock */
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei,
return rs->sr_err;
}
- if ( e && (op->ors_deref & LDAP_DEREF_FINDING) && is_entry_alias(e) ) {
- BDB_IDL_ZERO(candidates);
- e = deref_base( op, rs, e, &matched, locker, &lock,
- candidates, NULL );
+ if ( op->ors_deref & LDAP_DEREF_FINDING ) {
+ if ( matched && is_entry_alias( matched )) {
+ struct berval stub;
+
+ stub.bv_val = op->o_req_ndn.bv_val;
+ stub.bv_len = op->o_req_ndn.bv_len - matched->e_nname.bv_len - 1;
+ e = deref_base( op, rs, matched, &matched, locker, &lock,
+ candidates, NULL );
+ if ( e ) {
+ build_new_dn( &op->o_req_ndn, &e->e_nname, &stub,
+ op->o_tmpmemctx );
+ bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache,
+ e, &lock);
+ matched = NULL;
+ goto dn2entry_retry;
+ }
+ } else if ( e && is_entry_alias( e )) {
+ e = deref_base( op, rs, e, &matched, locker, &lock,
+ candidates, NULL );
+ }
}
if ( e == NULL ) {
erefs = is_entry_referral( matched )
? get_entry_referrals( op, matched )
: NULL;
- rs->sr_err = LDAP_REFERRAL;
+ if ( rs->sr_err == DB_NOTFOUND )
+ rs->sr_err = LDAP_REFERRAL;
rs->sr_matched = matched_dn.bv_val;
}
XXSRCS = init.c tools.c config.c \
add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
- extended.c referral.c operational.c alock.c \
+ extended.c referral.c operational.c \
attr.c index.c key.c dbcache.c filterindex.c trans.c \
dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c
SRCS = $(XXSRCS)
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
- extended.lo referral.lo operational.lo alock.lo \
+ extended.lo referral.lo operational.lo \
attr.lo index.lo key.lo dbcache.lo filterindex.lo trans.lo \
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo
struct ldapconn {
Connection *lc_conn;
-#define LDAP_BACK_PRIV_CONN ((void *)0x0)
-#define LDAP_BACK_PRIV_CONN_TLS ((void *)0x1)
+#define LDAP_BACK_PCONN ((void *)0x0)
+#define LDAP_BACK_PCONN_TLS ((void *)0x1)
+#define LDAP_BACK_PCONN_ID(c) ((void *)(c) > LDAP_BACK_PCONN_TLS ? (c)->c_connid : -1)
+#ifdef HAVE_TLS
+#define LDAP_BACK_PCONN_SET(op) ((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_TLS : LDAP_BACK_PCONN)
+#else /* ! HAVE_TLS */
+#define LDAP_BACK_PCONN_SET(op) (LDAP_BACK_PCONN)
+#endif /* ! HAVE_TLS */
+
LDAP *lc_ld;
struct berval lc_cred;
struct berval lc_bound_ndn;
struct berval lc_local_ndn;
- int lc_bound;
- int lc_ispriv;
- int lc_is_tls;
+ unsigned lc_lcflags;
+#define LDAP_BACK_CONN_ISSET(lc,f) ((lc)->lc_lcflags & (f))
+#define LDAP_BACK_CONN_SET(lc,f) ((lc)->lc_lcflags |= (f))
+#define LDAP_BACK_CONN_CLEAR(lc,f) ((lc)->lc_lcflags &= ~(f))
+#define LDAP_BACK_CONN_CPY(lc,f,mlc) \
+ do { \
+ if ( ((f) & (mlc)->lc_lcflags) == (f) ) { \
+ (lc)->lc_lcflags |= (f); \
+ } else { \
+ (lc)->lc_lcflags &= ~(f); \
+ } \
+ } while ( 0 )
+
+#define LDAP_BACK_FCONN_ISBOUND (0x01)
+#define LDAP_BACK_FCONN_ISANON (0x02)
+#define LDAP_BACK_FCONN_ISBMASK (LDAP_BACK_FCONN_ISBOUND|LDAP_BACK_FCONN_ISANON)
+#define LDAP_BACK_FCONN_ISPRIV (0x04)
+#define LDAP_BACK_FCONN_ISTLS (0x08)
+
+#define LDAP_BACK_CONN_ISBOUND(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
+#define LDAP_BACK_CONN_ISBOUND_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
+#define LDAP_BACK_CONN_ISBOUND_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISBMASK)
+#define LDAP_BACK_CONN_ISBOUND_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISBOUND, (mlc))
+#define LDAP_BACK_CONN_ISANON(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISANON)
+#define LDAP_BACK_CONN_ISANON_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISANON)
+#define LDAP_BACK_CONN_ISANON_CLEAR(lc) LDAP_BACK_CONN_ISBOUND_CLEAR((lc))
+#define LDAP_BACK_CONN_ISANON_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISANON, (mlc))
+#define LDAP_BACK_CONN_ISPRIV(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISPRIV)
+#define LDAP_BACK_CONN_ISPRIV_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISPRIV)
+#define LDAP_BACK_CONN_ISPRIV_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISPRIV)
+#define LDAP_BACK_CONN_ISPRIV_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISPRIV, (mlc))
+#define LDAP_BACK_CONN_ISTLS(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISTLS)
+#define LDAP_BACK_CONN_ISTLS_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISTLS)
+#define LDAP_BACK_CONN_ISTLS_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISTLS)
+#define LDAP_BACK_CONN_ISTLS_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISTLS, (mlc))
+
unsigned lc_refcnt;
unsigned lc_flags;
};
BerVarray idassert_authz;
/* end of ID assert stuff */
+ int nretries;
+#define LDAP_BACK_RETRY_UNDEFINED (-2)
+#define LDAP_BACK_RETRY_FOREVER (-1)
+#define LDAP_BACK_RETRY_NEVER (0)
+#define LDAP_BACK_RETRY_DEFAULT (3)
+
ldap_pvt_thread_mutex_t conn_mutex;
unsigned flags;
#define LDAP_BACK_F_NONE 0x00U
Avlnode *conntree;
+#if 0
+ /* FIXME: automatic rwm instantiation removed */
int rwm_started;
+#endif
};
typedef enum ldap_back_send_t {
/* define to use asynchronous StartTLS */
#define SLAP_STARTTLS_ASYNCHRONOUS
+/* timeout to use when calling ldap_result() */
+#define LDAP_BACK_RESULT_TIMEOUT (0)
+#define LDAP_BACK_RESULT_UTIMEOUT (100000)
+#define LDAP_BACK_TV_SET(tv) \
+ do { \
+ (tv)->tv_sec = LDAP_BACK_RESULT_TIMEOUT; \
+ (tv)->tv_usec = LDAP_BACK_RESULT_UTIMEOUT; \
+ } while ( 0 )
+
LDAP_END_DECL
#include "proto-ldap.h"
#define PRINT_CONNTREE 0
-static LDAP_REBIND_PROC ldap_back_rebind;
+static LDAP_REBIND_PROC ldap_back_default_rebind;
+
+LDAP_REBIND_PROC *ldap_back_rebind_f = ldap_back_default_rebind;
static int
ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs );
ch_free( lc->lc_bound_ndn.bv_val );
BER_BVZERO( &lc->lc_bound_ndn );
}
- lc->lc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
/* method is always LDAP_AUTH_SIMPLE if we got here */
rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val,
/* NOTE: use with care */
if ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
ldap_back_proxy_authz_bind( lc, op, rs );
- if ( lc->lc_bound == 0 ) {
+ if ( !LDAP_BACK_CONN_ISBOUND( lc ) ) {
rc = 1;
goto done;
}
}
- lc->lc_bound = 1;
+ LDAP_BACK_CONN_ISBOUND_SET( lc );
ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn );
if ( LDAP_BACK_SAVECRED( li ) ) {
lc->lc_cred.bv_len );
}
ber_bvreplace( &lc->lc_cred, &op->orb_cred );
- ldap_set_rebind_proc( lc->lc_ld, ldap_back_rebind, lc );
+ ldap_set_rebind_proc( lc->lc_ld, ldap_back_rebind_f, lc );
}
}
done:;
/* must re-insert if local DN changed as result of bind */
- if ( lc->lc_bound && !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) ) {
+ if ( LDAP_BACK_CONN_ISBOUND( lc )
+ && !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) )
+ {
int lerr;
/* wait for all other ops to release the connection */
int *is_tls,
const char *url,
unsigned flags,
+ int retries,
const char **text )
{
int rc = LDAP_SUCCESS;
- struct ldapinfo li;
+ struct ldapinfo dummy;
- /* this is ridicolous... */
- li.flags = flags;
+ /* this is ridiculous... */
+ dummy.flags = flags;
/* start TLS ("tls-[try-]{start,propagate}" statements) */
- if ( ( LDAP_BACK_USE_TLS( &li ) || ( *is_tls && LDAP_BACK_PROPAGATE_TLS( &li ) ) )
+ if ( ( LDAP_BACK_USE_TLS( &dummy ) || ( *is_tls && LDAP_BACK_PROPAGATE_TLS( &dummy ) ) )
&& !ldap_is_ldaps_url( url ) )
{
#ifdef SLAP_STARTTLS_ASYNCHRONOUS
rc = ldap_start_tls( ld, NULL, NULL, &msgid );
if ( rc == LDAP_SUCCESS ) {
LDAPMessage *res = NULL;
- int retries = 1;
- struct timeval tv = { 0, 100000 };
+ struct timeval tv;
+
+ LDAP_BACK_TV_SET( &tv );
retry:;
rc = ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res );
rc = LDAP_OTHER;
} else if ( rc == 0 ) {
- if ( retries ) {
- retries--;
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
+ if ( retries != LDAP_BACK_RETRY_NEVER ) {
+ ldap_pvt_thread_yield();
+ if ( retries > 0 ) {
+ retries--;
+ }
+ LDAP_BACK_TV_SET( &tv );
goto retry;
}
rc = LDAP_OTHER;
break;
default:
- if ( LDAP_BACK_TLS_CRITICAL( &li ) ) {
+ if ( LDAP_BACK_TLS_CRITICAL( &dummy ) ) {
*text = "could not start TLS";
break;
}
}
#ifdef HAVE_TLS
- rs->sr_err = ldap_back_start_tls( ld,
- op->o_protocol, &is_tls,
- li->url, li->flags, &rs->sr_text );
+ rs->sr_err = ldap_back_start_tls( ld, op->o_protocol, &is_tls,
+ li->url, li->flags, li->nretries, &rs->sr_text );
if ( rs->sr_err != LDAP_SUCCESS ) {
ldap_unbind_ext( ld, NULL, NULL );
goto error_return;
(*lcp)->lc_ld = ld;
(*lcp)->lc_refcnt = 1;
#ifdef HAVE_TLS
- (*lcp)->lc_is_tls = is_tls;
+ if ( is_tls ) {
+ LDAP_BACK_CONN_ISTLS_SET( *lcp );
+ } else {
+ LDAP_BACK_CONN_ISTLS_CLEAR( *lcp );
+ }
#endif /* HAVE_TLS */
error_return:;
lc_curr = { 0 };
int refcnt = 1;
- /* Searches for a ldapconn in the avl tree */
-
- /* Explicit binds must not be shared */
- if ( op->o_tag == LDAP_REQ_BIND
- || ( op->o_conn
- && op->o_conn->c_authz_backend
- && op->o_bd->be_private == op->o_conn->c_authz_backend->be_private ) )
- {
- lc_curr.lc_conn = op->o_conn;
-
- } else {
-#ifdef HAVE_TLS
- if ( op->o_conn->c_is_tls ) {
- lc_curr.lc_conn = LDAP_BACK_PRIV_CONN_TLS;
- } else
-#endif /* HAVE_TLS */
- {
- lc_curr.lc_conn = LDAP_BACK_PRIV_CONN;
- }
- }
-
/* Internal searches are privileged and shared. So is root. */
- /* FIXME: there seem to be concurrency issues */
if ( op->o_do_not_cache || be_isroot( op ) ) {
+ LDAP_BACK_CONN_ISPRIV_SET( &lc_curr );
lc_curr.lc_local_ndn = op->o_bd->be_rootndn;
-#ifdef HAVE_TLS
- if ( op->o_conn->c_is_tls ) {
- lc_curr.lc_conn = LDAP_BACK_PRIV_CONN_TLS;
- } else
-#endif /* HAVE_TLS */
- {
- lc_curr.lc_conn = LDAP_BACK_PRIV_CONN;
- }
- lc_curr.lc_ispriv = 1;
+ lc_curr.lc_conn = LDAP_BACK_PCONN_SET( op );
} else {
lc_curr.lc_local_ndn = op->o_ndn;
+ /* Explicit binds must not be shared */
+ if ( op->o_tag == LDAP_REQ_BIND || SLAP_IS_AUTHZ_BACKEND( op ) ) {
+ lc_curr.lc_conn = op->o_conn;
+
+ } else {
+ lc_curr.lc_conn = LDAP_BACK_PCONN_SET( op );
+ }
}
+ /* Searches for a ldapconn in the avl tree */
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
lc = (struct ldapconn *)avl_find( li->conntree,
lc->lc_conn = lc_curr.lc_conn;
ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn );
- if ( lc_curr.lc_ispriv ) {
+ if ( LDAP_BACK_CONN_ISPRIV( &lc_curr ) ) {
ber_dupbv( &lc->lc_cred, &li->acl_passwd );
ber_dupbv( &lc->lc_bound_ndn, &li->acl_authcDN );
- lc->lc_ispriv = lc_curr.lc_ispriv;
+ LDAP_BACK_CONN_ISPRIV_SET( lc );
} else {
BER_BVZERO( &lc->lc_cred );
BER_BVZERO( &lc->lc_bound_ndn );
- if ( op->o_conn && !BER_BVISEMPTY( &op->o_ndn )
- && op->o_bd->be_private == op->o_conn->c_authz_backend->be_private )
+ if ( !BER_BVISEMPTY( &op->o_ndn )
+ && SLAP_IS_AUTHZ_BACKEND( op ) )
{
ber_dupbv( &lc->lc_bound_ndn, &op->o_ndn );
}
* check if the non-TLS connection was already
* in cache; in case, destroy the newly created
* connection and use the existing one */
- if ( lc->lc_conn == LDAP_BACK_PRIV_CONN_TLS
+ if ( lc->lc_conn == LDAP_BACK_PCONN_TLS
&& !ldap_tls_inplace( lc->lc_ld ) )
{
struct ldapconn *tmplc;
- lc_curr.lc_conn = LDAP_BACK_PRIV_CONN;
+ lc_curr.lc_conn = LDAP_BACK_PCONN;
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
tmplc = (struct ldapconn *)avl_find( li->conntree,
(caddr_t)&lc_curr, ldap_back_conn_cmp );
}
#endif /* HAVE_TLS */
- lc->lc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
/* Inserts the newly created ldapconn in the avl tree */
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
int retries,
int dolock )
{
- int rc;
+ struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+
+ int rc = LDAP_BACK_CONN_ISBOUND( lc );
ber_int_t msgid;
assert( retries >= 0 );
- if ( !lc->lc_bound ) {
- struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+ if ( rc ) {
+ return rc;
+ }
- /*
- * FIXME: we need to let clients use proxyAuthz
- * otherwise we cannot do symmetric pools of servers;
- * we have to live with the fact that a user can
- * authorize itself as any ID that is allowed
- * by the authzTo directive of the "proxyauthzdn".
- */
- /*
- * NOTE: current Proxy Authorization specification
- * and implementation do not allow proxy authorization
- * control to be provided with Bind requests
- */
- /*
- * if no bind took place yet, but the connection is bound
- * and the "idassert-authcDN" (or other ID) is set,
- * then bind as the asserting identity and explicitly
- * add the proxyAuthz control to every operation with the
- * dn bound to the connection as control value.
- * This is done also if this is the authrizing backend,
- * but the "override" flag is given to idassert.
- * It allows to use SASL bind and yet proxyAuthz users
- */
- if ( op->o_conn != NULL &&
- !op->o_do_not_cache &&
- ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
- ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
- {
- (void)ldap_back_proxy_authz_bind( lc, op, rs );
- goto done;
- }
+ /*
+ * FIXME: we need to let clients use proxyAuthz
+ * otherwise we cannot do symmetric pools of servers;
+ * we have to live with the fact that a user can
+ * authorize itself as any ID that is allowed
+ * by the authzTo directive of the "proxyauthzdn".
+ */
+ /*
+ * NOTE: current Proxy Authorization specification
+ * and implementation do not allow proxy authorization
+ * control to be provided with Bind requests
+ */
+ /*
+ * if no bind took place yet, but the connection is bound
+ * and the "idassert-authcDN" (or other ID) is set,
+ * then bind as the asserting identity and explicitly
+ * add the proxyAuthz control to every operation with the
+ * dn bound to the connection as control value.
+ * This is done also if this is the authrizing backend,
+ * but the "override" flag is given to idassert.
+ * It allows to use SASL bind and yet proxyAuthz users
+ */
+ if ( op->o_conn != NULL &&
+ !op->o_do_not_cache &&
+ ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
+ ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
+ {
+ (void)ldap_back_proxy_authz_bind( lc, op, rs );
+ goto done;
+ }
#ifdef HAVE_CYRUS_SASL
- if ( lc->lc_ispriv && li->acl_authmethod == LDAP_AUTH_SASL ) {
- void *defaults = NULL;
-
-#if 1 /* will deal with this later... */
- if ( li->acl_secprops != NULL ) {
- rc = ldap_set_option( lc->lc_ld,
- LDAP_OPT_X_SASL_SECPROPS, li->acl_secprops);
-
- if( rc != LDAP_OPT_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
- "(%s,SECPROPS,\"%s\") failed!\n",
- li->url, li->acl_secprops, 0 );
- goto done;
- }
- }
-#endif
+ if ( LDAP_BACK_CONN_ISPRIV( lc )
+ && li->acl_authmethod == LDAP_AUTH_SASL )
+ {
+ void *defaults = NULL;
- defaults = lutil_sasl_defaults( lc->lc_ld,
- li->acl_sasl_mech.bv_val,
- li->acl_sasl_realm.bv_val,
- li->acl_authcID.bv_val,
- li->acl_passwd.bv_val,
- NULL );
+ if ( li->acl_secprops != NULL ) {
+ rc = ldap_set_option( lc->lc_ld,
+ LDAP_OPT_X_SASL_SECPROPS, li->acl_secprops);
- rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld,
- li->acl_authcDN.bv_val,
- li->acl_sasl_mech.bv_val, NULL, NULL,
- LDAP_SASL_QUIET, lutil_sasl_interact,
- defaults );
+ if ( rc != LDAP_OPT_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
+ "(%s,SECPROPS,\"%s\") failed!\n",
+ li->url, li->acl_secprops, 0 );
+ goto done;
+ }
+ }
- lutil_sasl_freedefs( defaults );
+ defaults = lutil_sasl_defaults( lc->lc_ld,
+ li->acl_sasl_mech.bv_val,
+ li->acl_sasl_realm.bv_val,
+ li->acl_authcID.bv_val,
+ li->acl_passwd.bv_val,
+ NULL );
+
+ rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld,
+ li->acl_authcDN.bv_val,
+ li->acl_sasl_mech.bv_val, NULL, NULL,
+ LDAP_SASL_QUIET, lutil_sasl_interact,
+ defaults );
- rs->sr_err = slap_map_api2result( rs );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- lc->lc_bound = 0;
- send_ldap_result( op, rs );
+ lutil_sasl_freedefs( defaults );
- } else {
- lc->lc_bound = 1;
- }
- goto done;
+ rs->sr_err = slap_map_api2result( rs );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+ send_ldap_result( op, rs );
+
+ } else {
+ LDAP_BACK_CONN_ISBOUND_SET( lc );
}
+ goto done;
+ }
#endif /* HAVE_CYRUS_SASL */
retry:;
- rs->sr_err = ldap_sasl_bind( lc->lc_ld,
- lc->lc_bound_ndn.bv_val,
- LDAP_SASL_SIMPLE, &lc->lc_cred,
- NULL, NULL, &msgid );
-
- if ( rs->sr_err == LDAP_SERVER_DOWN ) {
- if ( retries > 0 ) {
- if ( dolock ) {
- ldap_pvt_thread_mutex_lock( &li->conn_mutex );
- }
+ rs->sr_err = ldap_sasl_bind( lc->lc_ld,
+ lc->lc_bound_ndn.bv_val,
+ LDAP_SASL_SIMPLE, &lc->lc_cred,
+ NULL, NULL, &msgid );
+
+ if ( rs->sr_err == LDAP_SERVER_DOWN ) {
+ if ( retries != LDAP_BACK_RETRY_NEVER ) {
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+ }
- assert( lc->lc_refcnt > 0 );
- if ( lc->lc_refcnt == 1 ) {
- ldap_unbind_ext( lc->lc_ld, NULL, NULL );
- lc->lc_ld = NULL;
+ assert( lc->lc_refcnt > 0 );
+ if ( lc->lc_refcnt == 1 ) {
+ ldap_unbind_ext( lc->lc_ld, NULL, NULL );
+ lc->lc_ld = NULL;
- /* lc here must be the regular lc, reset and ready for init */
- rs->sr_err = ldap_back_prepare_conn( &lc, op, rs, sendok );
- }
- if ( dolock ) {
- ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
- }
- if ( rs->sr_err == LDAP_SUCCESS ) {
+ /* lc here must be the regular lc, reset and ready for init */
+ rs->sr_err = ldap_back_prepare_conn( &lc, op, rs, sendok );
+ }
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+ }
+ if ( rs->sr_err == LDAP_SUCCESS ) {
+ if ( retries > 0 ) {
retries--;
- goto retry;
}
+ goto retry;
}
+ }
- ldap_back_freeconn( op, lc );
- rs->sr_err = slap_map_api2result( rs );
+ ldap_back_freeconn( op, lc );
+ rs->sr_err = slap_map_api2result( rs );
- return 0;
- }
+ return 0;
+ }
- rc = ldap_back_op_result( lc, op, rs, msgid, sendok );
- if ( rc == LDAP_SUCCESS ) {
- lc->lc_bound = 1;
- }
+ rc = ldap_back_op_result( lc, op, rs, msgid, sendok );
+ if ( rc == LDAP_SUCCESS ) {
+ LDAP_BACK_CONN_ISBOUND_SET( lc );
+
+ } else {
+ ldap_back_release_conn( op, rs, lc );
}
done:;
- rc = lc->lc_bound;
+ rc = LDAP_BACK_CONN_ISBOUND( lc );
+
return rc;
}
int
ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
{
- return ldap_back_dobind_int( lc, op, rs, sendok, 1, 1 );
+ struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+
+ return ldap_back_dobind_int( lc, op, rs, sendok, li->nretries, 1 );
}
/*
- * ldap_back_rebind
+ * ldap_back_default_rebind
*
* This is a callback used for chasing referrals using the same
* credentials as the original user on this session.
*/
static int
-ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
+ldap_back_default_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
ber_int_t msgid, void *params )
{
struct ldapconn *lc = (struct ldapconn *)params;
assert( lc != NULL );
if ( !ldap_tls_inplace( ld ) ) {
- int is_tls = lc->lc_is_tls,
+ int is_tls = LDAP_BACK_CONN_ISTLS( lc ),
rc;
const char *text = NULL;
- rc = ldap_back_start_tls( ld, 0, &is_tls, url, lc->lc_flags, &text );
+ rc = ldap_back_start_tls( ld, 0, &is_tls, url, lc->lc_flags,
+ LDAP_BACK_RETRY_DEFAULT, &text );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
* remote server response */
if ( ERR_OK( rs->sr_err ) ) {
int rc;
- struct timeval tv = { 0, 100000 };
+ struct timeval tv;
+
+ LDAP_BACK_TV_SET( &tv );
retry:;
/* if result parsing fails, note the failure reason */
switch ( ldap_result( lc->lc_ld, msgid, 1, &tv, &res ) ) {
case 0:
- tv.tv_sec = 0;
- tv.tv_usec = 100000; /* 0.1 s */
+ LDAP_BACK_TV_SET( &tv );
ldap_pvt_thread_yield();
goto retry;
if ( lc->lc_refcnt == 1 ) {
ldap_unbind_ext( lc->lc_ld, NULL, NULL );
lc->lc_ld = NULL;
- lc->lc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
/* lc here must be the regular lc, reset and ready for init */
rc = ldap_back_prepare_conn( &lc, op, rs, sendok );
if ( rs->sr_err != LDAP_SUCCESS ) {
if ( li->idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
send_ldap_result( op, rs );
- lc->lc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
} else {
rs->sr_err = LDAP_SUCCESS;
}
}
-#if 0 /* will deal with this later... */
- if ( sasl_secprops != NULL ) {
- rs->sr_err = ldap_set_option( lc->lc_ld, LDAP_OPT_X_SASL_SECPROPS,
- (void *) sasl_secprops );
+ if ( li->idassert_secprops != NULL ) {
+ rs->sr_err = ldap_set_option( lc->lc_ld,
+ LDAP_OPT_X_SASL_SECPROPS,
+ (void *)li->idassert_secprops );
if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
send_ldap_result( op, rs );
- lc->lc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
goto done;
}
}
-#endif
defaults = lutil_sasl_defaults( lc->lc_ld,
li->idassert_sasl_mech.bv_val,
LDAP_SASL_QUIET, lutil_sasl_interact,
defaults );
- lutil_sasl_freedefs( defaults );
- if ( freeauthz ) {
- slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
- }
-
rs->sr_err = slap_map_api2result( rs );
if ( rs->sr_err != LDAP_SUCCESS ) {
- lc->lc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
send_ldap_result( op, rs );
} else {
- lc->lc_bound = 1;
+ LDAP_BACK_CONN_ISBOUND_SET( lc );
+ }
+
+ lutil_sasl_freedefs( defaults );
+ if ( freeauthz ) {
+ slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
}
+
goto done;
#endif /* HAVE_CYRUS_SASL */
}
switch ( li->idassert_authmethod ) {
+ case LDAP_AUTH_NONE:
+ LDAP_BACK_CONN_ISBOUND_SET( lc );
+ goto done;
+
case LDAP_AUTH_SIMPLE:
rs->sr_err = ldap_sasl_bind( lc->lc_ld,
binddn.bv_val, LDAP_SASL_SIMPLE,
&bindcred, NULL, NULL, &msgid );
break;
- case LDAP_AUTH_NONE:
- lc->lc_bound = 1;
- goto done;
-
default:
/* unsupported! */
- lc->lc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
send_ldap_result( op, rs );
goto done;
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR );
if ( rc == LDAP_SUCCESS ) {
- lc->lc_bound = 1;
+ LDAP_BACK_CONN_ISBOUND_SET( lc );
}
done:;
- return lc->lc_bound;
+ return LDAP_BACK_CONN_ISBOUND( lc );
}
/*
} else if ( li->idassert_authmethod == LDAP_AUTH_SASL ) {
if ( ( li->idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ )
- /* && ( !BER_BVISNULL( &op->o_conn->c_ndn ) || lc->lc_bound ) */ )
+ /* && ( !BER_BVISNULL( &op->o_conn->c_ndn )
+ || LDAP_BACK_CONN_ISBOUND( lc ) ) */ )
{
/* already asserted in SASL via native authz */
/* NOTE: the test on lc->lc_bound is used to trap
isupdate = be_shadow_update( op );
for ( i = 0, ml = op->oq_modify.rs_modlist; ml; ml = ml->sml_next ) {
- if ( !isupdate && !!get_manageDIT( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
+ if ( !isupdate && !get_manageDIT( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
{
continue;
}
extern int chain_init( void );
+extern LDAP_REBIND_PROC *ldap_back_rebind_f;
+
LDAP_END_DECL
#endif /* PROTO_LDAP_H */
stoptime = op->o_time + op->ors_tlimit;
} else {
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
+ LDAP_BACK_TV_SET( &tv );
}
if ( op->ors_attrs ) {
}
if ( rc == 0 ) {
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
+ LDAP_BACK_TV_SET( &tv );
ldap_pvt_thread_yield();
/* check time limit */
lc_curr.lc_conn = conn;
lc_curr.lc_local_ndn = conn->c_ndn;
- ldap_pvt_thread_mutex_trylock( &li->conn_mutex );
+ ldap_pvt_thread_mutex_lock( &li->conn_mutex );
lc = avl_delete( &li->conntree, (caddr_t)&lc_curr, ldap_back_conn_cmp );
ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
if ( lc ) {
Debug( LDAP_DEBUG_TRACE,
"=>ldap_back_conn_destroy: destroying conn %ld (refcnt=%u)\n",
- lc->lc_conn->c_connid, lc->lc_refcnt, 0 );
+ LDAP_BACK_PCONN_ID( lc->lc_conn ), lc->lc_refcnt, 0 );
assert( lc->lc_refcnt == 0 );
#define _BACK_LDBM_H_
#include "ldbm.h"
+#include "alock.h"
LDAP_BEGIN_DECL
int li_dbsyncwaitn;
int li_dbsyncwaitinterval;
int li_dbsyncwaitcount;
+ alock_info_t li_alock_info;
};
LDAP_END_DECL
int
ldbm_back_db_close( Backend *be )
{
+ struct ldbminfo *li = be->be_private;
+
Debug( LDAP_DEBUG_TRACE, "ldbm backend syncing\n", 0, 0, 0 );
ldbm_cache_flush_all( be );
Debug( LDAP_DEBUG_TRACE, "ldbm backend done syncing\n", 0, 0, 0 );
- cache_release_all( &((struct ldbminfo *) be->be_private)->li_cache );
+ cache_release_all( &li->li_cache );
+ if ( alock_close( &li->li_alock_info )) {
+ Debug( LDAP_DEBUG_ANY,
+ "ldbm_back_db_close: alock_close failed\n", 0, 0, 0 );
+ }
return 0;
}
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ int rc;
+
+ rc = alock_open( &li->li_alock_info, "slapd",
+ li->li_directory, ALOCK_UNIQUE );
+ if ( rc == ALOCK_BUSY ) {
+ Debug( LDAP_DEBUG_ANY,
+ "ldbm_back_db_open: database already in use\n",
+ 0, 0, 0 );
+ return -1;
+ } else if ( rc == ALOCK_RECOVER ) {
+ Debug( LDAP_DEBUG_ANY,
+ "ldbm_back_db_open: unclean shutdown detected;"
+ " database may be inconsistent!\n",
+ 0, 0, 0 );
+ rc = alock_recover( &li->li_alock_info );
+ }
+ if ( rc != ALOCK_CLEAN ) {
+ Debug( LDAP_DEBUG_ANY,
+ "ldbm_back_db_open: alock package is unstable;"
+ " database may be inconsistent!\n",
+ 0, 0, 0 );
+ }
li->li_dbenv = ldbm_initialize_env( li->li_directory,
li->li_dbcachesize, &li->li_envdirok );
/* LDAP v2 supporting correct attribute handling. */
LDAPRDN new_rdn = NULL;
LDAPRDN old_rdn = NULL;
- int isroot = -1;
int rc_id = 0;
ID id = NOID;
char textbuf[SLAP_TEXT_BUFLEN];
goto return_results;
}
+ } else {
+ p = (Entry *)&slap_entry_root;
+ }
- /* check parent for "children" acl */
- if ( ! access_allowed( op, p, children, NULL,
- op->oq_modrdn.rs_newSup != NULL ?
- ACL_WDEL : ACL_WRITE,
- NULL ) )
- {
- Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
- 0, 0 );
-
- send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
- NULL );
- goto return_results;
- }
+ /* check parent for "children" acl */
+ if ( ! access_allowed( op, p, children, NULL,
+ op->oq_modrdn.rs_newSup != NULL ?
+ ACL_WDEL : ACL_WRITE,
+ NULL ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
- Debug( LDAP_DEBUG_TRACE,
- "ldbm_back_modrdn: wr to children of entry %s OK\n",
- p_ndn.bv_val, 0, 0 );
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
+ NULL );
+ goto return_results;
+ }
- if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
- p_dn = slap_empty_bv;
- } else {
- dnParent( &e->e_name, &p_dn );
- }
+ if ( BER_BVISEMPTY( &p_ndn ))
+ p = NULL;
- Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n",
- p_dn.bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to children of entry %s OK\n",
+ p_ndn.bv_val, 0, 0 );
+ if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
+ p_dn = slap_empty_bv;
} else {
- /* no parent, must be root to modify rdn */
- isroot = be_isroot( op );
- if ( ! isroot ) {
- if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
- || be_shadow_update( op ) ) {
- int can_access;
- p = (Entry *)&slap_entry_root;
-
- can_access = access_allowed( op, p,
- children, NULL,
- op->oq_modrdn.rs_newSup ?
- ACL_WDEL : ACL_WRITE,
- NULL );
- p = NULL;
-
- /* check parent for "children" acl */
- if ( ! can_access ) {
- Debug( LDAP_DEBUG_TRACE,
- "<=- ldbm_back_modrdn: no "
- "access to parent\n", 0, 0, 0 );
-
- send_ldap_error( op, rs,
- LDAP_INSUFFICIENT_ACCESS,
- NULL );
- goto return_results;
- }
-
- } else {
- Debug( LDAP_DEBUG_TRACE,
- "<=- ldbm_back_modrdn: no parent & "
- "not root\n", 0, 0, 0);
-
- send_ldap_error( op, rs,
- LDAP_INSUFFICIENT_ACCESS,
- NULL );
- goto return_results;
- }
- }
-
- Debug( LDAP_DEBUG_TRACE,
- "ldbm_back_modrdn: no parent, locked root\n",
- 0, 0, 0 );
+ dnParent( &e->e_name, &p_dn );
}
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n",
+ p_dn.bv_val, 0, 0 );
+
new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
if ( op->oq_modrdn.rs_newSup != NULL ) {
"ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
np_ndn->bv_val, 0, 0);
- send_ldap_error( op, rs, LDAP_OTHER,
+ send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
"newSuperior not found" );
goto return_results;
}
}
} else {
-
- /* no parent, must be root to modify newSuperior */
- if ( isroot == -1 ) {
- isroot = be_isroot( op );
- }
-
- if ( ! isroot ) {
- if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
- || be_shadow_update( op ) ) {
- int can_access;
- np = (Entry *)&slap_entry_root;
-
- can_access = access_allowed( op, np,
- children, NULL, ACL_WADD, NULL );
- np = NULL;
-
- /* check parent for "children" acl */
- if ( ! can_access ) {
- Debug( LDAP_DEBUG_TRACE,
- "<=- ldbm_back_modrdn: no "
- "access to new superior\n", 0, 0, 0 );
+ if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
+ || be_shadow_update( op ) ) {
+ int can_access;
+ np = (Entry *)&slap_entry_root;
+
+ can_access = access_allowed( op, np,
+ children, NULL, ACL_WADD, NULL );
+ np = NULL;
+
+ /* check parent for "children" acl */
+ if ( ! can_access ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_modrdn: no "
+ "access to new superior\n", 0, 0, 0 );
send_ldap_error( op, rs,
LDAP_INSUFFICIENT_ACCESS,
goto return_results;
}
- } else {
- Debug( LDAP_DEBUG_TRACE,
- "<=- ldbm_back_modrdn: \"\" "
- "not allowed as new superior\n",
- 0, 0, 0);
-
- send_ldap_error( op, rs,
- LDAP_INSUFFICIENT_ACCESS,
- NULL );
- goto return_results;
- }
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_modrdn: \"\" "
+ "not allowed as new superior\n",
+ 0, 0, 0);
+
+ send_ldap_error( op, rs,
+ LDAP_INSUFFICIENT_ACCESS,
+ NULL );
+ goto return_results;
}
}
mod_DEFS = -DSLAPD_IMPORT
MOD_DEFS = $(@BUILD_META@_DEFS)
-shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA) \
- $(LDAP_LIBLREWRITE_LA)
+shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
+++ /dev/null
-* Short term:
-
-- add missing functions (FIXED)
-
-- review per-target error handling
-
-- dn cache and cache exploitation to refine the candidate selection (?) (FIXED)
-
-- review the group stuff (also in back-ldap!) (FIXED)
-
-- review the attribute stuff (also in bacl-ldap)
- note: this requires changing the acl stuff that checks "dnattr"
- to call a backend specific function that determines what need
- be done to retrieve the "dnattr" attribute from an entry.
-
-- rework compare and bind to attempt to operate on all candidate entries
- while checking at most one succeedes (FIXED, check bind)
-
-- clear previously bound targets when the bind is repeated (FIXED)
-
-- apply new logging to all the stuff (also in back-ldap)
-
-* Long term:
-
-- distributed entries
-
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1999-2005 The OpenLDAP Foundation.
- * Portions Copyright 2001-2003 Pierangelo Masarati.
- * Portions Copyright 1999-2003 Howard Chu.
- * 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>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by the Howard Chu for inclusion
- * in OpenLDAP Software and subsequently enhanced by Pierangelo
- * Masarati.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/socket.h>
-#include <ac/string.h>
-
-#include "slap.h"
-#include "../back-ldap/back-ldap.h"
-#include "back-meta.h"
-
-
-/* return 0 IFF we can retrieve the attributes
- * of entry with e_ndn
- */
-
-/*
- * FIXME: I never testd this function; I know it compiles ... :)
- */
-int
-meta_back_attribute(
- Backend *be,
- Connection *conn,
- Operation *op,
- Entry *target,
- struct berval *ndn,
- AttributeDescription *entry_at,
- BerVarray *vals
-)
-{
- struct metainfo *li = ( struct metainfo * )be->be_private;
- int rc = 1, i, j, count, is_oc, candidate;
- Attribute *attr;
- BerVarray abv, v;
- char **vs;
- struct berval mapped;
- LDAPMessage *result, *e;
- char *gattr[ 2 ];
- LDAP *ld;
-
- *vals = NULL;
- if ( target != NULL && dn_match( &target->e_nname, ndn ) ) {
- /* we already have a copy of the entry */
- /* attribute and objectclass mapping has already been done */
- attr = attr_find( target->e_attrs, entry_at );
- if ( attr == NULL ) {
- return 1;
- }
-
- for ( count = 0; attr->a_vals[ count ].bv_val != NULL; count++ )
- ;
- v = ( BerVarray )ch_calloc( ( count + 1 ), sizeof( struct berval ) );
- if ( v == NULL ) {
- return 1;
- }
-
- for ( j = 0, abv = attr->a_vals; --count >= 0; abv++ ) {
- if ( abv->bv_len > 0 ) {
- ber_dupbv( &v[ j ], abv );
- if ( v[ j ].bv_val == NULL ) {
- break;
- }
- }
- }
- v[ j ].bv_val = NULL;
- *vals = v;
-
- return 0;
- } /* else */
-
- candidate = meta_back_select_unique_candidate( li, ndn );
- if ( candidate == META_TARGET_NONE ) {
- return 1;
- }
-
- ldap_back_map( &li->targets[ candidate ]->at_map,
- &entry_at->ad_cname, &mapped, BACKLDAP_MAP );
- if ( mapped.bv_val == NULL || mapped.bv_val[0] == '\0' )
- return 1;
-
- rc = ldap_initialize( &ld, li->targets[ candidate ]->uri );
- if ( rc != LDAP_SUCCESS ) {
- return 1;
- }
-
- rc = ldap_bind_s( ld, li->targets[ candidate ]->binddn.bv_val,
- li->targets[ candidate ]->bindpw.bv_val, LDAP_AUTH_SIMPLE );
- if ( rc != LDAP_SUCCESS) {
- return 1;
- }
-
- gattr[ 0 ] = mapped.bv_val;
- gattr[ 1 ] = NULL;
- if ( ldap_search_ext_s( ld, ndn->bv_val, LDAP_SCOPE_BASE,
- "(objectClass=*)",
- gattr, 0, NULL, NULL, LDAP_NO_LIMIT,
- LDAP_NO_LIMIT, &result) == LDAP_SUCCESS) {
- if ( ( e = ldap_first_entry( ld, result ) ) != NULL ) {
- vs = ldap_get_values( ld, e, mapped.bv_val );
- if ( vs != NULL ) {
- for ( count = 0; vs[ count ] != NULL;
- count++ ) { }
- v = ( BerVarray )ch_calloc( ( count + 1 ),
- sizeof( struct berval ) );
- if ( v == NULL ) {
- ldap_value_free( vs );
- } else {
- is_oc = ( strcasecmp( "objectclass", mapped.bv_val ) == 0 );
- for ( i = 0, j = 0; i < count; i++ ) {
- ber_str2bv( vs[ i ], 0, 0, &v[ j ] );
- if ( !is_oc ) {
- if ( v[ j ].bv_val == NULL ) {
- ch_free( vs[ i ] );
- } else {
- j++;
- }
- } else {
- ldap_back_map( &li->targets[ candidate ]->oc_map, &v[ j ], &mapped, BACKLDAP_REMAP );
- if ( mapped.bv_val && mapped.bv_val[0] != '\0' ) {
- ber_dupbv( &v[ j ], &mapped );
- if ( v[ j ].bv_val ) {
- j++;
- }
- }
- ch_free( vs[ i ] );
- }
- }
- v[ j ].bv_val = NULL;
- *vals = v;
- rc = 0;
- ch_free( vs );
- }
- }
- }
- ldap_msgfree( result );
- }
- ldap_unbind( ld );
-
- return(rc);
-}
-
LDAP *msc_ld;
struct berval msc_bound_ndn;
struct berval msc_cred;
+ unsigned msc_mscflags;
+ /* NOTE: lc_lcflags is redefined to msc_mscflags to reuse the macros
+ * defined for back-ldap */
+#define lc_lcflags msc_mscflags
+#if 0
int msc_bound;
#define META_UNBOUND 0
#define META_BOUND 1
#define META_ANONYMOUS 2
+#endif
struct metainfo_t *msc_info;
} metasingleconn_t;
ldap_pvt_thread_mutex_t mc_mutex;
unsigned mc_refcnt;
+ struct berval mc_local_ndn;
+ /* NOTE: msc_mscflags is used to recycle the #define
+ * in metasingleconn_t */
+ unsigned msc_mscflags;
+
/*
* means that the connection is bound;
* of course only one target actually is ...
*/
- int mc_auth_target;
+ int mc_authz_target;
#define META_BOUND_NONE (-1)
#define META_BOUND_ALL (-2)
/* supersedes the connection stuff */
unsigned flags;
/* uses flags as defined in <back-ldap/back-ldap.h> */
-#define META_BACK_F_ONERR_STOP 0x00010000U
+#define META_BACK_F_ONERR_STOP 0x00010000U
+#define META_BACK_F_DEFER_ROOTDN_BIND 0x00020000U
+
#define META_BACK_ONERR_STOP(mi) ( (mi)->flags & META_BACK_F_ONERR_STOP )
#define META_BACK_ONERR_CONTINUE(mi) ( !META_BACK_ONERR_CONTINUE( (mi) ) )
+#define META_BACK_DEFER_ROOTDN_BIND(mi) ( (mi)->flags & META_BACK_F_DEFER_ROOTDN_BIND )
+
int mi_version;
time_t mi_timeout[ META_OP_LAST ];
} metainfo_t;
extern void
meta_dncache_free( void *entry );
+extern LDAP_REBIND_PROC *meta_back_rebind_f;
+
LDAP_END_DECL
#endif /* SLAPD_META_H */
#include "../back-ldap/back-ldap.h"
#include "back-meta.h"
-static LDAP_REBIND_PROC meta_back_rebind;
+static LDAP_REBIND_PROC meta_back_default_rebind;
+
+/*
+ * a module could register a replacement for this function
+ */
+LDAP_REBIND_PROC *meta_back_rebind_f = meta_back_default_rebind;
static int
meta_back_single_bind(
metaconn_t *mc = NULL;
int rc = LDAP_OTHER,
- i, gotit = 0, isroot = 0;
+ i,
+ gotit = 0,
+ isroot = 0;
SlapReply *candidates = meta_back_candidates_get( op );
rs->sr_err = LDAP_SUCCESS;
- Debug( LDAP_DEBUG_ARGS, "meta_back_bind: dn: %s.\n%s%s",
- op->o_req_dn.bv_val, "", "" );
+ Debug( LDAP_DEBUG_ARGS, "%s meta_back_bind: dn=\"%s\".\n",
+ op->o_log_prefix, op->o_req_dn.bv_val, 0 );
+
+ /* the test on the bind method should be superfluous */
+ if ( op->orb_method == LDAP_AUTH_SIMPLE
+ && be_isroot_dn( op->o_bd, &op->o_req_ndn ) )
+ {
+ if ( !be_isroot_pw( op ) ) {
+ rs->sr_err = LDAP_INVALID_CREDENTIALS;
+ rs->sr_text = NULL;
+ send_ldap_result( op, rs );
+ return rs->sr_err;
+ }
+
+ if ( META_BACK_DEFER_ROOTDN_BIND( mi ) ) {
+ rs->sr_err = LDAP_SUCCESS;
+ rs->sr_text = NULL;
+ send_ldap_result( op, rs );
+ return rs->sr_err;
+ }
- if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op ) ) {
isroot = 1;
- ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ) );
}
/* we need meta_back_getconn() not send result even on error,
* invalidCredentials */
mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_DONTSEND );
if ( !mc ) {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "meta_back_bind: no target "
+ "for dn \"%s\" (%d%s%s).",
+ op->o_req_dn.bv_val, rs->sr_err,
+ rs->sr_text ? ". " : "",
+ rs->sr_text ? rs->sr_text : "" );
Debug( LDAP_DEBUG_ANY,
- "meta_back_bind: no target "
- "for dn \"%s\" (%d: %s).\n",
- op->o_req_dn.bv_val, rs->sr_err,
- rs->sr_text ? rs->sr_text : "" );
+ "%s %s\n",
+ op->o_log_prefix, buf, 0 );
+
/* FIXME: there might be cases where we don't want
* to map the error onto invalidCredentials */
switch ( rs->sr_err ) {
/*
* Each target is scanned ...
*/
- mc->mc_auth_target = META_BOUND_NONE;
+ mc->mc_authz_target = META_BOUND_NONE;
for ( i = 0; i < mi->mi_ntargets; i++ ) {
int lerr;
Operation op2 = *op;
}
if ( gotit == 0 ) {
+ /* set rc to LDAP_SUCCESS only if at least
+ * one candidate has been tried */
+ rc = LDAP_SUCCESS;
gotit = 1;
} else if ( isroot == 0 ) {
* ONE CANDIDATE ONLY!
*/
Debug( LDAP_DEBUG_ANY,
- "==>meta_back_bind: more than one"
- " candidate is trying to bind...\n",
- 0, 0, 0 );
+ "### %s meta_back_bind: more than one"
+ " candidate is trying to bind...\n",
+ op->o_log_prefix, 0, 0 );
}
- if ( isroot && !BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) )
- {
+ if ( isroot ) {
+ if ( BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) )
+ {
+ metasingleconn_t *msc = &mc->mc_conns[ i ];
+
+ /* skip the target if no pseudorootdn is provided */
+ if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+ ch_free( msc->msc_bound_ndn.bv_val );
+ BER_BVZERO( &msc->msc_bound_ndn );
+ }
+
+ if ( LDAP_BACK_SAVECRED( mi ) &&
+ !BER_BVISNULL( &msc->msc_cred ) )
+ {
+ /* destroy sensitive data */
+ memset( msc->msc_cred.bv_val, 0,
+ msc->msc_cred.bv_len );
+ ch_free( msc->msc_cred.bv_val );
+ BER_BVZERO( &msc->msc_cred );
+ }
+
+ continue;
+ }
+
op2.o_req_dn = mi->mi_targets[ i ].mt_pseudorootdn;
op2.o_req_ndn = mi->mi_targets[ i ].mt_pseudorootdn;
op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw;
rc = rs->sr_err;
break;
}
-
- } else {
- rc = LDAP_SUCCESS;
}
}
- if ( isroot ) {
- mc->mc_auth_target = META_BOUND_ALL;
+ /* must re-insert if local DN changed as result of bind */
+ if ( rc == LDAP_SUCCESS ) {
+ if ( isroot ) {
+ mc->mc_authz_target = META_BOUND_ALL;
+ ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ) );
+ }
+
+ if ( !dn_match( &op->o_req_ndn, &mc->mc_local_ndn ) ) {
+ int lerr;
+
+ /* wait for all other ops to release the connection */
+retry_lock:;
+ ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
+ if ( mc->mc_refcnt > 1 ) {
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+ ldap_pvt_thread_yield();
+ goto retry_lock;
+ }
+
+ assert( mc->mc_refcnt == 1 );
+ mc = avl_delete( &mi->mi_conntree, (caddr_t)mc,
+ meta_back_conn_cmp );
+ assert( mc != NULL );
+
+ ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
+ lerr = avl_insert( &mi->mi_conntree, (caddr_t)mc,
+ meta_back_conn_cmp, meta_back_conn_dup );
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+ if ( lerr == -1 ) {
+ for ( i = 0; i < mi->mi_ntargets; ++i ) {
+ if ( mc->mc_conns[ i ].msc_ld != NULL ) {
+ meta_clear_one_candidate( &mc->mc_conns[ i ] );
+ }
+ }
+
+ /* we can do this because mc_refcnt == 1 */
+ mc->mc_refcnt = 0;
+ meta_back_conn_free( mc );
+ mc = NULL;
+ }
+ }
}
- meta_back_release_conn( op, mc );
+ if ( mc != NULL ) {
+ meta_back_release_conn( op, mc );
+ }
/*
* rc is LDAP_SUCCESS if at least one bind succeeded,
* err is the last error that occurred during a bind;
- * if at least (and at most?) one bind succeedes, fine.
+ * if at least (and at most?) one bind succeeds, fine.
*/
if ( rc != LDAP_SUCCESS ) {
*/
if ( rs->sr_err == LDAP_SUCCESS && gotit == 0 ) {
rs->sr_err = LDAP_INVALID_CREDENTIALS;
+ } else {
+ rs->sr_err = slap_map_api2result( rs );
}
-
- rs->sr_err = slap_map_api2result( rs );
send_ldap_result( op, rs );
return rs->sr_err;
+
}
return LDAP_SUCCESS;
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int msgid,
rebinding = 0;
+
+ if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+ ch_free( msc->msc_bound_ndn.bv_val );
+ BER_BVZERO( &msc->msc_bound_ndn );
+ }
+
+ if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
+ /* destroy sensitive data */
+ memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
+ ch_free( msc->msc_cred.bv_val );
+ BER_BVZERO( &msc->msc_cred );
+ }
+
/*
* Rewrite the bind dn if needed
*/
- dc.target = &mi->mi_targets[ candidate ];
+ dc.target = mt;
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "bindDN";
/* FIXME: this fixes the bind problem right now; we need
* to use the asynchronous version to get the "matched"
* and more in case of failure ... */
- /* FIXME: should be check if at least some of the op->o_ctrls
+ /* FIXME: should we check if at least some of the op->o_ctrls
* can/should be passed? */
rebind:;
rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,
op->o_ctrls, NULL, &msgid );
if ( rs->sr_err == LDAP_SUCCESS ) {
LDAPMessage *res;
- struct timeval tv = { 0, 100000 };
+ struct timeval tv;
int rc;
int nretries = mt->mt_nretries;
+ LDAP_BACK_TV_SET( &tv );
+
/*
* handle response!!!
*/
if ( nretries > 0 ) {
nretries--;
}
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
+ LDAP_BACK_TV_SET( &tv );
goto retry;
}
rs->sr_err = LDAP_BUSY;
if ( mc->mc_refcnt == 1 ) {
ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
- msc->msc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
}
ber_bvreplace( &msc->msc_bound_ndn, &op->o_req_dn );
- msc->msc_bound = META_BOUND;
- mc->mc_auth_target = candidate;
+ LDAP_BACK_CONN_ISBOUND_SET( msc );
+ mc->mc_authz_target = candidate;
if ( LDAP_BACK_SAVECRED( mi ) ) {
ber_bvreplace( &msc->msc_cred, &op->orb_cred );
- ldap_set_rebind_proc( msc->msc_ld, meta_back_rebind, msc );
+ ldap_set_rebind_proc( msc->msc_ld, meta_back_rebind_f, msc );
}
if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED
metatarget_t *mt = &mi->mi_targets[ candidate ];
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int rc;
- struct berval cred = BER_BVC( "" );
+ static struct berval cred = BER_BVC( "" );
int msgid,
rebinding = 0,
save_nretries = nretries;
+ assert( !LDAP_BACK_CONN_ISBOUND( msc ) );
+
/*
* Otherwise an anonymous bind is performed
* (note: if the target was already bound, the anonymous
BER_BVZERO( &msc->msc_bound_ndn );
}
- if ( !BER_BVISNULL( &msc->msc_cred ) ) {
+ if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
/* destroy sensitive data */
memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
ber_memfree( msc->msc_cred.bv_val );
NULL, NULL, &msgid );
if ( rc == LDAP_SUCCESS ) {
LDAPMessage *res;
- struct timeval tv = { 0, 100000 };
+ struct timeval tv;
+
+ LDAP_BACK_TV_SET( &tv );
/*
* handle response!!!
if ( nretries > 0 ) {
nretries--;
}
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
+ LDAP_BACK_TV_SET( &tv );
goto retry;
}
if ( mc->mc_refcnt == 1 ) {
ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
- msc->msc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
Debug( LDAP_DEBUG_TRACE,
"%s meta_back_dobind: conn=%ld%s\n",
- op->o_log_prefix, mc->mc_conn->c_connid,
+ op->o_log_prefix,
+ LDAP_BACK_PCONN_ID( mc->mc_conn ),
isroot ? " (isroot)" : "" );
ldap_pvt_thread_mutex_lock( &mc->mc_mutex );
/*
* all the targets are bound as pseudoroot
*/
- if ( mc->mc_auth_target == META_BOUND_ALL ) {
+ if ( mc->mc_authz_target == META_BOUND_ALL ) {
bound = 1;
goto done;
}
metatarget_t *mt = &mi->mi_targets[ i ];
metasingleconn_t *msc = &mc->mc_conns[ i ];
int rc;
+ char *rootdn = NULL;
/*
* Not a candidate
/*
* If the target is already bound it is skipped
*/
- if ( msc->msc_bound == META_BOUND && mc->mc_auth_target == i ) {
+ if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
++bound;
-
- Debug( LDAP_DEBUG_TRACE, "%s meta_back_dobind[%d]: "
- "authcTarget\n",
- op->o_log_prefix, i, 0 );
continue;
}
op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw;
op2.orb_method = LDAP_AUTH_SIMPLE;
+ rootdn = mi->mi_targets[ i ].mt_pseudorootdn.bv_val;
+
rc = meta_back_single_bind( &op2, rs, mc, i );
} else {
}
if ( rc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY, "%s meta_back_dobind[%d]: "
- "(anonymous) err=%d\n",
- op->o_log_prefix, i, rc );
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "meta_back_dobind[%d]: (%s) err=%d.",
+ i, rootdn ? rootdn : "anonymous", rc );
+ Debug( LDAP_DEBUG_ANY,
+ "%s %s\n",
+ op->o_log_prefix, buf, 0 );
/*
* null cred bind should always succeed
continue;
} /* else */
- Debug( LDAP_DEBUG_TRACE, "%s meta_back_dobind[%d]: "
- "(anonymous)\n",
- op->o_log_prefix, i, 0 );
-
- msc->msc_bound = META_ANONYMOUS;
+ Debug( LDAP_DEBUG_TRACE,
+ "%s meta_back_dobind[%d]: "
+ "(%s)\n",
+ op->o_log_prefix, i,
+ rootdn ? rootdn : "anonymous" );
+
+ if ( rootdn ) {
+ LDAP_BACK_CONN_ISBOUND_SET( msc );
+ } else {
+ LDAP_BACK_CONN_ISANON_SET( msc );
+ }
++bound;
}
Debug( LDAP_DEBUG_TRACE,
"%s meta_back_dobind: conn=%ld bound=%d\n",
- op->o_log_prefix, mc->mc_conn->c_connid, bound );
+ op->o_log_prefix, LDAP_BACK_PCONN_ID( mc->mc_conn ), bound );
if ( bound == 0 ) {
meta_back_release_conn( op, mc );
}
/*
- * meta_back_rebind
+ * meta_back_default_rebind
*
* This is a callback used for chasing referrals using the same
* credentials as the original user on this session.
*/
static int
-meta_back_rebind(
+meta_back_default_rebind(
LDAP *ld,
LDAP_CONST char *url,
ber_tag_t request,
}
if ( !BER_BVISNULL( &msc->msc_cred ) ) {
+ memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
ber_memfree( msc->msc_cred.bv_val );
BER_BVZERO( &msc->msc_cred );
}
metasingleconn_t *msc = &mc->mc_conns[ i ];
int lrc;
LDAPMessage *res = NULL;
- struct timeval tv = { 0 };
+ struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 100000; /* 0.1 s */
+ LDAP_BACK_TV_SET( &tv );
if ( msgid[ i ] == -1 ) {
continue;
return 0;
}
+static int
+check_true_false( char *str )
+{
+ if ( strcasecmp( str, "true" ) == 0 || strcasecmp( str, "yes" ) == 0 ) {
+ return 1;
+ }
+
+ if ( strcasecmp( str, "false" ) == 0 || strcasecmp( str, "no" ) == 0 ) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
int
meta_back_db_config(
BackendDB *be,
if ( argc == 1 ) {
fprintf( stderr,
- "%s: line %d: deprecated use of \"rebind-as-user {NO|yes}\" with no arguments.\n",
+ "%s: line %d: deprecated use of \"rebind-as-user {FALSE|true}\" with no arguments.\n",
fname, lineno );
mi->flags |= LDAP_BACK_F_SAVECRED;
} else {
- if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+ switch ( check_true_false( argv[ 1 ] ) ) {
+ case 0:
mi->flags &= ~LDAP_BACK_F_SAVECRED;
+ break;
- } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+ case 1:
mi->flags |= LDAP_BACK_F_SAVECRED;
+ break;
- } else {
+ default:
fprintf( stderr,
- "%s: line %d: \"rebind-as-user {NO|yes}\" unknown argument \"%s\".\n",
+ "%s: line %d: \"rebind-as-user {FALSE|true}\" unknown argument \"%s\".\n",
fname, lineno, argv[ 1 ] );
return 1;
}
if ( argc != 2 ) {
fprintf( stderr,
- "%s: line %d: \"chase-referrals\" needs 1 argument.\n",
+ "%s: line %d: \"chase-referrals {TRUE|false}\" needs 1 argument.\n",
fname, lineno );
return( 1 );
}
/* this is the default; we add it because the default might change... */
- if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+ switch ( check_true_false( argv[ 1 ] ) ) {
+ case 1:
*flagsp |= LDAP_BACK_F_CHASE_REFERRALS;
+ break;
- } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+ case 0:
*flagsp &= ~LDAP_BACK_F_CHASE_REFERRALS;
+ break;
- } else {
+ default:
fprintf( stderr,
- "%s: line %d: \"chase-referrals {YES|no}\": unknown argument \"%s\".\n",
+ "%s: line %d: \"chase-referrals {TRUE|false}\": unknown argument \"%s\".\n",
fname, lineno, argv[ 1 ] );
return( 1 );
}
if ( argc != 2 ) {
fprintf( stderr,
- "%s: line %d: \"t-f-support {NO|yes|discover}\" needs 1 argument.\n",
+ "%s: line %d: \"t-f-support {FALSE|true|discover}\" needs 1 argument.\n",
fname, lineno );
return( 1 );
}
- if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+ switch ( check_true_false( argv[ 1 ] ) ) {
+ case 0:
*flagsp &= ~(LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER);
+ break;
- } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+ case 1:
*flagsp |= LDAP_BACK_F_SUPPORT_T_F;
+ break;
- } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
- *flagsp |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+ default:
+ if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
+ *flagsp |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
- } else {
- fprintf( stderr,
+ } else {
+ fprintf( stderr,
"%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
- fname, lineno, argv[ 1 ] );
- return 1;
+ fname, lineno, argv[ 1 ] );
+ return 1;
+ }
+ break;
}
/* onerr? */
return 1;
}
+ /* bind-defer? */
+ } else if ( strcasecmp( argv[ 0 ], "pseudoroot-bind-defer" ) == 0 ) {
+ if ( argc != 2 ) {
+ fprintf( stderr,
+ "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\" takes 1 argument\n",
+ fname, lineno );
+ return( 1 );
+ }
+
+ switch ( check_true_false( argv[ 1 ] ) ) {
+ case 0:
+ mi->flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
+ break;
+
+ case 1:
+ mi->flags |= META_BACK_F_DEFER_ROOTDN_BIND;
+ break;
+
+ default:
+ fprintf( stderr,
+ "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\": invalid arg \"%s\".\n",
+ fname, lineno, argv[ 1 ] );
+ return 1;
+ }
+
} else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
char *sep, *next;
time_t *tv = mi->mi_ntargets ?
{
metaconn_t *mc1 = ( metaconn_t * )c1;
metaconn_t *mc2 = ( metaconn_t * )c2;
+ int rc;
+ /* If local DNs don't match, it is definitely not a match */
+ rc = ber_bvcmp( &mc1->mc_local_ndn, &mc2->mc_local_ndn );
+ if ( rc ) {
+ return rc;
+ }
+
+ /* For shared sessions, conn is NULL. Only explicitly
+ * bound sessions will have non-NULL conn.
+ */
return SLAP_PTRCMP( mc1->mc_conn, mc2->mc_conn );
}
metaconn_t *mc1 = ( metaconn_t * )c1;
metaconn_t *mc2 = ( metaconn_t * )c2;
- return( ( mc1->mc_conn == mc2->mc_conn ) ? -1 : 0 );
+ /* Cannot have more than one shared session with same DN */
+ if ( dn_match( &mc1->mc_local_ndn, &mc2->mc_local_ndn ) &&
+ mc1->mc_conn == mc2->mc_conn )
+ {
+ return -1;
+ }
+
+ return 0;
}
/*
static void
ravl_print( Avlnode *root, int depth )
{
- int i;
+ int i;
+ metaconn_t *mc = (metaconn_t *)root->avl_data;
if ( root == 0 ) {
return;
printf( " " );
}
- printf( "c(%d) %d\n", ( ( metaconn_t * )root->avl_data )->mc_conn->c_connid, root->avl_bf );
+ printf( "c(%d%s%s) %d\n",
+ LDAP_BACK_PCONN_ID( mc->mc_conn ),
+ BER_BVISNULL( &mc->mc_local_ndn ) ? "" : ": ",
+ BER_BVISNULL( &mc->mc_local_ndn ) ? "" : mc->mc_local_ndn.bv_val,
+ root->avl_bf );
ravl_print( root->avl_left, depth + 1 );
}
mc->mc_conns[ i ].msc_ld = NULL;
BER_BVZERO( &mc->mc_conns[ i ].msc_bound_ndn );
BER_BVZERO( &mc->mc_conns[ i ].msc_cred );
- mc->mc_conns[ i ].msc_bound = META_UNBOUND;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( &mc->mc_conns[ i ] );
mc->mc_conns[ i ].msc_info = mi;
}
- mc->mc_auth_target = META_BOUND_NONE;
+ BER_BVZERO( &mc->mc_local_ndn );
+ mc->msc_mscflags = 0;
+ mc->mc_authz_target = META_BOUND_NONE;
ldap_pvt_thread_mutex_init( &mc->mc_mutex );
mc->mc_refcnt = 1;
assert( mc != NULL );
assert( mc->mc_refcnt == 0 );
+ if ( !BER_BVISNULL( &mc->mc_local_ndn ) ) {
+ free( mc->mc_local_ndn.bv_val );
+ }
+
ldap_pvt_thread_mutex_destroy( &mc->mc_mutex );
free( mc );
}
if ( rs->sr_err == LDAP_SUCCESS ) {
LDAPMessage *res = NULL;
int rc, nretries = mt->mt_nretries;
- struct timeval tv = { 0, 0 };
+ struct timeval tv;
+
+ LDAP_BACK_TV_SET( &tv );
retry:;
rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
if ( nretries > 0 ) {
nretries--;
}
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
+ LDAP_BACK_TV_SET( &tv );
goto retry;
}
rs->sr_err = LDAP_OTHER;
ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
}
- msc->msc_bound = META_UNBOUND;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
error_return:;
if ( rs->sr_err == LDAP_SUCCESS ) {
ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
- msc->msc_bound = 0;
+ LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
switch ( rs->sr_type ) {
case REP_SEARCH:
- ((int *)op->o_callback->sc_private)[0] = (int)op->o_private;
+ ((long *)op->o_callback->sc_private)[0] = (long)op->o_private;
break;
case REP_SEARCHREF:
SlapReply *candidates = meta_back_candidates_get( op );
+ /* Internal searches are privileged and shared. So is root. */
+ /* FIXME: there seem to be concurrency issues */
+ if ( op->o_do_not_cache || be_isroot( op ) ) {
+ mc_curr.mc_local_ndn = op->o_bd->be_rootndn;
+ LDAP_BACK_CONN_ISPRIV_SET( &mc_curr );
+ mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
+
+ } else {
+ mc_curr.mc_local_ndn = op->o_ndn;
+
+ /* Explicit binds must not be shared */
+ if ( op->o_tag == LDAP_REQ_BIND || SLAP_IS_AUTHZ_BACKEND( op ) ) {
+ mc_curr.mc_conn = op->o_conn;
+
+ } else {
+ mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
+ }
+ }
+
/* Searches for a metaconn in the avl tree */
- mc_curr.mc_conn = op->o_conn;
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
mc = (metaconn_t *)avl_find( mi->mi_conntree,
(caddr_t)&mc_curr, meta_back_conn_cmp );
/* Looks like we didn't get a bind. Open a new session... */
if ( mc == NULL ) {
mc = metaconn_alloc( op );
- mc->mc_conn = op->o_conn;
+ mc->mc_conn = mc_curr.mc_conn;
+ ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
new_conn = 1;
}
for ( i = 0; i < mi->mi_ntargets; i++ ) {
+ metatarget_t *mt = &mi->mi_targets[ i ];
+ metasingleconn_t *msc = &mc->mc_conns[ i ];
/*
* The target is activated; if needed, it is
* also init'd
*/
- candidates[ i ].sr_err =
- meta_back_init_one_conn( op, rs,
- &mi->mi_targets[ i ],
- &mc->mc_conns[ i ], sendok );
+ candidates[ i ].sr_err = meta_back_init_one_conn( op,
+ rs, mt, msc, sendok );
if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
candidates[ i ].sr_tag = META_CANDIDATE;
ncandidates++;
-
+
+ if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
+ ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+ ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
+ LDAP_BACK_CONN_ISPRIV_SET( msc );
+
+ } else {
+ BER_BVZERO( &msc->msc_cred );
+ BER_BVZERO( &msc->msc_bound_ndn );
+ if ( !BER_BVISEMPTY( &op->o_ndn )
+ && SLAP_IS_AUTHZ_BACKEND( op )
+ && i == mc->mc_authz_target )
+ {
+ ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
+ }
+ }
+
} else {
/*
}
if ( op_type == META_OP_REQUIRE_SINGLE ) {
- int j;
+ metatarget_t *mt = NULL;
+ metasingleconn_t *msc = NULL;
+
+ int j;
for ( j = 0; j < mi->mi_ntargets; j++ ) {
candidates[ j ].sr_tag = META_NOT_CANDIDATE;
/* Retries searching for a metaconn in the avl tree
* the reason is that the connection might have been
* created by meta_back_get_candidate() */
- mc_curr.mc_conn = op->o_conn;
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
mc = (metaconn_t *)avl_find( mi->mi_conntree,
(caddr_t)&mc_curr, meta_back_conn_cmp );
/* Looks like we didn't get a bind. Open a new session... */
if ( mc == NULL ) {
mc = metaconn_alloc( op );
- mc->mc_conn = op->o_conn;
+ mc->mc_conn = mc_curr.mc_conn;
+ ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
new_conn = 1;
}
}
*/
( void )meta_clear_unused_candidates( op, i );
+ mt = &mi->mi_targets[ i ];
+ msc = &mc->mc_conns[ i ];
+
/*
* The target is activated; if needed, it is
* also init'd. In case of error, meta_back_init_one_conn
* sends the appropriate result.
*/
- err = meta_back_init_one_conn( op, rs, &mi->mi_targets[ i ],
- &mc->mc_conns[ i ], sendok );
+ err = meta_back_init_one_conn( op, rs, mt, msc, sendok );
if ( err != LDAP_SUCCESS ) {
/*
* FIXME: in case one target cannot
*/
candidates[ i ].sr_tag = META_NOT_CANDIDATE;
if ( new_conn ) {
- (void)meta_clear_one_candidate( &mc->mc_conns[ i ] );
+ (void)meta_clear_one_candidate( msc );
meta_back_freeconn( op, mc );
} else {
*candidate = i;
}
+ if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
+ ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+ ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
+ LDAP_BACK_CONN_ISPRIV_SET( msc );
+
+ } else {
+ BER_BVZERO( &msc->msc_cred );
+ BER_BVZERO( &msc->msc_bound_ndn );
+ if ( !BER_BVISEMPTY( &op->o_ndn )
+ && SLAP_IS_AUTHZ_BACKEND( op )
+ && i == mc->mc_authz_target )
+ {
+ ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
+ }
+ }
+
/*
* if no unique candidate ...
*/
/* Looks like we didn't get a bind. Open a new session... */
if ( mc == NULL ) {
mc = metaconn_alloc( op );
- mc->mc_conn = op->o_conn;
+ mc->mc_conn = mc_curr.mc_conn;
+ ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
new_conn = 1;
}
for ( i = 0; i < mi->mi_ntargets; i++ ) {
+ metatarget_t *mt = &mi->mi_targets[ i ];
+ metasingleconn_t *msc = &mc->mc_conns[ i ];
+
if ( i == cached
- || meta_back_is_candidate( &mi->mi_targets[ i ].mt_nsuffix,
- mi->mi_targets[ i ].mt_scope,
- &op->o_req_ndn, LDAP_SCOPE_SUBTREE ) )
+ || meta_back_is_candidate( &mt->mt_nsuffix,
+ mt->mt_scope,
+ &op->o_req_ndn,
+ LDAP_SCOPE_SUBTREE ) )
{
/*
* also init'd
*/
int lerr = meta_back_init_one_conn( op, rs,
- &mi->mi_targets[ i ],
- &mc->mc_conns[ i ], sendok );
+ mt, msc, sendok );
if ( lerr == LDAP_SUCCESS ) {
candidates[ i ].sr_tag = META_CANDIDATE;
candidates[ i ].sr_err = LDAP_SUCCESS;
ncandidates++;
+ if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
+ ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+ ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
+ LDAP_BACK_CONN_ISPRIV_SET( msc );
+
+ } else {
+ BER_BVZERO( &msc->msc_cred );
+ BER_BVZERO( &msc->msc_bound_ndn );
+ if ( !BER_BVISEMPTY( &op->o_ndn )
+ && SLAP_IS_AUTHZ_BACKEND( op )
+ && i == mc->mc_authz_target )
+ {
+ ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
+ }
+ }
+
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_init_one_conn(%d)\n",
op->o_log_prefix, i, 0 );
* be tried?
*/
if ( new_conn ) {
- ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
+ ( void )meta_clear_one_candidate( msc );
}
/* leave the target candidate, but record the error for later use */
candidates[ i ].sr_err = lerr;
} else {
if ( new_conn ) {
- ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
+ ( void )meta_clear_one_candidate( msc );
}
candidates[ i ].sr_tag = META_NOT_CANDIDATE;
}
if ( err != 0 ) {
Debug( LDAP_DEBUG_ANY,
"%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
- op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
+ op->o_log_prefix, ncandidates,
+ LDAP_BACK_PCONN_ID( mc->mc_conn ) );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "Internal server error";
Debug( LDAP_DEBUG_TRACE,
"%s meta_back_getconn: candidates=%d conn=%ld inserted\n",
- op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
+ op->o_log_prefix, ncandidates,
+ LDAP_BACK_PCONN_ID( mc->mc_conn ) );
} else {
Debug( LDAP_DEBUG_TRACE,
"%s meta_back_getconn: candidates=%d conn=%ld fetched\n",
- op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
+ op->o_log_prefix, ncandidates,
+ LDAP_BACK_PCONN_ID( mc->mc_conn ) );
}
return mc;
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1999-2005 The OpenLDAP Foundation.
- * Portions Copyright 2001-2003 Pierangelo Masarati.
- * Portions Copyright 1999-2003 Howard Chu.
- * 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>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by the Howard Chu for inclusion
- * in OpenLDAP Software and subsequently enhanced by Pierangelo
- * Masarati.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/socket.h>
-#include <ac/string.h>
-
-#include "slap.h"
-#include "../back-ldap/back-ldap.h"
-#include "back-meta.h"
-#include "lutil.h"
-
-/* return 0 IFF op_dn is a value in group_at (member) attribute
- * of entry with gr_dn AND that entry has an objectClass
- * value of group_oc (groupOfNames)
- */
-int
-meta_back_group(
- Backend *be,
- Connection *conn,
- Operation *op,
- Entry *target,
- struct berval *gr_ndn,
- struct berval *op_ndn,
- ObjectClass *group_oc,
- AttributeDescription *group_at
-)
-{
- struct metainfo *li = ( struct metainfo * )be->be_private;
- int rc = 1, candidate;
- Attribute *attr;
- AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
- LDAPMessage *result;
- char *gattr[ 2 ];
- char *filter = NULL, *ptr;
- LDAP *ld = NULL;
- struct berval mop_ndn = BER_BVNULL, mgr_ndn = BER_BVNULL;
-
- struct berval group_oc_name = BER_BVNULL;
- struct berval group_at_name = group_at->ad_cname;
-
- if ( group_oc->soc_names && group_oc->soc_names[ 0 ] ) {
- group_oc_name.bv_val = group_oc->soc_names[ 0 ];
- } else {
- group_oc_name.bv_val = group_oc->soc_oid;
- }
-
- if ( group_oc_name.bv_val ) {
- group_oc_name.bv_len = strlen( group_oc_name.bv_val );
- }
-
- if ( target != NULL && dn_match( &target->e_nname, gr_ndn ) ) {
- /* we already have a copy of the entry */
- /* attribute and objectclass mapping has already been done */
-
- /*
- * first we need to check if the objectClass attribute
- * has been retrieved; otherwise we need to repeat the search
- */
- attr = attr_find( target->e_attrs, ad_objectClass );
- if ( attr != NULL ) {
-
- /*
- * Now we can check for the group objectClass value
- */
- if ( !is_entry_objectclass( target, group_oc, 0 ) ) {
- return 1;
- }
-
- /*
- * This part has been reworked: the group attr compare
- * fails only if the attribute is PRESENT but the value
- * is NOT PRESENT; if the attribute is NOT PRESENT, the
- * search must be repeated as well.
- * This may happen if a search for an entry has already
- * been performed (target is not null) but the group
- * attribute has not been required
- */
- attr = attr_find( target->e_attrs, group_at );
- if ( attr != NULL ) {
- rc = value_find_ex( group_at,
- SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
- attr->a_vals, op_ndn );
- if ( rc != LDAP_SUCCESS ) {
- return 1;
- }
- return 0;
- } /* else: repeat the search */
- } /* else: repeat the search */
- } /* else: do the search */
-
- candidate = meta_back_select_unique_candidate( li, gr_ndn );
- if ( candidate == META_TARGET_NONE ) {
- goto cleanup;
- }
-
- /*
- * Rewrite the op ndn if needed
- */
- switch ( rewrite_session( li->targets[ candidate ]->rwinfo, "bindDn",
- op_ndn->bv_val, conn, &mop_ndn.bv_val ) ) {
- case REWRITE_REGEXEC_OK:
- if ( mop_ndn.bv_val != NULL && mop_ndn.bv_val[ 0 ] != '\0' ) {
- mop_ndn.bv_len = strlen( mop_ndn.bv_val );
- } else {
- mop_ndn = *op_ndn;
- }
- Debug( LDAP_DEBUG_ARGS,
- "rw> bindDn (op ndn in group):"
- " \"%s\" -> \"%s\"\n%s",
- op_ndn->bv_val, mop_ndn.bv_val, "" );
- break;
-
- case REWRITE_REGEXEC_UNWILLING:
- /* continues to next case */
-
- case REWRITE_REGEXEC_ERR:
- return 1;
- }
-
- /*
- * Rewrite the gr ndn if needed
- */
- switch ( rewrite_session( li->targets[ candidate ]->rwinfo,
- "searchBase",
- gr_ndn->bv_val, conn, &mgr_ndn.bv_val ) ) {
- case REWRITE_REGEXEC_OK:
- if ( mgr_ndn.bv_val != NULL && mgr_ndn.bv_val[ 0 ] != '\0' ) {
- mgr_ndn.bv_len = strlen( mgr_ndn.bv_val );
- } else {
- mgr_ndn = *gr_ndn;
- }
- Debug( LDAP_DEBUG_ARGS,
- "rw> searchBase (gr ndn in group):"
- " \"%s\" -> \"%s\"\n%s",
- gr_ndn->bv_val, mgr_ndn.bv_val, "" );
- break;
-
- case REWRITE_REGEXEC_UNWILLING:
- /* continues to next case */
-
- case REWRITE_REGEXEC_ERR:
- goto cleanup;
- }
-
- ldap_back_map( &li->targets[ candidate ]->oc_map,
- &group_oc_name, &group_oc_name, BACKLDAP_MAP );
- if ( group_oc_name.bv_val == NULL || group_oc_name.bv_val[0] == '\0' ) {
- goto cleanup;
- }
- ldap_back_map( &li->targets[ candidate ]->at_map,
- &group_at_name, &group_at_name, BACKLDAP_MAP );
- if ( group_at_name.bv_val == NULL || group_at_name.bv_val[0] == '\0' ) {
- goto cleanup;
- }
-
- filter = ch_malloc( sizeof( "(&(objectclass=)(=))" )
- + group_oc_name.bv_len
- + group_at_name.bv_len
- + mop_ndn.bv_len + 1 );
- if ( filter == NULL ) {
- goto cleanup;
- }
-
- rc = ldap_initialize( &ld, li->targets[ candidate ]->uri );
- if ( rc != LDAP_SUCCESS ) {
- goto cleanup;
- }
-
- rc = ldap_bind_s( ld, li->targets[ candidate ]->binddn.bv_val,
- li->targets[ candidate ]->bindpw.bv_val,
- LDAP_AUTH_SIMPLE );
- if ( rc != LDAP_SUCCESS ) {
- goto cleanup;
- }
-
- ptr = lutil_strcopy( filter, "(&(objectclass=" );
- ptr = lutil_strcopy( ptr , group_oc_name.bv_val );
- ptr = lutil_strcopy( ptr , ")(" );
- ptr = lutil_strcopy( ptr , group_at_name.bv_val );
- ptr = lutil_strcopy( ptr , "=" );
- ptr = lutil_strcopy( ptr , mop_ndn.bv_val );
- strcpy( ptr , "))" );
-
- gattr[ 0 ] = "objectclass";
- gattr[ 1 ] = NULL;
- rc = 1;
- if ( ldap_search_ext_s( ld, mgr_ndn.bv_val, LDAP_SCOPE_BASE, filter,
- gattr, 0, NULL, NULL, LDAP_NO_LIMIT,
- LDAP_NO_LIMIT, &result ) == LDAP_SUCCESS ) {
- if ( ldap_first_entry( ld, result ) != NULL ) {
- rc = 0;
- }
- ldap_msgfree( result );
- }
-
-cleanup:;
- if ( ld != NULL ) {
- ldap_unbind( ld );
- }
- if ( filter != NULL ) {
- ch_free( filter );
- }
- if ( mop_ndn.bv_val != op_ndn->bv_val ) {
- free( mop_ndn.bv_val );
- }
- if ( mgr_ndn.bv_val != gr_ndn->bv_val ) {
- free( mgr_ndn.bv_val );
- }
-
- return rc;
-}
-
meta_back_open(
BackendInfo *bi )
{
+ /* FIXME: need to remove the pagedResults, and likely more... */
bi->bi_controls = slap_known_controls;
+
return 0;
}
LDAPMessage *res = NULL, *e;
int rc = 0, sres = LDAP_SUCCESS;
char *matched = NULL;
- int i, last = 0, ncandidates = 0,
+ int last = 0, ncandidates = 0,
initial_candidates = 0, candidate_match = 0;
+ long i;
dncookie dc;
int is_ok = 0;
void *savepriv;
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
stoptime = op->o_time + op->ors_tlimit;
- tv.tv_sec = 0;
}
/*
sres = slap_map_api2result( rs );
snprintf( buf, sizeof( buf ),
- "%s meta_back_search[%d] "
- "match=\"%s\" err=%d\n",
+ "%s meta_back_search[%ld] "
+ "match=\"%s\" err=%ld\n",
op->o_log_prefix, i,
candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
- candidates[ i ].sr_err );
+ (long) candidates[ i ].sr_err );
Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 );
switch ( sres ) {
}
if ( gotit == 0 ) {
- tv.tv_sec = 0;
- tv.tv_usec = 100000; /* 0.1 s */
+ LDAP_BACK_TV_SET( &tv );
ldap_pvt_thread_yield();
} else {
* FIXME: only the last one gets caught!
*/
savepriv = op->o_private;
- op->o_private = (void *)mi->mi_ntargets;
+ op->o_private = (void *)(long)mi->mi_ntargets;
if ( candidate_match > 0 ) {
struct berval pmatched = BER_BVNULL;
Entry ent = { 0 };
BerElement ber = *e->lm_ber;
Attribute *attr, **attrp;
- struct berval *bv, bdn;
+ struct berval bdn,
+ dn = BER_BVNULL;
const char *text;
dncookie dc;
+ int rc;
if ( ber_scanf( &ber, "{m{", &bdn ) == LBER_ERROR ) {
return LDAP_DECODING_ERROR;
dc.rs = rs;
dc.ctx = "searchResult";
- rs->sr_err = ldap_back_dn_massage( &dc, &bdn, &ent.e_name );
+ rs->sr_err = ldap_back_dn_massage( &dc, &bdn, &dn );
if ( rs->sr_err != LDAP_SUCCESS) {
return rs->sr_err;
}
*
* FIXME: should we log anything, or delegate to dnNormalize?
*/
- if ( dnNormalize( 0, NULL, NULL, &ent.e_name, &ent.e_nname,
- op->o_tmpmemctx ) != LDAP_SUCCESS )
- {
+ rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname,
+ op->o_tmpmemctx );
+ if ( dn.bv_val != bdn.bv_val ) {
+ free( dn.bv_val );
+ }
+ BER_BVZERO( &dn );
+
+ if ( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_DN_SYNTAX;
}
if ( attr->a_desc == slap_schema.si_ad_objectClass
|| attr->a_desc == slap_schema.si_ad_structuralObjectClass )
{
+ struct berval *bv;
+
for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) {
ldap_back_map( &mi->mi_targets[ target ].mt_rwmap.rwm_oc,
bv, &mapped, BACKLDAP_REMAP );
&attr->a_vals[i] );
}
+ if ( rc ) {
+ LBER_FREE( attr->a_vals[i].bv_val );
+ if ( --last == i ) {
+ BER_BVZERO( &attr->a_vals[ i ] );
+ break;
+ }
+ attr->a_vals[i] = attr->a_vals[last];
+ BER_BVZERO( &attr->a_vals[last] );
+ i--;
+ continue;
+ }
+
if ( pretty ) {
LBER_FREE( attr->a_vals[i].bv_val );
attr->a_vals[i] = pval;
}
}
+
+ if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
+ attr_free( attr );
+ goto next_attr;
+ }
}
if ( last && attr->a_desc->ad_type->sat_equality &&
rs->sr_attrs = NULL;
if ( !BER_BVISNULL( &ent.e_name ) ) {
- if ( ent.e_name.bv_val != bdn.bv_val ) {
- free( ent.e_name.bv_val );
- }
+ free( ent.e_name.bv_val );
BER_BVZERO( &ent.e_name );
}
if ( !BER_BVISNULL( &ent.e_nname ) ) {
if ( mc ) {
Debug( LDAP_DEBUG_TRACE,
"=>meta_back_conn_destroy: destroying conn %ld\n",
- mc->mc_conn->c_connid, 0, 0 );
+ LDAP_BACK_PCONN_ID( mc->mc_conn ), 0, 0 );
assert( mc->mc_refcnt == 0 );
- /*
- * Cleanup rewrite session
- */
for ( i = 0; i < mi->mi_ntargets; ++i ) {
if ( mc->mc_conns[ i ].msc_ld != NULL ) {
meta_clear_one_candidate( &mc->mc_conns[ i ] );
struct entry_limbo_t *el_next;
} entry_limbo_t;
+int
+monitor_back_is_configured( void )
+{
+ return be_monitor != NULL;
+}
+
int
monitor_back_register_entry(
Entry *e,
monitor_callback_t *cb )
{
- monitor_info_t *mi = ( monitor_info_t * )be_monitor->be_private;
+ monitor_info_t *mi;
+
+ if ( be_monitor == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_back_register_entry(\"%s\"): "
+ "monitor database not configured.\n",
+ e->e_name.bv_val, 0, 0 );
+ return -1;
+ }
+
+ mi = ( monitor_info_t * )be_monitor->be_private;
assert( mi != NULL );
assert( e != NULL );
int scope,
struct berval *filter )
{
- monitor_info_t *mi = ( monitor_info_t * )be_monitor->be_private;
+ monitor_info_t *mi;
struct berval ndn = BER_BVNULL;
+ if ( be_monitor == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_back_register_entry_parent(base=\"%s\" scope=%s filter=\"%s\"): "
+ "monitor database not configured.\n",
+ BER_BVISNULL( base ) ? "" : base->bv_val,
+ scope == LDAP_SCOPE_BASE ? "base" : ( scope == LDAP_SCOPE_ONELEVEL ? "one" : "subtree" ),
+ BER_BVISNULL( filter ) ? "" : filter->bv_val );
+ return -1;
+ }
+
+ mi = ( monitor_info_t * )be_monitor->be_private;
+
assert( mi != NULL );
assert( e != NULL );
assert( e->e_private == NULL );
int scope,
struct berval *filter )
{
- monitor_info_t *mi = ( monitor_info_t * )be_monitor->be_private;
+ monitor_info_t *mi;
struct berval ndn = BER_BVNULL;
+ char *fname = ( a == NULL ? "callback" : "attrs" );
+
+ if ( be_monitor == NULL ) {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "monitor_back_register_entry_%s(base=\"%s\" scope=%s filter=\"%s\"): "
+ "monitor database not configured.\n",
+ fname,
+ BER_BVISNULL( base ) ? "" : base->bv_val,
+ scope == LDAP_SCOPE_BASE ? "base" : ( scope == LDAP_SCOPE_ONELEVEL ? "one" : "subtree" ),
+ BER_BVISNULL( filter ) ? "" : filter->bv_val );
+ Debug( LDAP_DEBUG_ANY, "%s\n", buf, 0, 0 );
+
+ return -1;
+ }
+
+ mi = ( monitor_info_t * )be_monitor->be_private;
assert( mi != NULL );
{
/* need a filter */
Debug( LDAP_DEBUG_ANY,
- "monitor_back_register_entry_*(\"\"): "
+ "monitor_back_register_entry_%s(\"\"): "
"need a valid filter\n",
- 0, 0, 0 );
+ fname, 0, 0 );
return -1;
}
if ( BER_BVISNULL( &ndn ) ) {
if ( monitor_filter2ndn( base, scope, filter, &ndn ) ) {
- /* entry does not exist */
- Debug( LDAP_DEBUG_ANY,
- "monitor_back_register_entry_*(\"\"): "
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "monitor_back_register_entry_%s(\"\"): "
"base=%s scope=%d filter=%s : "
"unable to find entry\n",
+ fname,
base->bv_val ? base->bv_val : "\"\"",
scope, filter->bv_val );
+
+ /* entry does not exist */
+ Debug( LDAP_DEBUG_ANY, "%s\n", buf, 0, 0 );
return -1;
}
if ( monitor_cache_get( mi, &ndn, &e ) != 0 ) {
/* entry does not exist */
Debug( LDAP_DEBUG_ANY,
- "monitor_back_register_entry_*(\"%s\"): "
+ "monitor_back_register_entry_%s(\"%s\"): "
"entry does not exist\n",
- ndn.bv_val, 0, 0 );
+ fname, ndn.bv_val, 0 );
rc = -1;
goto done;
}
if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
/* entry is volatile; cannot append callback */
Debug( LDAP_DEBUG_ANY,
- "monitor_back_register_entry_*(\"%s\"): "
+ "monitor_back_register_entry_%s(\"%s\"): "
"entry is volatile\n",
- e->e_name.bv_val, 0, 0 );
+ fname, e->e_name.bv_val, 0 );
rc = -1;
goto done;
}
*atp = attrs_dup( a );
if ( *atp == NULL ) {
Debug( LDAP_DEBUG_ANY,
- "monitor_back_register_entry_*(\"%s\"): "
+ "monitor_back_register_entry_%s(\"%s\"): "
"attrs_dup() failed\n",
- e->e_name.bv_val, 0, 0 );
+ fname, e->e_name.bv_val, 0 );
rc = -1;
goto done;
}
struct berval *ndn,
int sub ));
extern int
+monitor_back_is_configured LDAP_P(( void ));
+extern int
monitor_back_register_entry LDAP_P((
Entry *e,
monitor_callback_t *cb ));
BackendInfo *bd
)
{
- ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
-
perl_destruct(PERL_INTERPRETER);
-
- ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
-
- return 0;
-}
-
-int
-perl_back_destroy(
- BackendInfo *bd
-)
-{
perl_free(PERL_INTERPRETER);
PERL_INTERPRETER = NULL;
BackendInfo *bi
)
{
- char *embedding[] = { "", "-e", "0" };
-
- Debug( LDAP_DEBUG_TRACE, "perl backend open\n", 0, 0, 0 );
-
- if( PERL_INTERPRETER != NULL ) {
- Debug( LDAP_DEBUG_ANY, "perl backend open: already opened\n",
- 0, 0, 0 );
- return 1;
- }
-
- PERL_INTERPRETER = perl_alloc();
- perl_construct(PERL_INTERPRETER);
- perl_parse(PERL_INTERPRETER, perl_back_xs_init, 3, embedding, (char **)NULL);
- perl_run(PERL_INTERPRETER);
-
bi->bi_open = perl_back_open;
bi->bi_config = 0;
bi->bi_close = perl_back_close;
- bi->bi_destroy = perl_back_destroy;
+ bi->bi_destroy = 0;
bi->bi_db_init = perl_back_db_init;
bi->bi_db_config = perl_back_db_config;
BackendInfo *bi
)
{
+ char *embedding[] = { "", "-e", "0" };
+
+ Debug( LDAP_DEBUG_TRACE, "perl backend open\n", 0, 0, 0 );
+
+ if( PERL_INTERPRETER != NULL ) {
+ Debug( LDAP_DEBUG_ANY, "perl backend open: already opened\n",
+ 0, 0, 0 );
+ return 1;
+ }
+
ldap_pvt_thread_mutex_init( &perl_interpreter_mutex );
+
+ PERL_INTERPRETER = perl_alloc();
+ perl_construct(PERL_INTERPRETER);
+ perl_parse(PERL_INTERPRETER, perl_back_xs_init, 3, embedding, (char **)NULL);
+ perl_run(PERL_INTERPRETER);
return 0;
}
extern BI_open perl_back_open;
extern BI_close perl_back_close;
-extern BI_destroy perl_back_destroy;
extern BI_db_init perl_back_db_init;
extern BI_db_open perl_back_db_open;
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_add_attr(): "
- "error binding output parameter for %s[%d]\n",
+ "error binding output parameter for %s[%lu]\n",
at_rec->bam_ad->ad_cname.bv_val, i, 0 );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_add_attr(): "
- "error binding keyval parameter for %s[%d]\n",
+ "error binding keyval parameter for %s[%lu]\n",
at_rec->bam_ad->ad_cname.bv_val, i, 0 );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_add_attr(): "
- "error binding value parameter for %s[%d]\n",
+ "error binding value parameter for %s[%lu]\n",
at_rec->bam_ad->ad_cname.bv_val, i, 0 );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
}
Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
- "number of values in query: %d\n", count, 0, 0 );
+ "number of values in query: %lu\n", count, 0, 0 );
SQLFreeStmt( sth, SQL_DROP );
if ( count == 0 ) {
return 1;
BACKSQL_SUCCESS( rc );
rc = SQLFetch( sth ), k++ )
{
- for ( i = 0; i < row.ncols; i++ ) {
+ for ( i = 0; i < (unsigned long)row.ncols; i++ ) {
if ( row.value_len[ i ] > 0 ) {
struct berval bv;
* but we're accepting the attributes;
* should we fail at all? */
snprintf( buf, sizeof( buf ),
- "unable to %s value #%d "
+ "unable to %s value #%lu "
"of AttributeDescription %s",
pretty ? "prettify" : "validate",
- at->bam_ad->ad_cname.bv_val,
- k - oldcount );
+ k - oldcount,
+ at->bam_ad->ad_cname.bv_val );
Debug( LDAP_DEBUG_TRACE,
"==>backsql_get_attr_vals(\"%s\"): "
"%s (%d)\n",
* but we're accepting the attributes;
* should we fail at all? */
snprintf( buf, sizeof( buf ),
- "unable to normalize value #%d "
+ "unable to normalize value #%lu "
"of AttributeDescription %s",
- at->bam_ad->ad_cname.bv_val,
- k - oldcount );
+ k - oldcount,
+ at->bam_ad->ad_cname.bv_val );
Debug( LDAP_DEBUG_TRACE,
"==>backsql_get_attr_vals(\"%s\"): "
"%s (%d)\n",
/* note: works only with 32 bit architectures... */
snprintf( uuidbuf, sizeof( uuidbuf ),
"%08x-%04x-%04x-0000-000000000000",
- ( id->eid_oc_id & 0xFFFFFFFF ),
- ( ( id->eid_keyval & 0xFFFF0000 ) >> 020 /* 16 */ ),
- ( id->eid_keyval & 0xFFFF ) );
+ ( (unsigned)id->eid_oc_id & 0xFFFFFFFF ),
+ ( ( (unsigned)id->eid_keyval & 0xFFFF0000 ) >> 020 /* 16 */ ),
+ ( (unsigned)id->eid_keyval & 0xFFFF ) );
#endif /* ! BACKSQL_ARBITRARY_KEY */
uuid.bv_val = uuidbuf;
}
acl_destroy( bd->be_acl, frontendDB->be_acl );
- assert( bd->be_replogfile == NULL );
+ if ( bd->be_replogfile != NULL ) {
+ free( bd->be_replogfile );
+ }
assert( bd->be_replica == NULL );
}
int rw,
Entry **e )
{
- int rc;
-
*e = NULL;
- if (op->o_bd == NULL) {
- rc = LDAP_NO_SUCH_OBJECT;
- } else if ( op->o_bd->be_fetch ) {
- rc = ( op->o_bd->be_fetch )( op, ndn,
- oc, at, rw, e );
- } else {
- rc = LDAP_UNWILLING_TO_PERFORM;
+ if ( op->o_bd == NULL ) {
+ return LDAP_NO_SUCH_OBJECT;
}
- return rc;
+
+ if ( op->o_bd->be_fetch ) {
+ return op->o_bd->be_fetch( op, ndn, oc, at, rw, e );
+ }
+
+ return LDAP_UNWILLING_TO_PERFORM;
}
int
if (slapMode & SLAP_TOOL_MODE) {
for (i = 0; i<gi->gi_nodes; i++) {
same = 0;
- /* Same type as our main backend? */
- if ( gi->gi_n[i].gn_be->bd_info == on->on_info->oi_orig )
+ /* Same bi_open as our main backend? */
+ if ( gi->gi_n[i].gn_be->bd_info->bi_open ==
+ on->on_info->oi_orig->bi_open )
bsame = 1;
/* Loop thru the bd_info's and make sure we only
* invoke their bi_open functions once each.
*/
for ( j = 0; j<i; j++ ) {
- if ( gi->gi_n[i].gn_be->bd_info ==
- gi->gi_n[j].gn_be->bd_info ) {
+ if ( gi->gi_n[i].gn_be->bd_info->bi_open ==
+ gi->gi_n[j].gn_be->bd_info->bi_open ) {
same = 1;
break;
}
{
slap_overinst *on = (slap_overinst *)be->bd_info;
slap_overinfo *oi = on->on_info;
+ BackendInfo *bi = oi->oi_orig;
glueinfo *gi;
gi = ch_calloc( 1, sizeof(glueinfo));
oi->oi_bi.bi_entry_release_rw = glue_entry_release_rw;
- oi->oi_bi.bi_tool_entry_open = glue_tool_entry_open;
- oi->oi_bi.bi_tool_entry_close = glue_tool_entry_close;
- oi->oi_bi.bi_tool_entry_first = glue_tool_entry_first;
- oi->oi_bi.bi_tool_entry_next = glue_tool_entry_next;
- oi->oi_bi.bi_tool_entry_get = glue_tool_entry_get;
- oi->oi_bi.bi_tool_entry_put = glue_tool_entry_put;
- oi->oi_bi.bi_tool_entry_reindex = glue_tool_entry_reindex;
- oi->oi_bi.bi_tool_sync = glue_tool_sync;
+ /* Only advertise these if the root DB supports them */
+ if ( bi->bi_tool_entry_open )
+ oi->oi_bi.bi_tool_entry_open = glue_tool_entry_open;
+ if ( bi->bi_tool_entry_close )
+ oi->oi_bi.bi_tool_entry_close = glue_tool_entry_close;
+ if ( bi->bi_tool_entry_first )
+ oi->oi_bi.bi_tool_entry_first = glue_tool_entry_first;
+ if ( bi->bi_tool_entry_next )
+ oi->oi_bi.bi_tool_entry_next = glue_tool_entry_next;
+ if ( bi->bi_tool_entry_get )
+ oi->oi_bi.bi_tool_entry_get = glue_tool_entry_get;
+ if ( bi->bi_tool_entry_put )
+ oi->oi_bi.bi_tool_entry_put = glue_tool_entry_put;
+ if ( bi->bi_tool_entry_reindex )
+ oi->oi_bi.bi_tool_entry_reindex = glue_tool_entry_reindex;
+ if ( bi->bi_tool_sync )
+ oi->oi_bi.bi_tool_sync = glue_tool_sync;
/*FIXME : need to add support */
oi->oi_bi.bi_tool_dn2id_get = 0;
/* Find the top backend for this subordinate */
be = b0;
- while ( be=LDAP_STAILQ_NEXT( be, be_next )) {
+ while ( (be=LDAP_STAILQ_NEXT( be, be_next )) != NULL ) {
slap_overinfo *oi;
slap_overinst *on;
glueinfo *gi;
static glue_Addrec *ga_list;
/* Attach all the subordinate backends to their superior */
-static int
+int
glue_sub_attach()
{
glue_Addrec *ga, *gnext = NULL;
/* Find the top backend for this subordinate */
be = ga->ga_be;
- while ( be=LDAP_STAILQ_NEXT( be, be_next )) {
+ while ( (be=LDAP_STAILQ_NEXT( be, be_next )) != NULL ) {
slap_overinfo *oi;
slap_overinst *on;
glueinfo *gi;
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_ADVERTISE;
ga = ch_malloc( sizeof( glue_Addrec ));
- ga->ga_next = NULL;
+ ga->ga_next = ga_list;
ga->ga_be = be;
- if ( ga_list ) {
- glue_Addrec *g2 = ga_list;
-
- for ( ; g2 && g2->ga_next; g2=g2->ga_next );
- g2->ga_next = ga;
- } else {
- ga_list = ga;
- }
+ ga_list = ga;
if ( online )
rc = glue_sub_attach();
glue.on_bi.bi_chk_referrals = glue_chk_referrals;
glue.on_bi.bi_chk_controls = glue_chk_controls;
- rc = overlay_register( &glue );
- if ( rc ) return rc;
-
- return glue_sub_attach();
+ return overlay_register( &glue );
}
"SUP labeledURI SINGLE-VALUE )", NULL, NULL },
{ "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
&config_replica, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
- "SUP labeledURI )", NULL, NULL },
+ "SUP labeledURI X-ORDERED 'VALUES' )", NULL, NULL },
{ "replica-argsfile", NULL, 0, 0, 0, ARG_STRING,
&replica_argsFile, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
}
if( op->o_bd->be_bind ) {
+ op->o_conn->c_authz_cookie = NULL;
+
rs->sr_err = (op->o_bd->be_bind)( op, rs );
if ( rs->sr_err == 0 ) {
if( size == 0 ) {
ch_free( block );
+ return NULL;
}
ctx = slap_sl_context( block );
static int fp_parse_line(ConfigArgs *c);
static char *strtok_quote(char *line, char *sep, char **quote_ptr);
+static char *strtok_quote_ldif(char **line);
ConfigArgs *
new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **argv )
c->log, c->msg, 0);
return(ARG_BAD_CONF);
}
- ptr = (void *)((char *)ptr + (int)Conf->arg_item);
+ ptr = (void *)((char *)ptr + (long)Conf->arg_item);
} else if (arg_type & ARGS_POINTER) {
ptr = Conf->arg_item;
}
ptr = c->bi->bi_private;
else
return 1;
- ptr = (void *)((char *)ptr + (int)cf->arg_item);
+ ptr = (void *)((char *)ptr + (long)cf->arg_item);
} else {
ptr = cf->arg_item;
}
return 0;
}
+/* Split an LDIF line into space-separated tokens. Words may be grouped
+ * by quotes. A quoted string may begin in the middle of a word, but must
+ * end at the end of the word (be followed by whitespace or EOS). Any other
+ * quotes are passed through unchanged. All other characters are passed
+ * through unchanged.
+ */
+static char *
+strtok_quote_ldif( char **line )
+{
+ char *beg, *ptr, *quote=NULL;
+ int inquote=0;
+
+ ptr = *line;
+
+ if ( !ptr || !*ptr )
+ return NULL;
+
+ while( isspace( *ptr )) ptr++;
+
+ if ( *ptr == '"' ) {
+ inquote = 1;
+ ptr++;
+ }
+
+ beg = ptr;
+
+ for (;*ptr;ptr++) {
+ if ( *ptr == '"' ) {
+ if ( inquote && ( !ptr[1] || isspace(ptr[1]))) {
+ *ptr++ = '\0';
+ break;
+ }
+ inquote = 1;
+ quote = ptr;
+ continue;
+ }
+ if ( inquote )
+ continue;
+ if ( isspace( *ptr )) {
+ *ptr++ = '\0';
+ break;
+ }
+ }
+ if ( quote ) {
+ while ( quote < ptr ) {
+ *quote = quote[1];
+ quote++;
+ }
+ }
+ if ( !*ptr ) {
+ *line = NULL;
+ } else {
+ while ( isspace( *ptr )) ptr++;
+ *line = ptr;
+ }
+ return beg;
+}
+
+static void
+config_parse_ldif( ConfigArgs *c )
+{
+ char *next;
+ c->tline = ch_strdup(c->line);
+ next = c->tline;
+
+ while ((c->argv[c->argc] = strtok_quote_ldif( &next )) != NULL) {
+ c->argc++;
+ if ( c->argc >= c->argv_size ) {
+ char **tmp = ch_realloc( c->argv, (c->argv_size + ARGS_STEP) *
+ sizeof( *c->argv ));
+ c->argv = tmp;
+ c->argv_size += ARGS_STEP;
+ }
+ }
+ c->argv[c->argc] = NULL;
+}
+
int
config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
{
int rc = 0;
- char *saveline = NULL;
snprintf( c->log, sizeof( c->log ), "%s: value #%d",
ct->ad->ad_cname.bv_val, valx );
c->argv[0] = ct->ad->ad_cname.bv_val;
if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
- ber_len_t len;
-
- saveline = c->line;
- len = strlen( c->line );
- c->line = ch_malloc( len + STRLENOF( "\"\"" ) + 1 );
- sprintf( c->line, "\"%s\"", saveline );
- }
-
- if ( fp_parse_line( c ) ) {
- rc = 1;
+ c->argv[c->argc] = c->line;
+ c->argc++;
+ c->argv[c->argc] = NULL;
+ c->tline = NULL;
} else {
- rc = config_check_vals( ct, c, 1 );
- }
-
- if ( saveline ) {
- ch_free( c->line );
- c->line = saveline;
+ config_parse_ldif( c );
}
+ rc = config_check_vals( ct, c, 1 );
+ ch_free( c->tline );
if ( rc )
rc = LDAP_CONSTRAINT_VIOLATION;
- ch_free( c->tline );
return rc;
}
config_parse_add(ConfigTable *ct, ConfigArgs *c)
{
int rc = 0;
- char *saveline = NULL;
snprintf( c->log, sizeof( c->log ), "%s: value #%d",
ct->ad->ad_cname.bv_val, c->valx );
c->argv[0] = ct->ad->ad_cname.bv_val;
if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
- ber_len_t len;
-
- saveline = c->line;
- len = strlen( c->line );
-
- c->line = ch_malloc( len + STRLENOF( "\"\"" ) + 1 );
- sprintf( c->line, "\"%s\"", saveline );
- }
-
- if ( fp_parse_line( c ) ) {
- rc = 1;
+ c->argv[c->argc] = c->line;
+ c->argc++;
+ c->argv[c->argc] = NULL;
+ c->tline = NULL;
} else {
- c->op = LDAP_MOD_ADD;
- rc = config_add_vals( ct, c );
- }
-
- if ( saveline ) {
- ch_free( c->line );
- c->line = saveline;
+ config_parse_ldif( c );
}
-
+ c->op = LDAP_MOD_ADD;
+ rc = config_add_vals( ct, c );
ch_free( c->tline );
+
return rc;
}
return rs->sr_err;
}
+int
+slap_remove_control(
+ Operation *op,
+ SlapReply *rs,
+ int ctrl,
+ BI_chk_controls fnc )
+{
+ int i, j;
+
+ switch ( op->o_ctrlflag[ ctrl ] ) {
+ case SLAP_CONTROL_NONCRITICAL:
+ for ( i = 0, j = -1; op->o_ctrls[ i ] != NULL; i++ ) {
+ if ( strcmp( op->o_ctrls[ i ]->ldctl_oid, slap_known_controls[ ctrl - 1 ] ) == 0 )
+ {
+ j = i;
+ }
+ }
+
+ if ( j == -1 ) {
+ rs->sr_err = LDAP_OTHER;
+ break;
+ }
+
+ if ( fnc ) {
+ (void)fnc( op, rs );
+ }
+
+ op->o_tmpfree( op->o_ctrls[ j ], op->o_tmpmemctx );
+
+ if ( i > 1 ) {
+ AC_MEMCPY( &op->o_ctrls[ j ], &op->o_ctrls[ j + 1 ],
+ ( i - j ) * sizeof( LDAPControl * ) );
+
+ } else {
+ op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
+ op->o_ctrls = NULL;
+ }
+
+ op->o_ctrlflag[ ctrl ] = SLAP_CONTROL_IGNORED;
+
+ Debug( LDAP_DEBUG_ANY, "%s: "
+ "non-critical control \"%s\" not supported; stripped.\n",
+ op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
+ /* fall thru */
+
+ case SLAP_CONTROL_IGNORED:
+ case SLAP_CONTROL_NONE:
+ rs->sr_err = SLAP_CB_CONTINUE;
+ break;
+
+ case SLAP_CONTROL_CRITICAL:
+ rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+ if ( fnc ) {
+ (void)fnc( op, rs );
+ }
+ Debug( LDAP_DEBUG_ANY, "%s: "
+ "critical control \"%s\" not supported.\n",
+ op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
+ break;
+
+ default:
+ /* handle all cases! */
+ assert( 0 );
+ }
+
+ return rs->sr_err;
+}
+
#ifdef LDAP_DEVEL
static int parseManageDIT (
Operation *op,
goto done;
}
-#if 0
- /* defer cookie decoding/checks to backend... */
- if ( cookie.bv_len ) {
- PagedResultsCookie reqcookie;
- if( cookie.bv_len != sizeof( reqcookie ) ) {
- /* bad cookie */
- rs->sr_text = "paged results cookie is invalid";
- rc = LDAP_PROTOCOL_ERROR;
- goto done;
- }
-
- AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
-
- if ( reqcookie > op->o_pagedresults_state.ps_cookie ) {
- /* bad cookie */
- rs->sr_text = "paged results cookie is invalid";
- rc = LDAP_PROTOCOL_ERROR;
- goto done;
-
- } else if ( reqcookie < op->o_pagedresults_state.ps_cookie ) {
- rs->sr_text = "paged results cookie is invalid or old";
- rc = LDAP_UNWILLING_TO_PERFORM;
- goto done;
- }
-
- } else {
- /* Initial request. Initialize state. */
-#if 0
- if ( op->o_conn->c_pagedresults_state.ps_cookie != 0 ) {
- /* There's another pagedResults control on the
- * same connection; reject new pagedResults controls
- * (allowed by RFC2696) */
- rs->sr_text = "paged results cookie unavailable; try later";
- rc = LDAP_UNWILLING_TO_PERFORM;
- goto done;
- }
-#endif
- op->o_pagedresults_state.ps_cookie = 0;
- op->o_pagedresults_state.ps_count = 0;
- }
-#endif
-
ps = op->o_tmpalloc( sizeof(PagedResultsState), op->o_tmpmemctx );
*ps = op->o_conn->c_pagedresults_state;
ps->ps_size = size;
ber_socket_t i;
int ns, nwriters;
int at;
- ber_socket_t nfds, nrfds, nwfds;
+ ber_socket_t nfds;
+#if SLAP_EVENTS_ARE_INDEXED
+ ber_socket_t nrfds, nwfds;
+#endif
#define SLAPD_EBADF_LIMIT 16
time_t now;
#endif
) continue;
+ /* Don't log internal wake events */
+ if ( SLAP_EVENT_FD( i ) == wake_sds[0] )
+ continue;
+
r = SLAP_EVENT_IS_READ( i );
w = SLAP_EVENT_IS_WRITE( i );
if ( r || w ) {
if ( rc ) {
fd = SLAP_EVENT_FD( i );
+ /* Ignore wake events, they were handled above */
+ if ( fd == wake_sds[0] )
+ continue;
+
if( SLAP_EVENT_IS_WRITE( i ) ) {
Debug( LDAP_DEBUG_CONNS,
"daemon: write active on %d\n",
rc = slap_bv2ad( &ava->la_attr, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
- return LDAP_INVALID_SYNTAX;
+ rc = slap_bv2undef_ad( &ava->la_attr,
+ &ad, &text,
+ SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
}
ava->la_private = ( void * )ad;
rc = slap_bv2ad( &ava->la_attr, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
- return LDAP_INVALID_SYNTAX;
+ rc = slap_bv2undef_ad( &ava->la_attr,
+ &ad, &text,
+ SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
}
ava->la_private = ( void * )ad;
rc = slap_bv2ad( &ava->la_attr, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
- return LDAP_INVALID_SYNTAX;
+ rc = slap_bv2undef_ad( &ava->la_attr,
+ &ad, &text,
+ SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
}
ava->la_private = ( void * )ad;
rc = slap_bv2ad( &ava->la_attr, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
- return LDAP_INVALID_SYNTAX;
+ rc = slap_bv2undef_ad( &ava->la_attr,
+ &ad, &text,
+ SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
}
ava->la_private = ( void * )ad;
/*
* We can assume the input is a prettied or normalized DN
*/
-int
+ber_len_t
dn_rdnlen(
Backend *be,
struct berval *dn_in )
return 1;
}
+ if ( glue_sub_init() ) {
+ ldap_debug |= 1;
+ Debug( LDAP_DEBUG_ANY,
+ "%s: glue/subordinate init failed\n",
+ name, 0, 0 );
+
+ return 1;
+ }
+
if ( acl_init() ) {
ldap_debug |= 1;
Debug( LDAP_DEBUG_ANY,
}
}
- if ( glue_sub_init( ) != 0 ) {
+ if ( glue_sub_attach( ) != 0 ) {
Debug( LDAP_DEBUG_ANY,
"subordinate config error\n",
0, 0, 0 );
mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
mod->sml_op = mop;
mod->sml_flags = SLAP_MOD_INTERNAL;
+ mod->sml_next = NULL;
BER_BVZERO( &mod->sml_type );
mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
mod->sml_values =
mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
mod->sml_op = mop;
mod->sml_flags = SLAP_MOD_INTERNAL;
+ mod->sml_next = NULL;
BER_BVZERO( &mod->sml_type );
mod->sml_desc = slap_schema.si_ad_entryUUID;
mod->sml_values =
mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
mod->sml_op = mop;
mod->sml_flags = SLAP_MOD_INTERNAL;
+ mod->sml_next = NULL;
BER_BVZERO( &mod->sml_type );
mod->sml_desc = slap_schema.si_ad_creatorsName;
mod->sml_values =
mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
mod->sml_op = mop;
mod->sml_flags = SLAP_MOD_INTERNAL;
+ mod->sml_next = NULL;
BER_BVZERO( &mod->sml_type );
mod->sml_desc = slap_schema.si_ad_createTimestamp;
mod->sml_values =
mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
mod->sml_op = mop;
mod->sml_flags = SLAP_MOD_INTERNAL;
+ mod->sml_next = NULL;
BER_BVZERO( &mod->sml_type );
mod->sml_desc = slap_schema.si_ad_entryCSN;
mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
mod->sml_op = mop;
mod->sml_flags = SLAP_MOD_INTERNAL;
+ mod->sml_next = NULL;
BER_BVZERO( &mod->sml_type );
mod->sml_desc = slap_schema.si_ad_modifiersName;
mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
mod->sml_op = mop;
mod->sml_flags = SLAP_MOD_INTERNAL;
+ mod->sml_next = NULL;
BER_BVZERO( &mod->sml_type );
mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
static int
oc_create_required(
- ObjectClass *soc,
- char **attrs,
+ ObjectClass *soc,
+ char **attrs,
int *op,
- const char **err )
+ const char **err )
{
char **attrs1;
AttributeType *sat;
}
/* Now delete duplicates from the allowed list */
for ( satp = soc->soc_required; *satp; satp++ ) {
- i = at_find_in_list(*satp,soc->soc_allowed);
+ i = at_find_in_list(*satp, soc->soc_allowed);
if ( i >= 0 ) {
at_delete_from_list(i, &soc->soc_allowed);
}
static int
oc_add_sups(
- ObjectClass *soc,
- char **sups,
+ ObjectClass *soc,
+ char **sups,
int *op,
- const char **err )
+ const char **err )
{
int code;
ObjectClass *soc1;
code = oc_add_sups( soc, soc->soc_sup_oids, &op, err );
}
- if ( code != 0 ) return code;
- if( user && op ) return SLAP_SCHERR_CLASS_BAD_SUP;
+ if ( code != 0 ) {
+ goto done;
+ }
+
+ if ( user && op ) {
+ code = SLAP_SCHERR_CLASS_BAD_SUP;
+ goto done;
+ }
code = oc_create_required( soc, soc->soc_at_oids_must, &op, err );
- if ( code != 0 ) return code;
+ if ( code != 0 ) {
+ goto done;
+ }
code = oc_create_allowed( soc, soc->soc_at_oids_may, &op, err );
- if ( code != 0 ) return code;
+ if ( code != 0 ) {
+ goto done;
+ }
- if( user && op ) return SLAP_SCHERR_CLASS_BAD_USAGE;
+ if ( user && op ) {
+ code = SLAP_SCHERR_CLASS_BAD_USAGE;
+ goto done;
+ }
- if( !user ) soc->soc_flags |= SLAP_OC_HARDCODE;
+ if ( !user ) {
+ soc->soc_flags |= SLAP_OC_HARDCODE;
+ }
code = oc_insert(soc,err);
- if ( code == 0 && rsoc )
+done:;
+ if ( code != 0 ) {
+ if ( soc->soc_sups ) {
+ ch_free( soc->soc_sups );
+ }
+
+ if ( soc->soc_required ) {
+ ch_free( soc->soc_required );
+ }
+
+ if ( soc->soc_allowed ) {
+ ch_free( soc->soc_allowed );
+ }
+
+ ch_free( soc );
+
+ } else if ( rsoc ) {
*rsoc = soc;
+ }
return code;
}
int li_age;
int li_cycle;
struct re_s *li_task;
+ int li_success;
} log_info;
static ConfigDriver log_cf_gen;
enum {
LOG_DB = 1,
LOG_OPS,
- LOG_PURGE
+ LOG_PURGE,
+ LOG_SUCCESS
};
static ConfigTable log_cfats[] = {
log_cf_gen, "( OLcfgOvAt:4.3 NAME 'olcAccessLogPurge' "
"DESC 'Log cleanup parameters' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "logsuccess", NULL, 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LOG_SUCCESS,
+ log_cf_gen, "( OLcfgOvAt:4.4 NAME 'olcAccessLogSuccess' "
+ "DESC 'Log successful ops only' "
+ "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ NULL }
};
"DESC 'Access log configuration' "
"SUP olcOverlayConfig "
"MUST olcAccessLogDB "
- "MAY ( olcAccessLogOps $ olcAccessLogPurge ) )",
+ "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess ) )",
Cft_Overlay, log_cfats },
{ NULL }
};
"SYNTAX OMsInteger "
"SINGLE-VALUE )", &ad_reqResult },
{ "( " LOG_SCHEMA_AT ".7 NAME 'reqAuthzID' "
- "DESC 'AUthorization ID of requestor' "
+ "DESC 'Authorization ID of requestor' "
"EQUALITY distinguishedNameMatch "
"SYNTAX OMsDN "
"SINGLE-VALUE )", &ad_reqAuthzID },
agebv.bv_len += cyclebv.bv_len;
value_add_one( &c->rvalue_vals, &agebv );
break;
+ case LOG_SUCCESS:
+ if ( li->li_success )
+ c->value_int = li->li_success;
+ else
+ rc = 1;
+ break;
}
break;
case LDAP_MOD_DELETE:
li->li_age = 0;
li->li_cycle = 0;
break;
+ case LOG_SUCCESS:
+ li->li_success = 0;
+ break;
}
break;
default:
}
}
break;
+ case LOG_SUCCESS:
+ li->li_success = c->value_int;
+ break;
}
break;
}
struct berval bv;
char *ptr;
BerVarray vals;
- Operation op2;
+ Operation op2 = {0};
SlapReply rs2 = {REP_RESULT};
if ( rs->sr_type != REP_RESULT && rs->sr_type != REP_EXTENDED )
return SLAP_CB_CONTINUE;
+ if ( li->li_success && rs->sr_err != LDAP_SUCCESS )
+ return SLAP_CB_CONTINUE;
+
switch ( op->o_tag ) {
case LDAP_REQ_ADD: logop = LOG_EN_ADD; break;
case LDAP_REQ_DELETE: logop = LOG_EN_DELETE; break;
op2.ora_e = e;
op2.o_callback = &nullsc;
+ if ( lo->mask & LOG_OP_WRITES ) {
+ slap_get_commit_csn( op, NULL, &bv );
+ attr_merge_one( e, slap_schema.si_ad_entryCSN, &bv, NULL );
+ slap_queue_csn( &op2, &bv );
+ }
+
op2.o_bd->be_add( &op2, &rs2 );
+ slap_graduate_commit_csn( &op2 );
entry_free( e );
return SLAP_CB_CONTINUE;
SlapReply rs2 = {REP_RESULT};
Entry *e;
+ if ( !( li->li_ops & LOG_OP_UNBIND ))
+ return SLAP_CB_CONTINUE;
+
e = accesslog_entry( op, LOG_EN_UNBIND );
op2.o_hdr = op->o_hdr;
op2.o_tag = LDAP_REQ_ADD;
char buf[64];
struct berval bv;
- if ( !op->o_time )
+ if ( !op->o_time || !( li->li_ops & LOG_OP_ABANDON ))
return SLAP_CB_CONTINUE;
e = accesslog_entry( op, LOG_EN_ABANDON );
}
}
+/* NOTE: this is a quick workaround to let pcache minimally interact
+ * with pagedResults. A more articulated solutions would be to
+ * perform the remote query without control and cache all results,
+ * performing the pagedResults search only within the client
+ * and the proxy. This requires pcache to understand pagedResults. */
+static int
+proxy_cache_chk_controls(
+ Operation *op,
+ SlapReply *rs )
+{
+ const char *non = "";
+ const char *stripped = "";
+
+ switch( op->o_pagedresults ) {
+ case SLAP_CONTROL_NONCRITICAL:
+ non = "non-";
+ stripped = "; stripped";
+ /* fallthru */
+
+ case SLAP_CONTROL_CRITICAL:
+ Debug( LDAP_DEBUG_ANY, "%s: "
+ "%scritical pagedResults control "
+ "disabled with proxy cache%s.\n",
+ op->o_log_prefix, non, stripped );
+
+ slap_remove_control( op, rs, slap_cids.sc_pagedResults, NULL );
+ break;
+
+ default:
+ rs->sr_err = SLAP_CB_CONTINUE;
+ break;
+ }
+
+ return rs->sr_err;
+}
+
static int
proxy_cache_search(
Operation *op,
Debug( LDAP_DEBUG_ANY, "query template of incoming query = %s\n",
tempstr.bv_val, 0, 0 );
+ /* FIXME: cannot cache/answer requests with pagedResults control */
+
+
/* find attr set */
attr_set = get_attr_set(op->ors_attrs, qm, cm->numattrsets);
proxy_cache.on_bi.bi_db_destroy = proxy_cache_destroy;
proxy_cache.on_bi.bi_op_search = proxy_cache_search;
+ proxy_cache.on_bi.bi_chk_controls = proxy_cache_chk_controls;
+
proxy_cache.on_bi.bi_cf_ocs = pcocs;
code = config_register_schema( pccfg, pcocs );
"EQUALITY generalizedTimeMatch "
"ORDERING generalizedTimeOrderingMatch "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
- "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+ "SINGLE-VALUE "
+#if 0
+ /* Not until MANAGEDIT control is released */
+ "NO-USER-MODIFICATION "
+#endif
+ "USAGE directoryOperation )",
&ad_pwdAccountLockedTime },
{ "( 1.3.6.1.4.1.42.2.27.8.1.19 "
"NAME ( 'pwdFailureTime' ) "
if ( ppolicy_restrict( op, rs ) != SLAP_CB_CONTINUE )
return rs->sr_err;
+ /* If this is a replica, assume the master checked everything */
+ if ( be_shadow_update( op ))
+ return SLAP_CB_CONTINUE;
+
/* Check for password in entry */
if ((pa = attr_find( op->oq_add.rs_e->e_attrs,
slap_schema.si_ad_userPassword )))
}
}
/* If password aging is in effect, set the pwdChangedTime */
- if (( pp.pwdMaxAge || pp.pwdMinAge ) && !be_shadow_update( op )) {
+ if ( pp.pwdMaxAge || pp.pwdMinAge ) {
struct berval timestamp;
char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
time_t now = slap_get_time();
if ( rc != LDAP_SUCCESS ) return SLAP_CB_CONTINUE;
+ /* If this is a replica, we may need to tweak some of the
+ * master's modifications. Otherwise, just pass it through.
+ */
+ if ( be_shadow_update( op )) {
+ Modifications **prev;
+ int got_del_grace = 0, got_del_lock = 0, got_pw = 0;
+ Attribute *a_grace, *a_lock;
+
+ a_grace = attr_find( e->e_attrs, ad_pwdGraceUseTime );
+ a_lock = attr_find( e->e_attrs, ad_pwdAccountLockedTime );
+
+ for( prev = &op->oq_modify.rs_modlist, ml = *prev; ml;
+ prev = &ml->sml_next, ml = *prev ) {
+
+ if ( ml->sml_desc == slap_schema.si_ad_userPassword )
+ got_pw = 1;
+
+ /* If we're deleting an attr that didn't exist,
+ * drop this delete op
+ */
+ if ( ml->sml_op == LDAP_MOD_DELETE ) {
+ int drop = 0;
+
+ if ( ml->sml_desc == ad_pwdGraceUseTime ) {
+ got_del_grace = 1;
+ if ( !a_grace )
+ drop = 1;
+ } else
+ if ( ml->sml_desc == ad_pwdAccountLockedTime ) {
+ got_del_lock = 1;
+ if ( !a_lock )
+ drop = 1;
+ }
+ if ( drop ) {
+ *prev = ml->sml_next;
+ ml->sml_next = NULL;
+ slap_mods_free( ml, 1 );
+ }
+ }
+ }
+
+ /* If we're resetting the password, make sure grace and accountlock
+ * also get removed.
+ */
+ if ( got_pw ) {
+ if ( a_grace && !got_del_grace ) {
+ ml = (Modifications *) ch_malloc( sizeof( Modifications ) );
+ ml->sml_op = LDAP_MOD_DELETE;
+ ml->sml_flags = SLAP_MOD_INTERNAL;
+ ml->sml_type.bv_val = NULL;
+ ml->sml_desc = ad_pwdGraceUseTime;
+ ml->sml_values = NULL;
+ ml->sml_nvalues = NULL;
+ ml->sml_next = NULL;
+ *prev = ml;
+ prev = &ml->sml_next;
+ }
+ if ( a_lock && !got_del_lock ) {
+ ml = (Modifications *) ch_malloc( sizeof( Modifications ) );
+ ml->sml_op = LDAP_MOD_DELETE;
+ ml->sml_flags = SLAP_MOD_INTERNAL;
+ ml->sml_type.bv_val = NULL;
+ ml->sml_desc = ad_pwdAccountLockedTime;
+ ml->sml_values = NULL;
+ ml->sml_nvalues = NULL;
+ ml->sml_next = NULL;
+ *prev = ml;
+ }
+ }
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ be_entry_release_r( op, e );
+ return SLAP_CB_CONTINUE;
+ }
+
/* Did we receive a password policy request control? */
if ( op->o_ctrlflag[ppolicy_cid] ) {
send_ctrl = 1;
}
do_modify:
- if ((pwmod) && (!be_shadow_update( op ))) {
+ if (pwmod) {
struct berval timestamp;
char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
time_t now = slap_get_time();
modtail = mods;
}
+ if (attr_find(e->e_attrs, ad_pwdAccountLockedTime )) {
+ mods = (Modifications *) ch_malloc( sizeof( Modifications ) );
+ mods->sml_op = LDAP_MOD_DELETE;
+ mods->sml_flags = SLAP_MOD_INTERNAL;
+ mods->sml_type.bv_val = NULL;
+ mods->sml_desc = ad_pwdAccountLockedTime;
+ mods->sml_values = NULL;
+ mods->sml_nvalues = NULL;
+ mods->sml_next = NULL;
+ modtail->sml_next = mods;
+ modtail = mods;
+ }
+
/* Delete the pwdReset attribute, since it's being reset */
if ((zapReset) && (attr_find(e->e_attrs, ad_pwdReset ))) {
mods = (Modifications *) ch_malloc( sizeof( Modifications ) );
return LDAP_SUCCESS;
}
+static int
+attrPretty(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *out,
+ void *ctx )
+{
+ AttributeDescription *ad = NULL;
+ const char *err;
+ int code;
+
+ code = slap_bv2ad( val, &ad, &err );
+ if ( !code ) {
+ ber_dupbv_x( out, &ad->ad_type->sat_cname, ctx );
+ }
+ return code;
+}
+
+static int
+attrNormalize(
+ slap_mask_t use,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *out,
+ void *ctx )
+{
+ AttributeDescription *ad = NULL;
+ const char *err;
+ int code;
+
+ code = slap_bv2ad( val, &ad, &err );
+ if ( !code ) {
+ ber_str2bv_x( ad->ad_type->sat_oid, 0, 1, out, ctx );
+ }
+ return code;
+}
+
static int
ppolicy_db_init(
BackendDB *be
return code;
}
}
+ {
+ Syntax *syn;
+ MatchingRule *mr;
+
+ syn = ch_malloc( sizeof( Syntax ));
+ *syn = *ad_pwdAttribute->ad_type->sat_syntax;
+ syn->ssyn_pretty = attrPretty;
+ ad_pwdAttribute->ad_type->sat_syntax = syn;
+
+ mr = ch_malloc( sizeof( MatchingRule ));
+ *mr = *ad_pwdAttribute->ad_type->sat_equality;
+ mr->smr_normalize = attrNormalize;
+ ad_pwdAttribute->ad_type->sat_equality = mr;
+ }
}
on->on_bi.bi_private = ch_calloc( sizeof(pp_info), 1 );
return ( 1 );
}
pi->hash_passwords = 1;
+ return 0;
}
return SLAP_CONF_UNKNOWN;
}
char *text = NULL;
#ifdef ENABLE_REWRITE
- rc = rwm_op_dn_massage( op, rs, "searchDN" );
+ rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
+ "searchFilter", op->ors_filterstr.bv_val );
+ if ( rc == LDAP_SUCCESS )
+ rc = rwm_op_dn_massage( op, rs, "searchDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
int si_chkops; /* checkpointing info */
int si_chktime;
int si_numops; /* number of ops since last checkpoint */
+ int si_nopres; /* Skip present phase */
time_t si_chklast; /* time of last checkpoint */
Avlnode *si_mods; /* entries being modified */
sessionlog *si_logs;
SlapReply frs = { REP_RESULT };
int rc;
- fop = *op;
+ /* Use basic parameters from syncrepl search, but use
+ * current op's threadctx / tmpmemctx
+ */
+ fop = *fc->fss->s_op;
+
+ fop.o_hdr = op->o_hdr;
+ fop.o_bd = op->o_bd;
+ fop.o_time = op->o_time;
+ fop.o_tincr = op->o_tincr;
cb.sc_response = findbase_cb;
cb.sc_private = fc;
- fop.o_sync_mode &= SLAP_CONTROL_MASK; /* turn off sync mode */
+ fop.o_sync_mode = 0; /* turn off sync mode */
fop.o_managedsait = SLAP_CONTROL_CRITICAL;
fop.o_callback = &cb;
fop.o_tag = LDAP_REQ_SEARCH;
fop.ors_scope = LDAP_SCOPE_BASE;
- fop.ors_deref = fc->fss->s_op->ors_deref;
fop.ors_limit = NULL;
fop.ors_slimit = 1;
fop.ors_tlimit = SLAP_NO_LIMIT;
fop.ors_attrs = slap_anlist_no_attrs;
fop.ors_attrsonly = 1;
- fop.ors_filter = fc->fss->s_op->ors_filter;
- fop.ors_filterstr = fc->fss->s_op->ors_filterstr;
-
- fop.o_req_ndn = fc->fss->s_op->o_req_ndn;
fop.o_bd->bd_info = on->on_info->oi_orig;
rc = fop.o_bd->be_search( &fop, &frs );
sop.o_bd = op->o_bd;
sop.o_controls = op->o_controls;
sop.o_private = op->o_private;
+ sop.o_callback = NULL;
/* If queueing is allowed */
if ( queue ) {
"search base has changed" );
sprev->s_next = snext;
syncprov_drop_psearch( ss, 1 );
+ ss = sprev;
continue;
}
g2->ga_next = op2->o_groups;
op2->o_groups = g2;
}
+ /* Don't allow any further group caching */
+ op2->o_do_not_cache = 1;
/* Add op2 to conn so abandon will find us */
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
slap_callback *cb;
- int gotstate = 0, nochange = 0, do_present = 1;
+ int gotstate = 0, nochange = 0, do_present;
syncops *sop = NULL;
searchstate *ss;
sync_control *srs;
return rs->sr_err;
}
+ do_present = si->si_nopres ? 0 : 1;
+
srs = op->o_controls[slap_cids.sc_LDAPsync];
op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
enum {
SP_CHKPT = 1,
- SP_SESSL
+ SP_SESSL,
+ SP_NOPRES
};
static ConfigDriver sp_cf_gen;
sp_cf_gen, "( OLcfgOvAt:1.2 NAME 'olcSpSessionlog' "
"DESC 'Session log size in ops' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { "syncprov-nopresent", NULL, 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|SP_NOPRES,
+ sp_cf_gen, "( OLcfgOvAt:1.3 NAME 'olcSpNoPresent' "
+ "DESC 'Omit Present phase processing' "
+ "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
"NAME 'olcSyncProvConfig' "
"DESC 'SyncRepl Provider configuration' "
"SUP olcOverlayConfig "
- "MAY ( olcSpCheckpoint $ olcSpSessionlog ) )",
+ "MAY ( olcSpCheckpoint $ olcSpSessionlog $ olcSpNoPresent ) )",
Cft_Overlay, spcfg },
{ NULL, 0, NULL }
};
rc = 1;
}
break;
+ case SP_NOPRES:
+ if ( si->si_nopres ) {
+ c->value_int = 1;
+ } else {
+ rc = 1;
+ }
+ break;
}
return rc;
} else if ( c->op == LDAP_MOD_DELETE ) {
else
rc = LDAP_NO_SUCH_ATTRIBUTE;
break;
+ case SP_NOPRES:
+ if ( si->si_nopres )
+ si->si_nopres = 0;
+ else
+ rc = LDAP_NO_SUCH_ATTRIBUTE;
+ break;
}
return rc;
}
sl->sl_size = size;
}
break;
+ case SP_NOPRES:
+ si->si_nopres = c->value_int;
+ break;
}
return rc;
}
const char **text,
unsigned proxied ));
-LDAP_SLAPD_F (int) slap_ad_undef_remove LDAP_P((
- char *name ));
+LDAP_SLAPD_F (int) slap_ad_undef_promote LDAP_P((
+ char *name,
+ AttributeType *nat ));
LDAP_SLAPD_F (AttributeDescription *) ad_find_tags LDAP_P((
AttributeType *type,
*/
LDAP_SLAPD_F (int) glue_sub_init( void );
+LDAP_SLAPD_F (int) glue_sub_attach( void );
LDAP_SLAPD_F (int) glue_sub_add( BackendDB *be, int advert, int online );
LDAP_SLAPD_F (int) glue_sub_del( BackendDB *be );
const char *oid, int *cid ));
LDAP_SLAPD_F (int) slap_global_control LDAP_P ((
Operation *op, const char *oid, int *cid ));
+LDAP_SLAPD_F (int) slap_remove_control LDAP_P((
+ Operation *op,
+ SlapReply *rs,
+ int ctrl,
+ BI_chk_controls fnc ));
/*
* config.c
LDAP_SLAPD_F (int) rdn_validate LDAP_P(( struct berval * rdn ));
-LDAP_SLAPD_F (int) dn_rdnlen LDAP_P(( Backend *be, struct berval *dn ));
+LDAP_SLAPD_F (ber_len_t) dn_rdnlen LDAP_P(( Backend *be, struct berval *dn ));
LDAP_SLAPD_F (void) build_new_dn LDAP_P((
struct berval * new_dn,
"SASL match pattern %s could not be compiled by regexp engine\n",
reg->sr_match, 0, 0 );
+#ifdef ENABLE_REWRITE
+ /* Dummy block to force symbol references in librewrite */
+ if ( slapMode == ( SLAP_SERVER_MODE|SLAP_TOOL_MODE )) {
+ rewrite_info_init( 0 );
+ }
+#endif
return( LDAP_OTHER );
}
# Attribute Type Definitions
-attributetype ( 1.3.6.1.1.1.1.0 NAME 'uidNumber'
- DESC 'An integer uniquely identifying a user in an administrative domain'
- EQUALITY integerMatch
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
-
-attributetype ( 1.3.6.1.1.1.1.1 NAME 'gidNumber'
- DESC 'An integer uniquely identifying a group in an administrative domain'
- EQUALITY integerMatch
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+# builtin
+#attributetype ( 1.3.6.1.1.1.1.0 NAME 'uidNumber'
+# DESC 'An integer uniquely identifying a user in an administrative domain'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# builtin
+#attributetype ( 1.3.6.1.1.1.1.1 NAME 'gidNumber'
+# DESC 'An integer uniquely identifying a group in an administrative domain'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.1.1.1.2 NAME 'gecos'
DESC 'The GECOS field; the common name'
struct berval *asserted = (struct berval *) assertedValue;
struct berval assertedDN = *asserted;
struct berval assertedUID = BER_BVNULL;
- struct berval valueDN = BER_BVNULL;
+ struct berval valueDN = *value;
struct berval valueUID = BER_BVNULL;
int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
}
if ( !BER_BVISEMPTY( value ) ) {
- valueDN = *value;
valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
if ( !BER_BVISNULL( &valueUID ) ) {
SLAP_SYNTAX_HIDE, NULL, NULL},
#endif
- {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
- SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
+ {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
+ 0, UUIDValidate, NULL},
{"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
SLAP_SYNTAX_HIDE, csnValidate, NULL},
NULL, NULL,
"integerMatch" },
- {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
- "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
- SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
+ {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
+ "SYNTAX 1.3.6.1.1.16.1 )",
+ SLAP_MR_EQUALITY, NULL,
NULL, UUIDNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL},
- {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
- "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
- SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
+ {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
+ "SYNTAX 1.3.6.1.1.16.1 )",
+ SLAP_MR_ORDERING, NULL,
NULL, UUIDNormalize, octetStringOrderingMatch,
octetStringIndexer, octetStringFilter,
"UUIDMatch"},
NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
offsetof(struct slap_internal_schema, si_ad_entryDN) },
- { "entryUUID", "( 1.3.6.1.4.1.4203.666.1.6 NAME 'entryUUID' "
+ { "entryUUID", "( 1.3.6.1.1.16.4 NAME 'entryUUID' "
"DESC 'UUID of the entry' "
"EQUALITY UUIDMatch "
"ORDERING UUIDOrderingMatch "
- "SYNTAX 1.3.6.1.4.1.4203.666.2.6 "
+ "SYNTAX 1.3.6.1.1.16.1 "
"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
- NULL, SLAP_AT_HIDE|SLAP_AT_MANAGEABLE,
+ NULL, SLAP_AT_MANAGEABLE,
NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
offsetof(struct slap_internal_schema, si_ad_entryUUID) },
#ifdef LDAP_SUPERIOR_UUID
{ "superiorUUID", "( 1.3.6.1.4.1.4203.666.1.11 NAME 'superiorUUID' "
"DESC 'UUID of the superior entry' "
- "EQUALITY octetStringMatch "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
+ "EQUALITY UUIDMatch "
+ "ORDERING UUIDOrderingMatch "
+ "SYNTAX 1.3.6.1.1.16.1 "
"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
NULL, SLAP_AT_HIDE,
NULL, NULL,
NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
offsetof(struct slap_internal_schema, si_ad_uid) },
+ { "uidNumber", /* for ldapi:// */
+ "( 1.3.6.1.1.1.1.0 NAME 'uidNumber' "
+ "DESC 'An integer uniquely identifying a user "
+ "in an administrative domain' "
+ "EQUALITY integerMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )",
+ NULL, 0,
+ NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_uidNumber) },
+ { "gidNumber", /* for ldapi:// */
+ "( 1.3.6.1.1.1.1.1 NAME 'gidNumber' "
+ "DESC 'An integer uniquely identifying a group "
+ "in an administrative domain' "
+ "EQUALITY integerMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )",
+ NULL, 0,
+ NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_gidNumber) },
{ "userPassword", "( 2.5.4.35 NAME 'userPassword' "
"DESC 'RFC2256/2307: password of user' "
"EQUALITY octetStringMatch "
AttributeDescription *si_ad_name;
AttributeDescription *si_ad_cn;
AttributeDescription *si_ad_uid;
+ AttributeDescription *si_ad_uidNumber;
+ AttributeDescription *si_ad_gidNumber;
AttributeDescription *si_ad_userPassword;
AttributeDescription *si_ad_labeledURI;
#ifdef SLAPD_AUTHPASSWD
/* authorization backend */
Backend *c_authz_backend;
+ void *c_authz_cookie;
+#define SLAP_IS_AUTHZ_BACKEND( op ) \
+ ( (op)->o_bd != NULL \
+ && (op)->o_bd->be_private != NULL \
+ && (op)->o_conn != NULL \
+ && (op)->o_conn->c_authz_backend != NULL \
+ && ( (op)->o_bd->be_private == (op)->o_conn->c_authz_backend->be_private \
+ || (op)->o_bd->be_private == (op)->o_conn->c_authz_cookie ) )
AuthorizationInformation c_authz;
Connection conn = { 0 };
Listener listener;
char opbuf[OPERATION_BUFFER_SIZE];
- Operation *op;
+ Operation *op = NULL;
Entry e = { 0 }, *ep = &e;
char *attr = NULL;
int doclose = 0;
break;
}
- rc = glue_sub_init();
+ rc = glue_sub_attach();
if ( rc != 0 ) {
fprintf( stderr, "%s: subordinate configuration error\n", progname );
LDAP_LIST_ENTRY(nonpresent_entry) npe_link;
};
+#define SYNCDATA_DEFAULT 0 /* entries are plain LDAP entries */
+#define SYNCDATA_ACCESSLOG 1 /* entries are accesslog format */
+#define SYNCDATA_CHANGELOG 2 /* entries are changelog format */
+
typedef struct syncinfo_s {
struct slap_backend_db *si_be;
struct re_s *si_re;
int si_tlimit;
int si_refreshDelete;
int si_refreshPresent;
+ int si_syncdata;
Avlnode *si_presentlist;
LDAP *si_ld;
LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
static int syncuuid_cmp( const void *, const void * );
static void avl_ber_bvfree( void * );
static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray );
+static int syncrepl_message_to_op(
+ syncinfo_t *, Operation *, LDAPMessage * );
static int syncrepl_message_to_entry(
syncinfo_t *, Operation *, LDAPMessage *,
Modifications **, Entry **, int );
slap_parse_sync_cookie( &syncCookie, NULL );
}
}
- if ( syncrepl_message_to_entry( si, op, msg,
+ if ( si->si_syncdata ) {
+ entry = NULL;
+ modlist = NULL;
+ if ( syncrepl_message_to_op( si, op, msg ) == LDAP_SUCCESS &&
+ !BER_BVISNULL( &syncCookie.ctxcsn ) ) {
+ syncrepl_updateCookie( si, op, psub, &syncCookie );
+ }
+ } else if ( syncrepl_message_to_entry( si, op, msg,
&modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
rc_efree = syncrepl_entry( si, op, entry, &modlist,
syncstate, &syncUUID, &syncCookie_req, &syncCookie.ctxcsn );
- if ( !BER_BVISNULL( &syncCookie.octet_str ) )
+ if ( !BER_BVISNULL( &syncCookie.ctxcsn ) )
{
syncrepl_updateCookie( si, op, psub, &syncCookie );
}
&syncCookie_req.ctxcsn, &syncCookie.ctxcsn,
&text );
}
- if ( !BER_BVISNULL( &syncCookie.octet_str ) &&
+ if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
match < 0 && err == LDAP_SUCCESS )
{
syncrepl_updateCookie( si, op, psub, &syncCookie );
return NULL;
}
+typedef struct logschema {
+ struct berval ls_dn;
+ struct berval ls_req;
+ struct berval ls_mod;
+ struct berval ls_newRdn;
+ struct berval ls_delRdn;
+ struct berval ls_newSup;
+} logschema;
+
+static logschema changelog_sc = {
+ BER_BVC("targetDN"),
+ BER_BVC("changeType"),
+ BER_BVC("changes"),
+ BER_BVC("newRDN"),
+ BER_BVC("deleteOldRDN"),
+ BER_BVC("newSuperior")
+};
+
+static logschema accesslog_sc = {
+ BER_BVC("reqDN"),
+ BER_BVC("reqType"),
+ BER_BVC("reqMod"),
+ BER_BVC("reqNewRDN"),
+ BER_BVC("reqDeleteOldRDN"),
+ BER_BVC("reqNewSuperior")
+};
+
+static slap_verbmasks modops[] = {
+ { BER_BVC("add"), LDAP_REQ_ADD },
+ { BER_BVC("delete"), LDAP_REQ_DELETE },
+ { BER_BVC("modify"), LDAP_REQ_MODIFY },
+ { BER_BVC("modrdn"), LDAP_REQ_MODRDN},
+ { BER_BVNULL, 0 }
+};
+
+static Modifications *
+syncrepl_accesslog_mods(
+ syncinfo_t *si,
+ struct berval *vals
+)
+{
+ char *colon;
+ const char *text;
+ AttributeDescription *ad;
+ struct berval bv, bv2;
+ short op;
+ Modifications *mod = NULL, *modlist = NULL, **modtail;
+ int i;
+
+ modtail = &modlist;
+
+ for (i=0; !BER_BVISNULL( &vals[i] ); i++) {
+ ad = NULL;
+ bv = vals[i];
+
+ colon = strchr( bv.bv_val, ':' );
+ if ( !colon )
+ continue; /* invalid */
+ bv.bv_len = colon - bv.bv_val;
+ if ( slap_bv2ad( &bv, &ad, &text )) {
+ /* Invalid */
+ continue;
+ }
+ /* Ignore dynamically generated attrs */
+ if ( ad->ad_type->sat_flags & SLAP_AT_DYNAMIC )
+ continue;
+ /* Ignore excluded attrs */
+ if ( ldap_charray_inlist( si->si_exattrs,
+ ad->ad_type->sat_cname.bv_val ))
+ continue;
+
+ switch(colon[1]) {
+ case '+': op = LDAP_MOD_ADD; break;
+ case '-': op = LDAP_MOD_DELETE; break;
+ case '=': op = LDAP_MOD_REPLACE; break;
+ case '#': op = LDAP_MOD_INCREMENT; break;
+ default: continue;
+ }
+
+ if ( !mod || ad != mod->sml_desc || op != mod->sml_op ) {
+ mod = (Modifications *) ch_malloc( sizeof( Modifications ));
+ mod->sml_flags = 0;
+ mod->sml_op = op;
+ mod->sml_next = NULL;
+ mod->sml_desc = ad;
+ mod->sml_type = ad->ad_cname;
+ mod->sml_values = NULL;
+ mod->sml_nvalues = NULL;
+
+ *modtail = mod;
+ modtail = &mod->sml_next;
+ }
+ bv.bv_val = colon + 3;
+ bv.bv_len = vals[i].bv_len - ( bv.bv_val - vals[i].bv_val );
+ ber_dupbv( &bv2, &bv );
+ ber_bvarray_add( &mod->sml_values, &bv2 );
+ }
+ return modlist;
+}
+
+static Modifications *
+syncrepl_changelog_mods(
+ syncinfo_t *si,
+ struct berval *vals
+)
+{
+ return NULL; /* FIXME */
+}
+
+static int
+syncrepl_message_to_op(
+ syncinfo_t *si,
+ Operation *op,
+ LDAPMessage *msg
+)
+{
+ BerElement *ber = NULL;
+ Modifications *modlist = NULL;
+ logschema *ls;
+ SlapReply rs = { REP_RESULT };
+ slap_callback cb = { NULL, null_callback, NULL, NULL };
+
+ const char *text;
+ char txtbuf[SLAP_TEXT_BUFLEN];
+ size_t textlen = sizeof txtbuf;
+
+ struct berval bdn, dn = BER_BVNULL, ndn;
+ struct berval bv, *bvals = NULL;
+ struct berval rdn = BER_BVNULL, sup = BER_BVNULL,
+ prdn = BER_BVNULL, nrdn = BER_BVNULL,
+ psup = BER_BVNULL, nsup = BER_BVNULL;
+ int rc, deleteOldRdn = 0;
+
+ if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
+ Debug( LDAP_DEBUG_ANY,
+ "Message type should be entry (%d)", ldap_msgtype( msg ), 0, 0 );
+ return -1;
+ }
+
+ if ( si->si_syncdata == SYNCDATA_ACCESSLOG )
+ ls = &accesslog_sc;
+ else
+ ls = &changelog_sc;
+
+ rc = ldap_get_dn_ber( si->si_ld, msg, &ber, &bdn );
+
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "syncrepl_message_to_op : dn get failed (%d)", rc, 0, 0 );
+ return rc;
+ }
+
+ op->o_tag = LBER_DEFAULT;
+
+ while (( rc = ldap_get_attribute_ber( si->si_ld, msg, ber, &bv, &bvals ))
+ == LDAP_SUCCESS ) {
+ if ( bv.bv_val == NULL )
+ break;
+
+ if ( !ber_bvstrcasecmp( &bv, &ls->ls_dn )) {
+ bdn = bvals[0];
+ dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+ ber_dupbv( &op->o_req_dn, &dn );
+ ber_dupbv( &op->o_req_ndn, &ndn );
+ slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
+ slap_sl_free( dn.bv_val, op->o_tmpmemctx );
+ } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_req )) {
+ int i = verb_to_mask( bvals[0].bv_val, modops );
+ if ( i < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "syncrepl_message_to_op : unknown op %s",
+ bvals[0].bv_val, 0, 0 );
+ ch_free( bvals );
+ rc = -1;
+ goto done;
+ }
+ op->o_tag = modops[i].mask;
+ } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_mod )) {
+ /* Parse attribute into modlist */
+ if ( si->si_syncdata == SYNCDATA_ACCESSLOG )
+ modlist = syncrepl_accesslog_mods( si, bvals );
+ else
+ modlist = syncrepl_changelog_mods( si, bvals );
+ } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_newRdn )) {
+ rdn = bvals[0];
+ } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_delRdn )) {
+ if ( !ber_bvstrcasecmp( &slap_true_bv, bvals ))
+ deleteOldRdn = 1;
+ } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_newSup )) {
+ sup = bvals[0];
+ }
+ ch_free( bvals );
+ }
+
+ /* If we didn't get a mod type or a target DN, bail out */
+ if ( op->o_tag == LBER_DEFAULT || BER_BVISNULL( &dn )) {
+ rc = -1;
+ goto done;
+ }
+
+ op->o_callback = &cb;
+
+ switch( op->o_tag ) {
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_MODIFY:
+ /* If we didn't get required data, bail */
+ if ( !modlist ) goto done;
+
+ rc = slap_mods_check( modlist, &text, txtbuf, textlen, NULL );
+
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: mods check (%s)\n",
+ text, 0, 0 );
+ goto done;
+ }
+
+ if ( op->o_tag == LDAP_REQ_ADD ) {
+ op->ora_e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
+ op->ora_e->e_name = op->o_req_dn;
+ op->ora_e->e_nname = op->o_req_ndn;
+ rc = slap_mods2entry( modlist, &op->ora_e, 1, 0, &text, txtbuf, textlen);
+ if( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: mods2entry (%s)\n",
+ text, 0, 0 );
+ } else {
+ rc = op->o_bd->be_add( op, &rs );
+ }
+ be_entry_release_w( op, op->ora_e );
+ } else {
+ op->orm_modlist = modlist;
+ rc = op->o_bd->be_modify( op, &rs );
+ }
+ break;
+ case LDAP_REQ_MODRDN:
+ if ( BER_BVISNULL( &rdn )) goto done;
+
+ if ( rdnPretty( NULL, &rdn, &prdn, NULL ))
+ goto done;
+ if ( rdnNormalize( 0, NULL, NULL, &rdn, &nrdn, NULL ))
+ goto done;
+ if ( !BER_BVISNULL( &sup )) {
+ if ( dnPrettyNormal( NULL, &sup, &psup, &nsup, NULL ))
+ goto done;
+ op->orr_newSup = &psup;
+ op->orr_nnewSup = ⊅
+ }
+ op->orr_newrdn = prdn;
+ op->orr_nnewrdn = nrdn;
+ op->orr_deleteoldrdn = deleteOldRdn;
+ rc = op->o_bd->be_modrdn( op, &rs );
+ break;
+ }
+done:
+ if ( modlist )
+ slap_mods_free( modlist, op->o_tag != LDAP_REQ_ADD );
+ if ( !BER_BVISNULL( &rdn )) {
+ if ( !BER_BVISNULL( &nsup ))
+ ch_free( nsup.bv_val );
+ if ( !BER_BVISNULL( &psup ))
+ ch_free( psup.bv_val );
+ if ( !BER_BVISNULL( &nrdn ))
+ ch_free( nrdn.bv_val );
+ if ( !BER_BVISNULL( &prdn ))
+ ch_free( prdn.bv_val );
+ }
+ ber_free ( ber, 0 );
+ return rc;
+}
+
static int
syncrepl_message_to_entry(
syncinfo_t *si,
#define RETRYSTR "retry"
#define SLIMITSTR "sizelimit"
#define TLIMITSTR "timelimit"
+#define SYNCDATASTR "syncdata"
/* FIXME: undocumented */
#define OLDAUTHCSTR "bindprincipal"
{ BER_BVNULL, 0 }
};
+static slap_verbmasks datamodes[] = {
+ { BER_BVC("default"), SYNCDATA_DEFAULT },
+ { BER_BVC("accesslog"), SYNCDATA_ACCESSLOG },
+ { BER_BVC("changelog"), SYNCDATA_CHANGELOG },
+ { BER_BVNULL, 0 }
+};
+
static int
parse_syncrepl_line(
char **cargv,
STRLENOF( FILTERSTR "=" ) ) )
{
val = cargv[ i ] + STRLENOF( FILTERSTR "=" );
+ if ( si->si_filterstr.bv_val )
+ ch_free( si->si_filterstr.bv_val );
ber_str2bv( val, 0, 1, &si->si_filterstr );
} else if ( !strncasecmp( cargv[ i ], SEARCHBASESTR "=",
STRLENOF( SEARCHBASESTR "=" ) ) )
{
val = cargv[ i ] + STRLENOF( TLIMITSTR "=" );
si->si_tlimit = atoi( val );
+ } else if ( !strncasecmp( cargv[ i ], SYNCDATASTR "=",
+ STRLENOF( SYNCDATASTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( SYNCDATASTR "=" );
+ si->si_syncdata = verb_to_mask( val, datamodes );
} else if ( bindconf_parse( cargv[i], &si->si_bindconf )) {
fprintf( stderr, "Error: parse_syncrepl_line: "
"unknown keyword \"%s\"\n", cargv[ i ] );
ptr = lutil_strcopy( ptr, " " TLIMITSTR "=" );
ptr += sprintf( ptr, "%d", si->si_tlimit );
}
+
+ if ( si->si_syncdata ) {
+ if ( enum_to_verb( datamodes, si->si_syncdata, &bc ) >= 0 ) {
+ ptr = lutil_strcopy( ptr, " " SYNCDATASTR "=" );
+ ptr = lutil_strcopy( ptr, bc.bv_val );
+ }
+ }
bc.bv_len = ptr - buf;
bc.bv_val = buf;
ber_dupbv( bv, &bc );
ri->ri_port = atoi( hp );
}
if ( ri->ri_port <= 0 ) {
- ri->ri_port = 0;
+ ri->ri_port = LDAP_PORT;
}
ri->ri_hostname = strdup( val );
gots |= GOT_HOST;
if ( ldif_parse_line( line, &type, &value, &len ) < 0 ) {
return( NULL );
}
- port = 0;
+ port = LDAP_PORT;
if (( p = strchr( value, ':' )) != NULL ) {
*p = '\0';
p++;
}
if ( ri != NULL ) { /* write a single "replica:" line */
- if ( fprintf( fp, "replica: %s:%d\n", ri->ri_hostname,
- ri->ri_port ) < 0 ) {
+ if ( ri->ri_port != 0 ) {
+ rc = fprintf( fp, "replica: %s:%d\n", ri->ri_hostname,
+ ri->ri_port );
+ } else {
+ rc = fprintf( fp, "replica: %s\n", ri->ri_hostname );
+ }
+ if ( rc < 0 ) {
rc = -1;
goto bad;
}
+ rc = 0;
+
} else { /* write multiple "replica:" lines */
for ( i = 0; re->re_replicas && re->re_replicas[ i ].rh_hostname != NULL; i++ ) {
if ( fprintf( fp, "replica: %s:%d\n",
Ri *ri = (Ri *) ri_arg;
Debug( LDAP_DEBUG_ARGS, "begin replication thread for %s:%d\n",
- ((Ri *)ri)->ri_hostname, ((Ri *)ri)->ri_port, 0 );
+ ri->ri_hostname, ri->ri_port, 0 );
ri->ri_process( ri );
o: Example, Inc.
dc: example
+dn: ou=Groups,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Groups
+
+dn: cn=All,ou=Groups,dc=example,dc=com
+objectClass: groupOfNames
+cn: All
+member: uid=bjorn,ou=People,dc=example,dc=com
+member: uid=bjensen,ou=People,dc=example,dc=com
+
+dn: cn=ITD,ou=Groups,dc=example,dc=com
+objectClass: groupOfNames
+cn: ITD
+member: uid=bjorn,ou=People,dc=example,dc=com
+
+dn: uid=proxy,ou=Groups,dc=example,dc=com
+objectClass: inetOrgPerson
+cn: Proxy
+sn: Proxy
+uid: proxy
+
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People
sn: Proxy
uid: proxy
-dn: ou=Groups,dc=example,dc=com
-objectClass: organizationalUnit
-ou: Groups
-
-dn: cn=All,ou=Groups,dc=example,dc=com
-objectClass: groupOfNames
-cn: All
-member: uid=bjorn,ou=People,dc=example,dc=com
-member: uid=bjensen,ou=People,dc=example,dc=com
-
-dn: cn=ITD,ou=Groups,dc=example,dc=com
-objectClass: groupOfNames
-cn: ITD
-member: uid=bjorn,ou=People,dc=example,dc=com
-
-dn: uid=proxy,ou=Groups,dc=example,dc=com
-objectClass: inetOrgPerson
-cn: Proxy
-sn: Proxy
-uid: proxy
-
facsimileTelephoneNumber: +1 313 555 9700
telephoneNumber: +1 313 555 5331
-dn: ou=Groups,dc=example,dc=com
-objectClass: organizationalUnit
-ou: Groups
-
-dn: cn=All Staff,ou=Groups,dc=example,dc=com
-member: cn=Manager,dc=example,dc=com
-member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
- ple,dc=com
-member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
- =com
-member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
- mple,dc=com
-member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
- e,dc=com
-owner: cn=Manager,dc=example,dc=com
-cn: All Staff
-description: Everyone in the sample data
-objectClass: groupOfNames
-
-dn: cn=Alumni Assoc Staff,ou=Groups,dc=example,dc=com
-member: cn=Manager,dc=example,dc=com
-member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
-member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
-owner: cn=Manager,dc=example,dc=com
-description: All Alumni Assoc Staff
-cn: Alumni Assoc Staff
-objectClass: groupOfNames
-
-dn: cn=ITD Staff,ou=Groups,dc=example,dc=com
-owner: cn=Manager,dc=example,dc=com
-description: All ITD Staff
-cn: ITD Staff
-objectClass: groupOfUniqueNames
-uniqueMember: cn=Manager,dc=example,dc=com
-uniqueMember: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=
- example,dc=com
-uniqueMember: cn=James A Jones 2,ou=Information Technology Division,ou=People,
- dc=example,dc=com
-uniqueMember: cn=John Doe,ou=Information Technology Division,ou=People,dc=exam
- ple,dc=com
-
dn: ou=Information Technology Division,ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: Information Technology Division
facsimileTelephoneNumber: +1 313 555 4544
telephoneNumber: +1 313 555 9394
+dn: ou=Groups,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Groups
+
+dn: cn=All Staff,ou=Groups,dc=example,dc=com
+member: cn=Manager,dc=example,dc=com
+member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
+ ple,dc=com
+member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
+ mple,dc=com
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
+ e,dc=com
+owner: cn=Manager,dc=example,dc=com
+cn: All Staff
+description: Everyone in the sample data
+objectClass: groupOfNames
+
+dn: cn=Alumni Assoc Staff,ou=Groups,dc=example,dc=com
+member: cn=Manager,dc=example,dc=com
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+owner: cn=Manager,dc=example,dc=com
+description: All Alumni Assoc Staff
+cn: Alumni Assoc Staff
+objectClass: groupOfNames
+
+dn: cn=ITD Staff,ou=Groups,dc=example,dc=com
+owner: cn=Manager,dc=example,dc=com
+description: All ITD Staff
+cn: ITD Staff
+objectClass: groupOfUniqueNames
+uniqueMember: cn=Manager,dc=example,dc=com
+uniqueMember: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=
+ example,dc=com
+uniqueMember: cn=James A Jones 2,ou=Information Technology Division,ou=People,
+ dc=example,dc=com
+uniqueMember: cn=John Doe,ou=Information Technology Division,ou=People,dc=exam
+ ple,dc=com
+
SRCDIR="@srcdir@"
TOPSRCDIR="@top_srcdir@"
LN_S="@LN_S@"
+EGREP_CMD="@EGREP@"
-export SRCDIR TOPSRCDIR LN_S
+export SRCDIR TOPSRCDIR LN_S EGREP_CMD
# backends
AC_bdb=@BUILD_BDB@
AC_sql=sql@BUILD_SQL@
# overlays
-AC_glue=glue@BUILD_GLUE@
AC_pcache=pcache@BUILD_PROXYCACHE@
AC_ppolicy=ppolicy@BUILD_PPOLICY@
AC_refint=refint@BUILD_REFINT@
AC_ACI_ENABLED=aci@WITH_ACI_ENABLED@
export AC_bdb AC_hdb AC_ldap AC_ldbm AC_meta AC_monitor AC_relay AC_sql
-export AC_glue AC_pcache AC_ppolicy AC_refint AC_retcode AC_rwm AC_unique AC_syncprov
+export AC_pcache AC_ppolicy AC_refint AC_retcode AC_rwm AC_unique AC_syncprov
export AC_translucent AC_WITH_SASL AC_WITH_TLS AC_WITH_MODULES_ENABLED AC_ACI_ENABLED
export AC_valsort
#
# Strip comments
#
-egrep -iv '^#'
+grep -v '^#'
-e "s/^#${AC_relay}#//" \
-e "s/^#${AC_sql}#//" \
-e "s/^#${RDBMS}#//" \
- -e "s/^#${AC_glue}#//" \
-e "s/^#${AC_pcache}#//" \
-e "s/^#${AC_ppolicy}#//" \
-e "s/^#${AC_refint}#//" \
## <http://www.OpenLDAP.org/license.html>.
if test $# -eq 0 ; then
- SRCDIR="."
+ test -z "$SRCDIR" && SRCDIR="."
else
SRCDIR=$1; shift
fi
echo "running defines.sh $SRCDIR $BACKEND"
. $SRCDIR/scripts/defines.sh
-echo "Cleaning up in $DBDIR..."
-
-rm -f $DBDIR/[!C]*
+if test -d "$TESTDIR"; then
+ echo "Cleaning up in $TESTDIR..."
+ /bin/rm -rf testrun/db.*
+fi
+mkdir -p $TESTDIR
-echo "Starting slapd on TCP/IP port $PORT..."
-$SLAPD -f $PASSWDCONF -h $MASTERURI -d $LVL $TIMING > $MASTERLOG 2>&1 &
+echo "Starting slapd on TCP/IP port $PORT1..."
+$SLAPD -f $PASSWDCONF -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
PID=$!
+if test ${WAIT-0} != 0 ; then
+ echo PID $PID
+ read foo
+fi
+KILLPIDS="$PID"
echo "Testing slapd searching..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -b "$BASEDN" -h $LOCALHOST -p $PORT \
+ $LDAPSEARCH -L -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
if test $RC != 0 ; then
echo "ldapsearch failed!"
- kill -HUP $PID
+ test "$KILLSERVERS" != no && kill -HUP $KILLPIDS
exit $RC
fi
cat /dev/null > $TESTOUT
echo "Testing base suffix searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -s base -h $LOCALHOST -p $PORT \
+$LDAPSEARCH -L -S "" -b "$BASEDN" -s base -h $LOCALHOST -p $PORT1 \
'(objectclass=*)' >> $TESTOUT 2>&1
+RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed!"
- kill -HUP $PID
+ test "$KILLSERVERS" != no && kill -HUP $KILLPIDS
exit $RC
fi
echo " ------------ " >> $TESTOUT
echo "Testing user searching..."
-$LDAPSEARCH -L -S "" -b "uid=root,$BASEDN" -s base -h $LOCALHOST -p $PORT \
+$LDAPSEARCH -L -S "" -b "uid=root,$BASEDN" -s base -h $LOCALHOST -p $PORT1 \
'(objectclass=*)' >> $TESTOUT 2>&1
+RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed!"
- kill -HUP $PID
+ test "$KILLSERVERS" != no && kill -HUP $KILLPIDS
exit $RC
fi
echo " ------------ " >> $TESTOUT
echo "Testing exact searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT \
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
'(uid=root)' >> $TESTOUT 2>&1
+RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed!"
- kill -HUP $PID
+ test "$KILLSERVERS" != no && kill -HUP $KILLPIDS
exit $RC
fi
echo " ------------ " >> $TESTOUT
echo "Testing OR searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT \
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
'(|(objectclass=person)(cn=root))' >> $TESTOUT 2>&1
+RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed!"
- kill -HUP $PID
+ test "$KILLSERVERS" != no && kill -HUP $KILLPIDS
exit $RC
fi
echo " ------------ " >> $TESTOUT
echo "Testing AND searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT \
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
'(&(objectclass=person)(cn=root))' >> $TESTOUT 2>&1
+RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed!"
- kill -HUP $PID
+ test "$KILLSERVERS" != no && kill -HUP $KILLPIDS
exit $RC
fi
-kill -HUP $PID
+test "$KILLSERVERS" != no && kill -HUP $KILLPIDS
echo "Assuming everything is fine."
#echo "Comparing results"
echo ">>>>> Test succeeded"
-
exit 0
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
-mkdir -p $TESTRUN $DBDIR1
+mkdir -p $TESTDIR $DBDIR1
echo "Starting slapd on TCP/IP port $PORT1..."
. $CONFFILTER $BACKEND $MONITORDB < $SCHEMACONF > $CONF1
count=2
if test $RC = 0 ; then
- if test $MONITORDB = yes -o $MONITORDB = mod ; then
+ case $MONITORDB in yes | mod)
count=3
echo "Using ldapsearch to retrieve the cn=Monitor..."
$LDAPSEARCH -b "cn=Monitor" -s base -h $LOCALHOST -p $PORT1 \
'+extensibleObject' >> $SEARCHOUT 2>&1
RC=$?
- fi
+ ;;
+ esac
fi
test $KILLSERVERS != no && kill -HUP $KILLPIDS
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
-mkdir -p $TESTRUN $DBDIR1
+mkdir -p $TESTDIR $DBDIR1
echo "Running slapadd to build slapd database..."
. $CONFFILTER $BACKEND $MONITORDB < $CONF > $ADDCONF
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
- kill -HUP $PID
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
RC=$?
if test $RC != 0 ; then
echo "ldapmodrdn failed ($RC)!"
- kill -HUP $PID
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
RC=$?
if test $RC != 0 ; then
echo "ldapmodrdn failed ($RC)!"
- kill -HUP $PID
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
if test $? != 0 ; then
echo "comparison failed - modrdn operations did not complete correctly"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit 1
fi
echo "Testing modrdn with newSuperior as child of target "
$LDAPMODRDN -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
- /dev/null 2>&1 -s 'cn=Sub1, ou=FooBar, cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com' 'cn=James A Jones 1' \
+ $TESTOUT 2>&1 -s 'cn=Sub1, ou=FooBar, cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com' \
'cn=James A Jones 1, ou=Alumni Association, ou=People, dc=example, dc=com' 'cn=James A Jones 1'
RC=$?
exit $RC
fi
-echo "Waiting 5 seconds for slapadd to build slapd database..."
-sleep 5
-
echo "Starting slapd on TCP/IP port $PORT1..."
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
PID=$!
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
exit 0
## Note to developers: when SLAPD_DEBUG=-1 the command
-## awk '/^do_extended$/ {if (c) {print c} c=0} /<===slap_sasl_match:/ {c++} END {print c}' testrun/slapd.1.log
+## awk '/^do_extended$/ {if (c) {print c} c=0} /<===slap_sasl_match:/ {c++} END {print c}' $TESTDIR/slapd.1.log
## must return the sequence 1 2 3 4 5 6 7 8 9 9 1 2 3 4 5 6 7 8 9 9 9 1
## to indicate that the authzFrom and authzTo rules applied in the right order.
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
-if test "$BACKEND" != "bdb" -a "$BACKEND" != "hdb" ; then
+if test "$BACKEND" != "bdb" && test "$BACKEND" != "hdb" ; then
echo "Test does not support $BACKEND"
exit 0
fi
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
-if test "$BACKEND" != "bdb" -a "$BACKEND" != "hdb" ; then
+if test "$BACKEND" != "bdb" && test "$BACKEND" != "hdb" ; then
echo "Test does not support $BACKEND"
exit 0
fi
sleep 5
done
if test $RC != 0 ; then
- echo "ldapsearch failed $(RC)!"
+ echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
-if test "$BACKEND" != "bdb" -a "$BACKEND" != "hdb" ; then
+if test "$BACKEND" != "bdb" && test "$BACKEND" != "hdb" ; then
echo "Test does not support $BACKEND"
exit 0
fi
echo "Searching unmodified database..."
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 | \
- egrep "(manager|secretary):" | sed "s/george/foster/g" | \
+ $EGREP_CMD "(manager|secretary):" | sed "s/george/foster/g" | \
sort > $SEARCHOUT 2>&1
RC=$?
echo "Using ldapsearch to check dependents new rdn..."
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 | \
- egrep "(manager|secretary):" | sort > $SEARCHFLT 2>&1
+ $EGREP_CMD "(manager|secretary):" | sort > $SEARCHFLT 2>&1
RC=$?
if test $RC != 0 ; then
if test $? != 0 ; then
echo "comparison failed - modify operations did not complete correctly"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit 1
fi
echo "Using ldapsearch to verify dependents have been deleted..."
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 | \
- egrep "(manager|secretary):" > $SEARCHFLT 2>&1
+ $EGREP_CMD "(manager|secretary):" > $SEARCHFLT 2>&1
RC=$?
if test $RC != 0 ; then
RC=`grep -c foster $SEARCHFLT`
if test $RC != 0 ; then
echo "dependent modify failed - dependents were not deleted"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit 1
fi
echo "Comparison of database generated via slapadd succeeded"
echo "Cleaning up database directories..."
-/bin/rm -rf testrun/db.*
+/bin/rm -rf $TESTDIR/db.*
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
DN="cn=Mark Elliot,ou=Alumni Association,ou=People,$BASEDN"
echo "Comparing \"$DN\" on port $P..."
- $LDAPCOMPARE -h $LOCALHOST -p $P "$DN" "cn:Mark Elliot"
+ $LDAPCOMPARE -h $LOCALHOST -p $P "$DN" "cn:Mark Elliot" \
> $TESTOUT 2>&1
RC=$?
- if test $RC != 0 ; then
+ if test $RC != 6 ; then
echo "ldapcompare failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
DN="ou=Other,$BASEDN"
echo "Comparing \"$DN\" on port $P with manageDSAit control..."
- $LDAPCOMPARE -h $LOCALHOST -p $P -M "$DN" "ou:Other"
+ $LDAPCOMPARE -h $LOCALHOST -p $P -M "$DN" "ou:Other" \
> $TESTOUT 2>&1
RC=$?
- if test $RC != 0 ; then
+ if test $RC != 6 ; then
echo "ldapcompare failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
exit 0
;;
*)
- echo "Compare failed ($RC)!"
+ echo "Modify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
;;
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
;;
*)
- echo "Compare failed ($RC)!"
+ echo "WhoAmI failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
;;
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
# NOTE: this could be added to all tests...
-if test "$BACKEND" = "bdb" -o "$BACKEND" = "hdb" ; then
+if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
if test "x$DB_CONFIG" != "x" ; then \
if test -f $DB_CONFIG ; then
echo "==> using DB_CONFIG \"$DB_CONFIG\""