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