]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/modrdn.c
Code clean-up.
[openldap] / servers / slapd / back-ldbm / modrdn.c
1 /* modrdn.c - ldbm backend modrdn routine */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #include <ac/string.h>
8 #include <ac/socket.h>
9
10 #include "slap.h"
11 #include "back-ldbm.h"
12 #include "proto-back-ldbm.h"
13
14 int
15 ldbm_back_modrdn(
16     Backend     *be,
17     Connection  *conn,
18     Operation   *op,
19     char        *dn,
20     char        *newrdn,
21     int         deleteoldrdn
22 )
23 {
24         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
25         char            *matched = NULL;
26         char            *p_dn = NULL, *p_ndn = NULL;
27         char            *new_dn = NULL, *new_ndn = NULL;
28         char            sep[2];
29         Entry           *e, *p = NULL;
30         int                     rootlock = 0;
31         int                     rc = -1;
32
33         /* get entry with writer lock */
34         if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
35                 send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
36                 if ( matched != NULL ) {
37                         free( matched );
38                 }
39                 return( -1 );
40         }
41
42 #ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
43                 /* check parent for "children" acl */
44         if ( ! access_allowed( be, conn, op, e,
45                 "entry", NULL, ACL_WRITE ) )
46         {
47                 Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
48                         0, 0 );
49                 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
50                         "", "" );
51                 goto return_results;
52         }
53 #endif
54
55         if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
56                 /* parent + rdn + separator(s) + null */
57                 if( (p = dn2entry_w( be, p_ndn, &matched )) == NULL) {
58                         Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
59                                 0, 0, 0);
60                         send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
61                                 "", "");
62                         goto return_results;
63                 }
64
65 #ifndef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
66                 /* check parent for "children" acl */
67                 if ( ! access_allowed( be, conn, op, p,
68                         "children", NULL, ACL_WRITE ) )
69                 {
70                         Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
71                                 0, 0 );
72                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
73                                 "", "" );
74                         goto return_results;
75                 }
76 #endif
77
78                 p_dn = dn_parent( be, e->e_dn );
79                 new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn )
80                     + 3 );
81                 if ( dn_type( e->e_dn ) == DN_X500 ) {
82                         strcpy( new_dn, newrdn );
83                         strcat( new_dn, "," );
84                         strcat( new_dn, p_dn );
85                 } else {
86                         char *s;
87                         strcpy( new_dn, newrdn );
88                         s = strchr( newrdn, '\0' );
89                         s--;
90                         if ( *s != '.' && *s != '@' ) {
91                                 if ( (s = strpbrk( dn, ".@" )) != NULL ) {
92                                         sep[0] = *s;
93                                         sep[1] = '\0';
94                                         strcat( new_dn, sep );
95                                 }
96                         }
97                         strcat( new_dn, p_dn );
98                 }
99
100         } else {
101                 /* no parent, modrdn entry directly under root */
102                 if( ! be_isroot( be, op->o_ndn ) ) {
103                         Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
104                                 0, 0, 0);
105                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
106                                 "", "");
107                         goto return_results;
108                 }
109
110                 ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
111                 rootlock = 1;
112
113                 new_dn = ch_strdup( newrdn );
114         }
115
116         new_ndn = dn_normalize_case( ch_strdup( new_dn ) );
117
118         if ( (dn2id ( be, new_ndn ) ) != NOID ) {
119                 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
120                 goto return_results;
121         }
122
123         /* check for abandon */
124         ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
125         if ( op->o_abandon ) {
126                 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
127                 goto return_results;
128         }
129         ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
130
131         /* add new one */
132         if ( dn2id_add( be, new_ndn, e->e_id ) != 0 ) {
133                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
134                 goto return_results;
135         }
136
137         /* delete old one */
138         if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
139                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
140                 goto return_results;
141         }
142
143         (void) cache_delete_entry( &li->li_cache, e );
144         free( e->e_dn );
145         free( e->e_ndn );
146         e->e_dn = new_dn;
147         e->e_ndn = new_ndn;
148         (void) cache_update_entry( &li->li_cache, e );
149
150         /* 
151          * At some point here we need to update the attribute values in
152          * the entry itself that were effected by this RDN change
153          * (respecting the value of the deleteoldrdn parameter).
154          *
155          * Since the code to do this has not yet been written, treat this
156          * omission as a (documented) bug.
157          */
158
159         /* id2entry index */
160         if ( id2entry_add( be, e ) != 0 ) {
161                 entry_free( e );
162                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
163                 goto return_results;
164         }
165
166         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
167         rc = 0;
168
169 return_results:
170         if( new_dn != NULL ) free( new_dn );
171         if( new_ndn != NULL ) free( new_ndn );
172         if( p_dn != NULL ) free( p_dn );
173         if( p_ndn != NULL ) free( p_ndn );
174
175         if( matched != NULL ) free( matched );
176
177         if( p != NULL ) {
178                 /* free parent and writer lock */
179                 cache_return_entry_w( &li->li_cache, p );
180         }
181
182         if ( rootlock ) {
183                 /* release root writer lock */
184                 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
185         }
186
187         /* free entry and writer lock */
188         cache_return_entry_w( &li->li_cache, e );
189         return( rc );
190 }