]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb2/modrdn.c
Elimination of un-used code in bdb2i_cache_open and friends.
[openldap] / servers / slapd / back-bdb2 / modrdn.c
1 /* modrdn.c - bdb2 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-bdb2.h"
12 #include "proto-back-bdb2.h"
13
14 static int
15 bdb2i_back_modrdn_internal(
16     BackendDB   *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 = bdb2i_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 = bdb2i_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 ( (bdb2i_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 ( bdb2i_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 ( bdb2i_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) bdb2i_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
149         /* XXX
150          * At some point here we need to update the attribute values in
151          * the entry itself that were effected by this RDN change
152          * (respecting the value of the deleteoldrdn parameter).
153          *
154          * Since the code to do this has not yet been written, treat this
155          * omission as a (documented) bug.
156          */
157
158         /* id2entry index */
159         if ( bdb2i_id2entry_add( be, e ) != 0 ) {
160                 entry_free( e );
161                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
162                 goto return_results;
163         }
164
165         send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
166         rc = 0;
167
168 return_results:
169         if( new_dn != NULL ) free( new_dn );
170         if( new_ndn != NULL ) free( new_ndn );
171         if( p_dn != NULL ) free( p_dn );
172         if( p_ndn != NULL ) free( p_ndn );
173
174         if( matched != NULL ) free( matched );
175
176         if( p != NULL ) {
177                 /* free parent and writer lock */
178                 bdb2i_cache_return_entry_w( &li->li_cache, p );
179
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         bdb2i_cache_return_entry_w( &li->li_cache, e );
189         return( rc );
190 }
191
192
193 int
194 bdb2_back_modrdn(
195     BackendDB   *be,
196     Connection  *conn,
197     Operation   *op,
198     char        *dn,
199     char        *newrdn,
200     int         deleteoldrdn
201 )
202 {
203         DB_LOCK  lock;
204         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
205
206         struct timeval  time1, time2;
207         char   *elapsed_time;
208         int    ret;
209
210         gettimeofday( &time1, NULL );
211
212         if ( bdb2i_enter_backend_w( get_dbenv( be ), &lock ) != 0 ) {
213
214                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
215                 return( -1 );
216
217         }
218
219         ret = bdb2i_back_modrdn_internal( be, conn, op, dn,
220                                         newrdn, deleteoldrdn );
221
222         (void) bdb2i_leave_backend( get_dbenv( be ), lock );
223
224         if ( bdb2i_do_timing ) {
225
226                 gettimeofday( &time2, NULL);
227                 elapsed_time = bdb2i_elapsed( time1, time2 );
228                 Debug( LDAP_DEBUG_ANY, "conn=%d op=%d MODRDN elapsed=%s\n",
229                                 conn->c_connid, op->o_opid, elapsed_time );
230                 free( elapsed_time );
231
232         }
233
234         return( ret );
235 }
236
237