static int add_values(Entry *e, LDAPMod *mod, char *dn);
static int delete_values(Entry *e, LDAPMod *mod, char *dn);
static int replace_values(Entry *e, LDAPMod *mod, char *dn);
+static void add_lastmods(Operation *op, LDAPMod **mods);
-int
-ldbm_back_modify(
+
+static void
+add_lastmods( Operation *op, LDAPMod **mods )
+{
+ char buf[22];
+ struct berval bv;
+ struct berval *bvals[2];
+ LDAPMod **m;
+ LDAPMod *tmp;
+ struct tm *ltm;
+
+ Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
+
+ bvals[0] = &bv;
+ bvals[1] = NULL;
+
+ /* remove any attempts by the user to modify these attrs */
+ for ( m = mods; *m != NULL; m = &(*m)->mod_next ) {
+ if ( strcasecmp( (*m)->mod_type, "modifytimestamp" ) == 0 ||
+ strcasecmp( (*m)->mod_type, "modifiersname" ) == 0 ||
+ strcasecmp( (*m)->mod_type, "createtimestamp" ) == 0 ||
+ strcasecmp( (*m)->mod_type, "creatorsname" ) == 0 ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "add_lastmods: found lastmod attr: %s\n",
+ (*m)->mod_type, 0, 0 );
+ tmp = *m;
+ *m = (*m)->mod_next;
+ free( tmp->mod_type );
+ if ( tmp->mod_bvalues != NULL ) {
+ ber_bvecfree( tmp->mod_bvalues );
+ }
+ free( tmp );
+ if (!*m)
+ break;
+ }
+ }
+
+ if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
+ bv.bv_val = "NULLDN";
+ bv.bv_len = strlen( bv.bv_val );
+ } else {
+ bv.bv_val = op->o_dn;
+ bv.bv_len = strlen( bv.bv_val );
+ }
+ tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
+ tmp->mod_type = ch_strdup( "modifiersname" );
+ tmp->mod_op = LDAP_MOD_REPLACE;
+ tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
+ 2 * sizeof(struct berval *) );
+ tmp->mod_bvalues[0] = ber_bvdup( &bv );
+ tmp->mod_next = *mods;
+ *mods = tmp;
+
+ ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ bv.bv_val = buf;
+ bv.bv_len = strlen( bv.bv_val );
+ tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
+ tmp->mod_type = ch_strdup( "modifytimestamp" );
+ tmp->mod_op = LDAP_MOD_REPLACE;
+ tmp->mod_bvalues = (struct berval **) ch_calloc( 1, 2 * sizeof(struct berval *) );
+ tmp->mod_bvalues[0] = ber_bvdup( &bv );
+ tmp->mod_next = *mods;
+ *mods = tmp;
+}
+
+/* We need this function because of LDAP modrdn. If we do not
+ * add this there would be a bunch of code replication here
+ * and there and of course the likelihood of bugs increases.
+ * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
+ */
+
+int ldbm_internal_modify(
Backend *be,
Connection *conn,
Operation *op,
char *dn,
- LDAPMod *mods
+ LDAPMod *mods,
+ Entry *e
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
- Entry *e;
int i, err;
LDAPMod *mod;
- Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
+ if ( ((be->be_lastmod == ON)
+ || ((be->be_lastmod == UNDEFINED)&&(global_lastmod == ON)))
+ && (be->be_update_ndn == NULL)) {
+
+ /* XXX: It may be wrong, it changes mod time even if
+ * mod fails!
+ */
+ add_lastmods( op, &mods );
- /* acquire and lock entry */
- if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
- NULL );
- if ( matched != NULL ) {
- free( matched );
- }
- return( -1 );
}
if ( (err = acl_check_mods( be, conn, op, e, mods )) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, err, NULL, NULL );
- goto error_return;
+ return -1;
}
for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
if ( err != LDAP_SUCCESS ) {
/* unlock entry, delete from cache */
send_ldap_result( conn, op, err, NULL, NULL );
- goto error_return;
+ return -1;
}
}
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
- goto error_return;
+ return -1;
}
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- goto error_return;
+ return -1;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* modify indexes */
if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- goto error_return;
+ return -1;
}
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- goto error_return;
+ return -1;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ return 0;
+
+}/* int ldbm_internal_modify() */
+
+
+int
+ldbm_back_modify(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPMod *mods
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *matched;
+ Entry *e;
+
+ Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
+
+ /* acquire and lock entry */
+ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
+ NULL );
+ if ( matched != NULL ) {
+ free( matched );
+ }
+ return( -1 );
+ }
+
+ /* Modify the entry */
+ if ( ldbm_internal_modify( be, conn, op, dn, mods, e ) != 0 ) {
+
+ goto error_return;
+
+ }
+
/* change the entry itself */
if ( id2entry_add( be, e ) != 0 ) {
+ entry_free( e );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- goto error_return;
+ return -1;
}
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
char *new_dn = NULL, *new_ndn = NULL;
char sep[2];
Entry *e, *p = NULL;
- int rootlock = 0;
- int rc = -1;
+ int rootlock = 0;
+ int rc = -1;
+
+ char *new_rdn_val = NULL; /* Val of new rdn */
+ char *new_rdn_type = NULL; /* Type of new rdn */
+ char *old_rdn; /* Old rdn's attr type & val */
+ char *old_rdn_type = NULL; /* Type of old rdn attr. */
+ char *old_rdn_val = NULL; /* Old rdn attribute value */
+ struct berval add_bv; /* Stores new rdn att */
+ struct berval *add_bvals[2]; /* Stores new rdn att */
+ struct berval del_bv; /* Stores old rdn att */
+ struct berval *del_bvals[2]; /* Stores old rdn att */
+ LDAPMod mod[2]; /* Used to delete old rdn */
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn:()==>\n",
+ 0, 0, 0 );
/* get entry with writer lock */
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
#endif
p_dn = dn_parent( be, e->e_dn );
- new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn )
- + 3 );
- if ( dn_type( e->e_dn ) == DN_X500 ) {
- strcpy( new_dn, newrdn );
- strcat( new_dn, "," );
- strcat( new_dn, p_dn );
- } else {
- char *s;
- strcpy( new_dn, newrdn );
- s = strchr( newrdn, '\0' );
- s--;
- if ( *s != '.' && *s != '@' ) {
- if ( (s = strpbrk( dn, ".@" )) != NULL ) {
- sep[0] = *s;
- sep[1] = '\0';
- strcat( new_dn, sep );
- }
- }
- strcat( new_dn, p_dn );
- }
+
} else {
/* no parent, modrdn entry directly under root */
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
rootlock = 1;
- new_dn = ch_strdup( newrdn );
+
}
+ build_new_dn( &new_dn, e->e_dn, p_dn, newrdn );
new_ndn = dn_normalize_case( ch_strdup( new_dn ) );
+ /* Get attribute type and attribute value of our new rdn, we will
+ * need to add that to our new entry
+ */
+
+ if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out type of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ goto return_results;
+
+ }
+
+ if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out val of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ goto return_results;
+
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n",
+ new_rdn_val, new_rdn_type, 0 );
+
+ /* Retrieve the old rdn from the entry's dn */
+
+ if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn from dn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ goto return_results;
+
+ }
+
+ if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out the old_rdn type\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ goto return_results;
+
+ }
+
+ if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
+
+ /* Not a big deal but we may say something */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
+ old_rdn_type, new_rdn_type, 0 );
+
+ }
+
+ if ( dn_type( old_rdn ) == DN_X500 ) {
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
+ 0, 0, 0 );
+
+ /* Add new attribute value to the entry.
+ */
+
+ add_bvals[0] = &add_bv; /* Array of bervals */
+ add_bvals[1] = NULL;
+
+ add_bv.bv_val = new_rdn_val;
+ add_bv.bv_len = strlen(new_rdn_val);
+
+ mod[0].mod_type = old_rdn_type;
+ mod[0].mod_bvalues = add_bvals;
+ mod[0].mod_op = LDAP_MOD_ADD;
+ mod[0].mod_next = NULL;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: adding new rdn attr val =\"%s\"\n",
+ new_rdn_val, 0, 0 );
+
+ /* Remove old rdn value if required */
+
+ if (deleteoldrdn) {
+
+ del_bvals[0] = &del_bv; /* Array of bervals */
+ del_bvals[1] = NULL;
+ /* Get value of old rdn */
+
+ if ((old_rdn_val = rdn_attr_value( old_rdn ))
+ == NULL) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op,
+ LDAP_OPERATIONS_ERROR,
+ "", "" );
+ goto return_results;
+
+
+ }
+
+ /* Remove old value of rdn as an attribute. */
+
+ del_bv.bv_val = old_rdn_val;
+ del_bv.bv_len = strlen(old_rdn_val);
+
+ /* No need to normalize old_rdn_type, delete_values()
+ * does that for us
+ */
+ mod[0].mod_next = &mod[1];
+ mod[1].mod_type = old_rdn_type;
+ mod[1].mod_bvalues = del_bvals;
+ mod[1].mod_op = LDAP_MOD_DELETE;
+ mod[1].mod_next = NULL;
+
+ }/* if (deleteoldrdn) */
+
+ /* modify memory copy of entry */
+ if ( ldbm_internal_modify( be, conn, op, dn, &mod[0], e )
+ != 0 ) {
+
+ goto return_results;
+
+ }
+
+ } else {
+
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n",
+ 0, 0, 0 );
+ /* XXXV3: not sure of what to do here */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: not fully implemented...\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ goto return_results;
+
+ }
+
if ( (dn2id ( be, new_ndn ) ) != NOID ) {
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
goto return_results;
goto return_results;
}
+
(void) cache_delete_entry( &li->li_cache, e );
free( e->e_dn );
free( e->e_ndn );
e->e_ndn = new_ndn;
(void) cache_update_entry( &li->li_cache, e );
- /* XXX
- * At some point here we need to update the attribute values in
- * the entry itself that were effected by this RDN change
- * (respecting the value of the deleteoldrdn parameter).
- *
- * Since the code to do this has not yet been written, treat this
- * omission as a (documented) bug.
- */
-
- /* id2entry index */
+ /* id2entry index: commit */
if ( id2entry_add( be, e ) != 0 ) {
entry_free( e );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- goto return_results;
+ goto return_results_new;
}
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
rc = 0;
-return_results:
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn:()<==\n",
+ 0, 0, 0 );
+ goto return_results_new;
+
+return_results:
if( new_dn != NULL ) free( new_dn );
if( new_ndn != NULL ) free( new_ndn );
+return_results_new:
+ /* NOTE:
+ * new_dn and new_ndn are not deallocated because they are used by
+ * the cache entry at this point.
+ */
if( p_dn != NULL ) free( p_dn );
if( p_ndn != NULL ) free( p_ndn );
if( matched != NULL ) free( matched );
+ /* LDAP v2 supporting correct attribute handling. */
+ if( new_rdn_type != NULL ) free(new_rdn_type);
+ if( new_rdn_val != NULL ) free(new_rdn_val);
+ if( old_rdn != NULL ) free(old_rdn);
+ if( old_rdn_type != NULL ) free(old_rdn_type);
+ if( old_rdn_val != NULL ) free(old_rdn_val);
+
if( p != NULL ) {
/* free parent and writer lock */
cache_return_entry_w( &li->li_cache, p );
/* krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */
#endif
+/*
+ * modify.c
+ */
+
+/* We need this function because of LDAP modrdn. If we do not
+ * add this there would be a bunch of code replication here
+ * and there and of course the likelihood of bugs increases.
+ * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
+ */
+int ldbm_internal_modify LDAP_P((Backend *be, Connection *conn, Operation *op,
+ char *dn, LDAPMod *mods, Entry *e));
+
/*
* nextid.c
*/
return( ch_strdup( "" ) );
}
+char * dn_rdn(
+ Backend *be,
+ char *dn )
+{
+ char *s;
+ int inquote;
+
+ if( dn == NULL ) {
+ return NULL;
+ }
+
+ while(*dn && SPACE(*dn)) {
+ dn++;
+ }
+
+ if( *dn == '\0' ) {
+ return( NULL );
+ }
+
+ if ( be != NULL && be_issuffix( be, dn ) ) {
+ return( NULL );
+ }
+
+ dn = ch_strdup( dn );
+
+ /*
+ * no =, assume it is a dns name, like blah@some.domain.name
+ * if the blah@ part is there, return some.domain.name. if
+ * it's just some.domain.name, return domain.name.
+ */
+ if ( strchr( dn, '=' ) == NULL ) {
+ if ( (s = strchr( dn, '@' )) == NULL ) {
+ if ( (s = strchr( dn, '.' )) == NULL ) {
+ return( dn );
+ }
+ }
+ *s = '\0';
+ return( dn );
+ }
+
+ /*
+ * else assume it is an X.500-style name, which looks like
+ * foo=bar,sha=baz,...
+ */
+
+ inquote = 0;
+
+ for ( s = dn; *s; s++ ) {
+ if ( *s == '\\' ) {
+ if ( *(s + 1) ) {
+ s++;
+ }
+ continue;
+ }
+ if ( inquote ) {
+ if ( *s == '"' ) {
+ inquote = 0;
+ }
+ } else {
+ if ( *s == '"' ) {
+ inquote = 1;
+ } else if ( DNSEPARATOR( *s ) ) {
+ *s = '\0';
+ return( dn );
+ }
+ }
+ }
+
+ return( dn );
+}
+
/*
* dn_issuffix - tells whether suffix is a suffix of dn. both dn
* and suffix must be normalized.
return( dn );
}
+
+/*
+ * get_next_substring(), rdn_attr_type(), rdn_attr_value(), and
+ * build_new_dn().
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+/* get_next_substring:
+ *
+ * Gets next substring in s, using d (or the end of the string '\0') as a
+ * string delimiter, and places it in a duplicated memory space. Leading
+ * spaces are ignored. String s **must** be null-terminated.
+ */
+
+static char *
+get_next_substring( char * s, char d )
+{
+
+ char *str, *r;
+
+ r = str = ch_malloc( strlen(s) + 1 );
+
+ /* Skip leading spaces */
+
+ while ( *s && SPACE(*s) ) {
+
+ s++;
+
+ }/* while ( *s && SPACE(*s) ) */
+
+ /* Copy word */
+
+ while ( *s && (*s != d) ) {
+
+ /* Don't stop when you see trailing spaces may be a multi-word
+ * string, i.e. name=John Doe!
+ */
+
+ *str++ = *s++;
+
+ }/* while ( *s && (*s != d) ) */
+
+ *str = '\0';
+
+ return r;
+
+}/* char * get_word() */
+
+
+/* rdn_attr_type:
+ *
+ * Given a string (i.e. an rdn) of the form:
+ * "attribute_type = attribute_value"
+ * this function returns the type of an attribute, that is the
+ * string "attribute_type" which is placed in newly allocated
+ * memory. The returned string will be null-terminated.
+ */
+
+char * rdn_attr_type( char * s )
+{
+
+ return get_next_substring( s, '=' );
+
+}/* char * rdn_attr_type() */
+
+
+/* rdn_attr_value:
+ *
+ * Given a string (i.e. an rdn) of the form:
+ * "attribute_type = attribute_value"
+ * this function returns "attribute_type" which is placed in newly allocated
+ * memory. The returned string will be null-terminated and may contain
+ * spaces (i.e. "John Doe\0").
+ */
+
+char *
+rdn_attr_value( char * rdn )
+{
+
+ char *str;
+
+ if ( (str = strchr( rdn, '=' )) != NULL ) {
+
+ return get_next_substring(++str, '\0');
+
+ }/* if ( (str = strpbrk( rdn, "=" )) != NULL ) */
+
+ return NULL;
+
+}/* char * rdn_attr_value() */
+
+
+/* build_new_dn:
+ *
+ * Used by ldbm/bdb2_back_modrdn to create the new dn of entries being
+ * renamed.
+ *
+ * new_dn = parent (p_dn) + separator(s) + rdn (newrdn) + null.
+ */
+
+void
+build_new_dn( char ** new_dn, char *e_dn, char * p_dn, char * newrdn )
+{
+
+ if ( p_dn == NULL ) {
+
+ *new_dn = ch_strdup( newrdn );
+ return;
+
+ }
+
+ *new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn ) + 3 );
+
+ if ( dn_type( e_dn ) == DN_X500 ) {
+
+ strcpy( *new_dn, newrdn );
+ strcat( *new_dn, "," );
+ strcat( *new_dn, p_dn );
+
+ } else {
+
+ char *s;
+ char sep[2];
+
+ strcpy( *new_dn, newrdn );
+ s = strchr( newrdn, '\0' );
+ s--;
+
+ if ( (*s != '.') && (*s != '@') ) {
+
+ if ( (s = strpbrk( e_dn, ".@" )) != NULL ) {
+
+ sep[0] = *s;
+ sep[1] = '\0';
+ strcat( *new_dn, sep );
+
+ }/* if ( (s = strpbrk( dn, ".@" )) != NULL ) */
+
+ }/* if ( *s != '.' && *s != '@' ) */
+
+ strcat( *new_dn, p_dn );
+
+ }/* if ( dn_type( e_dn ) == DN_X500 ) {}else */
+
+}/* void build_new_dn() */
#include "slap.h"
static void modlist_free(LDAPMod *mods);
-static void add_lastmods(Operation *op, LDAPMod **mods);
void
if ( be->be_update_ndn == NULL ||
strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
{
- if ( (be->be_lastmod == ON || ( be->be_lastmod == UNDEFINED &&
- global_lastmod == ON ) ) && be->be_update_ndn == NULL ) {
- add_lastmods( op, &mods );
- }
+
if ( (*be->be_modify)( be, conn, op, ndn, mods ) == 0 ) {
replog( be, LDAP_REQ_MODIFY, ndn, mods, 0 );
}
free( mods );
}
}
-
-static void
-add_lastmods( Operation *op, LDAPMod **mods )
-{
- char buf[22];
- struct berval bv;
- struct berval *bvals[2];
- LDAPMod **m;
- LDAPMod *tmp;
- struct tm *ltm;
-
- Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
-
- bvals[0] = &bv;
- bvals[1] = NULL;
-
- /* remove any attempts by the user to modify these attrs */
- for ( m = mods; *m != NULL; m = &(*m)->mod_next ) {
- if ( strcasecmp( (*m)->mod_type, "modifytimestamp" ) == 0 ||
- strcasecmp( (*m)->mod_type, "modifiersname" ) == 0 ||
- strcasecmp( (*m)->mod_type, "createtimestamp" ) == 0 ||
- strcasecmp( (*m)->mod_type, "creatorsname" ) == 0 ) {
-
- Debug( LDAP_DEBUG_TRACE,
- "add_lastmods: found lastmod attr: %s\n",
- (*m)->mod_type, 0, 0 );
- tmp = *m;
- *m = (*m)->mod_next;
- free( tmp->mod_type );
- if ( tmp->mod_bvalues != NULL ) {
- ber_bvecfree( tmp->mod_bvalues );
- }
- free( tmp );
- if (!*m)
- break;
- }
- }
-
- if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
- bv.bv_val = "NULLDN";
- bv.bv_len = strlen( bv.bv_val );
- } else {
- bv.bv_val = op->o_dn;
- bv.bv_len = strlen( bv.bv_val );
- }
- tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
- tmp->mod_type = ch_strdup( "modifiersname" );
- tmp->mod_op = LDAP_MOD_REPLACE;
- tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
- 2 * sizeof(struct berval *) );
- tmp->mod_bvalues[0] = ber_bvdup( &bv );
- tmp->mod_next = *mods;
- *mods = tmp;
-
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
-#ifndef LDAP_LOCALTIME
- ltm = gmtime( ¤ttime );
- strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
-#else
- ltm = localtime( ¤ttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
-#endif
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
- bv.bv_val = buf;
- bv.bv_len = strlen( bv.bv_val );
- tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
- tmp->mod_type = ch_strdup( "modifytimestamp" );
- tmp->mod_op = LDAP_MOD_REPLACE;
- tmp->mod_bvalues = (struct berval **) ch_calloc( 1, 2 * sizeof(struct berval *) );
- tmp->mod_bvalues[0] = ber_bvdup( &bv );
- tmp->mod_next = *mods;
- *mods = tmp;
-}
char * dn_normalize LDAP_P(( char *dn ));
char * dn_normalize_case LDAP_P(( char *dn ));
char * dn_parent LDAP_P(( Backend *be, char *dn ));
+char * dn_rdn LDAP_P(( Backend *be, char *dn ));
int dn_issuffix LDAP_P(( char *dn, char *suffix ));
int dn_type LDAP_P(( char *dn ));
char * dn_upcase LDAP_P(( char *dn ));
-
+char * rdn_attr_value LDAP_P(( char * rdn ));
+char * rdn_attr_type LDAP_P(( char * rdn ));
+void build_new_dn LDAP_P(( char ** new_dn, char *e_dn, char * p_dn,
+ char * newrdn ));
/*
* entry.c
*/
SLURPD=../servers/slurpd/slurpd
LDAPSEARCH=../clients/tools/ldapsearch
LDAPMODIFY=../clients/tools/ldapmodify
+LDAPMODRDN=../clients/tools/ldapmodrdn
LDAPADD=../clients/tools/ldapadd
LVL=5
PORT=9009
MASTEROUT=$DBDIR/master.out
SLAVEOUT=$DBDIR/slave.out
TESTOUT=$DBDIR/ldapsearch.out
+TESTOUT_MODRDN=$DBDIR/ldapmodrdn.out
SEARCHOUTMASTER=$DATADIR/search.out.master
MODIFYOUTMASTER=$DATADIR/modify.out.master
ADDDELOUTMASTER=$DATADIR/adddel.out.master
-#!/bin/sh
+#! /bin/sh
-if [ $# -eq 0 ]; then
+if test $# -eq 0 ; then
SRCDIR="."
else
SRCDIR=$1; shift
fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
+
+echo "Cleaning up in $DBDIR..."
+
+rm -f $DBDIR/[!C]*
+
+echo "Running ldif2ldbm to build slapd database..."
+$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+RC=$?
+if test $RC != 0 ; then
+ echo "ldif2ldbm failed!"
+ exit $RC
+fi
+
+echo "Starting slapd on TCP/IP port $PORT..."
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
+PID=$!
+echo "Testing slapd modrdn operations..."
+
+# Make sure we can search the database
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'cn=Manager' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
+
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+cat /dev/null > $TESTOUT_MODRDN
+
+# -r used to do remove of old rdn
+
+echo "Testing modrdn(deleteoldrdn=0)..."
+$LDAPMODRDN -v -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD > \
+ /dev/null 2>&1 'cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US' 'cn=James A Jones III'
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodrdn failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+echo "Testing modrdn(deleteoldrdn=1)..."
+$LDAPMODRDN -v -D "$MANAGERDN" -r -h localhost -p $PORT -w $PASSWD > \
+ /dev/null 2>&1 'cn=James A Jones 2, ou=Information Technology Division, ou=People, o=University of Michigan, c=US' 'cn=James A Jones II'
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodrdn failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+echo "Using ldapsearch to retrieve all the entries..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'objectClass=*' | egrep -iv '^createtimestamp:|^modifytimestamp:' \
+ > $SEARCHOUT 2>&1
+RC=$?
+kill -HUP $PID
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ exit $RC
+fi
+
+echo "Comparing database to reference file"
+cmp $SEARCHOUT $MODRDNOUTMASTER
+if test $? != 0 ; then
+ echo "comparison failed - modrdn operations did not complete correctly"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+
-. $SRCDIR/scripts/defines.sh $SRCDIR
+# echo "modrdn test not yet written"
-echo "modrdn test not yet written"
exit 0