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