Home | History | Annotate | Line # | Download | only in back-ldif
ldif.c revision 1.1.1.6.6.1
      1  1.1.1.6.6.1    martin /*	$NetBSD: ldif.c,v 1.1.1.6.6.1 2019/08/10 06:17:18 martin Exp $	*/
      2      1.1.1.2     lukem 
      3          1.1     lukem /* ldif.c - the ldif backend */
      4      1.1.1.4      tron /* $OpenLDAP$ */
      5          1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6          1.1     lukem  *
      7  1.1.1.6.6.1    martin  * Copyright 2005-2019 The OpenLDAP Foundation.
      8          1.1     lukem  * All rights reserved.
      9          1.1     lukem  *
     10          1.1     lukem  * Redistribution and use in source and binary forms, with or without
     11          1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     12          1.1     lukem  * Public License.
     13          1.1     lukem  *
     14          1.1     lukem  * A copy of this license is available in the file LICENSE in the
     15          1.1     lukem  * top-level directory of the distribution or, alternatively, at
     16          1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     17          1.1     lukem  */
     18          1.1     lukem /* ACKNOWLEDGEMENTS:
     19          1.1     lukem  * This work was originally developed by Eric Stokes for inclusion
     20          1.1     lukem  * in OpenLDAP Software.
     21          1.1     lukem  */
     22          1.1     lukem 
     23      1.1.1.5  christos #include <sys/cdefs.h>
     24  1.1.1.6.6.1    martin __RCSID("$NetBSD: ldif.c,v 1.1.1.6.6.1 2019/08/10 06:17:18 martin Exp $");
     25      1.1.1.5  christos 
     26          1.1     lukem #include "portable.h"
     27          1.1     lukem #include <stdio.h>
     28          1.1     lukem #include <ac/string.h>
     29          1.1     lukem #include <sys/types.h>
     30          1.1     lukem #include <sys/stat.h>
     31          1.1     lukem #include <ac/dirent.h>
     32          1.1     lukem #include <fcntl.h>
     33          1.1     lukem #include <ac/errno.h>
     34          1.1     lukem #include <ac/unistd.h>
     35          1.1     lukem #include "slap.h"
     36          1.1     lukem #include "lutil.h"
     37          1.1     lukem #include "config.h"
     38          1.1     lukem 
     39      1.1.1.2     lukem struct ldif_tool {
     40      1.1.1.2     lukem 	Entry	**entries;			/* collected by bi_tool_entry_first() */
     41      1.1.1.2     lukem 	ID		elen;				/* length of entries[] array */
     42      1.1.1.2     lukem 	ID		ecount;				/* number of entries */
     43      1.1.1.2     lukem 	ID		ecurrent;			/* bi_tool_entry_next() position */
     44      1.1.1.2     lukem #	define	ENTRY_BUFF_INCREMENT 500 /* initial entries[] length */
     45      1.1.1.3      adam 	struct berval	*tl_base;
     46      1.1.1.3      adam 	int		tl_scope;
     47      1.1.1.3      adam 	Filter		*tl_filter;
     48      1.1.1.2     lukem };
     49          1.1     lukem 
     50      1.1.1.2     lukem /* Per-database data */
     51          1.1     lukem struct ldif_info {
     52      1.1.1.2     lukem 	struct berval li_base_path;			/* database directory */
     53      1.1.1.2     lukem 	struct ldif_tool li_tool;			/* for slap tools */
     54      1.1.1.2     lukem 	/*
     55      1.1.1.2     lukem 	 * Read-only LDAP requests readlock li_rdwr for filesystem input.
     56      1.1.1.2     lukem 	 * Update requests first lock li_modop_mutex for filesystem I/O,
     57      1.1.1.2     lukem 	 * and then writelock li_rdwr as well for filesystem output.
     58      1.1.1.2     lukem 	 * This allows update requests to do callbacks that acquire
     59      1.1.1.2     lukem 	 * read locks, e.g. access controls that inspect entries.
     60      1.1.1.2     lukem 	 * (An alternative would be recursive read/write locks.)
     61      1.1.1.2     lukem 	 */
     62      1.1.1.2     lukem 	ldap_pvt_thread_mutex_t	li_modop_mutex; /* serialize update requests */
     63      1.1.1.2     lukem 	ldap_pvt_thread_rdwr_t	li_rdwr;	/* no other I/O when writing */
     64          1.1     lukem };
     65          1.1     lukem 
     66      1.1.1.4      tron static int write_data( int fd, const char *spew, int len, int *save_errno );
     67      1.1.1.4      tron 
     68          1.1     lukem #ifdef _WIN32
     69          1.1     lukem #define mkdir(a,b)	mkdir(a)
     70      1.1.1.2     lukem #define move_file(from, to) (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
     71      1.1.1.2     lukem #else
     72      1.1.1.2     lukem #define move_file(from, to) rename(from, to)
     73          1.1     lukem #endif
     74      1.1.1.2     lukem #define move_dir(from, to) rename(from, to)
     75          1.1     lukem 
     76          1.1     lukem 
     77          1.1     lukem #define LDIF	".ldif"
     78          1.1     lukem #define LDIF_FILETYPE_SEP	'.'			/* LDIF[0] */
     79          1.1     lukem 
     80          1.1     lukem /*
     81          1.1     lukem  * Unsafe/translated characters in the filesystem.
     82          1.1     lukem  *
     83          1.1     lukem  * LDIF_UNSAFE_CHAR(c) returns true if the character c is not to be used
     84      1.1.1.2     lukem  * in relative filenames, except it should accept '\\', '{' and '}' even
     85      1.1.1.2     lukem  * if unsafe.  The value should be a constant expression.
     86          1.1     lukem  *
     87          1.1     lukem  * If '\\' is unsafe, #define LDIF_ESCAPE_CHAR as a safe character.
     88          1.1     lukem  * If '{' and '}' are unsafe, #define IX_FSL/IX_FSR as safe characters.
     89          1.1     lukem  * (Not digits, '-' or '+'.  IX_FSL == IX_FSR is allowed.)
     90          1.1     lukem  *
     91          1.1     lukem  * Characters are escaped as LDIF_ESCAPE_CHAR followed by two hex digits,
     92          1.1     lukem  * except '\\' is replaced with LDIF_ESCAPE_CHAR and {} with IX_FS[LR].
     93          1.1     lukem  * Also some LDIF special chars are hex-escaped.
     94          1.1     lukem  *
     95          1.1     lukem  * Thus an LDIF filename is a valid normalized RDN (or suffix DN)
     96          1.1     lukem  * followed by ".ldif", except with '\\' replaced with LDIF_ESCAPE_CHAR.
     97          1.1     lukem  */
     98          1.1     lukem 
     99          1.1     lukem #ifndef _WIN32
    100          1.1     lukem 
    101          1.1     lukem /*
    102          1.1     lukem  * Unix/MacOSX version.  ':' vs '/' can cause confusion on MacOSX so we
    103          1.1     lukem  * escape both.  We escape them on Unix so both OS variants get the same
    104          1.1     lukem  * filenames.
    105          1.1     lukem  */
    106          1.1     lukem #define LDIF_ESCAPE_CHAR	'\\'
    107          1.1     lukem #define LDIF_UNSAFE_CHAR(c)	((c) == '/' || (c) == ':')
    108          1.1     lukem 
    109          1.1     lukem #else /* _WIN32 */
    110          1.1     lukem 
    111          1.1     lukem /* Windows version - Microsoft's list of unsafe characters, except '\\' */
    112      1.1.1.2     lukem #define LDIF_ESCAPE_CHAR	'^'			/* Not '\\' (unsafe on Windows) */
    113          1.1     lukem #define LDIF_UNSAFE_CHAR(c)	\
    114          1.1     lukem 	((c) == '/' || (c) == ':' || \
    115          1.1     lukem 	 (c) == '<' || (c) == '>' || (c) == '"' || \
    116          1.1     lukem 	 (c) == '|' || (c) == '?' || (c) == '*')
    117          1.1     lukem 
    118          1.1     lukem #endif /* !_WIN32 */
    119          1.1     lukem 
    120          1.1     lukem /*
    121          1.1     lukem  * Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}bdb").
    122          1.1     lukem  * IX_DN* are for LDAP RDNs, IX_FS* for their .ldif filenames.
    123          1.1     lukem  */
    124          1.1     lukem #define IX_DNL	'{'
    125          1.1     lukem #define	IX_DNR	'}'
    126          1.1     lukem #ifndef IX_FSL
    127          1.1     lukem #define	IX_FSL	IX_DNL
    128          1.1     lukem #define IX_FSR	IX_DNR
    129          1.1     lukem #endif
    130          1.1     lukem 
    131          1.1     lukem /*
    132          1.1     lukem  * Test for unsafe chars, as well as chars handled specially by back-ldif:
    133          1.1     lukem  * - If the escape char is not '\\', it must itself be escaped.  Otherwise
    134          1.1     lukem  *   '\\' and the escape char would map to the same character.
    135          1.1     lukem  * - Escape the '.' in ".ldif", so the directory for an RDN that actually
    136          1.1     lukem  *   ends with ".ldif" can not conflict with a file of the same name.  And
    137          1.1     lukem  *   since some OSes/programs choke on multiple '.'s, escape all of them.
    138          1.1     lukem  * - If '{' and '}' are translated to some other characters, those
    139          1.1     lukem  *   characters must in turn be escaped when they occur in an RDN.
    140          1.1     lukem  */
    141          1.1     lukem #ifndef LDIF_NEED_ESCAPE
    142          1.1     lukem #define	LDIF_NEED_ESCAPE(c) \
    143          1.1     lukem 	((LDIF_UNSAFE_CHAR(c)) || \
    144          1.1     lukem 	 LDIF_MAYBE_UNSAFE(c, LDIF_ESCAPE_CHAR) || \
    145          1.1     lukem 	 LDIF_MAYBE_UNSAFE(c, LDIF_FILETYPE_SEP) || \
    146          1.1     lukem 	 LDIF_MAYBE_UNSAFE(c, IX_FSL) || \
    147          1.1     lukem 	 (IX_FSR != IX_FSL && LDIF_MAYBE_UNSAFE(c, IX_FSR)))
    148          1.1     lukem #endif
    149          1.1     lukem /*
    150          1.1     lukem  * Helper macro for LDIF_NEED_ESCAPE(): Treat character x as unsafe if
    151          1.1     lukem  * back-ldif does not already treat is specially.
    152          1.1     lukem  */
    153          1.1     lukem #define LDIF_MAYBE_UNSAFE(c, x) \
    154          1.1     lukem 	(!(LDIF_UNSAFE_CHAR(x) || (x) == '\\' || (x) == IX_DNL || (x) == IX_DNR) \
    155          1.1     lukem 	 && (c) == (x))
    156          1.1     lukem 
    157      1.1.1.2     lukem /* Collect other "safe char" tests here, until someone needs a fix. */
    158      1.1.1.2     lukem enum {
    159      1.1.1.2     lukem 	eq_unsafe = LDIF_UNSAFE_CHAR('='),
    160      1.1.1.2     lukem 	safe_filenames = STRLENOF("" LDAP_DIRSEP "") == 1 && !(
    161      1.1.1.2     lukem 		LDIF_UNSAFE_CHAR('-') || /* for "{-1}frontend" in bconfig.c */
    162      1.1.1.2     lukem 		LDIF_UNSAFE_CHAR(LDIF_ESCAPE_CHAR) ||
    163      1.1.1.2     lukem 		LDIF_UNSAFE_CHAR(IX_FSL) || LDIF_UNSAFE_CHAR(IX_FSR))
    164      1.1.1.2     lukem };
    165      1.1.1.2     lukem /* Sanity check: Try to force a compilation error if !safe_filenames */
    166      1.1.1.2     lukem typedef struct {
    167      1.1.1.2     lukem 	int assert_safe_filenames : safe_filenames ? 2 : -2;
    168      1.1.1.2     lukem } assert_safe_filenames[safe_filenames ? 2 : -2];
    169          1.1     lukem 
    170          1.1     lukem 
    171          1.1     lukem static ConfigTable ldifcfg[] = {
    172          1.1     lukem 	{ "directory", "dir", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
    173          1.1     lukem 		(void *)offsetof(struct ldif_info, li_base_path),
    174          1.1     lukem 		"( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
    175          1.1     lukem 			"DESC 'Directory for database content' "
    176          1.1     lukem 			"EQUALITY caseIgnoreMatch "
    177          1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    178          1.1     lukem 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
    179          1.1     lukem 		NULL, NULL, NULL, NULL }
    180          1.1     lukem };
    181          1.1     lukem 
    182          1.1     lukem static ConfigOCs ldifocs[] = {
    183          1.1     lukem 	{ "( OLcfgDbOc:2.1 "
    184          1.1     lukem 		"NAME 'olcLdifConfig' "
    185          1.1     lukem 		"DESC 'LDIF backend configuration' "
    186          1.1     lukem 		"SUP olcDatabaseConfig "
    187          1.1     lukem 		"MUST ( olcDbDirectory ) )", Cft_Database, ldifcfg },
    188          1.1     lukem 	{ NULL, 0, NULL }
    189          1.1     lukem };
    190          1.1     lukem 
    191          1.1     lukem 
    192      1.1.1.2     lukem /*
    193      1.1.1.2     lukem  * Handle file/directory names.
    194      1.1.1.2     lukem  */
    195      1.1.1.2     lukem 
    196          1.1     lukem /* Set *res = LDIF filename path for the normalized DN */
    197      1.1.1.2     lukem static int
    198      1.1.1.2     lukem ndn2path( Operation *op, struct berval *dn, struct berval *res, int empty_ok )
    199          1.1     lukem {
    200      1.1.1.2     lukem 	BackendDB *be = op->o_bd;
    201          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) be->be_private;
    202          1.1     lukem 	struct berval *suffixdn = &be->be_nsuffix[0];
    203          1.1     lukem 	const char *start, *end, *next, *p;
    204          1.1     lukem 	char ch, *ptr;
    205          1.1     lukem 	ber_len_t len;
    206          1.1     lukem 	static const char hex[] = "0123456789ABCDEF";
    207          1.1     lukem 
    208          1.1     lukem 	assert( dn != NULL );
    209          1.1     lukem 	assert( !BER_BVISNULL( dn ) );
    210          1.1     lukem 	assert( suffixdn != NULL );
    211          1.1     lukem 	assert( !BER_BVISNULL( suffixdn ) );
    212          1.1     lukem 	assert( dnIsSuffix( dn, suffixdn ) );
    213          1.1     lukem 
    214      1.1.1.2     lukem 	if ( dn->bv_len == 0 && !empty_ok ) {
    215      1.1.1.2     lukem 		return LDAP_UNWILLING_TO_PERFORM;
    216      1.1.1.2     lukem 	}
    217      1.1.1.2     lukem 
    218          1.1     lukem 	start = dn->bv_val;
    219          1.1     lukem 	end = start + dn->bv_len;
    220          1.1     lukem 
    221          1.1     lukem 	/* Room for dir, dirsep, dn, LDIF, "\hexpair"-escaping of unsafe chars */
    222          1.1     lukem 	len = li->li_base_path.bv_len + dn->bv_len + (1 + STRLENOF( LDIF ));
    223          1.1     lukem 	for ( p = start; p < end; ) {
    224          1.1     lukem 		ch = *p++;
    225          1.1     lukem 		if ( LDIF_NEED_ESCAPE( ch ) )
    226          1.1     lukem 			len += 2;
    227          1.1     lukem 	}
    228          1.1     lukem 	res->bv_val = ch_malloc( len + 1 );
    229          1.1     lukem 
    230          1.1     lukem 	ptr = lutil_strcopy( res->bv_val, li->li_base_path.bv_val );
    231          1.1     lukem 	for ( next = end - suffixdn->bv_len; end > start; end = next ) {
    232          1.1     lukem 		/* Set p = start of DN component, next = &',' or start of DN */
    233          1.1     lukem 		while ( (p = next) > start ) {
    234          1.1     lukem 			--next;
    235          1.1     lukem 			if ( DN_SEPARATOR( *next ) )
    236          1.1     lukem 				break;
    237          1.1     lukem 		}
    238          1.1     lukem 		/* Append <dirsep> <p..end-1: RDN or database-suffix> */
    239          1.1     lukem 		for ( *ptr++ = LDAP_DIRSEP[0]; p < end; *ptr++ = ch ) {
    240          1.1     lukem 			ch = *p++;
    241          1.1     lukem 			if ( LDIF_ESCAPE_CHAR != '\\' && ch == '\\' ) {
    242          1.1     lukem 				ch = LDIF_ESCAPE_CHAR;
    243          1.1     lukem 			} else if ( IX_FSL != IX_DNL && ch == IX_DNL ) {
    244          1.1     lukem 				ch = IX_FSL;
    245          1.1     lukem 			} else if ( IX_FSR != IX_DNR && ch == IX_DNR ) {
    246          1.1     lukem 				ch = IX_FSR;
    247          1.1     lukem 			} else if ( LDIF_NEED_ESCAPE( ch ) ) {
    248          1.1     lukem 				*ptr++ = LDIF_ESCAPE_CHAR;
    249          1.1     lukem 				*ptr++ = hex[(ch & 0xFFU) >> 4];
    250          1.1     lukem 				ch = hex[ch & 0x0FU];
    251          1.1     lukem 			}
    252          1.1     lukem 		}
    253          1.1     lukem 	}
    254          1.1     lukem 	ptr = lutil_strcopy( ptr, LDIF );
    255          1.1     lukem 	res->bv_len = ptr - res->bv_val;
    256          1.1     lukem 
    257          1.1     lukem 	assert( res->bv_len <= len );
    258      1.1.1.2     lukem 
    259      1.1.1.2     lukem 	return LDAP_SUCCESS;
    260          1.1     lukem }
    261          1.1     lukem 
    262      1.1.1.2     lukem /*
    263      1.1.1.2     lukem  * *dest = dupbv(<dir + LDAP_DIRSEP>), plus room for <more>-sized filename.
    264      1.1.1.2     lukem  * Return pointer past the dirname.
    265      1.1.1.2     lukem  */
    266      1.1.1.2     lukem static char *
    267      1.1.1.2     lukem fullpath_alloc( struct berval *dest, const struct berval *dir, ber_len_t more )
    268      1.1.1.2     lukem {
    269      1.1.1.2     lukem 	char *s = SLAP_MALLOC( dir->bv_len + more + 2 );
    270      1.1.1.2     lukem 
    271      1.1.1.2     lukem 	dest->bv_val = s;
    272      1.1.1.2     lukem 	if ( s == NULL ) {
    273      1.1.1.2     lukem 		dest->bv_len = 0;
    274      1.1.1.2     lukem 		Debug( LDAP_DEBUG_ANY, "back-ldif: out of memory\n", 0, 0, 0 );
    275      1.1.1.2     lukem 	} else {
    276      1.1.1.2     lukem 		s = lutil_strcopy( dest->bv_val, dir->bv_val );
    277      1.1.1.2     lukem 		*s++ = LDAP_DIRSEP[0];
    278      1.1.1.2     lukem 		*s = '\0';
    279      1.1.1.2     lukem 		dest->bv_len = s - dest->bv_val;
    280      1.1.1.2     lukem 	}
    281      1.1.1.2     lukem 	return s;
    282      1.1.1.2     lukem }
    283      1.1.1.2     lukem 
    284      1.1.1.2     lukem /*
    285      1.1.1.2     lukem  * Append filename to fullpath_alloc() dirname or replace previous filename.
    286      1.1.1.2     lukem  * dir_end = fullpath_alloc() return value.
    287      1.1.1.2     lukem  */
    288      1.1.1.2     lukem #define FILL_PATH(fpath, dir_end, filename) \
    289      1.1.1.2     lukem 	((fpath)->bv_len = lutil_strcopy(dir_end, filename) - (fpath)->bv_val)
    290      1.1.1.2     lukem 
    291      1.1.1.2     lukem 
    292      1.1.1.2     lukem /* .ldif entry filename length <-> subtree dirname length. */
    293      1.1.1.2     lukem #define ldif2dir_len(bv)  ((bv).bv_len -= STRLENOF(LDIF))
    294      1.1.1.2     lukem #define dir2ldif_len(bv)  ((bv).bv_len += STRLENOF(LDIF))
    295      1.1.1.2     lukem /* .ldif entry filename <-> subtree dirname, both with dirname length. */
    296      1.1.1.2     lukem #define ldif2dir_name(bv) ((bv).bv_val[(bv).bv_len] = '\0')
    297      1.1.1.2     lukem #define dir2ldif_name(bv) ((bv).bv_val[(bv).bv_len] = LDIF_FILETYPE_SEP)
    298      1.1.1.2     lukem 
    299      1.1.1.2     lukem /* Get the parent directory path, plus the LDIF suffix overwritten by a \0. */
    300      1.1.1.2     lukem static int
    301      1.1.1.2     lukem get_parent_path( struct berval *dnpath, struct berval *res )
    302      1.1.1.2     lukem {
    303      1.1.1.2     lukem 	ber_len_t i = dnpath->bv_len;
    304      1.1.1.2     lukem 
    305      1.1.1.2     lukem 	while ( i > 0 && dnpath->bv_val[ --i ] != LDAP_DIRSEP[0] ) ;
    306      1.1.1.2     lukem 	if ( res == NULL ) {
    307      1.1.1.2     lukem 		res = dnpath;
    308      1.1.1.2     lukem 	} else {
    309      1.1.1.2     lukem 		res->bv_val = SLAP_MALLOC( i + 1 + STRLENOF(LDIF) );
    310      1.1.1.2     lukem 		if ( res->bv_val == NULL )
    311      1.1.1.2     lukem 			return LDAP_OTHER;
    312      1.1.1.2     lukem 		AC_MEMCPY( res->bv_val, dnpath->bv_val, i );
    313      1.1.1.2     lukem 	}
    314      1.1.1.2     lukem 	res->bv_len = i;
    315      1.1.1.2     lukem 	strcpy( res->bv_val + i, LDIF );
    316      1.1.1.2     lukem 	res->bv_val[i] = '\0';
    317      1.1.1.2     lukem 	return LDAP_SUCCESS;
    318      1.1.1.2     lukem }
    319      1.1.1.2     lukem 
    320      1.1.1.2     lukem /* Make temporary filename pattern for mkstemp() based on dnpath. */
    321      1.1.1.2     lukem static char *
    322      1.1.1.2     lukem ldif_tempname( const struct berval *dnpath )
    323      1.1.1.2     lukem {
    324      1.1.1.2     lukem 	static const char suffix[] = ".XXXXXX";
    325      1.1.1.2     lukem 	ber_len_t len = dnpath->bv_len - STRLENOF( LDIF );
    326      1.1.1.2     lukem 	char *name = SLAP_MALLOC( len + sizeof( suffix ) );
    327      1.1.1.2     lukem 
    328      1.1.1.2     lukem 	if ( name != NULL ) {
    329      1.1.1.2     lukem 		AC_MEMCPY( name, dnpath->bv_val, len );
    330      1.1.1.2     lukem 		strcpy( name + len, suffix );
    331      1.1.1.2     lukem 	}
    332      1.1.1.2     lukem 	return name;
    333      1.1.1.2     lukem }
    334      1.1.1.2     lukem 
    335      1.1.1.4      tron /* CRC-32 table for the polynomial:
    336      1.1.1.4      tron  * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
    337      1.1.1.4      tron  *
    338      1.1.1.4      tron  * As used by zlib
    339      1.1.1.4      tron  */
    340      1.1.1.4      tron 
    341      1.1.1.4      tron static const ber_uint_t crctab[256] = {
    342      1.1.1.4      tron 	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
    343      1.1.1.4      tron 	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
    344      1.1.1.4      tron 	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
    345      1.1.1.4      tron 	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
    346      1.1.1.4      tron 	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
    347      1.1.1.4      tron 	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
    348      1.1.1.4      tron 	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
    349      1.1.1.4      tron 	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
    350      1.1.1.4      tron 	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
    351      1.1.1.4      tron 	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
    352      1.1.1.4      tron 	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
    353      1.1.1.4      tron 	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
    354      1.1.1.4      tron 	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
    355      1.1.1.4      tron 	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
    356      1.1.1.4      tron 	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
    357      1.1.1.4      tron 	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
    358      1.1.1.4      tron 	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
    359      1.1.1.4      tron 	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
    360      1.1.1.4      tron 	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
    361      1.1.1.4      tron 	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
    362      1.1.1.4      tron 	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
    363      1.1.1.4      tron 	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
    364      1.1.1.4      tron 	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
    365      1.1.1.4      tron 	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
    366      1.1.1.4      tron 	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
    367      1.1.1.4      tron 	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
    368      1.1.1.4      tron 	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
    369      1.1.1.4      tron 	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
    370      1.1.1.4      tron 	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
    371      1.1.1.4      tron 	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
    372      1.1.1.4      tron 	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
    373      1.1.1.4      tron 	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
    374      1.1.1.4      tron 	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
    375      1.1.1.4      tron 	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
    376      1.1.1.4      tron 	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
    377      1.1.1.4      tron 	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
    378      1.1.1.4      tron 	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
    379      1.1.1.4      tron 	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
    380      1.1.1.4      tron 	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
    381      1.1.1.4      tron 	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
    382      1.1.1.4      tron 	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
    383      1.1.1.4      tron 	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
    384      1.1.1.4      tron 	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
    385      1.1.1.4      tron 	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
    386      1.1.1.4      tron 	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
    387      1.1.1.4      tron 	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
    388      1.1.1.4      tron 	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
    389      1.1.1.4      tron 	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
    390      1.1.1.4      tron 	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
    391      1.1.1.4      tron 	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
    392      1.1.1.4      tron 	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
    393      1.1.1.4      tron 	0x2d02ef8dL
    394      1.1.1.4      tron };
    395      1.1.1.4      tron 
    396      1.1.1.4      tron #define CRC1	crc = crctab[(crc ^ *buf++) & 0xff] ^ (crc >> 8)
    397      1.1.1.4      tron #define CRC8	CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1
    398      1.1.1.4      tron unsigned int
    399      1.1.1.4      tron crc32(const void *vbuf, int len)
    400      1.1.1.4      tron {
    401      1.1.1.4      tron 	const unsigned char	*buf = vbuf;
    402      1.1.1.4      tron 	ber_uint_t		crc = 0xffffffff;
    403      1.1.1.4      tron 
    404      1.1.1.4      tron 	while (len > 7) {
    405      1.1.1.4      tron 		CRC8;
    406      1.1.1.4      tron 		len -= 8;
    407      1.1.1.4      tron 	}
    408      1.1.1.4      tron 	while (len) {
    409      1.1.1.4      tron 		CRC1;
    410      1.1.1.4      tron 		len--;
    411      1.1.1.4      tron 	}
    412      1.1.1.4      tron 
    413      1.1.1.4      tron 	return crc ^ 0xffffffff;
    414      1.1.1.4      tron }
    415      1.1.1.4      tron 
    416      1.1.1.2     lukem /*
    417      1.1.1.2     lukem  * Read a file, or stat() it if datap == NULL.  Allocate and fill *datap.
    418      1.1.1.2     lukem  * Return LDAP_SUCCESS, LDAP_NO_SUCH_OBJECT (no such file), or another error.
    419      1.1.1.2     lukem  */
    420      1.1.1.2     lukem static int
    421      1.1.1.2     lukem ldif_read_file( const char *path, char **datap )
    422      1.1.1.2     lukem {
    423      1.1.1.4      tron 	int rc = LDAP_SUCCESS, fd, len;
    424      1.1.1.2     lukem 	int res = -1;	/* 0:success, <0:error, >0:file too big/growing. */
    425          1.1     lukem 	struct stat st;
    426      1.1.1.4      tron 	char *data = NULL, *ptr = NULL;
    427      1.1.1.4      tron 	const char *msg;
    428          1.1     lukem 
    429      1.1.1.2     lukem 	if ( datap == NULL ) {
    430      1.1.1.2     lukem 		res = stat( path, &st );
    431      1.1.1.2     lukem 		goto done;
    432      1.1.1.2     lukem 	}
    433      1.1.1.2     lukem 	fd = open( path, O_RDONLY );
    434      1.1.1.2     lukem 	if ( fd >= 0 ) {
    435      1.1.1.2     lukem 		if ( fstat( fd, &st ) == 0 ) {
    436      1.1.1.2     lukem 			if ( st.st_size > INT_MAX - 2 ) {
    437      1.1.1.2     lukem 				res = 1;
    438      1.1.1.2     lukem 			} else {
    439      1.1.1.2     lukem 				len = st.st_size + 1; /* +1 detects file size > st.st_size */
    440      1.1.1.2     lukem 				*datap = data = ptr = SLAP_MALLOC( len + 1 );
    441      1.1.1.2     lukem 				if ( ptr != NULL ) {
    442      1.1.1.2     lukem 					while ( len && (res = read( fd, ptr, len )) ) {
    443      1.1.1.2     lukem 						if ( res > 0 ) {
    444      1.1.1.2     lukem 							len -= res;
    445      1.1.1.2     lukem 							ptr += res;
    446      1.1.1.2     lukem 						} else if ( errno != EINTR ) {
    447      1.1.1.2     lukem 							break;
    448      1.1.1.2     lukem 						}
    449      1.1.1.2     lukem 					}
    450      1.1.1.2     lukem 					*ptr = '\0';
    451      1.1.1.2     lukem 				}
    452      1.1.1.2     lukem 			}
    453          1.1     lukem 		}
    454      1.1.1.2     lukem 		if ( close( fd ) < 0 )
    455      1.1.1.2     lukem 			res = -1;
    456      1.1.1.2     lukem 	}
    457      1.1.1.2     lukem 
    458      1.1.1.2     lukem  done:
    459      1.1.1.2     lukem 	if ( res == 0 ) {
    460      1.1.1.4      tron #ifdef LDAP_DEBUG
    461      1.1.1.4      tron 		msg = "entry file exists";
    462      1.1.1.4      tron 		if ( datap ) {
    463      1.1.1.4      tron 			msg = "read entry file";
    464      1.1.1.4      tron 			len = ptr - data;
    465      1.1.1.4      tron 			ptr = strstr( data, "\n# CRC32" );
    466      1.1.1.4      tron 			if (!ptr) {
    467      1.1.1.4      tron 				msg = "read entry file without checksum";
    468      1.1.1.4      tron 			} else {
    469      1.1.1.4      tron 				unsigned int crc1 = 0, crc2 = 1;
    470      1.1.1.4      tron 				if ( sscanf( ptr + 9, "%08x", &crc1) == 1) {
    471      1.1.1.4      tron 					ptr = strchr(ptr+1, '\n');
    472      1.1.1.4      tron 					if ( ptr ) {
    473      1.1.1.4      tron 						ptr++;
    474      1.1.1.4      tron 						len -= (ptr - data);
    475      1.1.1.4      tron 						crc2 = crc32( ptr, len );
    476      1.1.1.4      tron 					}
    477      1.1.1.4      tron 				}
    478      1.1.1.4      tron 				if ( crc1 != crc2 ) {
    479      1.1.1.4      tron 					Debug( LDAP_DEBUG_ANY, "ldif_read_file: checksum error on \"%s\"\n",
    480      1.1.1.4      tron 						path, 0, 0 );
    481      1.1.1.4      tron 					return rc;
    482      1.1.1.4      tron 				}
    483      1.1.1.4      tron 			}
    484      1.1.1.4      tron 		}
    485      1.1.1.4      tron 		Debug( LDAP_DEBUG_TRACE, "ldif_read_file: %s: \"%s\"\n", msg, path, 0 );
    486      1.1.1.4      tron #endif /* LDAP_DEBUG */
    487      1.1.1.2     lukem 	} else {
    488      1.1.1.2     lukem 		if ( res < 0 && errno == ENOENT ) {
    489      1.1.1.2     lukem 			Debug( LDAP_DEBUG_TRACE, "ldif_read_file: "
    490      1.1.1.2     lukem 				"no entry file \"%s\"\n", path, 0, 0 );
    491      1.1.1.2     lukem 			rc = LDAP_NO_SUCH_OBJECT;
    492      1.1.1.2     lukem 		} else {
    493      1.1.1.4      tron 			msg = res < 0 ? STRERROR( errno ) : "bad stat() size";
    494      1.1.1.2     lukem 			Debug( LDAP_DEBUG_ANY, "ldif_read_file: %s for \"%s\"\n",
    495      1.1.1.2     lukem 				msg, path, 0 );
    496      1.1.1.2     lukem 			rc = LDAP_OTHER;
    497          1.1     lukem 		}
    498      1.1.1.2     lukem 		if ( data != NULL )
    499      1.1.1.2     lukem 			SLAP_FREE( data );
    500          1.1     lukem 	}
    501      1.1.1.2     lukem 	return rc;
    502          1.1     lukem }
    503          1.1     lukem 
    504          1.1     lukem /*
    505          1.1     lukem  * return nonnegative for success or -1 for error
    506          1.1     lukem  * do not return numbers less than -1
    507          1.1     lukem  */
    508      1.1.1.2     lukem static int
    509      1.1.1.2     lukem spew_file( int fd, const char *spew, int len, int *save_errno )
    510      1.1.1.2     lukem {
    511      1.1.1.4      tron 	int writeres;
    512      1.1.1.4      tron #define HEADER	"# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.\n"
    513      1.1.1.4      tron 	char header[sizeof(HEADER "# CRC32 12345678\n")];
    514      1.1.1.2     lukem 
    515      1.1.1.4      tron 	sprintf(header, HEADER "# CRC32 %08x\n", crc32(spew, len));
    516      1.1.1.4      tron 	writeres = write_data(fd, header, sizeof(header)-1, save_errno);
    517      1.1.1.4      tron 	return writeres < 0 ? writeres : write_data(fd, spew, len, save_errno);
    518      1.1.1.4      tron }
    519      1.1.1.4      tron 
    520      1.1.1.4      tron static int
    521      1.1.1.4      tron write_data( int fd, const char *spew, int len, int *save_errno )
    522      1.1.1.4      tron {
    523      1.1.1.4      tron 	int writeres = 0;
    524          1.1     lukem 	while(len > 0) {
    525          1.1     lukem 		writeres = write(fd, spew, len);
    526          1.1     lukem 		if(writeres == -1) {
    527      1.1.1.2     lukem 			*save_errno = errno;
    528      1.1.1.2     lukem 			if (*save_errno != EINTR)
    529      1.1.1.2     lukem 				break;
    530          1.1     lukem 		}
    531          1.1     lukem 		else {
    532          1.1     lukem 			spew += writeres;
    533          1.1     lukem 			len -= writeres;
    534          1.1     lukem 		}
    535          1.1     lukem 	}
    536          1.1     lukem 	return writeres;
    537          1.1     lukem }
    538          1.1     lukem 
    539      1.1.1.2     lukem /* Write an entry LDIF file.  Create parentdir first if non-NULL. */
    540          1.1     lukem static int
    541      1.1.1.2     lukem ldif_write_entry(
    542      1.1.1.2     lukem 	Operation *op,
    543      1.1.1.2     lukem 	Entry *e,
    544      1.1.1.2     lukem 	const struct berval *path,
    545      1.1.1.2     lukem 	const char *parentdir,
    546      1.1.1.2     lukem 	const char **text )
    547          1.1     lukem {
    548      1.1.1.2     lukem 	int rc = LDAP_OTHER, res, save_errno = 0;
    549      1.1.1.2     lukem 	int fd, entry_length;
    550      1.1.1.2     lukem 	char *entry_as_string, *tmpfname;
    551      1.1.1.2     lukem 
    552      1.1.1.2     lukem 	if ( op->o_abandon )
    553      1.1.1.2     lukem 		return SLAPD_ABANDON;
    554          1.1     lukem 
    555      1.1.1.2     lukem 	if ( parentdir != NULL && mkdir( parentdir, 0750 ) < 0 ) {
    556          1.1     lukem 		save_errno = errno;
    557      1.1.1.2     lukem 		Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
    558      1.1.1.2     lukem 			"cannot create parent directory",
    559      1.1.1.2     lukem 			parentdir, STRERROR( save_errno ) );
    560      1.1.1.2     lukem 		*text = "internal error (cannot create parent directory)";
    561      1.1.1.2     lukem 		return rc;
    562      1.1.1.2     lukem 	}
    563      1.1.1.2     lukem 
    564      1.1.1.2     lukem 	tmpfname = ldif_tempname( path );
    565      1.1.1.2     lukem 	fd = tmpfname == NULL ? -1 : mkstemp( tmpfname );
    566      1.1.1.2     lukem 	if ( fd < 0 ) {
    567      1.1.1.2     lukem 		save_errno = errno;
    568      1.1.1.2     lukem 		Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s for \"%s\": %s\n",
    569      1.1.1.2     lukem 			"cannot create file", e->e_dn, STRERROR( save_errno ) );
    570      1.1.1.2     lukem 		*text = "internal error (cannot create file)";
    571          1.1     lukem 
    572          1.1     lukem 	} else {
    573      1.1.1.2     lukem 		ber_len_t dn_len = e->e_name.bv_len;
    574          1.1     lukem 		struct berval rdn;
    575          1.1     lukem 
    576          1.1     lukem 		/* Only save the RDN onto disk */
    577          1.1     lukem 		dnRdn( &e->e_name, &rdn );
    578      1.1.1.2     lukem 		if ( rdn.bv_len != dn_len ) {
    579          1.1     lukem 			e->e_name.bv_val[rdn.bv_len] = '\0';
    580          1.1     lukem 			e->e_name.bv_len = rdn.bv_len;
    581          1.1     lukem 		}
    582          1.1     lukem 
    583      1.1.1.2     lukem 		res = -2;
    584      1.1.1.2     lukem 		ldap_pvt_thread_mutex_lock( &entry2str_mutex );
    585      1.1.1.2     lukem 		entry_as_string = entry2str( e, &entry_length );
    586      1.1.1.2     lukem 		if ( entry_as_string != NULL )
    587      1.1.1.2     lukem 			res = spew_file( fd, entry_as_string, entry_length, &save_errno );
    588      1.1.1.2     lukem 		ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
    589          1.1     lukem 
    590          1.1     lukem 		/* Restore full DN */
    591      1.1.1.2     lukem 		if ( rdn.bv_len != dn_len ) {
    592      1.1.1.2     lukem 			e->e_name.bv_val[rdn.bv_len] = ',';
    593      1.1.1.2     lukem 			e->e_name.bv_len = dn_len;
    594          1.1     lukem 		}
    595          1.1     lukem 
    596      1.1.1.2     lukem 		if ( close( fd ) < 0 && res >= 0 ) {
    597      1.1.1.2     lukem 			res = -1;
    598      1.1.1.2     lukem 			save_errno = errno;
    599      1.1.1.2     lukem 		}
    600          1.1     lukem 
    601      1.1.1.2     lukem 		if ( res >= 0 ) {
    602      1.1.1.2     lukem 			if ( move_file( tmpfname, path->bv_val ) == 0 ) {
    603      1.1.1.2     lukem 				Debug( LDAP_DEBUG_TRACE, "ldif_write_entry: "
    604      1.1.1.2     lukem 					"wrote entry \"%s\"\n", e->e_name.bv_val, 0, 0 );
    605      1.1.1.2     lukem 				rc = LDAP_SUCCESS;
    606          1.1     lukem 			} else {
    607      1.1.1.2     lukem 				save_errno = errno;
    608      1.1.1.2     lukem 				Debug( LDAP_DEBUG_ANY, "ldif_write_entry: "
    609      1.1.1.2     lukem 					"could not put entry file for \"%s\" in place: %s\n",
    610      1.1.1.2     lukem 					e->e_name.bv_val, STRERROR( save_errno ), 0 );
    611      1.1.1.2     lukem 				*text = "internal error (could not put entry file in place)";
    612      1.1.1.2     lukem 			}
    613      1.1.1.2     lukem 		} else if ( res == -1 ) {
    614      1.1.1.2     lukem 			Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
    615      1.1.1.2     lukem 				"write error to", tmpfname, STRERROR( save_errno ) );
    616      1.1.1.2     lukem 			*text = "internal error (write error to entry file)";
    617          1.1     lukem 		}
    618          1.1     lukem 
    619      1.1.1.2     lukem 		if ( rc != LDAP_SUCCESS ) {
    620          1.1     lukem 			unlink( tmpfname );
    621          1.1     lukem 		}
    622          1.1     lukem 	}
    623          1.1     lukem 
    624      1.1.1.2     lukem 	if ( tmpfname )
    625      1.1.1.2     lukem 		SLAP_FREE( tmpfname );
    626      1.1.1.2     lukem 	return rc;
    627          1.1     lukem }
    628          1.1     lukem 
    629      1.1.1.2     lukem /*
    630      1.1.1.2     lukem  * Read the entry at path, or if entryp==NULL just see if it exists.
    631      1.1.1.2     lukem  * pdn and pndn are the parent's DN and normalized DN, or both NULL.
    632      1.1.1.2     lukem  * Return an LDAP result code.
    633      1.1.1.2     lukem  */
    634      1.1.1.2     lukem static int
    635      1.1.1.2     lukem ldif_read_entry(
    636      1.1.1.2     lukem 	Operation *op,
    637      1.1.1.2     lukem 	const char *path,
    638          1.1     lukem 	struct berval *pdn,
    639      1.1.1.2     lukem 	struct berval *pndn,
    640      1.1.1.2     lukem 	Entry **entryp,
    641      1.1.1.2     lukem 	const char **text )
    642          1.1     lukem {
    643      1.1.1.2     lukem 	int rc;
    644      1.1.1.2     lukem 	Entry *entry;
    645      1.1.1.2     lukem 	char *entry_as_string;
    646      1.1.1.2     lukem 	struct berval rdn;
    647          1.1     lukem 
    648      1.1.1.2     lukem 	/* TODO: Does slapd prevent Abandon of Bind as per rfc4511?
    649      1.1.1.2     lukem 	 * If so we need not check for LDAP_REQ_BIND here.
    650      1.1.1.2     lukem 	 */
    651      1.1.1.2     lukem 	if ( op->o_abandon && op->o_tag != LDAP_REQ_BIND )
    652      1.1.1.2     lukem 		return SLAPD_ABANDON;
    653      1.1.1.2     lukem 
    654      1.1.1.2     lukem 	rc = ldif_read_file( path, entryp ? &entry_as_string : NULL );
    655      1.1.1.2     lukem 
    656      1.1.1.2     lukem 	switch ( rc ) {
    657      1.1.1.2     lukem 	case LDAP_SUCCESS:
    658      1.1.1.2     lukem 		if ( entryp == NULL )
    659      1.1.1.2     lukem 			break;
    660      1.1.1.2     lukem 		*entryp = entry = str2entry( entry_as_string );
    661      1.1.1.2     lukem 		SLAP_FREE( entry_as_string );
    662      1.1.1.2     lukem 		if ( entry == NULL ) {
    663      1.1.1.2     lukem 			rc = LDAP_OTHER;
    664      1.1.1.2     lukem 			if ( text != NULL )
    665      1.1.1.2     lukem 				*text = "internal error (cannot parse some entry file)";
    666      1.1.1.2     lukem 			break;
    667          1.1     lukem 		}
    668      1.1.1.2     lukem 		if ( pdn == NULL || BER_BVISEMPTY( pdn ) )
    669      1.1.1.2     lukem 			break;
    670      1.1.1.2     lukem 		/* Append parent DN to DN from LDIF file */
    671      1.1.1.2     lukem 		rdn = entry->e_name;
    672      1.1.1.2     lukem 		build_new_dn( &entry->e_name, pdn, &rdn, NULL );
    673      1.1.1.2     lukem 		SLAP_FREE( rdn.bv_val );
    674      1.1.1.2     lukem 		rdn = entry->e_nname;
    675      1.1.1.2     lukem 		build_new_dn( &entry->e_nname, pndn, &rdn, NULL );
    676      1.1.1.2     lukem 		SLAP_FREE( rdn.bv_val );
    677      1.1.1.2     lukem 		break;
    678      1.1.1.2     lukem 
    679      1.1.1.2     lukem 	case LDAP_OTHER:
    680      1.1.1.2     lukem 		if ( text != NULL )
    681      1.1.1.2     lukem 			*text = entryp
    682      1.1.1.2     lukem 				? "internal error (cannot read some entry file)"
    683      1.1.1.2     lukem 				: "internal error (cannot stat some entry file)";
    684      1.1.1.2     lukem 		break;
    685          1.1     lukem 	}
    686      1.1.1.2     lukem 
    687      1.1.1.2     lukem 	return rc;
    688          1.1     lukem }
    689          1.1     lukem 
    690      1.1.1.2     lukem /*
    691      1.1.1.2     lukem  * Read the operation's entry, or if entryp==NULL just see if it exists.
    692      1.1.1.2     lukem  * Return an LDAP result code.  May set *text to a message on failure.
    693      1.1.1.2     lukem  * If pathp is non-NULL, set it to the entry filename on success.
    694      1.1.1.2     lukem  */
    695          1.1     lukem static int
    696          1.1     lukem get_entry(
    697          1.1     lukem 	Operation *op,
    698          1.1     lukem 	Entry **entryp,
    699      1.1.1.2     lukem 	struct berval *pathp,
    700      1.1.1.2     lukem 	const char **text )
    701          1.1     lukem {
    702          1.1     lukem 	int rc;
    703          1.1     lukem 	struct berval path, pdn, pndn;
    704          1.1     lukem 
    705      1.1.1.2     lukem 	dnParent( &op->o_req_dn, &pdn );
    706      1.1.1.2     lukem 	dnParent( &op->o_req_ndn, &pndn );
    707      1.1.1.2     lukem 	rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
    708      1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS ) {
    709      1.1.1.2     lukem 		goto done;
    710          1.1     lukem 	}
    711      1.1.1.2     lukem 
    712      1.1.1.2     lukem 	rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, entryp, text );
    713          1.1     lukem 
    714          1.1     lukem 	if ( rc == LDAP_SUCCESS && pathp != NULL ) {
    715          1.1     lukem 		*pathp = path;
    716          1.1     lukem 	} else {
    717      1.1.1.2     lukem 		SLAP_FREE( path.bv_val );
    718          1.1     lukem 	}
    719      1.1.1.2     lukem  done:
    720          1.1     lukem 	return rc;
    721          1.1     lukem }
    722          1.1     lukem 
    723          1.1     lukem 
    724      1.1.1.2     lukem /*
    725      1.1.1.2     lukem  * RDN-named directory entry, with special handling of "attr={num}val" RDNs.
    726      1.1.1.2     lukem  * For sorting, filename "attr=val.ldif" is truncated to "attr="val\0ldif",
    727      1.1.1.2     lukem  * and filename "attr={num}val.ldif" to "attr={\0um}val.ldif".
    728      1.1.1.2     lukem  * Does not sort escaped chars correctly, would need to un-escape them.
    729      1.1.1.2     lukem  */
    730          1.1     lukem typedef struct bvlist {
    731          1.1     lukem 	struct bvlist *next;
    732      1.1.1.2     lukem 	char *trunc;	/* filename was truncated here */
    733      1.1.1.2     lukem 	int  inum;		/* num from "attr={num}" in filename, or INT_MIN */
    734      1.1.1.2     lukem 	char savech;	/* original char at *trunc */
    735      1.1.1.2     lukem 	/* BVL_NAME(&bvlist) is the filename, allocated after the struct: */
    736      1.1.1.2     lukem #	define BVL_NAME(bvl)     ((char *) ((bvl) + 1))
    737      1.1.1.2     lukem #	define BVL_SIZE(namelen) (sizeof(bvlist) + (namelen) + 1)
    738          1.1     lukem } bvlist;
    739          1.1     lukem 
    740      1.1.1.2     lukem static int
    741      1.1.1.2     lukem ldif_send_entry( Operation *op, SlapReply *rs, Entry *e, int scope )
    742          1.1     lukem {
    743      1.1.1.2     lukem 	int rc = LDAP_SUCCESS;
    744          1.1     lukem 
    745      1.1.1.2     lukem 	if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) {
    746      1.1.1.2     lukem 		if ( rs == NULL ) {
    747      1.1.1.2     lukem 			/* Save the entry for tool mode */
    748      1.1.1.2     lukem 			struct ldif_tool *tl =
    749      1.1.1.2     lukem 				&((struct ldif_info *) op->o_bd->be_private)->li_tool;
    750      1.1.1.2     lukem 
    751      1.1.1.2     lukem 			if ( tl->ecount >= tl->elen ) {
    752      1.1.1.2     lukem 				/* Allocate/grow entries */
    753      1.1.1.2     lukem 				ID elen = tl->elen ? tl->elen * 2 : ENTRY_BUFF_INCREMENT;
    754      1.1.1.2     lukem 				Entry **entries = (Entry **) SLAP_REALLOC( tl->entries,
    755      1.1.1.2     lukem 					sizeof(Entry *) * elen );
    756      1.1.1.2     lukem 				if ( entries == NULL ) {
    757      1.1.1.2     lukem 					Debug( LDAP_DEBUG_ANY,
    758      1.1.1.2     lukem 						"ldif_send_entry: out of memory\n", 0, 0, 0 );
    759      1.1.1.2     lukem 					rc = LDAP_OTHER;
    760      1.1.1.2     lukem 					goto done;
    761      1.1.1.2     lukem 				}
    762      1.1.1.2     lukem 				tl->elen = elen;
    763      1.1.1.2     lukem 				tl->entries = entries;
    764      1.1.1.2     lukem 			}
    765      1.1.1.2     lukem 			tl->entries[tl->ecount++] = e;
    766      1.1.1.2     lukem 			return rc;
    767          1.1     lukem 		}
    768          1.1     lukem 
    769      1.1.1.2     lukem 		else if ( !get_manageDSAit( op ) && is_entry_referral( e ) ) {
    770      1.1.1.2     lukem 			/* Send a continuation reference.
    771      1.1.1.2     lukem 			 * (ldif_back_referrals() handles baseobject referrals.)
    772      1.1.1.2     lukem 			 * Don't check the filter since it's only a candidate.
    773      1.1.1.2     lukem 			 */
    774      1.1.1.2     lukem 			BerVarray refs = get_entry_referrals( op, e );
    775      1.1.1.2     lukem 			rs->sr_ref = referral_rewrite( refs, &e->e_name, NULL, scope );
    776      1.1.1.2     lukem 			rs->sr_entry = e;
    777      1.1.1.2     lukem 			rc = send_search_reference( op, rs );
    778      1.1.1.2     lukem 			ber_bvarray_free( rs->sr_ref );
    779      1.1.1.2     lukem 			ber_bvarray_free( refs );
    780      1.1.1.2     lukem 			rs->sr_ref = NULL;
    781      1.1.1.2     lukem 			rs->sr_entry = NULL;
    782          1.1     lukem 		}
    783          1.1     lukem 
    784      1.1.1.2     lukem 		else if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
    785      1.1.1.2     lukem 			rs->sr_entry = e;
    786      1.1.1.2     lukem 			rs->sr_attrs = op->ors_attrs;
    787      1.1.1.4      tron 			/* Could set REP_ENTRY_MUSTBEFREED too for efficiency,
    788      1.1.1.4      tron 			 * but refraining lets us test unFREEable MODIFIABLE
    789      1.1.1.4      tron 			 * entries.  Like entries built on the stack.
    790      1.1.1.4      tron 			 */
    791      1.1.1.2     lukem 			rs->sr_flags = REP_ENTRY_MODIFIABLE;
    792      1.1.1.2     lukem 			rc = send_search_entry( op, rs );
    793      1.1.1.2     lukem 			rs->sr_entry = NULL;
    794      1.1.1.4      tron 			rs->sr_attrs = NULL;
    795          1.1     lukem 		}
    796          1.1     lukem 	}
    797          1.1     lukem 
    798      1.1.1.2     lukem  done:
    799      1.1.1.2     lukem 	entry_free( e );
    800      1.1.1.2     lukem 	return rc;
    801      1.1.1.2     lukem }
    802          1.1     lukem 
    803      1.1.1.2     lukem /* Read LDIF directory <path> into <listp>.  Set *fname_maxlenp. */
    804      1.1.1.2     lukem static int
    805      1.1.1.2     lukem ldif_readdir(
    806      1.1.1.2     lukem 	Operation *op,
    807      1.1.1.2     lukem 	SlapReply *rs,
    808      1.1.1.2     lukem 	const struct berval *path,
    809      1.1.1.2     lukem 	bvlist **listp,
    810      1.1.1.2     lukem 	ber_len_t *fname_maxlenp )
    811      1.1.1.2     lukem {
    812      1.1.1.2     lukem 	int rc = LDAP_SUCCESS;
    813      1.1.1.2     lukem 	DIR *dir_of_path;
    814          1.1     lukem 
    815      1.1.1.2     lukem 	*listp = NULL;
    816      1.1.1.2     lukem 	*fname_maxlenp = 0;
    817      1.1.1.2     lukem 
    818      1.1.1.2     lukem 	dir_of_path = opendir( path->bv_val );
    819      1.1.1.2     lukem 	if ( dir_of_path == NULL ) {
    820      1.1.1.2     lukem 		int save_errno = errno;
    821      1.1.1.2     lukem 		struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
    822      1.1.1.2     lukem 		int is_rootDSE = (path->bv_len == li->li_base_path.bv_len);
    823      1.1.1.2     lukem 
    824      1.1.1.2     lukem 		/* Absent directory is OK (leaf entry), except the database dir */
    825      1.1.1.2     lukem 		if ( is_rootDSE || save_errno != ENOENT ) {
    826      1.1.1.2     lukem 			Debug( LDAP_DEBUG_ANY,
    827      1.1.1.2     lukem 				"=> ldif_search_entry: failed to opendir \"%s\": %s\n",
    828      1.1.1.2     lukem 				path->bv_val, STRERROR( save_errno ), 0 );
    829      1.1.1.2     lukem 			rc = LDAP_OTHER;
    830      1.1.1.2     lukem 			if ( rs != NULL )
    831      1.1.1.2     lukem 				rs->sr_text =
    832      1.1.1.2     lukem 					save_errno != ENOENT ? "internal error (bad directory)"
    833      1.1.1.2     lukem 					: "internal error (database directory does not exist)";
    834          1.1     lukem 		}
    835      1.1.1.2     lukem 
    836      1.1.1.2     lukem 	} else {
    837      1.1.1.2     lukem 		bvlist *ptr;
    838      1.1.1.2     lukem 		struct dirent *dir;
    839      1.1.1.2     lukem 		int save_errno = 0;
    840      1.1.1.2     lukem 
    841      1.1.1.2     lukem 		while ( (dir = readdir( dir_of_path )) != NULL ) {
    842      1.1.1.2     lukem 			size_t fname_len;
    843          1.1     lukem 			bvlist *bvl, **prev;
    844      1.1.1.2     lukem 			char *trunc, *idxp, *endp, *endp2;
    845          1.1     lukem 
    846      1.1.1.2     lukem 			fname_len = strlen( dir->d_name );
    847      1.1.1.2     lukem 			if ( fname_len < STRLENOF( "x=" LDIF )) /* min filename size */
    848          1.1     lukem 				continue;
    849      1.1.1.2     lukem 			if ( strcmp( dir->d_name + fname_len - STRLENOF(LDIF), LDIF ))
    850          1.1     lukem 				continue;
    851          1.1     lukem 
    852      1.1.1.2     lukem 			if ( *fname_maxlenp < fname_len )
    853      1.1.1.2     lukem 				*fname_maxlenp = fname_len;
    854      1.1.1.2     lukem 
    855      1.1.1.2     lukem 			bvl = SLAP_MALLOC( BVL_SIZE( fname_len ) );
    856      1.1.1.2     lukem 			if ( bvl == NULL ) {
    857      1.1.1.2     lukem 				rc = LDAP_OTHER;
    858      1.1.1.2     lukem 				save_errno = errno;
    859      1.1.1.2     lukem 				break;
    860          1.1     lukem 			}
    861      1.1.1.2     lukem 			strcpy( BVL_NAME( bvl ), dir->d_name );
    862          1.1     lukem 
    863      1.1.1.2     lukem 			/* Make it sortable by ("attr=val" or <preceding {num}, num>) */
    864      1.1.1.2     lukem 			trunc = BVL_NAME( bvl ) + fname_len - STRLENOF( LDIF );
    865      1.1.1.2     lukem 			if ( (idxp = strchr( BVL_NAME( bvl ) + 2, IX_FSL )) != NULL &&
    866      1.1.1.2     lukem 				 (endp = strchr( ++idxp, IX_FSR )) != NULL && endp > idxp &&
    867      1.1.1.2     lukem 				 (eq_unsafe || idxp[-2] == '=' || endp + 1 == trunc) )
    868      1.1.1.2     lukem 			{
    869      1.1.1.2     lukem 				/* attr={n}val or bconfig.c's "pseudo-indexed" attr=val{n} */
    870      1.1.1.2     lukem 				bvl->inum = strtol( idxp, &endp2, 10 );
    871      1.1.1.2     lukem 				if ( endp2 == endp ) {
    872      1.1.1.2     lukem 					trunc = idxp;
    873      1.1.1.2     lukem 					goto truncate;
    874      1.1.1.2     lukem 				}
    875      1.1.1.2     lukem 			}
    876      1.1.1.2     lukem 			bvl->inum = INT_MIN;
    877      1.1.1.2     lukem 		truncate:
    878      1.1.1.2     lukem 			bvl->trunc = trunc;
    879      1.1.1.2     lukem 			bvl->savech = *trunc;
    880      1.1.1.2     lukem 			*trunc = '\0';
    881      1.1.1.2     lukem 
    882      1.1.1.2     lukem 			/* Insertion sort */
    883      1.1.1.2     lukem 			for ( prev = listp; (ptr = *prev) != NULL; prev = &ptr->next ) {
    884      1.1.1.2     lukem 				int cmp = strcmp( BVL_NAME( bvl ), BVL_NAME( ptr ));
    885      1.1.1.2     lukem 				if ( cmp < 0 || (cmp == 0 && bvl->inum < ptr->inum) )
    886          1.1     lukem 					break;
    887          1.1     lukem 			}
    888          1.1     lukem 			*prev = bvl;
    889          1.1     lukem 			bvl->next = ptr;
    890          1.1     lukem 		}
    891          1.1     lukem 
    892      1.1.1.2     lukem 		if ( closedir( dir_of_path ) < 0 ) {
    893      1.1.1.2     lukem 			save_errno = errno;
    894      1.1.1.2     lukem 			rc = LDAP_OTHER;
    895      1.1.1.2     lukem 			if ( rs != NULL )
    896      1.1.1.2     lukem 				rs->sr_text = "internal error (bad directory)";
    897      1.1.1.2     lukem 		}
    898      1.1.1.2     lukem 		if ( rc != LDAP_SUCCESS ) {
    899      1.1.1.2     lukem 			Debug( LDAP_DEBUG_ANY, "ldif_search_entry: %s \"%s\": %s\n",
    900      1.1.1.2     lukem 				"error reading directory", path->bv_val,
    901      1.1.1.2     lukem 				STRERROR( save_errno ) );
    902          1.1     lukem 		}
    903          1.1     lukem 	}
    904      1.1.1.2     lukem 
    905          1.1     lukem 	return rc;
    906          1.1     lukem }
    907          1.1     lukem 
    908      1.1.1.2     lukem /*
    909      1.1.1.2     lukem  * Send an entry, recursively search its children, and free or save it.
    910      1.1.1.2     lukem  * Return an LDAP result code.  Parameters:
    911      1.1.1.2     lukem  *  op, rs  operation and reply.  rs == NULL for slap tools.
    912      1.1.1.2     lukem  *  e       entry to search, or NULL for rootDSE.
    913      1.1.1.2     lukem  *  scope   scope for the part of the search from this entry.
    914      1.1.1.2     lukem  *  path    LDIF filename -- bv_len and non-directory part are overwritten.
    915      1.1.1.2     lukem  */
    916          1.1     lukem static int
    917      1.1.1.2     lukem ldif_search_entry(
    918      1.1.1.2     lukem 	Operation *op,
    919      1.1.1.2     lukem 	SlapReply *rs,
    920      1.1.1.2     lukem 	Entry *e,
    921      1.1.1.2     lukem 	int scope,
    922      1.1.1.2     lukem 	struct berval *path )
    923          1.1     lukem {
    924      1.1.1.2     lukem 	int rc = LDAP_SUCCESS;
    925      1.1.1.2     lukem 	struct berval dn = BER_BVC( "" ), ndn = BER_BVC( "" );
    926      1.1.1.2     lukem 
    927      1.1.1.2     lukem 	if ( scope != LDAP_SCOPE_BASE && e != NULL ) {
    928      1.1.1.2     lukem 		/* Copy DN/NDN since we send the entry with REP_ENTRY_MODIFIABLE,
    929      1.1.1.2     lukem 		 * which bconfig.c seems to need.  (TODO: see config_rename_one.)
    930      1.1.1.2     lukem 		 */
    931      1.1.1.2     lukem 		if ( ber_dupbv( &dn,  &e->e_name  ) == NULL ||
    932      1.1.1.2     lukem 			 ber_dupbv( &ndn, &e->e_nname ) == NULL )
    933      1.1.1.2     lukem 		{
    934      1.1.1.2     lukem 			Debug( LDAP_DEBUG_ANY,
    935      1.1.1.2     lukem 				"ldif_search_entry: out of memory\n", 0, 0, 0 );
    936      1.1.1.2     lukem 			rc = LDAP_OTHER;
    937      1.1.1.2     lukem 			goto done;
    938      1.1.1.2     lukem 		}
    939      1.1.1.2     lukem 	}
    940      1.1.1.2     lukem 
    941      1.1.1.2     lukem 	/* Send the entry if appropriate, and free or save it */
    942      1.1.1.2     lukem 	if ( e != NULL )
    943      1.1.1.2     lukem 		rc = ldif_send_entry( op, rs, e, scope );
    944      1.1.1.2     lukem 
    945      1.1.1.2     lukem 	/* Search the children */
    946      1.1.1.2     lukem 	if ( scope != LDAP_SCOPE_BASE && rc == LDAP_SUCCESS ) {
    947      1.1.1.2     lukem 		bvlist *list, *ptr;
    948      1.1.1.2     lukem 		struct berval fpath;	/* becomes child pathname */
    949      1.1.1.2     lukem 		char *dir_end;	/* will point past dirname in fpath */
    950      1.1.1.2     lukem 
    951      1.1.1.2     lukem 		ldif2dir_len( *path );
    952      1.1.1.2     lukem 		ldif2dir_name( *path );
    953      1.1.1.2     lukem 		rc = ldif_readdir( op, rs, path, &list, &fpath.bv_len );
    954      1.1.1.2     lukem 
    955      1.1.1.2     lukem 		if ( list != NULL ) {
    956      1.1.1.2     lukem 			const char **text = rs == NULL ? NULL : &rs->sr_text;
    957      1.1.1.2     lukem 
    958      1.1.1.2     lukem 			if ( scope == LDAP_SCOPE_ONELEVEL )
    959      1.1.1.2     lukem 				scope = LDAP_SCOPE_BASE;
    960      1.1.1.2     lukem 			else if ( scope == LDAP_SCOPE_SUBORDINATE )
    961      1.1.1.2     lukem 				scope = LDAP_SCOPE_SUBTREE;
    962      1.1.1.2     lukem 
    963      1.1.1.2     lukem 			/* Allocate fpath and fill in directory part */
    964      1.1.1.2     lukem 			dir_end = fullpath_alloc( &fpath, path, fpath.bv_len );
    965      1.1.1.2     lukem 			if ( dir_end == NULL )
    966      1.1.1.2     lukem 				rc = LDAP_OTHER;
    967      1.1.1.2     lukem 
    968      1.1.1.2     lukem 			do {
    969      1.1.1.2     lukem 				ptr = list;
    970      1.1.1.2     lukem 
    971      1.1.1.2     lukem 				if ( rc == LDAP_SUCCESS ) {
    972      1.1.1.2     lukem 					*ptr->trunc = ptr->savech;
    973      1.1.1.2     lukem 					FILL_PATH( &fpath, dir_end, BVL_NAME( ptr ));
    974      1.1.1.2     lukem 
    975      1.1.1.2     lukem 					rc = ldif_read_entry( op, fpath.bv_val, &dn, &ndn,
    976      1.1.1.2     lukem 						&e, text );
    977      1.1.1.2     lukem 					switch ( rc ) {
    978      1.1.1.2     lukem 					case LDAP_SUCCESS:
    979      1.1.1.2     lukem 						rc = ldif_search_entry( op, rs, e, scope, &fpath );
    980      1.1.1.2     lukem 						break;
    981      1.1.1.2     lukem 					case LDAP_NO_SUCH_OBJECT:
    982      1.1.1.2     lukem 						/* Only the search baseDN may produce noSuchObject. */
    983      1.1.1.2     lukem 						rc = LDAP_OTHER;
    984      1.1.1.2     lukem 						if ( rs != NULL )
    985      1.1.1.2     lukem 							rs->sr_text = "internal error "
    986      1.1.1.2     lukem 								"(did someone just remove an entry file?)";
    987      1.1.1.2     lukem 						Debug( LDAP_DEBUG_ANY, "ldif_search_entry: "
    988      1.1.1.2     lukem 							"file listed in parent directory does not exist: "
    989      1.1.1.2     lukem 							"\"%s\"\n", fpath.bv_val, 0, 0 );
    990      1.1.1.2     lukem 						break;
    991      1.1.1.2     lukem 					}
    992      1.1.1.2     lukem 				}
    993      1.1.1.2     lukem 
    994      1.1.1.2     lukem 				list = ptr->next;
    995      1.1.1.2     lukem 				SLAP_FREE( ptr );
    996      1.1.1.2     lukem 			} while ( list != NULL );
    997      1.1.1.2     lukem 
    998      1.1.1.2     lukem 			if ( !BER_BVISNULL( &fpath ) )
    999      1.1.1.2     lukem 				SLAP_FREE( fpath.bv_val );
   1000      1.1.1.2     lukem 		}
   1001      1.1.1.2     lukem 	}
   1002      1.1.1.2     lukem 
   1003      1.1.1.2     lukem  done:
   1004      1.1.1.2     lukem 	if ( !BER_BVISEMPTY( &dn ) )
   1005      1.1.1.2     lukem 		ber_memfree( dn.bv_val );
   1006      1.1.1.2     lukem 	if ( !BER_BVISEMPTY( &ndn ) )
   1007      1.1.1.2     lukem 		ber_memfree( ndn.bv_val );
   1008      1.1.1.2     lukem 	return rc;
   1009      1.1.1.2     lukem }
   1010      1.1.1.2     lukem 
   1011      1.1.1.2     lukem static int
   1012      1.1.1.2     lukem search_tree( Operation *op, SlapReply *rs )
   1013      1.1.1.2     lukem {
   1014      1.1.1.2     lukem 	int rc = LDAP_SUCCESS;
   1015      1.1.1.2     lukem 	Entry *e = NULL;
   1016          1.1     lukem 	struct berval path;
   1017          1.1     lukem 	struct berval pdn, pndn;
   1018          1.1     lukem 
   1019      1.1.1.2     lukem 	(void) ndn2path( op, &op->o_req_ndn, &path, 1 );
   1020      1.1.1.2     lukem 	if ( !BER_BVISEMPTY( &op->o_req_ndn ) ) {
   1021      1.1.1.2     lukem 		/* Read baseObject */
   1022      1.1.1.2     lukem 		dnParent( &op->o_req_dn, &pdn );
   1023      1.1.1.2     lukem 		dnParent( &op->o_req_ndn, &pndn );
   1024      1.1.1.2     lukem 		rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, &e,
   1025      1.1.1.2     lukem 			rs == NULL ? NULL : &rs->sr_text );
   1026      1.1.1.2     lukem 	}
   1027      1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS )
   1028      1.1.1.2     lukem 		rc = ldif_search_entry( op, rs, e, op->ors_scope, &path );
   1029      1.1.1.2     lukem 
   1030          1.1     lukem 	ch_free( path.bv_val );
   1031          1.1     lukem 	return rc;
   1032          1.1     lukem }
   1033          1.1     lukem 
   1034          1.1     lukem 
   1035      1.1.1.2     lukem /*
   1036      1.1.1.2     lukem  * Prepare to create or rename an entry:
   1037      1.1.1.2     lukem  * Check that the entry does not already exist.
   1038      1.1.1.2     lukem  * Check that the parent entry exists and can have subordinates,
   1039      1.1.1.2     lukem  * unless need_dir is NULL or adding the suffix entry.
   1040      1.1.1.2     lukem  *
   1041      1.1.1.2     lukem  * Return an LDAP result code.  May set *text to a message on failure.
   1042      1.1.1.2     lukem  * If success, set *dnpath to LDIF entry path and *need_dir to
   1043      1.1.1.2     lukem  * (directory must be created ? dirname : NULL).
   1044      1.1.1.2     lukem  */
   1045      1.1.1.2     lukem static int
   1046      1.1.1.2     lukem ldif_prepare_create(
   1047      1.1.1.2     lukem 	Operation *op,
   1048      1.1.1.2     lukem 	Entry *e,
   1049      1.1.1.2     lukem 	struct berval *dnpath,
   1050      1.1.1.2     lukem 	char **need_dir,
   1051      1.1.1.2     lukem 	const char **text )
   1052          1.1     lukem {
   1053      1.1.1.2     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1054      1.1.1.2     lukem 	struct berval *ndn = &e->e_nname;
   1055      1.1.1.2     lukem 	struct berval ppath = BER_BVNULL;
   1056      1.1.1.2     lukem 	struct stat st;
   1057      1.1.1.2     lukem 	Entry *parent = NULL;
   1058      1.1.1.2     lukem 	int rc;
   1059      1.1.1.2     lukem 
   1060      1.1.1.2     lukem 	if ( op->o_abandon )
   1061      1.1.1.2     lukem 		return SLAPD_ABANDON;
   1062      1.1.1.2     lukem 
   1063      1.1.1.2     lukem 	rc = ndn2path( op, ndn, dnpath, 0 );
   1064      1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS ) {
   1065      1.1.1.2     lukem 		return rc;
   1066      1.1.1.2     lukem 	}
   1067      1.1.1.2     lukem 
   1068      1.1.1.2     lukem 	if ( stat( dnpath->bv_val, &st ) == 0 ) { /* entry .ldif file */
   1069      1.1.1.2     lukem 		rc = LDAP_ALREADY_EXISTS;
   1070      1.1.1.2     lukem 
   1071      1.1.1.2     lukem 	} else if ( errno != ENOENT ) {
   1072      1.1.1.2     lukem 		Debug( LDAP_DEBUG_ANY,
   1073      1.1.1.2     lukem 			"ldif_prepare_create: cannot stat \"%s\": %s\n",
   1074      1.1.1.2     lukem 			dnpath->bv_val, STRERROR( errno ), 0 );
   1075      1.1.1.2     lukem 		rc = LDAP_OTHER;
   1076      1.1.1.2     lukem 		*text = "internal error (cannot check entry file)";
   1077      1.1.1.2     lukem 
   1078      1.1.1.2     lukem 	} else if ( need_dir != NULL ) {
   1079      1.1.1.2     lukem 		*need_dir = NULL;
   1080      1.1.1.2     lukem 		rc = get_parent_path( dnpath, &ppath );
   1081      1.1.1.2     lukem 		/* If parent dir exists, so does parent .ldif:
   1082      1.1.1.2     lukem 		 * The directory gets created after and removed before the .ldif.
   1083      1.1.1.2     lukem 		 * Except with the database directory, which has no matching entry.
   1084      1.1.1.2     lukem 		 */
   1085      1.1.1.2     lukem 		if ( rc == LDAP_SUCCESS && stat( ppath.bv_val, &st ) < 0 ) {
   1086      1.1.1.2     lukem 			rc = errno == ENOENT && ppath.bv_len > li->li_base_path.bv_len
   1087      1.1.1.2     lukem 				? LDAP_NO_SUCH_OBJECT : LDAP_OTHER;
   1088      1.1.1.2     lukem 		}
   1089      1.1.1.2     lukem 		switch ( rc ) {
   1090      1.1.1.2     lukem 		case LDAP_NO_SUCH_OBJECT:
   1091      1.1.1.2     lukem 			/* No parent dir, check parent .ldif */
   1092      1.1.1.2     lukem 			dir2ldif_name( ppath );
   1093      1.1.1.2     lukem 			rc = ldif_read_entry( op, ppath.bv_val, NULL, NULL,
   1094      1.1.1.2     lukem 				(op->o_tag != LDAP_REQ_ADD || get_manageDSAit( op )
   1095      1.1.1.2     lukem 				 ? &parent : NULL),
   1096      1.1.1.2     lukem 				text );
   1097      1.1.1.2     lukem 			switch ( rc ) {
   1098      1.1.1.2     lukem 			case LDAP_SUCCESS:
   1099      1.1.1.2     lukem 				/* Check that parent is not a referral, unless
   1100      1.1.1.2     lukem 				 * ldif_back_referrals() already checked.
   1101      1.1.1.2     lukem 				 */
   1102      1.1.1.2     lukem 				if ( parent != NULL ) {
   1103      1.1.1.2     lukem 					int is_ref = is_entry_referral( parent );
   1104      1.1.1.2     lukem 					entry_free( parent );
   1105      1.1.1.2     lukem 					if ( is_ref ) {
   1106      1.1.1.2     lukem 						rc = LDAP_AFFECTS_MULTIPLE_DSAS;
   1107      1.1.1.2     lukem 						*text = op->o_tag == LDAP_REQ_MODDN
   1108      1.1.1.2     lukem 							? "newSuperior is a referral object"
   1109      1.1.1.2     lukem 							: "parent is a referral object";
   1110      1.1.1.2     lukem 						break;
   1111      1.1.1.2     lukem 					}
   1112      1.1.1.2     lukem 				}
   1113      1.1.1.2     lukem 				/* Must create parent directory. */
   1114      1.1.1.2     lukem 				ldif2dir_name( ppath );
   1115      1.1.1.2     lukem 				*need_dir = ppath.bv_val;
   1116      1.1.1.2     lukem 				break;
   1117      1.1.1.2     lukem 			case LDAP_NO_SUCH_OBJECT:
   1118      1.1.1.2     lukem 				*text = op->o_tag == LDAP_REQ_MODDN
   1119      1.1.1.2     lukem 					? "newSuperior object does not exist"
   1120      1.1.1.2     lukem 					: "parent does not exist";
   1121      1.1.1.2     lukem 				break;
   1122      1.1.1.2     lukem 			}
   1123          1.1     lukem 			break;
   1124      1.1.1.2     lukem 		case LDAP_OTHER:
   1125      1.1.1.2     lukem 			Debug( LDAP_DEBUG_ANY,
   1126      1.1.1.2     lukem 				"ldif_prepare_create: cannot stat \"%s\" parent dir: %s\n",
   1127      1.1.1.2     lukem 				ndn->bv_val, STRERROR( errno ), 0 );
   1128      1.1.1.2     lukem 			*text = "internal error (cannot stat parent dir)";
   1129      1.1.1.2     lukem 			break;
   1130      1.1.1.2     lukem 		}
   1131      1.1.1.2     lukem 		if ( *need_dir == NULL && ppath.bv_val != NULL )
   1132      1.1.1.2     lukem 			SLAP_FREE( ppath.bv_val );
   1133      1.1.1.2     lukem 	}
   1134      1.1.1.2     lukem 
   1135      1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS ) {
   1136      1.1.1.2     lukem 		SLAP_FREE( dnpath->bv_val );
   1137      1.1.1.2     lukem 		BER_BVZERO( dnpath );
   1138      1.1.1.2     lukem 	}
   1139      1.1.1.2     lukem 	return rc;
   1140          1.1     lukem }
   1141          1.1     lukem 
   1142      1.1.1.2     lukem static int
   1143      1.1.1.2     lukem apply_modify_to_entry(
   1144      1.1.1.2     lukem 	Entry *entry,
   1145      1.1.1.2     lukem 	Modifications *modlist,
   1146      1.1.1.2     lukem 	Operation *op,
   1147      1.1.1.4      tron 	SlapReply *rs,
   1148      1.1.1.4      tron 	char *textbuf )
   1149          1.1     lukem {
   1150          1.1     lukem 	int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS;
   1151          1.1     lukem 	int is_oc = 0;
   1152          1.1     lukem 	Modification *mods;
   1153          1.1     lukem 
   1154          1.1     lukem 	if (!acl_check_modlist(op, entry, modlist)) {
   1155          1.1     lukem 		return LDAP_INSUFFICIENT_ACCESS;
   1156          1.1     lukem 	}
   1157          1.1     lukem 
   1158          1.1     lukem 	for (; modlist != NULL; modlist = modlist->sml_next) {
   1159          1.1     lukem 		mods = &modlist->sml_mod;
   1160          1.1     lukem 
   1161          1.1     lukem 		if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
   1162          1.1     lukem 			is_oc = 1;
   1163          1.1     lukem 		}
   1164          1.1     lukem 		switch (mods->sm_op) {
   1165          1.1     lukem 		case LDAP_MOD_ADD:
   1166          1.1     lukem 			rc = modify_add_values(entry, mods,
   1167          1.1     lukem 				   get_permissiveModify(op),
   1168          1.1     lukem 				   &rs->sr_text, textbuf,
   1169      1.1.1.4      tron 				   SLAP_TEXT_BUFLEN );
   1170          1.1     lukem 			break;
   1171      1.1.1.2     lukem 
   1172          1.1     lukem 		case LDAP_MOD_DELETE:
   1173          1.1     lukem 			rc = modify_delete_values(entry, mods,
   1174          1.1     lukem 				get_permissiveModify(op),
   1175          1.1     lukem 				&rs->sr_text, textbuf,
   1176      1.1.1.4      tron 				SLAP_TEXT_BUFLEN );
   1177          1.1     lukem 			break;
   1178      1.1.1.2     lukem 
   1179          1.1     lukem 		case LDAP_MOD_REPLACE:
   1180          1.1     lukem 			rc = modify_replace_values(entry, mods,
   1181          1.1     lukem 				 get_permissiveModify(op),
   1182          1.1     lukem 				 &rs->sr_text, textbuf,
   1183      1.1.1.4      tron 				 SLAP_TEXT_BUFLEN );
   1184          1.1     lukem 			break;
   1185          1.1     lukem 
   1186          1.1     lukem 		case LDAP_MOD_INCREMENT:
   1187          1.1     lukem 			rc = modify_increment_values( entry,
   1188          1.1     lukem 				mods, get_permissiveModify(op),
   1189          1.1     lukem 				&rs->sr_text, textbuf,
   1190      1.1.1.4      tron 				SLAP_TEXT_BUFLEN );
   1191          1.1     lukem 			break;
   1192          1.1     lukem 
   1193          1.1     lukem 		case SLAP_MOD_SOFTADD:
   1194          1.1     lukem 			mods->sm_op = LDAP_MOD_ADD;
   1195          1.1     lukem 			rc = modify_add_values(entry, mods,
   1196          1.1     lukem 				   get_permissiveModify(op),
   1197          1.1     lukem 				   &rs->sr_text, textbuf,
   1198      1.1.1.4      tron 				   SLAP_TEXT_BUFLEN );
   1199          1.1     lukem 			mods->sm_op = SLAP_MOD_SOFTADD;
   1200          1.1     lukem 			if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
   1201          1.1     lukem 				rc = LDAP_SUCCESS;
   1202          1.1     lukem 			}
   1203          1.1     lukem 			break;
   1204      1.1.1.4      tron 
   1205      1.1.1.4      tron 		case SLAP_MOD_SOFTDEL:
   1206      1.1.1.4      tron 			mods->sm_op = LDAP_MOD_DELETE;
   1207      1.1.1.4      tron 			rc = modify_delete_values(entry, mods,
   1208      1.1.1.4      tron 				   get_permissiveModify(op),
   1209      1.1.1.4      tron 				   &rs->sr_text, textbuf,
   1210      1.1.1.4      tron 				   SLAP_TEXT_BUFLEN );
   1211      1.1.1.4      tron 			mods->sm_op = SLAP_MOD_SOFTDEL;
   1212      1.1.1.4      tron 			if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
   1213      1.1.1.4      tron 				rc = LDAP_SUCCESS;
   1214      1.1.1.4      tron 			}
   1215      1.1.1.4      tron 			break;
   1216      1.1.1.4      tron 
   1217      1.1.1.4      tron 		case SLAP_MOD_ADD_IF_NOT_PRESENT:
   1218      1.1.1.4      tron 			if ( attr_find( entry->e_attrs, mods->sm_desc ) ) {
   1219      1.1.1.4      tron 				rc = LDAP_SUCCESS;
   1220      1.1.1.4      tron 				break;
   1221      1.1.1.4      tron 			}
   1222      1.1.1.4      tron 			mods->sm_op = LDAP_MOD_ADD;
   1223      1.1.1.4      tron 			rc = modify_add_values(entry, mods,
   1224      1.1.1.4      tron 				   get_permissiveModify(op),
   1225      1.1.1.4      tron 				   &rs->sr_text, textbuf,
   1226      1.1.1.4      tron 				   SLAP_TEXT_BUFLEN );
   1227      1.1.1.4      tron 			mods->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
   1228      1.1.1.4      tron 			break;
   1229          1.1     lukem 		}
   1230          1.1     lukem 		if(rc != LDAP_SUCCESS) break;
   1231          1.1     lukem 	}
   1232          1.1     lukem 
   1233      1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS ) {
   1234      1.1.1.2     lukem 		rs->sr_text = NULL; /* Needed at least with SLAP_MOD_SOFTADD */
   1235          1.1     lukem 		if ( is_oc ) {
   1236          1.1     lukem 			entry->e_ocflags = 0;
   1237          1.1     lukem 		}
   1238          1.1     lukem 		/* check that the entry still obeys the schema */
   1239      1.1.1.2     lukem 		rc = entry_schema_check( op, entry, NULL, 0, 0, NULL,
   1240      1.1.1.4      tron 			  &rs->sr_text, textbuf, SLAP_TEXT_BUFLEN );
   1241          1.1     lukem 	}
   1242          1.1     lukem 
   1243          1.1     lukem 	return rc;
   1244          1.1     lukem }
   1245          1.1     lukem 
   1246      1.1.1.2     lukem 
   1247      1.1.1.2     lukem static int
   1248          1.1     lukem ldif_back_referrals( Operation *op, SlapReply *rs )
   1249          1.1     lukem {
   1250      1.1.1.2     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1251      1.1.1.2     lukem 	struct berval path, dn = op->o_req_dn, ndn = op->o_req_ndn;
   1252      1.1.1.2     lukem 	ber_len_t min_dnlen;
   1253      1.1.1.2     lukem 	Entry *entry = NULL, **entryp;
   1254      1.1.1.2     lukem 	BerVarray ref;
   1255      1.1.1.2     lukem 	int rc;
   1256          1.1     lukem 
   1257      1.1.1.2     lukem 	min_dnlen = op->o_bd->be_nsuffix[0].bv_len;
   1258      1.1.1.2     lukem 	if ( min_dnlen == 0 ) {
   1259      1.1.1.2     lukem 		/* Catch root DSE (empty DN), it is not a referral */
   1260      1.1.1.2     lukem 		min_dnlen = 1;
   1261          1.1     lukem 	}
   1262      1.1.1.2     lukem 	if ( ndn2path( op, &ndn, &path, 0 ) != LDAP_SUCCESS ) {
   1263      1.1.1.2     lukem 		return LDAP_SUCCESS;	/* Root DSE again */
   1264          1.1     lukem 	}
   1265          1.1     lukem 
   1266      1.1.1.2     lukem 	entryp = get_manageDSAit( op ) ? NULL : &entry;
   1267          1.1     lukem 	ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
   1268          1.1     lukem 
   1269      1.1.1.2     lukem 	for (;;) {
   1270      1.1.1.2     lukem 		dnParent( &dn, &dn );
   1271      1.1.1.2     lukem 		dnParent( &ndn, &ndn );
   1272      1.1.1.2     lukem 		rc = ldif_read_entry( op, path.bv_val, &dn, &ndn,
   1273      1.1.1.2     lukem 			entryp, &rs->sr_text );
   1274      1.1.1.2     lukem 		if ( rc != LDAP_NO_SUCH_OBJECT )
   1275      1.1.1.2     lukem 			break;
   1276          1.1     lukem 
   1277      1.1.1.2     lukem 		rc = LDAP_SUCCESS;
   1278      1.1.1.2     lukem 		if ( ndn.bv_len < min_dnlen )
   1279      1.1.1.2     lukem 			break;
   1280      1.1.1.2     lukem 		(void) get_parent_path( &path, NULL );
   1281      1.1.1.2     lukem 		dir2ldif_name( path );
   1282      1.1.1.2     lukem 		entryp = &entry;
   1283      1.1.1.2     lukem 	}
   1284          1.1     lukem 
   1285      1.1.1.2     lukem 	ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
   1286      1.1.1.2     lukem 	SLAP_FREE( path.bv_val );
   1287          1.1     lukem 
   1288      1.1.1.2     lukem 	if ( entry != NULL ) {
   1289      1.1.1.2     lukem 		if ( is_entry_referral( entry ) ) {
   1290          1.1     lukem 			Debug( LDAP_DEBUG_TRACE,
   1291          1.1     lukem 				"ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
   1292      1.1.1.2     lukem 				(unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_dn );
   1293          1.1     lukem 
   1294      1.1.1.2     lukem 			ref = get_entry_referrals( op, entry );
   1295      1.1.1.2     lukem 			rs->sr_ref = referral_rewrite( ref, &entry->e_name, &op->o_req_dn,
   1296      1.1.1.2     lukem 				op->o_tag == LDAP_REQ_SEARCH ?
   1297      1.1.1.2     lukem 				op->ors_scope : LDAP_SCOPE_DEFAULT );
   1298      1.1.1.2     lukem 			ber_bvarray_free( ref );
   1299      1.1.1.2     lukem 
   1300      1.1.1.2     lukem 			if ( rs->sr_ref != NULL ) {
   1301      1.1.1.2     lukem 				/* send referral */
   1302      1.1.1.2     lukem 				rc = rs->sr_err = LDAP_REFERRAL;
   1303      1.1.1.2     lukem 				rs->sr_matched = entry->e_dn;
   1304      1.1.1.2     lukem 				send_ldap_result( op, rs );
   1305      1.1.1.2     lukem 				ber_bvarray_free( rs->sr_ref );
   1306      1.1.1.2     lukem 				rs->sr_ref = NULL;
   1307      1.1.1.2     lukem 			} else {
   1308          1.1     lukem 				rc = LDAP_OTHER;
   1309      1.1.1.2     lukem 				rs->sr_text = "bad referral object";
   1310          1.1     lukem 			}
   1311          1.1     lukem 			rs->sr_matched = NULL;
   1312          1.1     lukem 		}
   1313          1.1     lukem 
   1314      1.1.1.2     lukem 		entry_free( entry );
   1315          1.1     lukem 	}
   1316          1.1     lukem 
   1317          1.1     lukem 	return rc;
   1318          1.1     lukem }
   1319          1.1     lukem 
   1320          1.1     lukem 
   1321          1.1     lukem /* LDAP operations */
   1322          1.1     lukem 
   1323          1.1     lukem static int
   1324          1.1     lukem ldif_back_bind( Operation *op, SlapReply *rs )
   1325          1.1     lukem {
   1326          1.1     lukem 	struct ldif_info *li;
   1327          1.1     lukem 	Attribute *a;
   1328          1.1     lukem 	AttributeDescription *password = slap_schema.si_ad_userPassword;
   1329          1.1     lukem 	int return_val;
   1330      1.1.1.2     lukem 	Entry *entry = NULL;
   1331          1.1     lukem 
   1332          1.1     lukem 	switch ( be_rootdn_bind( op, rs ) ) {
   1333          1.1     lukem 	case SLAP_CB_CONTINUE:
   1334          1.1     lukem 		break;
   1335          1.1     lukem 
   1336          1.1     lukem 	default:
   1337          1.1     lukem 		/* in case of success, front end will send result;
   1338          1.1     lukem 		 * otherwise, be_rootdn_bind() did */
   1339          1.1     lukem 		return rs->sr_err;
   1340          1.1     lukem 	}
   1341          1.1     lukem 
   1342          1.1     lukem 	li = (struct ldif_info *) op->o_bd->be_private;
   1343          1.1     lukem 	ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
   1344      1.1.1.2     lukem 	return_val = get_entry(op, &entry, NULL, NULL);
   1345          1.1     lukem 
   1346          1.1     lukem 	/* no object is found for them */
   1347          1.1     lukem 	if(return_val != LDAP_SUCCESS) {
   1348          1.1     lukem 		rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
   1349          1.1     lukem 		goto return_result;
   1350          1.1     lukem 	}
   1351          1.1     lukem 
   1352          1.1     lukem 	/* they don't have userpassword */
   1353          1.1     lukem 	if((a = attr_find(entry->e_attrs, password)) == NULL) {
   1354          1.1     lukem 		rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
   1355          1.1     lukem 		return_val = 1;
   1356          1.1     lukem 		goto return_result;
   1357          1.1     lukem 	}
   1358          1.1     lukem 
   1359          1.1     lukem 	/* authentication actually failed */
   1360          1.1     lukem 	if(slap_passwd_check(op, entry, a, &op->oq_bind.rb_cred,
   1361          1.1     lukem 			     &rs->sr_text) != 0) {
   1362          1.1     lukem 		rs->sr_err = LDAP_INVALID_CREDENTIALS;
   1363          1.1     lukem 		return_val = 1;
   1364          1.1     lukem 		goto return_result;
   1365          1.1     lukem 	}
   1366          1.1     lukem 
   1367          1.1     lukem 	/* let the front-end send success */
   1368      1.1.1.2     lukem 	return_val = LDAP_SUCCESS;
   1369          1.1     lukem 
   1370          1.1     lukem  return_result:
   1371          1.1     lukem 	ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
   1372      1.1.1.2     lukem 	if(return_val != LDAP_SUCCESS)
   1373          1.1     lukem 		send_ldap_result( op, rs );
   1374          1.1     lukem 	if(entry != NULL)
   1375          1.1     lukem 		entry_free(entry);
   1376          1.1     lukem 	return return_val;
   1377          1.1     lukem }
   1378          1.1     lukem 
   1379      1.1.1.2     lukem static int
   1380      1.1.1.2     lukem ldif_back_search( Operation *op, SlapReply *rs )
   1381          1.1     lukem {
   1382          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1383          1.1     lukem 
   1384          1.1     lukem 	ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
   1385      1.1.1.2     lukem 	rs->sr_err = search_tree( op, rs );
   1386          1.1     lukem 	ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
   1387          1.1     lukem 	send_ldap_result(op, rs);
   1388          1.1     lukem 
   1389          1.1     lukem 	return rs->sr_err;
   1390          1.1     lukem }
   1391          1.1     lukem 
   1392      1.1.1.2     lukem static int
   1393      1.1.1.2     lukem ldif_back_add( Operation *op, SlapReply *rs )
   1394      1.1.1.2     lukem {
   1395          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1396          1.1     lukem 	Entry * e = op->ora_e;
   1397      1.1.1.2     lukem 	struct berval path;
   1398      1.1.1.2     lukem 	char *parentdir;
   1399          1.1     lukem 	char textbuf[SLAP_TEXT_BUFLEN];
   1400      1.1.1.2     lukem 	int rc;
   1401          1.1     lukem 
   1402      1.1.1.2     lukem 	Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn, 0, 0 );
   1403          1.1     lukem 
   1404      1.1.1.2     lukem 	rc = entry_schema_check( op, e, NULL, 0, 1, NULL,
   1405          1.1     lukem 		&rs->sr_text, textbuf, sizeof( textbuf ) );
   1406      1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS )
   1407      1.1.1.2     lukem 		goto send_res;
   1408          1.1     lukem 
   1409      1.1.1.2     lukem 	rc = slap_add_opattrs( op, &rs->sr_text, textbuf, sizeof( textbuf ), 1 );
   1410      1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS )
   1411      1.1.1.2     lukem 		goto send_res;
   1412      1.1.1.2     lukem 
   1413      1.1.1.2     lukem 	ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
   1414      1.1.1.2     lukem 
   1415      1.1.1.2     lukem 	rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text );
   1416      1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS ) {
   1417      1.1.1.2     lukem 		ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
   1418      1.1.1.2     lukem 		rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text );
   1419      1.1.1.2     lukem 		ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
   1420      1.1.1.2     lukem 
   1421      1.1.1.2     lukem 		SLAP_FREE( path.bv_val );
   1422      1.1.1.2     lukem 		if ( parentdir != NULL )
   1423      1.1.1.2     lukem 			SLAP_FREE( parentdir );
   1424          1.1     lukem 	}
   1425          1.1     lukem 
   1426      1.1.1.2     lukem 	ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
   1427          1.1     lukem 
   1428      1.1.1.2     lukem  send_res:
   1429      1.1.1.2     lukem 	rs->sr_err = rc;
   1430      1.1.1.2     lukem 	Debug( LDAP_DEBUG_TRACE, "ldif_back_add: err: %d text: %s\n",
   1431      1.1.1.2     lukem 		rc, rs->sr_text ? rs->sr_text : "", 0 );
   1432      1.1.1.2     lukem 	send_ldap_result( op, rs );
   1433          1.1     lukem 	slap_graduate_commit_csn( op );
   1434      1.1.1.4      tron 	rs->sr_text = NULL;	/* remove possible pointer to textbuf */
   1435          1.1     lukem 	return rs->sr_err;
   1436          1.1     lukem }
   1437          1.1     lukem 
   1438      1.1.1.2     lukem static int
   1439      1.1.1.2     lukem ldif_back_modify( Operation *op, SlapReply *rs )
   1440      1.1.1.2     lukem {
   1441          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1442          1.1     lukem 	Modifications * modlst = op->orm_modlist;
   1443          1.1     lukem 	struct berval path;
   1444          1.1     lukem 	Entry *entry;
   1445      1.1.1.4      tron 	char textbuf[SLAP_TEXT_BUFLEN];
   1446      1.1.1.2     lukem 	int rc;
   1447          1.1     lukem 
   1448          1.1     lukem 	slap_mods_opattrs( op, &op->orm_modlist, 1 );
   1449          1.1     lukem 
   1450      1.1.1.2     lukem 	ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
   1451          1.1     lukem 
   1452      1.1.1.2     lukem 	rc = get_entry( op, &entry, &path, &rs->sr_text );
   1453      1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS ) {
   1454      1.1.1.4      tron 		rc = apply_modify_to_entry( entry, modlst, op, rs, textbuf );
   1455      1.1.1.2     lukem 		if ( rc == LDAP_SUCCESS ) {
   1456      1.1.1.2     lukem 			ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
   1457      1.1.1.2     lukem 			rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text );
   1458      1.1.1.2     lukem 			ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
   1459          1.1     lukem 		}
   1460          1.1     lukem 
   1461          1.1     lukem 		entry_free( entry );
   1462          1.1     lukem 		SLAP_FREE( path.bv_val );
   1463          1.1     lukem 	}
   1464          1.1     lukem 
   1465      1.1.1.2     lukem 	ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
   1466      1.1.1.2     lukem 
   1467      1.1.1.2     lukem 	rs->sr_err = rc;
   1468      1.1.1.2     lukem 	send_ldap_result( op, rs );
   1469          1.1     lukem 	slap_graduate_commit_csn( op );
   1470      1.1.1.4      tron 	rs->sr_text = NULL;	/* remove possible pointer to textbuf */
   1471          1.1     lukem 	return rs->sr_err;
   1472          1.1     lukem }
   1473          1.1     lukem 
   1474      1.1.1.2     lukem static int
   1475      1.1.1.2     lukem ldif_back_delete( Operation *op, SlapReply *rs )
   1476      1.1.1.2     lukem {
   1477          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1478          1.1     lukem 	struct berval path;
   1479      1.1.1.2     lukem 	int rc = LDAP_SUCCESS;
   1480          1.1     lukem 
   1481          1.1     lukem 	if ( BER_BVISEMPTY( &op->o_csn )) {
   1482          1.1     lukem 		struct berval csn;
   1483      1.1.1.3      adam 		char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];
   1484          1.1     lukem 
   1485          1.1     lukem 		csn.bv_val = csnbuf;
   1486          1.1     lukem 		csn.bv_len = sizeof( csnbuf );
   1487          1.1     lukem 		slap_get_csn( op, &csn, 1 );
   1488          1.1     lukem 	}
   1489          1.1     lukem 
   1490      1.1.1.2     lukem 	ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
   1491      1.1.1.2     lukem 	ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
   1492      1.1.1.2     lukem 	if ( op->o_abandon ) {
   1493      1.1.1.2     lukem 		rc = SLAPD_ABANDON;
   1494      1.1.1.2     lukem 		goto done;
   1495      1.1.1.2     lukem 	}
   1496      1.1.1.2     lukem 
   1497      1.1.1.2     lukem 	rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
   1498      1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS ) {
   1499      1.1.1.2     lukem 		goto done;
   1500      1.1.1.2     lukem 	}
   1501          1.1     lukem 
   1502      1.1.1.2     lukem 	ldif2dir_len( path );
   1503      1.1.1.2     lukem 	ldif2dir_name( path );
   1504      1.1.1.2     lukem 	if ( rmdir( path.bv_val ) < 0 ) {
   1505          1.1     lukem 		switch ( errno ) {
   1506          1.1     lukem 		case ENOTEMPTY:
   1507      1.1.1.2     lukem 			rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
   1508          1.1     lukem 			break;
   1509          1.1     lukem 		case ENOENT:
   1510          1.1     lukem 			/* is leaf, go on */
   1511          1.1     lukem 			break;
   1512          1.1     lukem 		default:
   1513      1.1.1.2     lukem 			rc = LDAP_OTHER;
   1514      1.1.1.2     lukem 			rs->sr_text = "internal error (cannot delete subtree directory)";
   1515          1.1     lukem 			break;
   1516          1.1     lukem 		}
   1517          1.1     lukem 	}
   1518          1.1     lukem 
   1519      1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS ) {
   1520      1.1.1.2     lukem 		dir2ldif_name( path );
   1521      1.1.1.2     lukem 		if ( unlink( path.bv_val ) < 0 ) {
   1522      1.1.1.2     lukem 			rc = LDAP_NO_SUCH_OBJECT;
   1523      1.1.1.2     lukem 			if ( errno != ENOENT ) {
   1524      1.1.1.2     lukem 				rc = LDAP_OTHER;
   1525      1.1.1.2     lukem 				rs->sr_text = "internal error (cannot delete entry file)";
   1526          1.1     lukem 			}
   1527          1.1     lukem 		}
   1528          1.1     lukem 	}
   1529          1.1     lukem 
   1530      1.1.1.2     lukem 	if ( rc == LDAP_OTHER ) {
   1531      1.1.1.2     lukem 		Debug( LDAP_DEBUG_ANY, "ldif_back_delete: %s \"%s\": %s\n",
   1532      1.1.1.2     lukem 			"cannot delete", path.bv_val, STRERROR( errno ) );
   1533      1.1.1.2     lukem 	}
   1534      1.1.1.2     lukem 
   1535      1.1.1.2     lukem 	SLAP_FREE( path.bv_val );
   1536      1.1.1.2     lukem  done:
   1537      1.1.1.2     lukem 	ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
   1538      1.1.1.2     lukem 	ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
   1539      1.1.1.2     lukem 	rs->sr_err = rc;
   1540      1.1.1.2     lukem 	send_ldap_result( op, rs );
   1541          1.1     lukem 	slap_graduate_commit_csn( op );
   1542          1.1     lukem 	return rs->sr_err;
   1543          1.1     lukem }
   1544          1.1     lukem 
   1545          1.1     lukem 
   1546          1.1     lukem static int
   1547          1.1     lukem ldif_move_entry(
   1548          1.1     lukem 	Operation *op,
   1549          1.1     lukem 	Entry *entry,
   1550      1.1.1.2     lukem 	int same_ndn,
   1551      1.1.1.2     lukem 	struct berval *oldpath,
   1552      1.1.1.2     lukem 	const char **text )
   1553          1.1     lukem {
   1554      1.1.1.2     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1555          1.1     lukem 	struct berval newpath;
   1556      1.1.1.2     lukem 	char *parentdir = NULL, *trash;
   1557      1.1.1.2     lukem 	int rc, rename_res;
   1558          1.1     lukem 
   1559      1.1.1.2     lukem 	if ( same_ndn ) {
   1560      1.1.1.2     lukem 		rc = LDAP_SUCCESS;
   1561      1.1.1.2     lukem 		newpath = *oldpath;
   1562      1.1.1.2     lukem 	} else {
   1563      1.1.1.2     lukem 		rc = ldif_prepare_create( op, entry, &newpath,
   1564      1.1.1.2     lukem 			op->orr_newSup ? &parentdir : NULL, text );
   1565      1.1.1.2     lukem 	}
   1566          1.1     lukem 
   1567      1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS ) {
   1568      1.1.1.2     lukem 		ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
   1569      1.1.1.2     lukem 
   1570      1.1.1.2     lukem 		rc = ldif_write_entry( op, entry, &newpath, parentdir, text );
   1571      1.1.1.2     lukem 		if ( rc == LDAP_SUCCESS && !same_ndn ) {
   1572      1.1.1.2     lukem 			trash = oldpath->bv_val; /* will be .ldif file to delete */
   1573      1.1.1.2     lukem 			ldif2dir_len( newpath );
   1574      1.1.1.2     lukem 			ldif2dir_len( *oldpath );
   1575      1.1.1.2     lukem 			/* Move subdir before deleting old entry,
   1576      1.1.1.2     lukem 			 * so .ldif always exists if subdir does.
   1577      1.1.1.2     lukem 			 */
   1578      1.1.1.2     lukem 			ldif2dir_name( newpath );
   1579      1.1.1.2     lukem 			ldif2dir_name( *oldpath );
   1580      1.1.1.2     lukem 			rename_res = move_dir( oldpath->bv_val, newpath.bv_val );
   1581      1.1.1.2     lukem 			if ( rename_res != 0 && errno != ENOENT ) {
   1582      1.1.1.2     lukem 				rc = LDAP_OTHER;
   1583      1.1.1.2     lukem 				*text = "internal error (cannot move this subtree)";
   1584      1.1.1.2     lukem 				trash = newpath.bv_val;
   1585          1.1     lukem 			}
   1586      1.1.1.2     lukem 
   1587      1.1.1.2     lukem 			/* Delete old entry, or if error undo change */
   1588      1.1.1.2     lukem 			for (;;) {
   1589      1.1.1.2     lukem 				dir2ldif_name( newpath );
   1590      1.1.1.2     lukem 				dir2ldif_name( *oldpath );
   1591      1.1.1.2     lukem 				if ( unlink( trash ) == 0 )
   1592      1.1.1.2     lukem 					break;
   1593      1.1.1.2     lukem 				if ( rc == LDAP_SUCCESS ) {
   1594      1.1.1.2     lukem 					/* Prepare to undo change and return failure */
   1595      1.1.1.2     lukem 					rc = LDAP_OTHER;
   1596      1.1.1.2     lukem 					*text = "internal error (cannot move this entry)";
   1597      1.1.1.2     lukem 					trash = newpath.bv_val;
   1598      1.1.1.2     lukem 					if ( rename_res != 0 )
   1599      1.1.1.2     lukem 						continue;
   1600      1.1.1.2     lukem 					/* First move subdirectory back */
   1601      1.1.1.2     lukem 					ldif2dir_name( newpath );
   1602      1.1.1.2     lukem 					ldif2dir_name( *oldpath );
   1603      1.1.1.2     lukem 					if ( move_dir( newpath.bv_val, oldpath->bv_val ) == 0 )
   1604      1.1.1.2     lukem 						continue;
   1605      1.1.1.2     lukem 				}
   1606      1.1.1.2     lukem 				*text = "added new but couldn't delete old entry!";
   1607      1.1.1.2     lukem 				break;
   1608          1.1     lukem 			}
   1609      1.1.1.2     lukem 
   1610      1.1.1.2     lukem 			if ( rc != LDAP_SUCCESS ) {
   1611      1.1.1.2     lukem 				char s[128];
   1612      1.1.1.2     lukem 				snprintf( s, sizeof s, "%s (%s)", *text, STRERROR( errno ));
   1613      1.1.1.2     lukem 				Debug( LDAP_DEBUG_ANY,
   1614      1.1.1.2     lukem 					"ldif_move_entry: %s: \"%s\" -> \"%s\"\n",
   1615      1.1.1.2     lukem 					s, op->o_req_dn.bv_val, entry->e_dn );
   1616          1.1     lukem 			}
   1617          1.1     lukem 		}
   1618      1.1.1.2     lukem 
   1619      1.1.1.2     lukem 		ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
   1620      1.1.1.2     lukem 		if ( !same_ndn )
   1621      1.1.1.2     lukem 			SLAP_FREE( newpath.bv_val );
   1622      1.1.1.2     lukem 		if ( parentdir != NULL )
   1623      1.1.1.2     lukem 			SLAP_FREE( parentdir );
   1624          1.1     lukem 	}
   1625          1.1     lukem 
   1626      1.1.1.2     lukem 	return rc;
   1627          1.1     lukem }
   1628          1.1     lukem 
   1629          1.1     lukem static int
   1630      1.1.1.2     lukem ldif_back_modrdn( Operation *op, SlapReply *rs )
   1631          1.1     lukem {
   1632          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1633          1.1     lukem 	struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
   1634          1.1     lukem 	struct berval p_dn, old_path;
   1635          1.1     lukem 	Entry *entry;
   1636      1.1.1.4      tron 	char textbuf[SLAP_TEXT_BUFLEN];
   1637      1.1.1.2     lukem 	int rc, same_ndn;
   1638          1.1     lukem 
   1639          1.1     lukem 	slap_mods_opattrs( op, &op->orr_modlist, 1 );
   1640          1.1     lukem 
   1641      1.1.1.2     lukem 	ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
   1642          1.1     lukem 
   1643      1.1.1.2     lukem 	rc = get_entry( op, &entry, &old_path, &rs->sr_text );
   1644          1.1     lukem 	if ( rc == LDAP_SUCCESS ) {
   1645          1.1     lukem 		/* build new dn, and new ndn for the entry */
   1646          1.1     lukem 		if ( op->oq_modrdn.rs_newSup != NULL ) {
   1647          1.1     lukem 			p_dn = *op->oq_modrdn.rs_newSup;
   1648          1.1     lukem 		} else {
   1649          1.1     lukem 			dnParent( &entry->e_name, &p_dn );
   1650          1.1     lukem 		}
   1651      1.1.1.2     lukem 		build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL );
   1652          1.1     lukem 		dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL );
   1653      1.1.1.2     lukem 		same_ndn = !ber_bvcmp( &entry->e_nname, &new_ndn );
   1654          1.1     lukem 		ber_memfree_x( entry->e_name.bv_val, NULL );
   1655          1.1     lukem 		ber_memfree_x( entry->e_nname.bv_val, NULL );
   1656          1.1     lukem 		entry->e_name = new_dn;
   1657          1.1     lukem 		entry->e_nname = new_ndn;
   1658          1.1     lukem 
   1659          1.1     lukem 		/* perform the modifications */
   1660      1.1.1.4      tron 		rc = apply_modify_to_entry( entry, op->orr_modlist, op, rs, textbuf );
   1661          1.1     lukem 		if ( rc == LDAP_SUCCESS )
   1662      1.1.1.2     lukem 			rc = ldif_move_entry( op, entry, same_ndn, &old_path,
   1663      1.1.1.2     lukem 				&rs->sr_text );
   1664          1.1     lukem 
   1665          1.1     lukem 		entry_free( entry );
   1666          1.1     lukem 		SLAP_FREE( old_path.bv_val );
   1667          1.1     lukem 	}
   1668          1.1     lukem 
   1669      1.1.1.2     lukem 	ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
   1670          1.1     lukem 	rs->sr_err = rc;
   1671          1.1     lukem 	send_ldap_result( op, rs );
   1672          1.1     lukem 	slap_graduate_commit_csn( op );
   1673      1.1.1.4      tron 	rs->sr_text = NULL;	/* remove possible pointer to textbuf */
   1674          1.1     lukem 	return rs->sr_err;
   1675          1.1     lukem }
   1676          1.1     lukem 
   1677          1.1     lukem 
   1678          1.1     lukem /* Return LDAP_SUCCESS IFF we retrieve the specified entry. */
   1679          1.1     lukem static int
   1680          1.1     lukem ldif_back_entry_get(
   1681          1.1     lukem 	Operation *op,
   1682          1.1     lukem 	struct berval *ndn,
   1683          1.1     lukem 	ObjectClass *oc,
   1684          1.1     lukem 	AttributeDescription *at,
   1685          1.1     lukem 	int rw,
   1686          1.1     lukem 	Entry **e )
   1687          1.1     lukem {
   1688          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
   1689          1.1     lukem 	struct berval op_dn = op->o_req_dn, op_ndn = op->o_req_ndn;
   1690          1.1     lukem 	int rc;
   1691          1.1     lukem 
   1692          1.1     lukem 	assert( ndn != NULL );
   1693          1.1     lukem 	assert( !BER_BVISNULL( ndn ) );
   1694          1.1     lukem 
   1695          1.1     lukem 	ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
   1696          1.1     lukem 	op->o_req_dn = *ndn;
   1697          1.1     lukem 	op->o_req_ndn = *ndn;
   1698      1.1.1.2     lukem 	rc = get_entry( op, e, NULL, NULL );
   1699          1.1     lukem 	op->o_req_dn = op_dn;
   1700          1.1     lukem 	op->o_req_ndn = op_ndn;
   1701          1.1     lukem 	ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
   1702          1.1     lukem 
   1703          1.1     lukem 	if ( rc == LDAP_SUCCESS && oc && !is_entry_objectclass_or_sub( *e, oc ) ) {
   1704          1.1     lukem 		rc = LDAP_NO_SUCH_ATTRIBUTE;
   1705          1.1     lukem 		entry_free( *e );
   1706          1.1     lukem 		*e = NULL;
   1707          1.1     lukem 	}
   1708          1.1     lukem 
   1709          1.1     lukem 	return rc;
   1710          1.1     lukem }
   1711          1.1     lukem 
   1712          1.1     lukem 
   1713          1.1     lukem /* Slap tools */
   1714          1.1     lukem 
   1715      1.1.1.2     lukem static int
   1716      1.1.1.2     lukem ldif_tool_entry_open( BackendDB *be, int mode )
   1717      1.1.1.2     lukem {
   1718      1.1.1.2     lukem 	struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
   1719          1.1     lukem 
   1720      1.1.1.2     lukem 	tl->ecurrent = 0;
   1721      1.1.1.2     lukem 	return 0;
   1722      1.1.1.2     lukem }
   1723          1.1     lukem 
   1724      1.1.1.2     lukem static int
   1725      1.1.1.2     lukem ldif_tool_entry_close( BackendDB *be )
   1726      1.1.1.2     lukem {
   1727      1.1.1.2     lukem 	struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
   1728      1.1.1.2     lukem 	Entry **entries = tl->entries;
   1729      1.1.1.2     lukem 	ID i;
   1730      1.1.1.2     lukem 
   1731      1.1.1.2     lukem 	for ( i = tl->ecount; i--; )
   1732      1.1.1.2     lukem 		if ( entries[i] )
   1733      1.1.1.2     lukem 			entry_free( entries[i] );
   1734      1.1.1.2     lukem 	SLAP_FREE( entries );
   1735      1.1.1.2     lukem 	tl->entries = NULL;
   1736      1.1.1.2     lukem 	tl->ecount = tl->elen = 0;
   1737          1.1     lukem 	return 0;
   1738          1.1     lukem }
   1739          1.1     lukem 
   1740      1.1.1.2     lukem static ID
   1741      1.1.1.2     lukem ldif_tool_entry_next( BackendDB *be )
   1742          1.1     lukem {
   1743      1.1.1.2     lukem 	struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
   1744      1.1.1.2     lukem 
   1745      1.1.1.3      adam 	do {
   1746      1.1.1.3      adam 		Entry *e = tl->entries[ tl->ecurrent ];
   1747      1.1.1.3      adam 
   1748      1.1.1.3      adam 		if ( tl->ecurrent >= tl->ecount ) {
   1749      1.1.1.3      adam 			return NOID;
   1750      1.1.1.3      adam 		}
   1751      1.1.1.3      adam 
   1752      1.1.1.3      adam 		++tl->ecurrent;
   1753      1.1.1.3      adam 
   1754      1.1.1.3      adam 		if ( tl->tl_base && !dnIsSuffixScope( &e->e_nname, tl->tl_base, tl->tl_scope ) ) {
   1755      1.1.1.3      adam 			continue;
   1756      1.1.1.3      adam 		}
   1757      1.1.1.3      adam 
   1758      1.1.1.3      adam 		if ( tl->tl_filter && test_filter( NULL, e, tl->tl_filter  ) != LDAP_COMPARE_TRUE ) {
   1759      1.1.1.3      adam 			continue;
   1760      1.1.1.3      adam 		}
   1761      1.1.1.3      adam 
   1762      1.1.1.3      adam 		break;
   1763      1.1.1.3      adam 	} while ( 1 );
   1764      1.1.1.3      adam 
   1765      1.1.1.3      adam 	return tl->ecurrent;
   1766          1.1     lukem }
   1767          1.1     lukem 
   1768          1.1     lukem static ID
   1769      1.1.1.3      adam ldif_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f )
   1770          1.1     lukem {
   1771      1.1.1.2     lukem 	struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
   1772          1.1     lukem 
   1773      1.1.1.3      adam 	tl->tl_base = base;
   1774      1.1.1.3      adam 	tl->tl_scope = scope;
   1775      1.1.1.3      adam 	tl->tl_filter = f;
   1776      1.1.1.3      adam 
   1777      1.1.1.2     lukem 	if ( tl->entries == NULL ) {
   1778          1.1     lukem 		Operation op = {0};
   1779          1.1     lukem 
   1780          1.1     lukem 		op.o_bd = be;
   1781          1.1     lukem 		op.o_req_dn = *be->be_suffix;
   1782          1.1     lukem 		op.o_req_ndn = *be->be_nsuffix;
   1783          1.1     lukem 		op.ors_scope = LDAP_SCOPE_SUBTREE;
   1784      1.1.1.2     lukem 		if ( search_tree( &op, NULL ) != LDAP_SUCCESS ) {
   1785      1.1.1.2     lukem 			tl->ecurrent = tl->ecount; /* fail ldif_tool_entry_next() */
   1786      1.1.1.4      tron 			return NOID; /* fail ldif_tool_entry_get() */
   1787      1.1.1.2     lukem 		}
   1788          1.1     lukem 	}
   1789          1.1     lukem 	return ldif_tool_entry_next( be );
   1790          1.1     lukem }
   1791          1.1     lukem 
   1792      1.1.1.2     lukem static Entry *
   1793      1.1.1.2     lukem ldif_tool_entry_get( BackendDB *be, ID id )
   1794      1.1.1.2     lukem {
   1795      1.1.1.2     lukem 	struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
   1796      1.1.1.2     lukem 	Entry *e = NULL;
   1797          1.1     lukem 
   1798      1.1.1.2     lukem 	--id;
   1799      1.1.1.2     lukem 	if ( id < tl->ecount ) {
   1800      1.1.1.2     lukem 		e = tl->entries[id];
   1801      1.1.1.2     lukem 		tl->entries[id] = NULL;
   1802          1.1     lukem 	}
   1803      1.1.1.2     lukem 	return e;
   1804          1.1     lukem }
   1805          1.1     lukem 
   1806      1.1.1.2     lukem static ID
   1807      1.1.1.2     lukem ldif_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
   1808      1.1.1.2     lukem {
   1809      1.1.1.2     lukem 	int rc;
   1810      1.1.1.2     lukem 	const char *errmsg = NULL;
   1811      1.1.1.2     lukem 	struct berval path;
   1812      1.1.1.2     lukem 	char *parentdir;
   1813      1.1.1.2     lukem 	Operation op = {0};
   1814          1.1     lukem 
   1815      1.1.1.2     lukem 	op.o_bd = be;
   1816      1.1.1.2     lukem 	rc = ldif_prepare_create( &op, e, &path, &parentdir, &errmsg );
   1817      1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS ) {
   1818      1.1.1.2     lukem 		rc = ldif_write_entry( &op, e, &path, parentdir, &errmsg );
   1819      1.1.1.2     lukem 
   1820      1.1.1.2     lukem 		SLAP_FREE( path.bv_val );
   1821      1.1.1.2     lukem 		if ( parentdir != NULL )
   1822      1.1.1.2     lukem 			SLAP_FREE( parentdir );
   1823      1.1.1.2     lukem 		if ( rc == LDAP_SUCCESS )
   1824      1.1.1.2     lukem 			return 1;
   1825          1.1     lukem 	}
   1826      1.1.1.2     lukem 
   1827      1.1.1.2     lukem 	if ( errmsg == NULL && rc != LDAP_OTHER )
   1828      1.1.1.2     lukem 		errmsg = ldap_err2string( rc );
   1829      1.1.1.2     lukem 	if ( errmsg != NULL )
   1830      1.1.1.2     lukem 		snprintf( text->bv_val, text->bv_len, "%s", errmsg );
   1831      1.1.1.2     lukem 	return NOID;
   1832          1.1     lukem }
   1833          1.1     lukem 
   1834          1.1     lukem 
   1835          1.1     lukem /* Setup */
   1836          1.1     lukem 
   1837          1.1     lukem static int
   1838          1.1     lukem ldif_back_db_init( BackendDB *be, ConfigReply *cr )
   1839          1.1     lukem {
   1840          1.1     lukem 	struct ldif_info *li;
   1841          1.1     lukem 
   1842          1.1     lukem 	li = ch_calloc( 1, sizeof(struct ldif_info) );
   1843          1.1     lukem 	be->be_private = li;
   1844          1.1     lukem 	be->be_cf_ocs = ldifocs;
   1845      1.1.1.2     lukem 	ldap_pvt_thread_mutex_init( &li->li_modop_mutex );
   1846      1.1.1.2     lukem 	ldap_pvt_thread_rdwr_init( &li->li_rdwr );
   1847          1.1     lukem 	SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
   1848          1.1     lukem 	return 0;
   1849          1.1     lukem }
   1850          1.1     lukem 
   1851          1.1     lukem static int
   1852          1.1     lukem ldif_back_db_destroy( Backend *be, ConfigReply *cr )
   1853          1.1     lukem {
   1854          1.1     lukem 	struct ldif_info *li = be->be_private;
   1855          1.1     lukem 
   1856      1.1.1.2     lukem 	ch_free( li->li_base_path.bv_val );
   1857      1.1.1.2     lukem 	ldap_pvt_thread_rdwr_destroy( &li->li_rdwr );
   1858      1.1.1.2     lukem 	ldap_pvt_thread_mutex_destroy( &li->li_modop_mutex );
   1859          1.1     lukem 	free( be->be_private );
   1860          1.1     lukem 	return 0;
   1861          1.1     lukem }
   1862          1.1     lukem 
   1863          1.1     lukem static int
   1864      1.1.1.2     lukem ldif_back_db_open( Backend *be, ConfigReply *cr )
   1865          1.1     lukem {
   1866          1.1     lukem 	struct ldif_info *li = (struct ldif_info *) be->be_private;
   1867          1.1     lukem 	if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */
   1868          1.1     lukem 		Debug( LDAP_DEBUG_ANY, "missing base path for back-ldif\n", 0, 0, 0);
   1869          1.1     lukem 		return 1;
   1870          1.1     lukem 	}
   1871          1.1     lukem 	return 0;
   1872          1.1     lukem }
   1873          1.1     lukem 
   1874          1.1     lukem int
   1875      1.1.1.2     lukem ldif_back_initialize( BackendInfo *bi )
   1876          1.1     lukem {
   1877          1.1     lukem 	static char *controls[] = {
   1878          1.1     lukem 		LDAP_CONTROL_MANAGEDSAIT,
   1879          1.1     lukem 		NULL
   1880          1.1     lukem 	};
   1881          1.1     lukem 	int rc;
   1882          1.1     lukem 
   1883          1.1     lukem 	bi->bi_flags |=
   1884          1.1     lukem 		SLAP_BFLAG_INCREMENT |
   1885          1.1     lukem 		SLAP_BFLAG_REFERRALS;
   1886          1.1     lukem 
   1887          1.1     lukem 	bi->bi_controls = controls;
   1888          1.1     lukem 
   1889          1.1     lukem 	bi->bi_open = 0;
   1890          1.1     lukem 	bi->bi_close = 0;
   1891          1.1     lukem 	bi->bi_config = 0;
   1892          1.1     lukem 	bi->bi_destroy = 0;
   1893          1.1     lukem 
   1894          1.1     lukem 	bi->bi_db_init = ldif_back_db_init;
   1895          1.1     lukem 	bi->bi_db_config = config_generic_wrapper;
   1896          1.1     lukem 	bi->bi_db_open = ldif_back_db_open;
   1897          1.1     lukem 	bi->bi_db_close = 0;
   1898          1.1     lukem 	bi->bi_db_destroy = ldif_back_db_destroy;
   1899          1.1     lukem 
   1900          1.1     lukem 	bi->bi_op_bind = ldif_back_bind;
   1901          1.1     lukem 	bi->bi_op_unbind = 0;
   1902          1.1     lukem 	bi->bi_op_search = ldif_back_search;
   1903          1.1     lukem 	bi->bi_op_compare = 0;
   1904          1.1     lukem 	bi->bi_op_modify = ldif_back_modify;
   1905          1.1     lukem 	bi->bi_op_modrdn = ldif_back_modrdn;
   1906          1.1     lukem 	bi->bi_op_add = ldif_back_add;
   1907          1.1     lukem 	bi->bi_op_delete = ldif_back_delete;
   1908          1.1     lukem 	bi->bi_op_abandon = 0;
   1909          1.1     lukem 
   1910          1.1     lukem 	bi->bi_extended = 0;
   1911          1.1     lukem 
   1912          1.1     lukem 	bi->bi_chk_referrals = ldif_back_referrals;
   1913          1.1     lukem 
   1914          1.1     lukem 	bi->bi_connection_init = 0;
   1915          1.1     lukem 	bi->bi_connection_destroy = 0;
   1916          1.1     lukem 
   1917          1.1     lukem 	bi->bi_entry_get_rw = ldif_back_entry_get;
   1918          1.1     lukem 
   1919          1.1     lukem #if 0	/* NOTE: uncomment to completely disable access control */
   1920          1.1     lukem 	bi->bi_access_allowed = slap_access_always_allowed;
   1921          1.1     lukem #endif
   1922          1.1     lukem 
   1923          1.1     lukem 	bi->bi_tool_entry_open = ldif_tool_entry_open;
   1924          1.1     lukem 	bi->bi_tool_entry_close = ldif_tool_entry_close;
   1925      1.1.1.3      adam 	bi->bi_tool_entry_first = backend_tool_entry_first;
   1926      1.1.1.3      adam 	bi->bi_tool_entry_first_x = ldif_tool_entry_first_x;
   1927          1.1     lukem 	bi->bi_tool_entry_next = ldif_tool_entry_next;
   1928          1.1     lukem 	bi->bi_tool_entry_get = ldif_tool_entry_get;
   1929          1.1     lukem 	bi->bi_tool_entry_put = ldif_tool_entry_put;
   1930          1.1     lukem 	bi->bi_tool_entry_reindex = 0;
   1931          1.1     lukem 	bi->bi_tool_sync = 0;
   1932      1.1.1.2     lukem 
   1933          1.1     lukem 	bi->bi_tool_dn2id_get = 0;
   1934          1.1     lukem 	bi->bi_tool_entry_modify = 0;
   1935          1.1     lukem 
   1936          1.1     lukem 	bi->bi_cf_ocs = ldifocs;
   1937          1.1     lukem 
   1938          1.1     lukem 	rc = config_register_schema( ldifcfg, ldifocs );
   1939          1.1     lukem 	if ( rc ) return rc;
   1940          1.1     lukem 	return 0;
   1941          1.1     lukem }
   1942