]> git.sur5r.net Git - openldap/commitdiff
Modrdn fix to support deleteoldrdn (LDAP v2).
authorJuan Gomez <gomez@openldap.org>
Wed, 19 May 1999 01:36:03 +0000 (01:36 +0000)
committerJuan Gomez <gomez@openldap.org>
Wed, 19 May 1999 01:36:03 +0000 (01:36 +0000)
servers/slapd/back-ldbm/modify.c
servers/slapd/back-ldbm/modrdn.c
servers/slapd/back-ldbm/proto-back-ldbm.h
servers/slapd/dn.c
servers/slapd/modify.c
servers/slapd/proto-slap.h
tests/scripts/defines.sh
tests/scripts/test005-modrdn

index 1ef124d5544cd6f8d4208ae648b0db144c0cf4b5..3772d423848d3f0162bc3cdd64abcd7a2edbd2dc 100644 (file)
 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( &currenttime_mutex );
+#ifndef LDAP_LOCALTIME
+       ltm = gmtime( &currenttime );
+       strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+       ltm = localtime( &currenttime );
+       strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+       ldap_pvt_thread_mutex_unlock( &currenttime_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 ) {
@@ -65,7 +142,7 @@ ldbm_back_modify(
                if ( err != LDAP_SUCCESS ) {
                        /* unlock entry, delete from cache */
                        send_ldap_result( conn, op, err, NULL, NULL );
-                       goto error_return;
+                       return -1;
                }
        }
 
@@ -73,35 +150,73 @@ ldbm_back_modify(
        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 );
index 35b7f1eae8ef744f1f5b6407b7f95bdd5a78c6be..fb38b6411814aa769edc6dda3804b2af7f9b1326 100644 (file)
@@ -27,8 +27,23 @@ ldbm_back_modrdn(
        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 ) {
@@ -76,26 +91,7 @@ ldbm_back_modrdn(
 #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 */
@@ -110,11 +106,154 @@ ldbm_back_modrdn(
                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;
@@ -140,6 +279,7 @@ ldbm_back_modrdn(
                goto return_results;
        }
 
+
        (void) cache_delete_entry( &li->li_cache, e );
        free( e->e_dn );
        free( e->e_ndn );
@@ -147,33 +287,41 @@ ldbm_back_modrdn(
        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 );
index 603325d27db56752ae75f52bf691bade4241dad0..33c7edea66145669fe1a3d6ccfe17ccbaab97520 100644 (file)
@@ -122,6 +122,18 @@ int index_add_values LDAP_P(( Backend *be, char *type, struct berval **vals, ID
 /* 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
  */
index 70863dc6d9529f3832f392234f9b484965bbbccd..8b0c5cb18755bec0a3846b976f30c7e7e01ef6e9 100644 (file)
@@ -220,6 +220,77 @@ dn_parent(
        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.
@@ -271,3 +342,156 @@ dn_upcase( char *dn )
 
        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() */
index c1ddd3faf40f03548c8b532cbdc80550f265be77..44982c11dddaed2d15d94e6f8d0d90c1210b0515 100644 (file)
@@ -21,7 +21,6 @@
 #include "slap.h"
 
 static void    modlist_free(LDAPMod *mods);
-static void    add_lastmods(Operation *op, LDAPMod **mods);
 
 
 void
@@ -154,10 +153,7 @@ do_modify(
                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 );
                        }
@@ -191,76 +187,3 @@ modlist_free(
                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( &currenttime_mutex );
-#ifndef LDAP_LOCALTIME
-       ltm = gmtime( &currenttime );
-       strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
-#else
-       ltm = localtime( &currenttime );
-       strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
-#endif
-       ldap_pvt_thread_mutex_unlock( &currenttime_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;
-}
index 7a766f78c996b152c7ac8b6c10f5519acf548618..52372983ae2a5597f8047b2a3f3fff656cb64b96 100644 (file)
@@ -102,10 +102,14 @@ void connection_activity LDAP_P(( Connection *conn ));
 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
  */
index 49a6656fb7e6b768b9ce7ad6a6586ea373c50a03..03337899e29fea66111f5164b284d14f1c7a85da 100755 (executable)
@@ -5,6 +5,7 @@ SLAPD=../servers/slapd/slapd
 SLURPD=../servers/slurpd/slurpd
 LDAPSEARCH=../clients/tools/ldapsearch
 LDAPMODIFY=../clients/tools/ldapmodify
+LDAPMODRDN=../clients/tools/ldapmodrdn
 LDAPADD=../clients/tools/ldapadd
 LVL=5
 PORT=9009
@@ -32,6 +33,7 @@ LDIFFLT=$DBDIR/ldif.flt
 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
index 510f898554902cc41b644b3d0acfba16233f6814..e6069758f626643f93fd0ad790da37886d8a40b1 100755 (executable)
@@ -1,12 +1,99 @@
-#!/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