[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: modrdn:->TRY THIS! & pls send feedback
Don Badrak wrote:
> All,
>
> Ok, I tried the modrdn patch Juan Gomeze submitted against 1.2.1.
> Everything compiled fine, and it passed the modrdn tests.
>
> When I tried to modify a entry, I get this error:
>
> ldap_modrdn2_s: Type or value exists
>
> Here's the entry I was modifying.
>
> dn: cn=C H Monk Jr,ou=People,o=U.S. Census Bureau,c=US
> sn: Monk
> cn: C Harvey Monk Jr
> givenname: C
> initials: Harvey
> generationqualifier: Jr
> telephonenumber: +1 301 457 2255
> flastname: cmonk
> ccmailpostoffice: FTD1
> department: FTD
> physicaldeliveryofficename: 3-2104
> mail: C.Harvey.Monk.Jr@ccMail.Census.GOV
> mailacceptinggeneralid: charveymonkjr
> maildrop: C.Harvey.Monk.Jr@ccMail.Census.GOV
> objectclass: top
> objectclass: person
>
> And the modification I was trying to make (this is the file ldapmodrdn.19990519.1):
>
> cn=C H Monk Jr,ou=People,o=U.S. Census Bureau,c=US
> cn=C Harvey Monk Jr
>
> It did the same thing both with and without the -r flag. Here is the output
> from the ldapmodrn -d 15:
>
> % ldapmodrdn -v -d 15 -D "cn=Manager,o=U.S. Census Bureau,c=US" -w xxxxxx -f ldapmodrdn.19990519.1
>
> ldap_init
> ldap_bind_s
> ldap_simple_bind_s
> ldap_simple_bind
> ldap_send_initial_request
> open_ldap_connection
> ldap_connect_to_host: ldap-master.geo.census.gov:389
> sd 4 connected to: 148.129.238.22
> ldap_delayed_open successful, ld_host is (null)
> ldap_send_server_request
> ber_flush: 56 bytes to sd 4
> 0 6 02 01 01 ` 1 02 01 02 04 $ c n = M
> a n a g e r , o = U . S . 20 C e
> n s u s 20 B u r e a u , c = U S
> 80 06 x x x x x x
> ldap_result
> wait4msg (infinite timeout)
> ** Connections:
> * host: ldap-master.geo.census.gov port: 389 (default)
> refcnt: 2 status: Connected
> last used: Wed May 19 16:49:01 1999
>
> ** Outstanding Requests:
> * msgid 1, origid 1, status InProgress
> outstanding referrals 0, parent count 0
> ** Response Queue:
> Empty
> do_ldap_select
> read1msg
> ber_get_next
> ber_get_next: tag 0x30 len 12 contents:
> ber_dump: buf 0x1003e8a8, ptr 0x1003e8a8, end 0x1003e8b4
> current len 12, contents:
> 02 01 01 a 07 0a 01 00 04 00 04 00
> got result msgid 1, original id 1
> new result: res_errno: 0, res_error: <>, res_matched: <>
> read1msg: 0 new referrals
> request 1 done
> res_errno: 0, res_error: <>, res_matched: <>
> ldap_free_request (origid 1, msgid 1)
> ldap_free_connection
> ldap_free_connection: refcnt 1
> ldap_result2error
> ldap_msgfree
> modrdn cn=C H Monk Jr,ou=People,o=U.S. Census Bureau,c=US:
> cn=C Harvey Monk Jr
> keeping old RDN
> ldap_modrdn
> ldap_send_initial_request
> ldap_send_server_request
> ber_flush: 83 bytes to sd 4
> 0 Q 02 01 02 l L 04 2 c n = C 20 H 20
> M o n k 20 J r , o u = P e o p l
> e , o = U . S . 20 C e n s u s 20
> B u r e a u , c = U S 04 13 c n =
> C 20 H a r v e y 20 M o n k 20 J r
> 01 01 00
> ldap_result
> wait4msg (infinite timeout)
> ** Connections:
> * host: ldap-master.geo.census.gov port: 389 (default)
> refcnt: 2 status: Connected
> last used: Wed May 19 16:49:01 1999
>
> ** Outstanding Requests:
> * msgid 2, origid 2, status InProgress
> outstanding referrals 0, parent count 0
> ** Response Queue:
> Empty
> do_ldap_select
> read1msg
> ber_get_next
> ber_get_next: tag 0x30 len 12 contents:
> ber_dump: buf 0x1003e8a8, ptr 0x1003e8a8, end 0x1003e8b4
> current len 12, contents:
> 02 01 02 m 07 0a 01 14 04 00 04 00
> got result msgid 2, original id 2
> ldap_chase_referrals
> new result: res_errno: 20, res_error: <>, res_matched: <>
> read1msg: 0 new referrals
> request 2 done
> res_errno: 20, res_error: <>, res_matched: <>
> ldap_free_request (origid 2, msgid 2)
> ldap_free_connection
> ldap_free_connection: refcnt 1
> ldap_result2error
> ldap_msgfree
> ldap_perror
> ldap_modrdn2_s: Type or value exists
> ldap_unbind
> ldap_free_connection
> ldap_send_unbind
> ber_flush: 7 bytes to sd 4
> 0 05 02 01 03 B 00
> ldap_free_connection: actually freed
>
> --
> This is the same way I was doing it in prior versions of OpenLDAP, which
> had modrdn working correctly.
>
> Any ideas?
>
> Don
> --
> Don Badrak <dbadrak@census.gov> 301.457.8263 work
> Telecommunications Office 301.457.4438 fax
> U.S. Bureau of the Census
> Suitland MD, USA
diff -rc ldap_old/include/ldap.h ldap/include/ldap.h
*** ldap_old/include/ldap.h Sat Jan 23 13:05:03 1999
--- ldap/include/ldap.h Fri May 21 09:45:51 1999
***************
*** 214,219 ****
--- 214,220 ----
#define LDAP_MOD_ADD 0x00
#define LDAP_MOD_DELETE 0x01
#define LDAP_MOD_REPLACE 0x02
+ #define LDAP_MOD_SOFTADD 0x04 /* Just make sure value is there */
#define LDAP_MOD_BVALUES 0x80
char *mod_type;
union {
diff -rc ldap_old/servers/slapd/back-ldbm/modify.c ldap/servers/slapd/back-ldbm/modify.c
*** ldap_old/servers/slapd/back-ldbm/modify.c Thu Jan 28 21:11:50 1999
--- ldap/servers/slapd/back-ldbm/modify.c Fri May 21 09:48:37 1999
***************
*** 14,56 ****
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);
! 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;
int i, err;
LDAPMod *mod;
! 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 );
}
if ( (err = acl_check_mods( be, conn, op, e, mods )) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, err, NULL, NULL );
! goto error_return;
}
for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_ADD:
err = add_values( e, mod, op->o_ndn );
break;
case LDAP_MOD_DELETE:
--- 14,138 ----
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);
!
! 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,
! Entry *e
)
{
int i, err;
LDAPMod *mod;
! 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 );
}
if ( (err = acl_check_mods( be, conn, op, e, mods )) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, err, NULL, NULL );
! return -1;
}
for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
+ case LDAP_MOD_SOFTADD:
case LDAP_MOD_ADD:
err = add_values( e, mod, op->o_ndn );
+ if ( (mod->mod_op & LDAP_MOD_SOFTADD)
+ && (err == LDAP_TYPE_OR_VALUE_EXISTS)) {
+ err = LDAP_SUCCESS;
+ }
break;
case LDAP_MOD_DELETE:
***************
*** 65,71 ****
if ( err != LDAP_SUCCESS ) {
/* unlock entry, delete from cache */
send_ldap_result( conn, op, err, NULL, NULL );
! goto error_return;
}
}
--- 147,153 ----
if ( err != LDAP_SUCCESS ) {
/* unlock entry, delete from cache */
send_ldap_result( conn, op, err, NULL, NULL );
! return -1;
}
}
***************
*** 73,79 ****
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;
}
/* check for abandon */
--- 155,161 ----
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 );
! return -1;
}
/* check for abandon */
***************
*** 80,86 ****
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
! goto error_return;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
--- 162,168 ----
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
! return -1;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
***************
*** 87,93 ****
/* 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;
}
/* check for abandon */
--- 169,175 ----
/* modify indexes */
if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
! return -1;
}
/* check for abandon */
***************
*** 94,107 ****
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
! goto error_return;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* change the entry itself */
if ( id2entry_add( be, e ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
! goto error_return;
}
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
--- 176,227 ----
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
! 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 );
! return -1;
}
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
diff -rc ldap_old/servers/slapd/back-ldbm/modrdn.c ldap/servers/slapd/back-ldbm/modrdn.c
*** ldap_old/servers/slapd/back-ldbm/modrdn.c Thu Feb 11 12:29:34 1999
--- ldap/servers/slapd/back-ldbm/modrdn.c Fri May 21 09:49:07 1999
***************
*** 27,35 ****
char *new_dn = NULL, *new_ndn = NULL;
char sep[2];
Entry *e, *p = NULL;
! int rootlock = 0;
! int rc = -1;
/* get entry with writer lock */
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
--- 27,50 ----
char *new_dn = NULL, *new_ndn = NULL;
char sep[2];
Entry *e, *p = NULL;
! 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 ) {
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
***************
*** 76,102 ****
#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 */
if( ! be_isroot( be, op->o_ndn ) ) {
--- 91,98 ----
#endif
p_dn = dn_parent( be, e->e_dn );
+
} else {
/* no parent, modrdn entry directly under root */
if( ! be_isroot( be, op->o_ndn ) ) {
***************
*** 110,120 ****
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
rootlock = 1;
! new_dn = ch_strdup( newrdn );
}
new_ndn = dn_normalize_case( ch_strdup( new_dn ) );
if ( (dn2id ( be, new_ndn ) ) != NOID ) {
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
goto return_results;
--- 106,259 ----
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
rootlock = 1;
!
}
+ 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_SOFTADD;
+ 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,145 ****
--- 279,285 ----
goto return_results;
}
+
(void) cache_delete_entry( &li->li_cache, e );
free( e->e_dn );
free( e->e_ndn );
***************
*** 147,178 ****
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 */
if ( id2entry_add( be, e ) != 0 ) {
entry_free( e );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
! goto return_results;
}
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
rc = 0;
! return_results:
if( new_dn != NULL ) free( new_dn );
if( new_ndn != NULL ) free( new_ndn );
if( p_dn != NULL ) free( p_dn );
if( p_ndn != NULL ) free( p_ndn );
if( matched != NULL ) free( matched );
if( p != NULL ) {
/* free parent and writer lock */
--- 287,326 ----
e->e_ndn = new_ndn;
(void) cache_update_entry( &li->li_cache, e );
! /* id2entry index: commit */
if ( id2entry_add( be, e ) != 0 ) {
entry_free( e );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
! goto return_results_new;
}
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
rc = 0;
! 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 */
diff -rc ldap_old/servers/slapd/back-ldbm/proto-back-ldbm.h ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
*** ldap_old/servers/slapd/back-ldbm/proto-back-ldbm.h Wed Feb 10 11:36:53 1999
--- ldap/servers/slapd/back-ldbm/proto-back-ldbm.h Tue May 18 11:07:55 1999
***************
*** 123,128 ****
--- 123,140 ----
#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
*/
diff -rc ldap_old/servers/slapd/dn.c ldap/servers/slapd/dn.c
*** ldap_old/servers/slapd/dn.c Tue Mar 2 10:30:05 1999
--- ldap/servers/slapd/dn.c Tue May 18 12:30:07 1999
***************
*** 220,225 ****
--- 220,296 ----
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,273 ****
--- 342,497 ----
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() */
diff -rc ldap_old/servers/slapd/modify.c ldap/servers/slapd/modify.c
*** ldap_old/servers/slapd/modify.c Thu Jan 28 21:11:49 1999
--- ldap/servers/slapd/modify.c Tue May 18 12:59:00 1999
***************
*** 21,27 ****
#include "slap.h"
static void modlist_free(LDAPMod *mods);
- static void add_lastmods(Operation *op, LDAPMod **mods);
void
--- 21,26 ----
***************
*** 154,163 ****
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 );
}
--- 153,159 ----
if ( be->be_update_ndn == NULL ||
strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
{
!
if ( (*be->be_modify)( be, conn, op, ndn, mods ) == 0 ) {
replog( be, LDAP_REQ_MODIFY, ndn, mods, 0 );
}
***************
*** 190,266 ****
ber_bvecfree( mods->mod_bvalues );
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;
}
--- 186,189 ----
diff -rc ldap_old/servers/slapd/proto-slap.h ldap/servers/slapd/proto-slap.h
*** ldap_old/servers/slapd/proto-slap.h Sun Feb 7 10:42:24 1999
--- ldap/servers/slapd/proto-slap.h Tue May 18 12:32:36 1999
***************
*** 102,111 ****
char * dn_normalize LDAP_P(( char *dn ));
char * dn_normalize_case LDAP_P(( char *dn ));
char * dn_parent 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 ));
!
/*
* entry.c
*/
--- 102,115 ----
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
*/
Only in ldap/tests/data: modrdn.out.master
diff -rc ldap_old/tests/scripts/defines.sh ldap/tests/scripts/defines.sh
*** ldap_old/tests/scripts/defines.sh Tue Jan 19 20:44:54 1999
--- ldap/tests/scripts/defines.sh Tue May 18 15:13:18 1999
***************
*** 5,10 ****
--- 5,11 ----
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,37 ****
--- 33,39 ----
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
diff -rc ldap_old/tests/scripts/test005-modrdn ldap/tests/scripts/test005-modrdn
*** ldap_old/tests/scripts/test005-modrdn Wed Jan 13 17:02:14 1999
--- ldap/tests/scripts/test005-modrdn Tue May 18 15:30:38 1999
***************
*** 1,12 ****
! #!/bin/sh
! if [ $# -eq 0 ]; then
SRCDIR="."
else
SRCDIR=$1; shift
fi
! . $SRCDIR/scripts/defines.sh $SRCDIR
- echo "modrdn test not yet written"
exit 0
--- 1,99 ----
! #! /bin/sh
! 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"
+
+
! # echo "modrdn test not yet written"
exit 0
- References:
- modrdn
- From: Don Badrak <dbadrak@geo.census.gov>