r10299: remove the public (un)lock functions and introduce a transaction based
[samba.git] / source / lib / ldb / modules / rdn_name.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb objectguid module
29  *
30  *  Description: add a unique objectGUID onto every new record
31  *
32  *  Author: Simo Sorce
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include <time.h>
39
40 struct private_data {
41         const char *error_string;
42 };
43
44 static int rdn_name_search(struct ldb_module *module, const struct ldb_dn *base,
45                                   enum ldb_scope scope, const char *expression,
46                                   const char * const *attrs, struct ldb_message ***res)
47 {
48         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n");
49         return ldb_next_search(module, base, scope, expression, attrs, res);
50 }
51
52 static int rdn_name_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
53                                     enum ldb_scope scope, struct ldb_parse_tree *tree,
54                                     const char * const *attrs, struct ldb_message ***res)
55 {
56         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n");
57         return ldb_next_search_bytree(module, base, scope, tree, attrs, res);
58 }
59
60 static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
61 {
62         int i;
63
64         for (i = 0; i < msg->num_elements; i++) {
65                 if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {
66                         return &msg->elements[i];
67                 }
68         }
69
70         return NULL;
71 }
72
73 /* add_record: add crateTimestamp/modifyTimestamp attributes */
74 static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg)
75 {
76         struct private_data *data = (struct private_data *)module->private_data;
77
78         struct ldb_message *msg2;
79         struct ldb_message_element *attribute;
80         struct ldb_dn_component *rdn;
81         int i, ret;
82
83         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n");
84
85         /* do not manipulate our control entries */
86         if (ldb_dn_is_special(msg->dn)) {
87                 return ldb_next_add_record(module, msg);
88         }
89
90         /* Perhaps someone above us knows better */
91         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
92                 return ldb_next_add_record(module, msg);
93         }
94
95         msg2 = talloc(module, struct ldb_message);
96         if (!msg2) {
97                 return -1;
98         }
99
100         msg2->dn = msg->dn;
101         msg2->num_elements = msg->num_elements;
102         msg2->private_data = msg->private_data;
103         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
104         for (i = 0; i < msg2->num_elements; i++) {
105                 msg2->elements[i] = msg->elements[i];
106         }
107
108         rdn = ldb_dn_get_rdn(msg2, msg2->dn);
109         if (!rdn) {
110                 talloc_free(msg2);
111                 return -1;
112         }
113         
114         if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) {
115                 talloc_free(msg2);
116                 return -1;
117         }
118
119         attribute = rdn_name_find_attribute(msg2, rdn->name);
120
121         if (!attribute) {
122                 if (ldb_msg_add_value(module->ldb, msg2, rdn->name, &rdn->value) != 0) {
123                         talloc_free(msg2);
124                         return -1;
125                 }
126         } else {
127                 const struct ldb_attrib_handler *handler
128                         = ldb_attrib_handler(module->ldb, rdn->name);
129                 for (i=0; i < attribute->num_values; i++) {
130                         if (handler->comparison_fn(module->ldb, msg2, &rdn->value, &attribute->values[i]) == 0) {
131                                 /* overwrite so it matches in case */
132                                 attribute->values[i] = rdn->value;
133                                 break;
134                         }
135                 }
136                 if (i == attribute->num_values) {
137                         data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name);
138                         ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", data->error_string);
139                         talloc_free(msg2);
140                         return -1;
141                 }
142         }
143
144         ret = ldb_next_add_record(module, msg2);
145         talloc_free(msg2);
146
147         return ret;
148 }
149
150 /* modify_record: change modifyTimestamp as well */
151 static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_message *msg)
152 {
153         struct ldb_message *msg2;
154         struct ldb_message_element *attribute;
155         struct ldb_dn_component *rdn;
156         int ret, i;
157
158         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n");
159
160         /* do not manipulate our control entries */
161         if (ldb_dn_is_special(msg->dn)) {
162                 return ldb_next_modify_record(module, msg);
163         }
164
165         /* Perhaps someone above us knows better */
166         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
167                 return ldb_next_modify_record(module, msg);
168         }
169
170         msg2 = talloc(module, struct ldb_message);
171         if (!msg2) {
172                 return -1;
173         }
174
175         msg2->dn = msg->dn;
176         msg2->num_elements = msg->num_elements;
177         msg2->private_data = msg->private_data;
178         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
179         for (i = 0; i < msg2->num_elements; i++) {
180                 msg2->elements[i] = msg->elements[i];
181         }
182         
183         rdn = ldb_dn_get_rdn(msg2, msg2->dn);
184         if (!rdn) {
185                 talloc_free(msg2);
186                 return -1;
187         }
188         
189         if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) {
190                 talloc_free(msg2);
191                 return -1;
192         }
193
194         attribute = rdn_name_find_attribute(msg2, "name");
195         if (!attribute) {
196                 talloc_free(msg2);
197                 return -1;
198         }
199
200         attribute->flags = LDB_FLAG_MOD_REPLACE;
201
202         ret = ldb_next_modify_record(module, msg2);
203         talloc_free(msg2);
204
205         return ret;
206 }
207
208 static int rdn_name_delete_record(struct ldb_module *module, const struct ldb_dn *dn)
209 {
210         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_delete_record\n");
211         return ldb_next_delete_record(module, dn);
212 }
213
214 static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
215 {
216         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n");
217         return ldb_next_rename_record(module, olddn, newdn);
218 }
219
220 static int rdn_start_trans(struct ldb_module *module)
221 {
222         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_start_trans\n");
223         return ldb_next_start_trans(module);
224 }
225
226 static int rdn_end_trans(struct ldb_module *module, int status)
227 {
228         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_end_trans\n");
229         return ldb_next_end_trans(module, status);
230 }
231
232 /* return extended error information */
233 static const char *rdn_name_errstring(struct ldb_module *module)
234 {
235         struct private_data *data = (struct private_data *)module->private_data;
236
237         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_errstring\n");
238         if (data->error_string) {
239                 const char *error;
240
241                 error = data->error_string;
242                 data->error_string = NULL;
243                 return error;
244         }
245
246         return ldb_next_errstring(module);
247 }
248
249 static int rdn_name_destructor(void *module_ctx)
250 {
251         /* struct ldb_module *ctx = module_ctx; */
252         /* put your clean-up functions here */
253         return 0;
254 }
255
256 static const struct ldb_module_ops rdn_name_ops = {
257         .name              = "rdn_name",
258         .search            = rdn_name_search,
259         .search_bytree     = rdn_name_search_bytree,
260         .add_record        = rdn_name_add_record,
261         .modify_record     = rdn_name_modify_record,
262         .delete_record     = rdn_name_delete_record,
263         .rename_record     = rdn_name_rename_record,
264         .start_transaction = rdn_start_trans,
265         .end_transaction   = rdn_end_trans,
266         .errstring         = rdn_name_errstring
267 };
268
269
270 /* the init function */
271 #ifdef HAVE_DLOPEN_DISABLED
272  struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
273 #else
274 struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *options[])
275 #endif
276 {
277         struct ldb_module *ctx;
278         struct private_data *data;
279
280         ctx = talloc(ldb, struct ldb_module);
281         if (!ctx)
282                 return NULL;
283
284         data = talloc(ctx, struct private_data);
285         if (!data) {
286                 talloc_free(ctx);
287                 return NULL;
288         }
289
290         data->error_string = NULL;
291         ctx->private_data = data;
292         ctx->ldb = ldb;
293         ctx->prev = ctx->next = NULL;
294         ctx->ops = &rdn_name_ops;
295
296         talloc_set_destructor (ctx, rdn_name_destructor);
297
298         return ctx;
299 }