summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/back-ldif
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/slapd/back-ldif
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/slapd/back-ldif')
-rw-r--r--ldap/servers/slapd/back-ldif/Makefile81
-rw-r--r--ldap/servers/slapd/back-ldif/add.c189
-rw-r--r--ldap/servers/slapd/back-ldif/back-ldif.h94
-rw-r--r--ldap/servers/slapd/back-ldif/bind.c108
-rw-r--r--ldap/servers/slapd/back-ldif/close.c79
-rw-r--r--ldap/servers/slapd/back-ldif/compare.c82
-rw-r--r--ldap/servers/slapd/back-ldif/config.c203
-rw-r--r--ldap/servers/slapd/back-ldif/delete.c136
-rw-r--r--ldap/servers/slapd/back-ldif/dllmain.c132
-rw-r--r--ldap/servers/slapd/back-ldif/init.c114
-rw-r--r--ldap/servers/slapd/back-ldif/libback-ldif.def12
-rw-r--r--ldap/servers/slapd/back-ldif/modify.c557
-rw-r--r--ldap/servers/slapd/back-ldif/modrdn.c282
-rw-r--r--ldap/servers/slapd/back-ldif/monitor.c124
-rw-r--r--ldap/servers/slapd/back-ldif/search.c197
-rw-r--r--ldap/servers/slapd/back-ldif/start.c31
-rw-r--r--ldap/servers/slapd/back-ldif/unbind.c27
17 files changed, 2448 insertions, 0 deletions
diff --git a/ldap/servers/slapd/back-ldif/Makefile b/ldap/servers/slapd/back-ldif/Makefile
new file mode 100644
index 00000000..1b7037cd
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/Makefile
@@ -0,0 +1,81 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# GNU Makefile for LDAP Back-ldif backend
+#
+
+LDAP_SRC = ../../..
+MCOM_ROOT = ../../../../..
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+NSPR20=true # probably should be defined somewhere else (not sure where)
+
+OBJDEST = $(OBJDIR)/lib/libback-ldif
+LIBDIR = $(LDAP_LIBDIR)
+SERVER_OBJDEST = $(OBJDIR)/servers/obj
+
+include $(MCOM_ROOT)/ldapserver/nsdefs.mk
+include $(MCOM_ROOT)/ldapserver/nsconfig.mk
+include $(LDAP_SRC)/nsldap.mk
+
+BACKLDIF_OBJS = close.o delete.o modrdn.o unbind.o add.o \
+ compare.o init.o search.o bind.o config.o modify.o monitor.o \
+ start.o
+
+OBJS = $(addprefix $(OBJDEST)/, $(BACKLDIF_OBJS))
+
+SERVER_OBJS= ch_malloc.o entry.o result.o modutil.o
+
+EXTRA_OBJS = $(addprefix $(SERVER_OBJDEST)/, $(SERVER_OBJS))
+
+INCLUDES += -I..
+
+ifeq ($(ARCH), WINNT)
+BACKLDIF_DLL_OBJ = $(addprefix $(OBJDEST)/, dllmain.o)
+endif
+
+LDAP_BACKLDIF= $(addprefix $(LIBDIR)/, $(LIBBACK_LDIF_DLL).$(DLL_SUFFIX))
+
+ifeq ($(ARCH), WINNT)
+EXTRA_LIBS_DEP += $(LIBSECURITY) $(LIBNSPR) \
+ $(LDAP_COMMON_LIBS_DEP) $(LDAP_SDK_LIBS_DEP) \
+ $(LIBSLAPD_DEP) $(LIBLDAPU_DEP)
+
+EXTRA_LIBS += $(LIBSECURITY) $(LIBNSPR) \
+ $(LDAP_COMMON_LIBS) $(LDAP_SDK_LIBS) \
+ $(LIBSLAPD) $(THREADSLIB) $(LIBLDAPU)
+endif
+
+ifeq ($(ARCH), AIX)
+EXTRA_LIBS += $(DLL_EXTRA_LIBS)
+endif
+
+clientSDK:
+
+all: $(OBJDEST) $(LIBDIR) $(LDAP_BACKLDIF)
+
+$(LIBDIR):
+ $(MKDIR) $(LIBDIR)
+
+$(LDAP_BACKLDIF): $(OBJS) $(BACKLDIF_DLL_OBJ)
+ $(LINK_DLL) $(BACKLDIF_DLL_OBJ) $(EXTRA_LIBS)
+
+$(SERVER_OBJDEST)/ch_malloc.o: ../ch_malloc.c
+ $(CC) -c $(CFLAGS) $(MCC_INCLUDE) $< $(OFFLAG)$*.o
+
+clean:
+ $(RM) $(OBJS)
+ifeq ($(ARCH), WINNT)
+ $(RM) $(BACKLDIF_DLL_OBJ)
+endif
+ $(RM) $(LDAP_BACKLDIF)
+
+$(OBJDEST):
+ $(MKDIR) $(OBJDEST)
+
diff --git a/ldap/servers/slapd/back-ldif/add.c b/ldap/servers/slapd/back-ldif/add.c
new file mode 100644
index 00000000..cd0b81dc
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/add.c
@@ -0,0 +1,189 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: add.c
+ *
+ * Functions:
+ *
+ * ldif_back_add() - ldap ldif back-end add routine
+ * ldifentry_init() - takes an Entry and makes an ldif_Entry
+ *
+ */
+
+#include "back-ldif.h"
+ldif_Entry * ldifentry_init(Slapi_Entry *);
+
+/*
+ * Function: ldif_back_add
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: For changetype: add, this function adds the entry
+ */
+int
+ldif_back_add( Slapi_PBlock *pb )
+{
+ LDIF *db; /*Stores the ldif database*/
+ char *dn = NULL, *parentdn = NULL;
+ Slapi_Entry *e; /*The new entry to add*/
+ ldif_Entry *new, *old; /*Used for various accounting purposes*/
+ ldif_Entry *prev; /*Used to add new ldif_Entry to db*/
+ ldif_Entry *tprev; /*Dummy pointer for traversing the list*/
+ char *errbuf = NULL;
+
+ prev = NULL;
+ tprev = NULL;
+
+ /*Turn on tracing to see this printed out*/
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_add\n", 0, 0, 0 );
+
+ /*Get the database, the dn and the entry to add*/
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_ADD_TARGET, &dn ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e ) < 0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*Check to make sure the entry passes the schema check*/
+ if ( slapi_entry_schema_check( pb, e ) != 0 ) {
+ LDAPDebug( LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0, 0 );
+ slapi_send_ldap_result( pb, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL, 0, NULL );
+ return( -1 );
+ }
+
+ prev = NULL;
+
+ /*Lock the database*/
+ PR_Lock( db->ldif_lock );
+
+ /*
+ * Attempt to find this dn in db. If there is no such dn,
+ * ldif_find_entry should return NULL, and prev should point
+ * to the last element in the list.
+ */
+ if ((old = (ldif_Entry *)ldif_find_entry(pb, db, dn, &prev)) != NULL) {
+
+ /*
+ * If we've reached this code, there is an entry in db
+ * whose dn matches dn, so release the db lock,
+ * tell the user and return
+ */
+ PR_Unlock( db->ldif_lock );
+ slapi_send_ldap_result( pb, LDAP_ALREADY_EXISTS, NULL, NULL, 0, NULL );
+ return( -1 );
+ }
+
+
+ /*
+ * Get the parent dn and see if the corresponding entry exists.
+ * If the parent does not exist, only allow the "root" user to
+ * add the entry.
+ */
+ if ( (parentdn = slapi_dn_beparent( pb, dn )) != NULL ) {
+ int rc;
+ if ((old = (ldif_Entry *)ldif_find_entry( pb, db, parentdn, &tprev)) == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
+ LDAPDebug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0, 0, 0 );
+ goto error_return;
+ }
+ rc= slapi_access_allowed( pb, e, NULL, NULL, SLAPI_ACL_ADD );
+ if ( rc!=LDAP_SUCCESS ) {
+ LDAPDebug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,0, 0 );
+ slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL );
+ goto error_return;
+ }
+ } else { /* no parent */
+ int isroot;
+ slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
+ if ( !isroot ) {
+ LDAPDebug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0, 0, 0 );
+ slapi_send_ldap_result( pb, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, 0, NULL );
+ goto error_return;
+ }
+
+ }
+
+ /*
+ * Before we add the entry, find out if the syntax of the aci
+ * aci attribute values are correct or not. We don't want to add
+ * the entry if the syntax is incorrect.
+ */
+ if ( slapi_acl_verify_aci_syntax(pb, e, &errbuf) != 0 ) {
+ slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, errbuf, 0, NULL );
+ if (errbuf) free(errbuf);
+ goto error_return;
+ }
+
+ /*Make a new element for the linked list*/
+ if ( (new = (ldif_Entry *)ldifentry_init( e )) == NULL){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ goto error_return;
+
+ }
+
+ /*Add the new element to the end of the list of entries in db*/
+ if ( update_db(pb, db, new, prev, LDIF_DB_ADD) != 0)
+ {
+ ldifentry_free( new );
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ goto error_return;
+
+ }
+
+ /*We have been sucessful. Tell the user*/
+ slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
+
+ /*Release the database lock*/
+ PR_Unlock( db->ldif_lock );
+
+ /*Free the parentdn, and return*/
+ if ( parentdn != NULL ){
+ free( (void *)parentdn );
+ }
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_add\n", 0, 0, 0 );
+ return( 0 );
+
+ error_return:;
+ if ( parentdn != NULL ){
+ free( (void *)parentdn );
+ }
+
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+}
+
+/*
+ * Function: ldifentry_init
+ *
+ * Returns: a pointer to an ldif_Entry, or NULL
+ *
+ * Description: Takes a pointer to an Entry, and sticks
+ * it into an ldif_Entry structure.
+ * Note, uses Malloc.
+ */
+ldif_Entry *
+ldifentry_init(Slapi_Entry *e)
+{
+ ldif_Entry *new;
+
+ /*Alloc a new ldif_entry*/
+ new = (ldif_Entry *) malloc(sizeof(ldif_Entry));
+
+ /*Did it work? if not, return NULL*/
+ if (new == NULL) {
+ return (NULL);
+ }
+ /*If it did work, then fill it*/
+ new->lde_e = e;
+ new->next = NULL;
+
+ /*Send it*/
+ return (new);
+}
+
+
+
diff --git a/ldap/servers/slapd/back-ldif/back-ldif.h b/ldap/servers/slapd/back-ldif/back-ldif.h
new file mode 100644
index 00000000..5875c985
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/back-ldif.h
@@ -0,0 +1,94 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: back-ldif.h
+ *
+ * Description: This header file contains the definitions
+ * for the data structures used in the ldif backend database
+ */
+
+#define SLAPD_LOGGING 1
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+/* include NSPR header files */
+#include "prlock.h"
+
+#include "ldaplog.h"
+#include "portable.h"
+#include "dirver.h"
+#include "slap.h"
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <sys/socket.h>
+#endif /* _WIN32 */
+
+/*Defines*/
+#define LDIF_DB_ADD 0
+#define LDIF_DB_DELETE 1
+#define LDIF_DB_REPLACE 2
+
+
+/*This structure basically allows the entries to be linked listed*/
+struct ldif_entry{
+ Slapi_Entry *lde_e; /*ptr to the Entry datatype, but you knew that*/
+ struct ldif_entry *next; /*ptr to the next list element.*/
+};
+typedef struct ldif_entry ldif_Entry;
+
+
+/*Holds the data from the ldif file*/
+struct ldif {
+ long ldif_n; /*The number of entries in the database*/
+ long ldif_tries; /*The number of accesses to the database*/
+ long ldif_hits; /*The number of succesful searches to the db*/
+ char *ldif_file; /*From where we read the ldif data*/
+ PRLock *ldif_lock; /*Write & read lock.(a simple locking model)*/
+ ldif_Entry *ldif_entries; /*The linked list of entries*/
+};
+typedef struct ldif LDIF;
+
+
+/*Prototypes*/
+ int ldif_back_modify( Slapi_PBlock * );
+ int update_db(Slapi_PBlock *, LDIF *, ldif_Entry *, ldif_Entry *, int);
+ int db2disk(Slapi_PBlock *, LDIF *);
+ void ldifentry_free(ldif_Entry *);
+ ldif_Entry *ldifentry_dup(ldif_Entry *);
+ ldif_Entry *ldif_find_entry(Slapi_PBlock *, LDIF *, char *, ldif_Entry **);
+ int apply_mods( Slapi_Entry *, LDAPMod ** );
+
+ int ldif_back_add( Slapi_PBlock *);
+ ldif_Entry *ldifentry_init(Slapi_Entry *);
+ int ldif_back_config( Slapi_PBlock *);
+ static char * ldif_read_one_record( FILE *);
+ int ldif_back_delete( Slapi_PBlock *);
+ int has_children(LDIF *, ldif_Entry *);
+ int ldif_back_init( Slapi_PBlock *);
+
+ int ldif_back_search( Slapi_PBlock * );
+
+ int ldif_back_modrdn( Slapi_PBlock * );
+ static int rdn2typeval(char *, char **, struct berval *);
+ void add_mod( LDAPMod ***, int, char *, struct berval ** );
+
+ int ldif_back_bind( Slapi_PBlock * );
+ int ldif_back_unbind( Slapi_PBlock * );
+
+ int ldif_back_start( Slapi_PBlock * );
+ void ldif_back_close( Slapi_PBlock * );
+ void ldif_back_flush( Slapi_PBlock * );
+ void ldif_free_db(LDIF *);
+
+ int ldif_back_compare( Slapi_PBlock * );
+
+ char * get_monitordn(Slapi_PBlock * );
+ int ldif_back_monitor_info( Slapi_PBlock *pb, LDIF *db);
diff --git a/ldap/servers/slapd/back-ldif/bind.c b/ldap/servers/slapd/back-ldif/bind.c
new file mode 100644
index 00000000..b95a589f
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/bind.c
@@ -0,0 +1,108 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: bind.c
+ *
+ * Functions:
+ *
+ * ldif_back_bind() - ldap ldif back-end bind routine
+ *
+ */
+
+#include "back-ldif.h"
+
+/*
+ * Function: ldif_back_bind
+ *
+ * Returns: returns 0|1 if good, -1 else.
+ *
+ * Description: performs an ldap bind.
+ */
+int
+ldif_back_bind( Slapi_PBlock *pb )
+{
+ char *dn; /*Storage for the dn*/
+ int method; /*Storage for the bind method*/
+ struct berval *cred; /*Storage for the bind credentials*/
+ struct berval **bvals;
+ LDIF *db; /*The database*/
+ ldif_Entry *e, *prev; /*Used for searching the db*/
+ int rc, syntax; /*Storage for error return values*/
+ Slapi_Attr *attr;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_bind\n", 0, 0, 0 );
+
+ prev = NULL;
+
+ /*Get the parameters*/
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_BIND_TARGET, &dn ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &cred ) < 0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*Lock the database*/
+ PR_Lock( db->ldif_lock );
+
+
+ /*Find the entry that the person is attempting to bind as*/
+ if ( (e = (ldif_Entry *)ldif_find_entry( pb, db, dn, &prev )) == NULL ) {
+
+ /* Allow noauth binds */
+ if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
+ rc = SLAPI_BIND_ANONYMOUS;
+ } else {
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
+ rc = SLAPI_BIND_FAIL;
+ }
+
+ /*Unlock the database*/
+ PR_Unlock( db->ldif_lock );
+
+ return( rc );
+ }
+
+ switch ( method ) {
+ case LDAP_AUTH_SIMPLE:
+ if ( cred->bv_len == 0 ) {
+ PR_Unlock( db->ldif_lock );
+ return( SLAPI_BIND_ANONYMOUS );
+ }
+
+ if ( slapi_entry_attr_find( e->lde_e, "userpassword", &attr ) != 0 ) {
+ slapi_send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( SLAPI_BIND_FAIL );
+ }
+ /*
+ * XXXmcs: slapi_attr_get_values() is deprecated and should be avoided
+ * See XXXmcs comments in ../attr.c for detailed information.
+ */
+ slapi_attr_get_values( attr, &bvals );
+
+ if ( slapi_pw_find( bvals, cred ) != 0 ) {
+ slapi_send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( SLAPI_BIND_FAIL );
+ }
+ break;
+
+ default:
+ slapi_send_ldap_result( pb, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL,
+ "auth method not supported", 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( SLAPI_BIND_FAIL );
+ }
+
+ PR_Unlock( db->ldif_lock );
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_bind\n", 0, 0, 0 );
+
+ /* success: front end will send result */
+ return( SLAPI_BIND_SUCCESS );
+}
diff --git a/ldap/servers/slapd/back-ldif/close.c b/ldap/servers/slapd/back-ldif/close.c
new file mode 100644
index 00000000..34048eca
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/close.c
@@ -0,0 +1,79 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: close.c
+ *
+ * Functions:
+ *
+ * ldif_back_close() - ldap ldif back-end close routine
+ *
+ */
+
+#include "back-ldif.h"
+
+/*
+ * Function: ldif_free_db
+ *
+ * Returns: void
+ *
+ * Description: frees up the ldif database
+ */
+void
+ldif_free_db(LDIF *db)
+{
+ ldif_Entry *cur; /*Used for walking down the list*/
+
+ /*If db is null, there is nothing to do*/
+ if (db == NULL) {
+ return;
+ }
+
+ /*Walk down the list, freeing up the ldif_entries*/
+ for (cur = db->ldif_entries; cur != NULL; cur = cur->next){
+ ldifentry_free(cur);
+ }
+
+ /*Free the ldif_file string, and then the db itself*/
+ free ((void *)db->ldif_file);
+ free((void *) db);
+}
+
+
+
+/*
+ * Function: ldif_back_close
+ *
+ * Returns: void
+ *
+ * Description: closes the ldif backend, frees up the database
+ */
+void
+ldif_back_close( Slapi_PBlock *pb )
+{
+ LDIF *db;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm backend syncing\n", 0, 0, 0 );
+ slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db );
+ ldif_free_db(db);
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm backend done syncing\n", 0, 0, 0 );
+}
+
+/*
+ * Function: ldif_back_flush
+ *
+ * Returns: void
+ *
+ * Description: does nothing
+ */
+void
+ldif_back_flush( Slapi_PBlock *pb )
+{
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm backend flushing\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm backend done flushing\n", 0, 0, 0 );
+ return;
+}
+
+
diff --git a/ldap/servers/slapd/back-ldif/compare.c b/ldap/servers/slapd/back-ldif/compare.c
new file mode 100644
index 00000000..bb0c3754
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/compare.c
@@ -0,0 +1,82 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: compare.c
+ *
+ * Functions:
+ *
+ * ldif_back_compare() - ldap ldif back-end compare routine
+ *
+ */
+
+#include "back-ldif.h"
+
+/*
+ * Function: ldif_back_compare
+ *
+ * Returns: -1, 0 or 1
+ *
+ * Description: compares entries in the ldif backend
+ */
+int
+ldif_back_compare( Slapi_PBlock *pb )
+{
+ LDIF *db; /*The Database*/
+ ldif_Entry *e, *prev; /*Used for searching the database*/
+ char *dn, *type; /*The dn and the type*/
+ struct berval *bval;
+ Slapi_Attr *attr;
+ int rc;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_compare\n", 0, 0, 0 );
+ prev = NULL;
+
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_COMPARE_TARGET, &dn ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_COMPARE_TYPE, &type ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_COMPARE_VALUE, &bval ) < 0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*Lock the database*/
+ PR_Lock( db->ldif_lock );
+
+
+ /*Find the entry for comparison*/
+ if ( (e = (ldif_Entry*) ldif_find_entry( pb, db, dn, &prev )) == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( 1 );
+ }
+
+ /*Check the access*/
+ rc= slapi_access_allowed( pb, e->lde_e, type, bval, SLAPI_ACL_COMPARE );
+ if ( rc!=LDAP_SUCCESS ) {
+ slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( 1 );
+ }
+
+ /*find the attribute*/
+ if ( slapi_entry_attr_find( e->lde_e, type, &attr ) != 0 ) {
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( 1 );
+ }
+
+ if ( slapi_attr_value_find( attr, bval ) == 0 ) {
+ slapi_send_ldap_result( pb, LDAP_COMPARE_TRUE, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( 0 );
+ }
+
+ slapi_send_ldap_result( pb, LDAP_COMPARE_FALSE, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_compare\n", 0, 0, 0 );
+ return( 0 );
+}
+
diff --git a/ldap/servers/slapd/back-ldif/config.c b/ldap/servers/slapd/back-ldif/config.c
new file mode 100644
index 00000000..a62335a5
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/config.c
@@ -0,0 +1,203 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: config.c
+ *
+ * Functions:
+ *
+ * ldif_back_config() - Reads in and stores ldif file for ldif backend
+ * ldif_read_one_record() - Reads in one record from ldif file as a string
+ *
+ */
+
+#include "back-ldif.h"
+#define LDAPMOD_MAXLINE 4096
+#define safe_realloc( ptr, size ) ( ptr == NULL ? malloc( size ) : \
+ realloc( ptr, size ))
+static char *ldif_read_one_record();
+
+
+/*
+ * Function: ldif_back_config
+ *
+ * Returns: 0 if success, -1 if not
+ *
+ * Description: Reads the data in the ldif file specified in ldif.conf
+ * stores it in db
+ */
+int
+ldif_back_config( Slapi_PBlock *pb )
+{
+ LDIF *db; /*The ldif file will be read into this structure*/
+ char *fname; /*Config file name*/
+ int lineno, argc; /*Config file stuff*/
+ char **argv; /*More config file stuff*/
+ FILE *fp; /*Pointer to ldif file*/
+ char *buf; /*Tmp storage for ldif entries*/
+ int first; /*Boolean to determine if db is empty*/
+ ldif_Entry *cur; /*For db manipulation*/
+ ldif_Entry *new; /*For db manipulation*/
+ Slapi_Entry *tmp; /*Used for initialization purposes*/
+
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_config\n", 0, 0, 0 );
+
+ /*
+ * Get the private_info structure you created in ldif_back_init().
+ * Also get the config file name, current line number, and arguments
+ * from the current line, broken out into an argv.
+ */
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_CONFIG_FILENAME, &fname ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_CONFIG_LINENO, &lineno ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_CONFIG_ARGC, &argc ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_CONFIG_ARGV, &argv ) < 0 ){
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: unable to get data from front end\n", 0, 0, 0);
+ return(-1);
+ }
+
+
+ /*
+ * Process the config info. For example, if the config file
+ * contains a line like this:
+ *
+ * file /path/to/ldif/file
+ *
+ * then argv[0] would be "file", and argv[1] would be the file
+ * name.
+ */
+
+ /*Check for the correct number of arguments*/
+ if (argc != 2){
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: Unable to configure; invalid ldif input file specification line format (file: %s, line: %d)\n",
+ fname, lineno, 0);
+ return(-1);
+ }
+
+ /*Check for the right format*/
+ if (strcmp(argv[0], "file") != 0){
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: unable to configure; invalid parameter \"%s\" in config file (file: %s, line: %d)\n",
+ argv[0], fname, lineno );
+ return(-1);
+ }
+
+ /*Now we fopen the file and grab up the contents*/
+ fp = fopen (argv[1], "r");
+ if (fp == NULL){
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: unable to read ldif file %s\n", argv[1], 0, 0);
+ fp = fopen (argv[1], "w");
+ if(fp == NULL){
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: unable to create ldif file %s\n", argv[1], 0, 0);
+ return -1;
+ }
+ }
+
+ first = 1;
+
+ /* Lock the database first, just to be safe*/
+ PR_Lock( db->ldif_lock );
+
+ /*Save the filename, for modifications to the file later*/
+ if ((db->ldif_file = strdup(argv[1])) == NULL){
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: out of memory\n", 0, 0, 0);
+ PR_Unlock( db->ldif_lock );
+ fclose(fp);
+ return(-1);
+ }
+
+ /*
+ * Loop through the entries in the file, and add them to the end
+ * of the linked list
+ */
+ while ((buf = ldif_read_one_record(fp)) != NULL){
+
+ /*Create a new element for the linked list of entries*/
+ tmp = (Slapi_Entry *) slapi_str2entry(buf,
+ SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF);
+ new = (ldif_Entry *) ldifentry_init(tmp);
+ if (new == NULL){
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: unable to read in ldif file; out of memory\n",0 ,0 ,0 );
+ PR_Unlock( db->ldif_lock );
+ fclose(fp);
+ return(-1);
+ }
+
+ /*
+ * If this is the first entry we are adding,
+ * we have to make it the first element in the list
+ */
+ if (first){
+ db->ldif_entries = new;
+ first = 0;
+ } else{
+ cur->next = new;
+ }
+
+ /*Reset the pointer to the last element in the list*/
+ cur = new;
+
+ /*Increment the number of entries*/
+ db->ldif_n++;
+
+ /*Free the buffer*/
+ free ((void *) buf );
+
+ }
+
+ /*By now, the database should be read in*/
+ PR_Unlock( db->ldif_lock );
+ fclose(fp);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_config\n", 0, 0, 0 );
+ return( 0 );
+}
+
+
+
+/*
+ * Function: ldif_read_one_record
+ *
+ * Returns: a long string representing an ldif record
+ *
+ * Description: Returns a huge string comprised of 1 ldif record
+ * read from fp.
+ *
+ */
+static char *
+ldif_read_one_record( FILE *fp )
+{
+ int len, gotnothing;
+ char *buff, line[ LDAPMOD_MAXLINE ];
+ int lcur, lmax;
+
+ lcur = lmax = 0;
+ buff = NULL;
+ gotnothing = 1;
+
+ while ( fgets( line, sizeof(line), fp ) != NULL ) {
+ if ( (len = strlen( line )) < 2 ) {
+ if ( gotnothing ) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ gotnothing = 0;
+ if ( lcur + len + 1 > lmax ) {
+ lmax = LDAPMOD_MAXLINE
+ * (( lcur + len + 1 ) / LDAPMOD_MAXLINE + 1 );
+ if (( buff = (char *)safe_realloc( buff, lmax )) == NULL ) {
+ perror( "safe_realloc" );
+ exit( LDAP_NO_MEMORY );
+ }
+ }
+ strcpy( buff + lcur, line );
+ lcur += len;
+ }
+
+ return( buff );
+}
+
diff --git a/ldap/servers/slapd/back-ldif/delete.c b/ldap/servers/slapd/back-ldif/delete.c
new file mode 100644
index 00000000..cf155ad4
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/delete.c
@@ -0,0 +1,136 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: delete.c
+ *
+ * Functions:
+ *
+ * ldif_back_delete() - ldap ldif back-end delete routine
+ * has_children() - determines if an entry has any children
+ *
+ */
+
+#include "back-ldif.h"
+
+/*
+ * Function: ldif_back_delete
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: For changetype: delete, this function deletes the entry
+ */
+int
+ldif_back_delete( Slapi_PBlock *pb )
+{
+ LDIF *db; /*The database*/
+ ldif_Entry *bye, *prev; /*"bye" is the record to be deleted*/
+ char *dn; /*Storage for the dn*/
+ int rc;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_delete\n", 0, 0, 0 );
+
+ prev = NULL;
+
+ /*Get the database and the dn to delete*/
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_DELETE_TARGET, &dn ) < 0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*Lock the database*/
+ PR_Lock( db->ldif_lock );
+
+ /* Find the entry we're about to delete*/
+ bye = (ldif_Entry *) ldif_find_entry(pb, db, dn, &prev);
+ if (bye == NULL) {
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
+ LDAPDebug( LDAP_DEBUG_TRACE, "entry for delete does not exist\n", 0, 0, 0 );
+ PR_Unlock( db->ldif_lock );
+ return(-1);
+ }
+
+ /*Make sure that we are trying to delete a leaf.*/
+ if ( has_children( db, bye ) ) {
+ slapi_send_ldap_result( pb, LDAP_NOT_ALLOWED_ON_NONLEAF, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+ /*Check the access*/
+ rc= slapi_access_allowed( pb, bye->lde_e, "entry", NULL, SLAPI_ACL_DELETE );
+ if ( rc!=LDAP_SUCCESS) {
+ slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+ /* Delete from disk and database */
+ if ( update_db(pb, db, NULL, prev, LDIF_DB_DELETE) != 0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return(-1);
+
+ }
+
+ /*Success*/
+ slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_delete\n", 0, 0, 0 );
+ return( 0 );
+}
+
+/*
+ * Function: has_children
+ *
+ * Returns: returns 1 if the entry has kids, 0 else.
+ *
+ * Description: Determines if the entry has children
+ */
+int
+has_children(LDIF *db, ldif_Entry *p)
+{
+ char *parentdn; /*Basically the dn of p (copied)*/
+ char *childdn; /*Will be used to test if p has any children*/
+ ldif_Entry *cur; /*Used to walk down the list*/
+ int has_kid = 0; /*Flag to return*/
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> has_children\n", 0, 0, 0);
+
+ /*If there is no p or db, then there can be no children*/
+ if (p == NULL || db == NULL){
+ return(0);
+ }
+
+ /*Get a copy of p's dn, and normalize it (squeeze any unneeded spaces out)*/
+ parentdn = strdup( slapi_entry_get_dn(p->lde_e) );
+ (void) slapi_dn_normalize( parentdn );
+
+ /*Walk down the list, seeing if each entry has p as a parent*/
+ for (cur = db->ldif_entries; cur != NULL; cur = cur->next){
+ childdn = strdup(slapi_entry_get_dn(cur->lde_e));
+ (void) slapi_dn_normalize(childdn);
+
+ /*Test to see if this childdn is a child of the parentdn*/
+ if (slapi_dn_issuffix( childdn, parentdn ) && strlen(childdn) > strlen(parentdn))
+ {
+ has_kid = 1;
+ free( (void *) childdn);
+ break;
+ }
+ free( (void *) childdn);
+
+ }
+
+ free( (void *) parentdn );
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= has_children %d\n", has_kid, 0, 0);
+ return( has_kid );
+}
+
+
+
+
diff --git a/ldap/servers/slapd/back-ldif/dllmain.c b/ldap/servers/slapd/back-ldif/dllmain.c
new file mode 100644
index 00000000..69d0ceb5
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/dllmain.c
@@ -0,0 +1,132 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * Microsoft Windows specifics for LIBLDAP DLL
+ */
+#include "ldap.h"
+
+
+#ifdef _WIN32
+/* Lifted from Q125688
+ * How to Port a 16-bit DLL to a Win32 DLL
+ * on the MSVC 4.0 CD
+ */
+BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
+{
+ WSADATA wsadata;
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ /* Code from LibMain inserted here. Return TRUE to keep the
+ DLL loaded or return FALSE to fail loading the DLL.
+
+ You may have to modify the code in your original LibMain to
+ account for the fact that it may be called more than once.
+ You will get one DLL_PROCESS_ATTACH for each process that
+ loads the DLL. This is different from LibMain which gets
+ called only once when the DLL is loaded. The only time this
+ is critical is when you are using shared data sections.
+ If you are using shared data sections for statically
+ allocated data, you will need to be careful to initialize it
+ only once. Check your code carefully.
+
+ Certain one-time initializations may now need to be done for
+ each process that attaches. You may also not need code from
+ your original LibMain because the operating system may now
+ be doing it for you.
+ */
+ /*
+ * 16 bit code calls UnlockData()
+ * which is mapped to UnlockSegment in windows.h
+ * in 32 bit world UnlockData is not defined anywhere
+ * UnlockSegment is mapped to GlobalUnfix in winbase.h
+ * and the docs for both UnlockSegment and GlobalUnfix say
+ * ".. function is oboslete. Segments have no meaning
+ * in the 32-bit environment". So we do nothing here.
+ */
+
+ if( errno = WSAStartup(0x0101, &wsadata ) != 0 )
+ return FALSE;
+
+ break;
+
+ case DLL_THREAD_ATTACH:
+ /* Called each time a thread is created in a process that has
+ already loaded (attached to) this DLL. Does not get called
+ for each thread that exists in the process before it loaded
+ the DLL.
+
+ Do thread-specific initialization here.
+ */
+ break;
+
+ case DLL_THREAD_DETACH:
+ /* Same as above, but called when a thread in the process
+ exits.
+
+ Do thread-specific cleanup here.
+ */
+ break;
+
+ case DLL_PROCESS_DETACH:
+ /* Code from _WEP inserted here. This code may (like the
+ LibMain) not be necessary. Check to make certain that the
+ operating system is not doing it for you.
+ */
+ WSACleanup();
+
+ break;
+ }
+ /* The return value is only used for DLL_PROCESS_ATTACH; all other
+ conditions are ignored. */
+ return TRUE; // successful DLL_PROCESS_ATTACH
+}
+#else
+int CALLBACK
+LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine )
+{
+ /*UnlockData( 0 );*/
+ return( 1 );
+}
+#endif
+
+#ifdef LDAP_DEBUG
+#ifndef _WIN32
+#include <stdarg.h>
+#include <stdio.h>
+
+void LDAPDebug( int level, char* fmt, ... )
+{
+ static char debugBuf[1024];
+
+ if (slapd_ldap_debug & level)
+ {
+ va_list ap;
+ va_start (ap, fmt);
+ _snprintf (debugBuf, sizeof(debugBuf), fmt, ap);
+ va_end (ap);
+
+ OutputDebugString (debugBuf);
+ }
+}
+#endif
+#endif
+
+#ifndef _WIN32
+
+/* The 16-bit version of the RTL does not implement perror() */
+
+#include <stdio.h>
+
+void perror( const char *msg )
+{
+ char buf[128];
+ wsprintf( buf, "%s: error %d\n", msg, WSAGetLastError()) ;
+ OutputDebugString( buf );
+}
+
+#endif
diff --git a/ldap/servers/slapd/back-ldif/init.c b/ldap/servers/slapd/back-ldif/init.c
new file mode 100644
index 00000000..8196d371
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/init.c
@@ -0,0 +1,114 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: init.c
+ *
+ * Functions:
+ *
+ * ldif_back_init() - ldap ldif back-end initialize routine
+ *
+ */
+
+#include "back-ldif.h"
+
+static Slapi_PluginDesc pdesc = { "ldif-backend", "Netscape", PRODUCTTEXT,
+ "LDIF backend database plugin" };
+
+#ifdef _WIN32
+int *module_ldap_debug = 0;
+
+void plugin_init_debug_level(int *level_ptr)
+{
+ module_ldap_debug = level_ptr;
+}
+#endif
+
+/*
+ * Function: ldif_back_init
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: Allocates a database for filling by ldif_back_config
+ */
+int
+ldif_back_init( Slapi_PBlock *pb )
+{
+ LDIF *db; /*This will hold the ldif file in memory*/
+ int rc;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_init\n", 0, 0, 0 );
+
+ /*
+ * Allocate and initialize db with everything we
+ * need to keep track of in this backend. In ldif_back_config(),
+ * we will fill in db with things like the name
+ * of the ldif file containing the database, and any other
+ * options we allow people to set through the config file.
+ */
+
+ /*Allocate memory for our database and check if success*/
+ db = (LDIF *) malloc( sizeof(LDIF) );
+ if (db == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: unable to initialize; out of memory\n", 0, 0, 0);
+ return(-1);
+ }
+
+ /*Fill with initial values, including the mutex*/
+ db->ldif_n = 0;
+ db->ldif_entries = NULL;
+ db->ldif_tries = 0;
+ db->ldif_hits = 0;
+ db->ldif_file = NULL;
+ db->ldif_lock = PR_NewLock();
+ if (&db->ldif_lock == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: Lock creation failed\n", 0, 0, 0);
+ return(-1);
+ }
+
+
+ /*
+ * set SLAPI_PLUGIN_PRIVATE field in pb, so it's available
+ * later in ldif_back_config(), ldif_back_search(), etc.
+ */
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_PRIVATE, (void *) db );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_BIND_FN,
+ (void *) ldif_back_bind );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_UNBIND_FN,
+ (void *) ldif_back_unbind );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_SEARCH_FN,
+ (void *) ldif_back_search );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_COMPARE_FN,
+ (void *) ldif_back_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_MODIFY_FN,
+ (void *) ldif_back_modify );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_MODRDN_FN,
+ (void *) ldif_back_modrdn );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_ADD_FN,
+ (void *) ldif_back_add );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_DELETE_FN,
+ (void *) ldif_back_delete );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_CONFIG_FN,
+ (void *) ldif_back_config );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN,
+ (void *) ldif_back_close );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_FLUSH_FN,
+ (void *) ldif_back_flush );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN,
+ (void *) ldif_back_start );
+ if (rc != 0) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Ldif Backend: unable to pass database information to front end\n",0 ,0 ,0);
+ return(-1);
+ }
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_init\n", 0, 0, 0 );
+
+ return( 0 );
+}
+
+
diff --git a/ldap/servers/slapd/back-ldif/libback-ldif.def b/ldap/servers/slapd/back-ldif/libback-ldif.def
new file mode 100644
index 00000000..f4724f97
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/libback-ldif.def
@@ -0,0 +1,12 @@
+; BEGIN COPYRIGHT BLOCK
+; Copyright 2001 Sun Microsystems, Inc.
+; Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+; All rights reserved.
+; END COPYRIGHT BLOCK
+;
+DESCRIPTION 'Directory Server LDIF Backend Plugin'
+EXPORTS
+ ldif_back_init @2
+ plugin_init_debug_level @3
+
+
diff --git a/ldap/servers/slapd/back-ldif/modify.c b/ldap/servers/slapd/back-ldif/modify.c
new file mode 100644
index 00000000..53f0bb2e
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/modify.c
@@ -0,0 +1,557 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: modify.c
+ *
+ * Functions:
+ *
+ * ldif_back_modify() - ldif backend modify function
+ * update_db() - updates memory and disk db to reflect changes
+ * db2disk() - writes out ldif database to disk
+ * ldifentry_free() - frees an ldif_Entry
+ * ldifentry_dup() - copies an ldif_Entry
+ * ldif_find_entry() - searches an ldif DB for a particular dn
+ * apply_mods() - applies the modifications to an Entry
+ *
+ */
+
+#include "back-ldif.h"
+
+/*Prototypes*/
+void ldifentry_free(ldif_Entry *);
+ldif_Entry * ldifentry_dup(ldif_Entry *);
+int apply_mods( Slapi_Entry *, LDAPMod ** );
+ldif_Entry * ldif_find_entry(Slapi_PBlock *, LDIF *, char *, ldif_Entry **);
+int db2disk(Slapi_PBlock *, LDIF *);
+int update_db(Slapi_PBlock *, LDIF *, ldif_Entry *, ldif_Entry *, int );
+
+/*
+ * Function: ldif_back_modify
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: For changetype: modify, this makes the changes
+ */
+int
+ldif_back_modify( Slapi_PBlock *pb )
+{
+ LDIF *db; /*The ldif file is stored here*/
+ ldif_Entry *entry, *entry2,*prev; /*For db manipulation*/
+ int err; /*House keeping stuff*/
+ LDAPMod **mods; /*Used to apply the modifications*/
+ char *dn; /*Storage for the dn*/
+ char *errbuf = NULL; /* To get error back */
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_modify\n", 0, 0, 0 );
+ prev = NULL;
+
+ /*Get the database, the dn and the mods*/
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_MODIFY_TARGET, &dn ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ) < 0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+ /*Lock the database*/
+ PR_Lock( db->ldif_lock );
+
+ /*
+ * Find the entry we are about to modify.
+ * prev will point to the previous element in the list,
+ * NULL if there is no previous element.
+ */
+ if ( (entry = (ldif_Entry *)ldif_find_entry( pb, db, dn, &prev)) == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+ /*Check acl, note that entry is not an Entry, but a ldif_Entry*/
+ if ( (err = slapi_acl_check_mods( pb, entry->lde_e, mods, &errbuf )) != LDAP_SUCCESS ) {
+ slapi_send_ldap_result( pb, err, NULL, errbuf, 0, NULL );
+ if (errbuf) free (errbuf);
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
+
+ /* Create a copy of the entry and apply the changes to it */
+ if ( (entry2 = (ldif_Entry *) ldifentry_dup( entry )) == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
+
+ /*Actually apply the modifications*/
+ if ( (err = apply_mods( entry2->lde_e, mods )) != 0 ) {
+ slapi_send_ldap_result( pb, err, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
+
+ /* Check for abandon */
+ if ( slapi_op_abandoned( pb ) ) {
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
+
+ /* Check that the entry still obeys the schema */
+ if ( slapi_entry_schema_check( pb, entry2->lde_e ) != 0 ) {
+ slapi_send_ldap_result( pb, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
+
+ /* Check for abandon again */
+ if ( slapi_op_abandoned( pb ) ) {
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
+
+ /* Change the entry itself both on disk and in the cache */
+ if ( update_db(pb, db, entry2, prev, LDIF_DB_REPLACE) != 0) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
+
+ slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_modify\n", 0, 0, 0 );
+ return( 0 );
+
+ error_return:;
+ if ( entry2 != NULL ) {
+ ldifentry_free( entry2 );
+ }
+
+ return( -1 );
+}
+
+/*
+ * Function: update_db
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: Will update the database in memory, and on disk
+ * if prev == NULL, then the element to be deleted/replaced
+ * is the first in the list.
+ * mode = LDIF_DB_ADD | LDIF_DB_REPLACE | LDIF_DB_DELETE
+ * The database should be locked when this function is called.
+ * Note that on replaces and deletes, the old ldif_Entry's
+ * are freed.
+ */
+int
+update_db(Slapi_PBlock *pb, LDIF *db, ldif_Entry *new, ldif_Entry *prev, int mode)
+{
+ ldif_Entry *tmp; /*Used to free the removed/replaced entries*/
+ char *buf; /*Used to convert entries to strings for output to file*/
+ FILE *fp; /*File ptr to the ldif file*/
+ int len; /*Used by slapi_entry2str*/
+ int db_updated=0; /*Flag to designate if db in memory has been updated*/
+
+ /*Make sure that the database is not null. Everything else can be, though*/
+ if (db == NULL){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*
+ * If we are adding an entry, then prev should be pointing
+ * to the last element in the list, or null if the list is empty,
+ * and new should not be null.
+ */
+ if (mode == LDIF_DB_ADD) {
+
+ /*Make sure there is something to add*/
+ if ( new == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*If prev is null, then there had better be no entries in the list*/
+ if (prev == NULL){
+ if( db->ldif_entries != NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+ /*There are no elements, so let's add the new one*/
+ db->ldif_entries = new;
+ db->ldif_n++;
+
+ /*Set a flag*/
+ db_updated = 1;
+
+ }
+ /*
+ * Last error case to test for is if prev is not null, and prev->next
+ * points to something. This means that we are not at the end of the list
+ */
+ if (prev != NULL) {
+ if (prev->next != NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*We're at the end of the list, so tack the new entry onto the end*/
+ prev->next = new;
+ db->ldif_n++;
+
+ db_updated = 1;
+
+ }
+
+ /*If the database has been updated in memory, update the disk*/
+ if (db_updated && db->ldif_file!=NULL) {
+
+ /*Update the disk by appending to the ldif file*/
+ fp = fopen(db->ldif_file, "a");
+ if (fp == NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ /*This is s pretty serious problem, so we exit*/
+ exit(-1);
+ }
+
+ /*Convert the entry to ldif format*/
+ buf = slapi_entry2str(new->lde_e, &len);
+ fprintf(fp, "%s\n", buf);
+ free ( (void *) buf);
+ fclose(fp);
+ return(0);
+ } else {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ fclose(fp);
+ return(-1);
+
+ }
+
+ } else if (mode == LDIF_DB_DELETE){
+
+ /*We're not deleting the first entry in the list*/
+ if (prev != NULL){
+ /*Make sure there is something to delete*/
+ if (prev->next == NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+ tmp = prev->next;
+ prev->next = tmp->next;
+ db->ldif_n--;
+ ldifentry_free(tmp);
+
+ db_updated = 1;
+
+ } else { /*We are deleting the first entry in the list*/
+
+ /*Make sure there is something to delete*/
+ if (db->ldif_entries == NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ tmp = db->ldif_entries;
+ db->ldif_entries = tmp->next;
+ db->ldif_n--;
+
+ /*Free the entry, and set the flag*/
+ ldifentry_free(tmp);
+ db_updated = 1;
+ }
+
+ /*
+ * Update the disk by rewriting entire ldif file
+ * I know, I know, but simplicity is the key here.
+ */
+ if (db_updated) {
+ return(db2disk(pb, db));
+ } else {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+
+ }
+
+ } else if (mode == LDIF_DB_REPLACE) {
+
+ /*Make sure there is something to replace with*/
+ if ( new == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+
+ /*We're not replacing the first element in the list*/
+ if (prev != NULL){
+
+ /*Make sure there is something to replace*/
+ if (prev->next == NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*Splice out the old entry, and put in the new*/
+ tmp = prev->next;
+ prev->next = new;
+ new->next = tmp->next;
+
+ /*Free it*/
+ ldifentry_free(tmp);
+ db_updated = 1;
+ } else { /*We are replacing the first entry in the list*/
+
+ /*Make sure there is something to replace*/
+ if (db->ldif_entries == NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ /*Splice out the old entry, and put in the new*/
+ tmp = db->ldif_entries;
+ db->ldif_entries = new;
+ new->next = tmp->next;
+
+ /*Free it*/
+ ldifentry_free(tmp);
+ db_updated = 1;
+ }
+
+ /*Update the disk by rewriting entire ldif file*/
+ if (db_updated) {
+ return(db2disk(pb, db));
+ } else {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+ }
+}
+
+/*
+ * Function: db2disk
+ *
+ * Returns: returns 0 if good, exits else
+ *
+ * Description: Takes an ldif database, db, and writes it out to disk
+ * if it can't open the file, there's trouble, so we exit
+ * because this function is usually called after the db
+ * in memory has been updated.
+ *
+ */
+int
+db2disk(Slapi_PBlock *pb, LDIF *db)
+{
+ ldif_Entry *cur; /*Used for walking down the list*/
+ char *buf; /*temp storage for Entry->ldif converter*/
+ FILE *fp; /*File pointer to ldif target file*/
+ int len; /*length returned by slapi_entry2str*/
+
+ /*Open the file*/
+ fp = fopen(db->ldif_file, "w");
+ if (fp == NULL) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ /*This is s pretty serious problem, so we exit*/
+ exit(-1);
+ }
+
+ /*
+ * Walk down the list, converting each entry to a string,
+ * writing the string out to fp
+ */
+ for (cur = db->ldif_entries; cur != NULL; cur = cur->next){
+ buf = slapi_entry2str(cur->lde_e, &len);
+ fprintf(fp, "%s\n",buf);
+ free ( (void *) buf);
+ }
+
+ fclose(fp);
+ return(0);
+
+}
+
+
+/*
+ * Function: ldifentry_free
+ *
+ * Returns: void
+ *
+ * Description: Frees an ldif_Entry
+ */
+void
+ldifentry_free(ldif_Entry *e)
+{
+
+ /*Make sure that there is actually something to free*/
+ if (e == NULL){
+ return;
+ }
+
+ /*Free the entry*/
+ slapi_entry_free(e->lde_e);
+
+ /*Free the entire thing*/
+ free ((void *) e);
+}
+
+/*
+ * Function: ldifentry_dup
+ *
+ * Returns: a pointer to the new ldif_entry, or NULL
+ *
+ * Description: Copies and returns a pointer to a new
+ * ldif_Entry whose contents are a copy of e's contents
+ * Note: uses malloc
+ */
+ldif_Entry *
+ldifentry_dup(ldif_Entry *e)
+{
+ ldif_Entry *new;
+
+ /*Let's make sure that e is not null*/
+ if (e == NULL){
+ return(NULL);
+ }
+
+ /*Allocate a new ldif_entry, and return it if it is null*/
+ new = (ldif_Entry *) malloc( (sizeof(ldif_Entry)));
+ if (new == NULL) {
+ return(new);
+ }
+
+ /*Copy the Entry in e*/
+ new->lde_e = slapi_entry_dup(e->lde_e);
+ new->next = NULL;
+
+ return(new);
+
+
+}
+
+/*
+ * Function: ldif_find_entry
+ *
+ * Returns: A pointer to the matched ldif_Entry, or Null
+ *
+ * Description: Goes down the list of entries in db to find the entry
+ * matching dn. Returns a pointer to the entry,
+ * and sets prev to point to the entry before the match.
+ * If there is no match, prev points to the last
+ * entry in the list, and null is returned.
+ * If the first element matches, prev points to NULL
+ */
+ldif_Entry *
+ldif_find_entry(Slapi_PBlock *pb, LDIF *db, char *dn, ldif_Entry **prev)
+{
+ ldif_Entry *cur; /*Used for walking down the list*/
+ char *finddn, *targetdn; /*Copies of dns for searching */
+ int found_it = 0; /*A flag to denote a successful search*/
+
+ /*Set cur to the start of the list*/
+ cur =db->ldif_entries;
+
+ /*Increase the number of accesses*/
+ db->ldif_tries++;
+
+ /*Make a copy of the target dn, and normalize it*/
+ targetdn = strdup(dn);
+ (void) slapi_dn_normalize(targetdn);
+
+
+ /*Go down the list until we find the entry*/
+ while(cur != NULL) {
+ finddn = strdup(slapi_entry_get_dn(cur->lde_e));
+ (void) slapi_dn_normalize(finddn);
+
+
+ /*Test to see if we got the entry matching the dn*/
+ if (strcasecmp(targetdn, finddn) == 0)
+ {
+ found_it = 1;
+ free ((void *)finddn);
+ db->ldif_hits++;
+ break;
+ }
+
+ /*Udpate the pointers*/
+ *prev = cur;
+ cur = cur->next;
+ free ((void *)finddn);
+
+ }
+
+ free ((void *)targetdn);
+
+
+ /*
+ * If we didn't find a matching entry, we should
+ * return, and let the caller handle this (possible) error
+ */
+ if (!found_it){
+ return(NULL);
+ }
+
+ /*
+ * If the first entry matches, we have to set prev to null,
+ * so the caller knows.
+ */
+ if (*prev == cur){
+ *prev = NULL;
+ }
+
+ return( cur );
+}
+
+/*
+ * Function: apply_mods
+ *
+ * Returns: LDAP_SUCCESS if success
+ *
+ * Description: Applies the modifications specified in mods to e.
+ */
+int
+apply_mods( Slapi_Entry *e, LDAPMod **mods )
+{
+ int err, i, j;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> apply_mods\n", 0, 0, 0 );
+
+ err = LDAP_SUCCESS;
+ for ( j = 0; mods[j] != NULL; j++ ) {
+ switch ( mods[j]->mod_op & ~LDAP_MOD_BVALUES ) {
+ case LDAP_MOD_ADD:
+ LDAPDebug( LDAP_DEBUG_ARGS, " add: %s\n",
+ mods[j]->mod_type, 0, 0 );
+ err = slapi_entry_add_values( e, mods[j]->mod_type,
+ mods[j]->mod_bvalues );
+ break;
+
+ case LDAP_MOD_DELETE:
+ LDAPDebug( LDAP_DEBUG_ARGS, " delete: %s\n",
+ mods[j]->mod_type, 0, 0 );
+ err = slapi_entry_delete_values( e, mods[j]->mod_type,
+ mods[j]->mod_bvalues );
+ break;
+
+ case LDAP_MOD_REPLACE:
+ LDAPDebug( LDAP_DEBUG_ARGS, " replace: %s\n",
+ mods[j]->mod_type, 0, 0 );
+ err = entry_replace_values( e, mods[j]->mod_type,
+ mods[j]->mod_bvalues );
+ break;
+ }
+ for ( i = 0; mods[j]->mod_bvalues != NULL &&
+ mods[j]->mod_bvalues[i] != NULL; i++ ) {
+ LDAPDebug( LDAP_DEBUG_ARGS, " %s: %s\n",
+ mods[j]->mod_type, mods[j]->mod_bvalues[i]->bv_val,
+ 0 );
+ }
+ LDAPDebug( LDAP_DEBUG_ARGS, " -\n", 0, 0, 0 );
+
+ if ( err != LDAP_SUCCESS ) {
+ break;
+ }
+ }
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= apply_mods %d\n", err, 0, 0 );
+ return( err );
+}
diff --git a/ldap/servers/slapd/back-ldif/modrdn.c b/ldap/servers/slapd/back-ldif/modrdn.c
new file mode 100644
index 00000000..d2dfcdb8
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/modrdn.c
@@ -0,0 +1,282 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: modrdn.c
+ *
+ * Functions:
+ *
+ * ldif_back_modrdn() - ldap ldif back-end modrdn routine
+ * rdn2typval() - rdn to typval converter
+ * ldif_add_mod() - Adds a modification to be performed.
+ *
+ */
+
+#include "back-ldif.h"
+int rdn2typval(char *, char **, struct berval *);
+void ldif_add_mod( LDAPMod ***, int, char *, struct berval ** );
+
+/*
+ * Function: ldif_back_modrdn
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: For changetype: modrdn, this modifies the rdn of the entry
+ */
+int
+ldif_back_modrdn( Slapi_PBlock *pb )
+{
+ LDIF *db; /*ldif backend database*/
+ ldif_Entry *prev, *tprev, *entry, *entry2, *test;
+ char *pdn, *newdn; /*Used for dn manipulation*/
+ char *dn, *newrdn, *type; /*Used for dn manipulation*/
+ int i; /*A counter*/
+ char **rdns, **dns; /*Used for dn manipulation*/
+ int deleteoldrdn; /*Flag from user to delete old rdn*/
+ struct berval bv;
+ struct berval *bvps[2];
+ LDAPMod **mods; /*Holds the list of modifications*/
+ int rc;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_modrdn\n", 0, 0, 0 );
+
+ prev = NULL;
+
+ /*Get the information from the front end, including the database*/
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db )< 0 ||
+ slapi_pblock_get( pb, SLAPI_MODRDN_TARGET, &dn ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_MODRDN_DELOLDRDN, &deleteoldrdn ) <0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+
+ }
+
+ /*Lock the database*/
+ PR_Lock( db->ldif_lock );
+
+ /*
+ * Find the entry we are about to modify
+ * prev will point to the previous element in the list,
+ * NULL if there is no previous element
+ */
+ if ( (entry = (ldif_Entry *)ldif_find_entry( pb, db, dn, &prev)) == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+ /*Make sure that we are trying to modify the rdn of a leaf.*/
+ if ( has_children( db, entry ) ) {
+ slapi_send_ldap_result( pb, LDAP_NOT_ALLOWED_ON_NONLEAF, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+
+ /* Create a copy of the entry and apply the changes to it */
+ if ( (entry2 = (ldif_Entry *)ldifentry_dup( entry )) == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+ /*Check the access*/
+ rc= slapi_access_allowed( pb, entry2->lde_e, NULL, NULL, SLAPI_ACL_WRITE );
+ if ( rc!=LDAP_SUCCESS ) {
+ slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL );
+ ldifentry_free( entry2 );
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+ /* Construct the new dn */
+ if ( (pdn = slapi_dn_beparent( pb, dn )) != NULL ) {
+
+ /* parent + rdn + separator(s) + null */
+ newdn = (char *) malloc( strlen( pdn ) + strlen( newrdn ) + 3 );
+ if (newdn == NULL){
+ LDAPDebug( LDAP_DEBUG_ANY,"malloc failed", 0, 0, 0 );
+ exit(1);
+ }
+
+ strcpy( newdn, newrdn );
+ strcat( newdn, ", " );
+ strcat( newdn, pdn );
+ } else {
+ newdn = strdup( newrdn );
+ }
+ free( pdn );
+
+ /*Normalize the newdn, that is, squeeze out all unnecessary spaces*/
+ (void) slapi_dn_normalize( newdn );
+
+
+ /* Add the new dn to our working copy of the entry */
+ slapi_entry_set_dn( entry2->lde_e, newdn );
+
+
+ /* See if an entry with the new name already exists */
+ if ( (test = (ldif_Entry *)ldif_find_entry( pb, db, newdn, &tprev )) != NULL ) {
+ slapi_send_ldap_result( pb, LDAP_ALREADY_EXISTS, NULL, NULL, 0, NULL );
+
+ goto error_return;
+ }
+
+
+ /*
+ * Delete old rdn values from the entry if deleteoldrdn is set.
+ * Add new rdn values to the entry.
+ */
+ mods = NULL;
+ bvps[0] = &bv;
+ bvps[1] = NULL;
+ if ( (dns = ldap_explode_dn( dn, 0 )) != NULL ) {
+ if ( (rdns = ldap_explode_rdn( dns[0], 0 )) != NULL ) {
+ for ( i = 0; rdns[i] != NULL; i++ ) {
+
+ /* Delete from entry attributes */
+ if ( deleteoldrdn && rdn2typval( rdns[i], &type, &bv ) == 0 ) {
+ ldif_add_mod( &mods, LDAP_MOD_DELETE, type, bvps );
+ }
+ }
+ ldap_value_free( rdns );
+ }
+ ldap_value_free( dns );
+ }
+ if ( dns == NULL || rdns == NULL ) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ goto error_return;
+ }
+ /* Add new rdn values to the entry */
+ if ( (rdns = ldap_explode_rdn( newrdn, 0 )) != NULL ) {
+ for ( i = 0; rdns[i] != NULL; i++ ) {
+ /* Add to entry */
+ if ( rdn2typval( rdns[i], &type, &bv ) == 0 ) {
+ ldif_add_mod( &mods, LDAP_MOD_ADD, type, bvps );
+ }
+ }
+ ldap_value_free( rdns );
+ } else {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ goto error_return;
+ }
+ bv.bv_val = newdn;
+ bv.bv_len = strlen( newdn );
+ ldif_add_mod( &mods, LDAP_MOD_REPLACE, "entrydn", bvps );
+
+ /* Check for abandon */
+ if ( slapi_op_abandoned( pb ) ) {
+ goto error_return;
+ }
+
+ /* Apply the mods we built above to the copy of the entry */
+ if ( apply_mods( entry2->lde_e, mods ) != 0 ) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+
+ goto error_return;
+ }
+
+ /* Update the database and the disk */
+ if ( update_db(pb, db, entry2, prev, LDIF_DB_REPLACE) != 0) {
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+
+ goto error_return;
+ }
+
+ /*Unlock the database, and tell the user the good news*/
+ PR_Unlock( db->ldif_lock );
+ slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_modrdn\n", 0, 0, 0 );
+ return( 0 );
+
+error_return:;
+
+ /* Result already sent above - just free stuff */
+ PR_Unlock( db->ldif_lock );
+ ldifentry_free( entry2 );
+
+ return( -1 );
+}
+
+/*
+ * Function: rdn2typval
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: converts an rdn to a typeval
+ */
+int
+rdn2typval(char *rdn, char **type, struct berval *bv)
+{
+ char *s;
+
+ if ( (s = strchr( rdn, '=' )) == NULL ) {
+ return( -1 );
+ }
+ *s++ = '\0';
+
+ *type = rdn;
+ bv->bv_val = s;
+ bv->bv_len = strlen( s );
+
+ return( 0 );
+}
+
+/*
+ * Function: ldif_add_mod
+ *
+ * Returns: void
+ *
+ * Description: Adds a modification (add, delete, etc) to the list
+ * of modifications that will eventually be made to some entry
+ */
+void
+ldif_add_mod( LDAPMod ***modlist, int modtype, char *type, struct berval **bvps )
+{
+ int i;
+
+ for ( i = 0; modlist[i] != NULL; i++ ) {
+ ; /* NULL */
+ }
+
+ *modlist = (LDAPMod **) realloc( (char *) *modlist,
+ (i + 2) * sizeof(LDAPMod *) );
+
+ if (*modlist == NULL){
+ LDAPDebug( LDAP_DEBUG_ANY, "realloc failed", 0, 0, 0 );
+ exit(1);
+ }
+ (*modlist)[i] = (LDAPMod *) malloc( sizeof(LDAPMod) );
+
+ if ((*modlist)[i] == NULL){
+ LDAPDebug( LDAP_DEBUG_ANY,"malloc failed", 0, 0, 0 );
+ exit(1);
+ }
+
+ (*modlist)[i]->mod_type = (char *) strdup( type );
+ if ((*modlist)[i]->mod_type == NULL){
+ LDAPDebug( LDAP_DEBUG_ANY,"strdup failed", 0, 0, 0 );
+ exit(1);
+ }
+
+
+ (*modlist)[i]->mod_op = modtype;
+ (*modlist)[i]->mod_bvalues = (struct berval **) malloc(2*sizeof(struct berval *));
+ if ((*modlist)[i]->mod_bvalues == NULL){
+ LDAPDebug( LDAP_DEBUG_ANY,"malloc failed",0, 0, 0 );
+ exit(1);
+ }
+ (*modlist)[i]->mod_bvalues[0] = ber_bvdup( bvps[0] );
+ (*modlist)[i]->mod_bvalues[1] = NULL;
+ (*modlist)[i+1] = NULL;
+}
+
+
+
+
+
+
+
diff --git a/ldap/servers/slapd/back-ldif/monitor.c b/ldap/servers/slapd/back-ldif/monitor.c
new file mode 100644
index 00000000..b4b721b0
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/monitor.c
@@ -0,0 +1,124 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: monitor.c
+ *
+ * Functions:
+ *
+ * ldif_back_monitor_info() - ldap ldif back-end initialize routine
+ *
+ * get_monitordn() - gets the monitor dn for this backend
+ *
+ */
+
+#include "back-ldif.h"
+
+extern char Versionstr[];
+
+
+/*
+ * Function: ldif_back_monitor_info
+ *
+ * Returns: returns 1
+ *
+ * Description: This function wraps up backend specific monitor information
+ * and returns it to the client as an entry. This function
+ * is usually called by ldif_back_search upon receipt of
+ * the monitor dn for this backend.
+ */
+int
+ldif_back_monitor_info( Slapi_PBlock *pb, LDIF *db)
+{
+ Slapi_Entry *e; /*Entry*/
+ char buf[BUFSIZ]; /*Buffer for getting the attrs*/
+ struct berval val; /*More attribute storage*/
+ struct berval *vals[2]; /*Even more*/
+ char *type; /*Database name (type) */
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ /*Alloc the entry and set the monitordn*/
+ e = slapi_entry_alloc();
+ slapi_entry_set_dn(e, (char *) get_monitordn(pb));
+
+ /* Get the database name (be_type) */
+ slapi_pblock_get( pb, SLAPI_BE_TYPE, &type);
+ sprintf( buf, "%s", type );
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ slapi_entry_attr_merge( e, "database", vals );
+
+ /*Lock the database*/
+ PR_Lock( db->ldif_lock );
+
+ /*Get the number of database hits */
+ sprintf( buf, "%ld", db->ldif_hits);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ slapi_entry_attr_merge( e, "entrycachehits", vals );
+
+ /*Get the number of database tries */
+ sprintf( buf, "%ld", db->ldif_tries);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ slapi_entry_attr_merge( e, "entrycachetries", vals );
+
+ /*Get the current size of the entrycache (db) */
+ sprintf( buf, "%ld", db->ldif_n);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ slapi_entry_attr_merge( e, "currententrycachesize", vals );
+
+
+ /*
+ * Get the maximum size of the entrycache (db)
+ * in this database, there is no max, so return the current size
+ */
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ slapi_entry_attr_merge( e, "maxentrycachesize", vals );
+
+ /* Release the lock*/
+ PR_Unlock( db->ldif_lock );
+
+ /*Send the results back to the client*/
+ slapi_send_ldap_search_entry( pb, e, NULL, NULL, 0 );
+ slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 1, NULL );
+
+ slapi_entry_free( e );
+
+ return(1);
+
+
+}
+
+
+/*
+ * Function: get_monitordn
+ *
+ * Returns: returns ptr to string if success, NULL else
+ *
+ * Description: get_monitordn takes a pblock and extracts the
+ * monitor dn of this backend. The monitordn is a special
+ * signal to the backend to return backend specific monitor
+ * information (usually called by back_ldif_search()).
+ */
+char *
+get_monitordn(Slapi_PBlock *pb )
+{
+ char *mdn;
+
+ slapi_pblock_get( pb, SLAPI_BE_MONITORDN, &mdn );
+
+ if (mdn == NULL) {
+ return(NULL);
+
+ }
+
+ return(strdup(mdn));
+
+}
diff --git a/ldap/servers/slapd/back-ldif/search.c b/ldap/servers/slapd/back-ldif/search.c
new file mode 100644
index 00000000..1f9adbfb
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/search.c
@@ -0,0 +1,197 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: search.c
+ *
+ * Functions:
+ *
+ * ldif_back_search() - ldif backend search function
+ *
+ */
+
+#include "back-ldif.h"
+
+/*
+ * Function: ldif_back_search
+ *
+ * Returns: returns 0 if good, -1 else.
+ *
+ * Description: Searches the database for entries satisfying the
+ * user's criteria
+ */
+int
+ldif_back_search( Slapi_PBlock *pb )
+{
+ LDIF *db; /*The database*/
+ char *base; /*Base of the search*/
+ int scope; /*Scope of the search*/
+ int deref; /*Should we dereference aliases?*/
+ int slimit; /*Size limit of the search*/
+ int tlimit; /*Time limit of the search*/
+ Slapi_Filter *filter; /*The filter*/
+ time_t dummy=0; /*Used for time()*/
+ char **attrs; /*Attributes*/
+ int attrsonly; /*Should we just return the attributes found?*/
+ time_t optime; /*Time the operation started*/
+ int nentries; /*Number of entries found thus far*/
+ ldif_Entry *cur; /*Used for traversing the list of entries*/
+ int hitflag=0; /*Used to test if we found the entry in the db*/
+ char *freeme; /*Tmp storage for monitordn*/
+ time_t currtime; /*The current time*/
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_search\n", 0, 0, 0 );
+
+ /*
+ * Get private information created in the init routine.
+ * Also get the parameters of the search operation. These come
+ * more or less directly from the client.
+ */
+ if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_DEREF, &deref ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &slimit ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs ) < 0 ||
+ slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly ) <0 ||
+ slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime ) < 0){
+ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
+ return(-1);
+ }
+
+
+ /*
+ * If we get a search request for the backend monitor dn,
+ * call ldif_back_monitor_info(), which packages up the
+ * backend database analysis info and sends it back to the
+ * client
+ */
+ if ( scope == LDAP_SCOPE_BASE ) {
+
+ /*Get the backend's monitor dn*/
+ freeme = (char *) get_monitordn(pb);
+
+ if (freeme != NULL){
+
+ /*
+ * Compare the monitor dn with the base,
+ * if they match, call monitor_info, which
+ * will return all the relevant info to the client
+ */
+ if ( strcasecmp( base, freeme) == 0 ) {
+ ldif_back_monitor_info( pb, db );
+ free ((void *) freeme);
+ return(-1);
+ }
+ free ((void *) freeme);
+ }
+ }
+
+
+ /*
+ * First we lock the whole database (clumsy, inefficient and
+ * inelegant, but simple)
+ */
+ PR_Lock( db->ldif_lock );
+
+ /*Increase the number of accesses*/
+ db->ldif_tries++;
+
+ /*
+ * Look through each entry in the ldif file and see if it matches
+ * the filter and scope of the search. Do this by calling the
+ * slapi_filter_test() routine.
+ */
+ nentries = 0;
+ for (cur=db->ldif_entries; cur != NULL; cur = cur->next ) {
+
+ /*Make sure we're not exceeding our time limit...*/
+ currtime = time(&dummy);
+ if ((tlimit > 0) && ((currtime - optime) > tlimit)){
+ slapi_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, NULL);
+
+ /*We "hit" the cache*/
+ if (hitflag)
+ {
+ db->ldif_hits++;
+ }
+
+ PR_Unlock( db->ldif_lock );
+ return(-1);
+ }
+
+ /*...or that we haven't been abandoned*/
+ if ( slapi_op_abandoned( pb ) ) {
+
+ /*We "hit" the cache*/
+ if (hitflag)
+ {
+ db->ldif_hits++;
+ }
+
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+ /*Test for exceedence of size limit*/
+ if ((slimit > -1) && (nentries >= slimit)){
+ slapi_send_ldap_result( pb, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, nentries, NULL);
+
+ /*We hit the "cache"*/
+ if (hitflag)
+ {
+ db->ldif_hits++;
+ }
+ PR_Unlock( db->ldif_lock );
+ return(-1);
+ }
+
+
+
+ /*Test if this entry matches the filter*/
+ if ( slapi_vattr_filter_test( pb, cur->lde_e, filter, 1 /* verify access */ ) == 0 ) {
+
+ /* Entry matches - send it */
+ hitflag = 1;
+
+ switch ( slapi_send_ldap_search_entry( pb, cur->lde_e, NULL, attrs,
+ attrsonly ) ) {
+ case 0: /* Entry sent ok */
+ nentries++;
+ break;
+ case 1: /* Entry not sent - because of acl, etc. */
+ break;
+ case -1:/* Connection closed */
+ /* Clean up and return */
+
+ /*We "hit" the cache*/
+ if (hitflag)
+ {
+ db->ldif_hits++;
+ }
+ PR_Unlock( db->ldif_lock );
+ return( -1 );
+ }
+
+
+ }
+ }
+
+ /*If we succeeded, we should update the ldif_hits entry of db*/
+ if (hitflag)
+ {
+ db->ldif_hits++;
+ }
+
+
+ /* Search is done, send LDAP_SUCCESS */
+ slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, nentries, NULL );
+ PR_Unlock( db->ldif_lock );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_search\n", 0, 0, 0 );
+ return( -1 );
+
+}
diff --git a/ldap/servers/slapd/back-ldif/start.c b/ldap/servers/slapd/back-ldif/start.c
new file mode 100644
index 00000000..4e22cb08
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/start.c
@@ -0,0 +1,31 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: start.c
+ *
+ * Functions:
+ *
+ * ldif_back_start() - ldap ldif back-end start routine
+ *
+ */
+#include "back-ldif.h"
+
+/*
+ * Function: ldif_back_start
+ *
+ * Returns: returns 0
+ *
+ * Description: After the config file is read, the backend start function is called.
+ * This allows the backend writer to start any threads or perform any
+ * operations that need to be done after the config file has been read in.
+ * The ldif backend requires no such operations to be performed.
+ *
+ */
+int
+ldif_back_start( Slapi_PBlock *pb )
+{
+ return( 0 );
+}
diff --git a/ldap/servers/slapd/back-ldif/unbind.c b/ldap/servers/slapd/back-ldif/unbind.c
new file mode 100644
index 00000000..77c45adb
--- /dev/null
+++ b/ldap/servers/slapd/back-ldif/unbind.c
@@ -0,0 +1,27 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * File: unbind.c
+ *
+ * Functions:
+ *
+ * ldif_back_unbind() - ldap ldif back-end unbind routine
+ *
+ */
+#include "back-ldif.h"
+
+/*
+ * Function: ldif_back_unbind
+ *
+ * Returns: returns 0
+ *
+ * Description: performs an ldap unbind.
+ */
+int
+ldif_back_unbind( Slapi_PBlock *pb )
+{
+ return( 0 );
+}