7ee715f561920d612d6a4980ead8b725a63d25f3
[mdw/samba.git] / source4 / lib / ldb / ldb_tdb / ldb_tdb.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5    Copyright (C) Stefan Metzmacher  2004
6    Copyright (C) Simo Sorce       2006
7    
8
9      ** NOTE! The following LGPL license applies to the ldb
10      ** library. This does NOT imply that all of Samba is released
11      ** under the LGPL
12    
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 */
27
28 /*
29  *  Name: ldb_tdb
30  *
31  *  Component: ldb tdb backend
32  *
33  *  Description: core functions for tdb backend
34  *
35  *  Author: Andrew Tridgell
36  *  Author: Stefan Metzmacher
37  *
38  *  Modifications:
39  *
40  *  - description: make the module use asyncronous calls
41  *    date: Feb 2006
42  *    Author: Simo Sorce
43  */
44
45 #include "includes.h"
46 #include "ldb/include/includes.h"
47
48 #include "ldb/ldb_tdb/ldb_tdb.h"
49
50
51 /*
52   map a tdb error code to a ldb error code
53 */
54 static int ltdb_err_map(enum TDB_ERROR tdb_code)
55 {
56         switch (tdb_code) {
57         case TDB_SUCCESS:
58                 return LDB_SUCCESS;
59         case TDB_ERR_CORRUPT:
60         case TDB_ERR_OOM:
61         case TDB_ERR_EINVAL:
62                 return LDB_ERR_OPERATIONS_ERROR;
63         case TDB_ERR_IO:
64                 return LDB_ERR_PROTOCOL_ERROR;
65         case TDB_ERR_LOCK:
66         case TDB_ERR_NOLOCK:
67                 return LDB_ERR_BUSY;
68         case TDB_ERR_LOCK_TIMEOUT:
69                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
70         case TDB_ERR_EXISTS:
71                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
72         case TDB_ERR_NOEXIST:
73                 return LDB_ERR_NO_SUCH_OBJECT;
74         case TDB_ERR_RDONLY:
75                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
76         }
77         return LDB_ERR_OTHER;
78 }
79
80
81 struct ldb_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,
82                                           void *context,
83                                           int (*callback)(struct ldb_context *, void *, struct ldb_reply *))
84 {
85         struct ltdb_context *ac;
86         struct ldb_handle *h;
87
88         h = talloc_zero(ltdb, struct ldb_handle);
89         if (h == NULL) {
90                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
91                 return NULL;
92         }
93
94         h->module = module;
95
96         ac = talloc_zero(h, struct ltdb_context);
97         if (ac == NULL) {
98                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
99                 talloc_free(h);
100                 return NULL;
101         }
102
103         h->private_data = (void *)ac;
104
105         h->state = LDB_ASYNC_INIT;
106         h->status = LDB_SUCCESS;
107
108         ac->module = module;
109         ac->context = context;
110         ac->callback = callback;
111
112         return h;
113 }
114
115 /*
116   form a TDB_DATA for a record key
117   caller frees
118
119   note that the key for a record can depend on whether the 
120   dn refers to a case sensitive index record or not
121 */
122 struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn)
123 {
124         struct ldb_context *ldb = module->ldb;
125         TDB_DATA key;
126         char *key_str = NULL;
127         char *dn_folded = NULL;
128
129         /*
130           most DNs are case insensitive. The exception is index DNs for
131           case sensitive attributes
132
133           there are 3 cases dealt with in this code:
134
135           1) if the dn doesn't start with @ then uppercase the attribute
136              names and the attributes values of case insensitive attributes
137           2) if the dn starts with @ then leave it alone - the indexing code handles
138              the rest
139         */
140
141         dn_folded = ldb_dn_linearize_casefold(ldb, dn);
142         if (!dn_folded) {
143                 goto failed;
144         }
145
146         key_str = talloc_asprintf(ldb, "DN=%s", dn_folded);
147
148         talloc_free(dn_folded);
149
150         if (!key_str) {
151                 goto failed;
152         }
153
154         key.dptr = (uint8_t *)key_str;
155         key.dsize = strlen(key_str) + 1;
156
157         return key;
158
159 failed:
160         errno = ENOMEM;
161         key.dptr = NULL;
162         key.dsize = 0;
163         return key;
164 }
165
166 /*
167   check special dn's have valid attributes
168   currently only @ATTRIBUTES is checked
169 */
170 int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
171 {
172         int i, j;
173  
174         if (! ldb_dn_is_special(msg->dn) ||
175             ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
176                 return 0;
177         }
178
179         /* we have @ATTRIBUTES, let's check attributes are fine */
180         /* should we check that we deny multivalued attributes ? */
181         for (i = 0; i < msg->num_elements; i++) {
182                 for (j = 0; j < msg->elements[i].num_values; j++) {
183                         if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
184                                 char *err_string = talloc_strdup(module, "Invalid attribute value in an @ATTRIBUTES entry");
185                                 if (err_string) {
186                                         ldb_set_errstring(module->ldb, err_string);
187                                 }
188                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
189                         }
190                 }
191         }
192
193         return 0;
194 }
195
196
197 /*
198   we've made a modification to a dn - possibly reindex and 
199   update sequence number
200 */
201 static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn)
202 {
203         int ret = 0;
204
205         if (ldb_dn_is_special(dn) &&
206             (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
207              ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
208                 ret = ltdb_reindex(module);
209         }
210
211         if (ret == 0 &&
212             !(ldb_dn_is_special(dn) &&
213               ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
214                 ret = ltdb_increase_sequence_number(module);
215         }
216
217         return ret;
218 }
219
220 /*
221   store a record into the db
222 */
223 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
224 {
225         struct ltdb_private *ltdb = module->private_data;
226         TDB_DATA tdb_key, tdb_data;
227         int ret;
228
229         tdb_key = ltdb_key(module, msg->dn);
230         if (!tdb_key.dptr) {
231                 return LDB_ERR_OTHER;
232         }
233
234         ret = ltdb_pack_data(module, msg, &tdb_data);
235         if (ret == -1) {
236                 talloc_free(tdb_key.dptr);
237                 return LDB_ERR_OTHER;
238         }
239
240         ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
241         if (ret == -1) {
242                 ret = ltdb_err_map(tdb_error(ltdb->tdb));
243                 goto done;
244         }
245         
246         ret = ltdb_index_add(module, msg);
247         if (ret == -1) {
248                 tdb_delete(ltdb->tdb, tdb_key);
249         }
250
251 done:
252         talloc_free(tdb_key.dptr);
253         talloc_free(tdb_data.dptr);
254
255         return ret;
256 }
257
258
259 static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg)
260 {
261         int ret;
262         
263         ret = ltdb_check_special_dn(module, msg);
264         if (ret != LDB_SUCCESS) {
265                 return ret;
266         }
267         
268         if (ltdb_cache_load(module) != 0) {
269                 return LDB_ERR_OPERATIONS_ERROR;
270         }
271
272         ret = ltdb_store(module, msg, TDB_INSERT);
273
274         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
275                 char *dn;
276
277                 dn = ldb_dn_linearize(module, msg->dn);
278                 if (!dn) {
279                         return ret;
280                 }
281                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Entry %s already exists", dn));
282                 talloc_free(dn);
283                 return ret;
284         }
285         
286         if (ret == LDB_SUCCESS) {
287                 ret = ltdb_modified(module, msg->dn);
288                 if (ret != LDB_SUCCESS) {
289                         return LDB_ERR_OPERATIONS_ERROR;
290                 }
291         }
292
293         return ret;
294 }
295
296 /*
297   add a record to the database
298 */
299 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
300 {
301         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
302         struct ltdb_context *ltdb_ac;
303         int tret, ret = LDB_SUCCESS;
304
305         if (req->controls != NULL) {
306                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
307                 if (check_critical_controls(req->controls)) {
308                         return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
309                 }
310         }
311         
312         req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
313         if (req->handle == NULL) {
314                 return LDB_ERR_OPERATIONS_ERROR;
315         }
316         ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
317
318         tret = ltdb_add_internal(module, req->op.add.message);
319         if (tret != LDB_SUCCESS) {
320                 req->handle->status = tret;
321                 goto done;
322         }
323         
324         if (ltdb_ac->callback) {
325                 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
326         }
327 done:
328         req->handle->state = LDB_ASYNC_DONE;
329         return ret;
330 }
331
332 /*
333   delete a record from the database, not updating indexes (used for deleting
334   index records)
335 */
336 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
337 {
338         struct ltdb_private *ltdb = module->private_data;
339         TDB_DATA tdb_key;
340         int ret;
341
342         tdb_key = ltdb_key(module, dn);
343         if (!tdb_key.dptr) {
344                 return LDB_ERR_OTHER;
345         }
346
347         ret = tdb_delete(ltdb->tdb, tdb_key);
348         talloc_free(tdb_key.dptr);
349
350         if (ret != 0) {
351                 ret = ltdb_err_map(tdb_error(ltdb->tdb));
352         }
353
354         return ret;
355 }
356
357 static int ltdb_delete_internal(struct ldb_module *module, const struct ldb_dn *dn)
358 {
359         struct ldb_message *msg;
360         int ret;
361
362         msg = talloc(module, struct ldb_message);
363         if (msg == NULL) {
364                 return LDB_ERR_OPERATIONS_ERROR;
365         }
366
367         /* in case any attribute of the message was indexed, we need
368            to fetch the old record */
369         ret = ltdb_search_dn1(module, dn, msg);
370         if (ret != 1) {
371                 /* not finding the old record is an error */
372                 talloc_free(msg);
373                 return LDB_ERR_NO_SUCH_OBJECT;
374         }
375
376         ret = ltdb_delete_noindex(module, dn);
377         if (ret != LDB_SUCCESS) {
378                 talloc_free(msg);
379                 return LDB_ERR_NO_SUCH_OBJECT;
380         }
381
382         /* remove any indexed attributes */
383         ret = ltdb_index_del(module, msg);
384         if (ret != LDB_SUCCESS) {
385                 talloc_free(msg);
386                 return LDB_ERR_OPERATIONS_ERROR;
387         }
388
389         ret = ltdb_modified(module, dn);
390         if (ret != LDB_SUCCESS) {
391                 return LDB_ERR_OPERATIONS_ERROR;
392         }
393
394         talloc_free(msg);
395         return LDB_SUCCESS;
396 }
397
398 /*
399   delete a record from the database
400 */
401 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
402 {
403         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
404         struct ltdb_context *ltdb_ac;
405         int tret, ret = LDB_SUCCESS;
406
407         if (req->controls != NULL) {
408                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
409                 if (check_critical_controls(req->controls)) {
410                         return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
411                 }
412         }
413         
414         req->handle = NULL;
415
416         if (ltdb_cache_load(module) != 0) {
417                 return LDB_ERR_OPERATIONS_ERROR;
418         }
419
420         req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
421         if (req->handle == NULL) {
422                 return LDB_ERR_OPERATIONS_ERROR;
423         }
424         ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
425
426         tret = ltdb_delete_internal(module, req->op.del.dn);
427         if (tret != LDB_SUCCESS) {
428                 req->handle->status = tret; 
429                 goto done;
430         }
431
432         if (ltdb_ac->callback) {
433                 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
434         }
435 done:
436         req->handle->state = LDB_ASYNC_DONE;
437         return ret;
438 }
439
440 /*
441   find an element by attribute name. At the moment this does a linear search, it should
442   be re-coded to use a binary search once all places that modify records guarantee
443   sorted order
444
445   return the index of the first matching element if found, otherwise -1
446 */
447 static int find_element(const struct ldb_message *msg, const char *name)
448 {
449         unsigned int i;
450         for (i=0;i<msg->num_elements;i++) {
451                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
452                         return i;
453                 }
454         }
455         return -1;
456 }
457
458
459 /*
460   add an element to an existing record. Assumes a elements array that we
461   can call re-alloc on, and assumed that we can re-use the data pointers from the 
462   passed in additional values. Use with care!
463
464   returns 0 on success, -1 on failure (and sets errno)
465 */
466 static int msg_add_element(struct ldb_context *ldb,
467                            struct ldb_message *msg, struct ldb_message_element *el)
468 {
469         struct ldb_message_element *e2;
470         unsigned int i;
471
472         e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
473                               msg->num_elements+1);
474         if (!e2) {
475                 errno = ENOMEM;
476                 return -1;
477         }
478
479         msg->elements = e2;
480
481         e2 = &msg->elements[msg->num_elements];
482
483         e2->name = el->name;
484         e2->flags = el->flags;
485         e2->values = NULL;
486         if (el->num_values != 0) {
487                 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
488                 if (!e2->values) {
489                         errno = ENOMEM;
490                         return -1;
491                 }
492         }
493         for (i=0;i<el->num_values;i++) {
494                 e2->values[i] = el->values[i];
495         }
496         e2->num_values = el->num_values;
497
498         msg->num_elements++;
499
500         return 0;
501 }
502
503 /*
504   delete all elements having a specified attribute name
505 */
506 static int msg_delete_attribute(struct ldb_module *module,
507                                 struct ldb_context *ldb,
508                                 struct ldb_message *msg, const char *name)
509 {
510         char *dn;
511         unsigned int i, j;
512
513         dn = ldb_dn_linearize(ldb, msg->dn);
514         if (dn == NULL) {
515                 return -1;
516         }
517
518         for (i=0;i<msg->num_elements;i++) {
519                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
520                         for (j=0;j<msg->elements[i].num_values;j++) {
521                                 ltdb_index_del_value(module, dn, &msg->elements[i], j);
522                         }
523                         talloc_free(msg->elements[i].values);
524                         if (msg->num_elements > (i+1)) {
525                                 memmove(&msg->elements[i], 
526                                         &msg->elements[i+1], 
527                                         sizeof(struct ldb_message_element)*
528                                         (msg->num_elements - (i+1)));
529                         }
530                         msg->num_elements--;
531                         i--;
532                         msg->elements = talloc_realloc(msg, msg->elements, 
533                                                          struct ldb_message_element, 
534                                                          msg->num_elements);
535                 }
536         }
537
538         talloc_free(dn);
539         return 0;
540 }
541
542 /*
543   delete all elements matching an attribute name/value 
544
545   return 0 on success, -1 on failure
546 */
547 static int msg_delete_element(struct ldb_module *module,
548                               struct ldb_message *msg, 
549                               const char *name,
550                               const struct ldb_val *val)
551 {
552         struct ldb_context *ldb = module->ldb;
553         unsigned int i;
554         int found;
555         struct ldb_message_element *el;
556         const struct ldb_attrib_handler *h;
557
558         found = find_element(msg, name);
559         if (found == -1) {
560                 return -1;
561         }
562
563         el = &msg->elements[found];
564
565         h = ldb_attrib_handler(ldb, el->name);
566
567         for (i=0;i<el->num_values;i++) {
568                 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
569                         if (i<el->num_values-1) {
570                                 memmove(&el->values[i], &el->values[i+1],
571                                         sizeof(el->values[i])*(el->num_values-(i+1)));
572                         }
573                         el->num_values--;
574                         if (el->num_values == 0) {
575                                 return msg_delete_attribute(module, ldb, msg, name);
576                         }
577                         return 0;
578                 }
579         }
580
581         return -1;
582 }
583
584
585 /*
586   modify a record - internal interface
587
588   yuck - this is O(n^2). Luckily n is usually small so we probably
589   get away with it, but if we ever have really large attribute lists 
590   then we'll need to look at this again
591 */
592 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
593 {
594         struct ldb_context *ldb = module->ldb;
595         struct ltdb_private *ltdb = module->private_data;
596         TDB_DATA tdb_key, tdb_data;
597         struct ldb_message *msg2;
598         unsigned i, j;
599         int ret;
600
601         tdb_key = ltdb_key(module, msg->dn);
602         if (!tdb_key.dptr) {
603                 return LDB_ERR_OTHER;
604         }
605
606         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
607         if (!tdb_data.dptr) {
608                 talloc_free(tdb_key.dptr);
609                 return ltdb_err_map(tdb_error(ltdb->tdb));
610         }
611
612         msg2 = talloc(tdb_key.dptr, struct ldb_message);
613         if (msg2 == NULL) {
614                 talloc_free(tdb_key.dptr);
615                 return LDB_ERR_OTHER;
616         }
617
618         ret = ltdb_unpack_data(module, &tdb_data, msg2);
619         if (ret == -1) {
620                 ret = LDB_ERR_OTHER;
621                 goto failed;
622         }
623
624         if (!msg2->dn) {
625                 msg2->dn = msg->dn;
626         }
627
628         for (i=0;i<msg->num_elements;i++) {
629                 struct ldb_message_element *el = &msg->elements[i];
630                 struct ldb_message_element *el2;
631                 struct ldb_val *vals;
632                 char *err_string;
633                 char *dn;
634
635                 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
636
637                 case LDB_FLAG_MOD_ADD:
638                         /* add this element to the message. fail if it
639                            already exists */
640                         ret = find_element(msg2, el->name);
641
642                         if (ret == -1) {
643                                 if (msg_add_element(ldb, msg2, el) != 0) {
644                                         ret = LDB_ERR_OTHER;
645                                         goto failed;
646                                 }
647                                 continue;
648                         }
649
650                         el2 = &msg2->elements[ret];
651
652                         /* An attribute with this name already exists, add all
653                          * values if they don't already exist. */
654
655                         for (j=0;j<el->num_values;j++) {
656                                 if (ldb_msg_find_val(el2, &el->values[j])) {
657                                         err_string = talloc_strdup(module, "Type or value exists");
658                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
659                                         ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
660                                         goto failed;
661                                 }
662                         }
663
664                         vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
665                                                 el2->num_values + el->num_values);
666
667                         if (vals == NULL) {
668                                 ret = LDB_ERR_OTHER;
669                                 goto failed;
670                         }
671
672                         for (j=0;j<el->num_values;j++) {
673                                 vals[el2->num_values + j] =
674                                         ldb_val_dup(vals, &el->values[j]);
675                         }
676
677                         el2->values = vals;
678                         el2->num_values += el->num_values;
679
680                         break;
681
682                 case LDB_FLAG_MOD_REPLACE:
683                         /* replace all elements of this attribute name with the elements
684                            listed. The attribute not existing is not an error */
685                         msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
686
687                         /* add the replacement element, if not empty */
688                         if (msg->elements[i].num_values != 0 &&
689                             msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
690                                 ret = LDB_ERR_OTHER;
691                                 goto failed;
692                         }
693                         break;
694
695                 case LDB_FLAG_MOD_DELETE:
696
697                         dn = ldb_dn_linearize(msg2, msg->dn);
698                         if (dn == NULL) {
699                                 ret = LDB_ERR_OTHER;
700                                 goto failed;
701                         }
702
703                         /* we could be being asked to delete all
704                            values or just some values */
705                         if (msg->elements[i].num_values == 0) {
706                                 if (msg_delete_attribute(module, ldb, msg2, 
707                                                          msg->elements[i].name) != 0) {
708                                         err_string = talloc_asprintf(module, "No such attribute: %s for delete on %s", 
709                                                                      msg->elements[i].name, dn);
710                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
711                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
712                                         goto failed;
713                                 }
714                                 break;
715                         }
716                         for (j=0;j<msg->elements[i].num_values;j++) {
717                                 if (msg_delete_element(module,
718                                                        msg2, 
719                                                        msg->elements[i].name,
720                                                        &msg->elements[i].values[j]) != 0) {
721                                         err_string = talloc_asprintf(module, "No matching attribute value when deleting attribute: %s on %s", 
722                                                                      msg->elements[i].name, dn);
723                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
724                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
725                                         goto failed;
726                                 }
727                                 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
728                                         ret = LDB_ERR_OTHER;
729                                         goto failed;
730                                 }
731                         }
732                         break;
733                 default:
734                         err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x", 
735                                                      msg->elements[i].name, 
736                                                      msg->elements[i].flags & LDB_FLAG_MOD_MASK);
737                         if (err_string) ldb_set_errstring(module->ldb, err_string);
738                         ret = LDB_ERR_PROTOCOL_ERROR;
739                         goto failed;
740                 }
741         }
742
743         /* we've made all the mods - save the modified record back into the database */
744         ret = ltdb_store(module, msg2, TDB_MODIFY);
745         if (ret != LDB_SUCCESS) {
746                 goto failed;
747         }
748
749         if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
750                 ret = LDB_ERR_OPERATIONS_ERROR;
751                 goto failed;
752         }
753
754         talloc_free(tdb_key.dptr);
755         free(tdb_data.dptr);
756         return ret;
757
758 failed:
759         talloc_free(tdb_key.dptr);
760         free(tdb_data.dptr);
761         return ret;
762 }
763
764 /*
765   modify a record
766 */
767 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
768 {
769         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
770         struct ltdb_context *ltdb_ac;
771         int tret, ret = LDB_SUCCESS;
772
773         if (req->controls != NULL) {
774                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
775                 if (check_critical_controls(req->controls)) {
776                         return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
777                 }
778         }
779         
780         req->handle = NULL;
781
782         req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
783         if (req->handle == NULL) {
784                 return LDB_ERR_OPERATIONS_ERROR;
785         }
786         ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
787
788         tret = ltdb_check_special_dn(module, req->op.mod.message);
789         if (tret != LDB_SUCCESS) {
790                 req->handle->status = tret;
791                 goto done;
792         }
793         
794         if (ltdb_cache_load(module) != 0) {
795                 ret = LDB_ERR_OPERATIONS_ERROR;
796                 goto done;
797         }
798
799         tret = ltdb_modify_internal(module, req->op.mod.message);
800         if (tret != LDB_SUCCESS) {
801                 req->handle->status = tret;
802                 goto done;
803         }
804
805         if (ltdb_ac->callback) {
806                 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
807         }
808 done:
809         req->handle->state = LDB_ASYNC_DONE;
810         return ret;
811 }
812
813 /*
814   rename a record
815 */
816 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
817 {
818         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
819         struct ltdb_context *ltdb_ac;
820         struct ldb_message *msg;
821         int tret, ret = LDB_SUCCESS;
822
823         if (req->controls != NULL) {
824                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
825                 if (check_critical_controls(req->controls)) {
826                         return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
827                 }
828         }
829         
830         req->handle = NULL;
831
832         if (ltdb_cache_load(module) != 0) {
833                 return LDB_ERR_OPERATIONS_ERROR;
834         }
835
836         req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
837         if (req->handle == NULL) {
838                 return LDB_ERR_OPERATIONS_ERROR;
839         }
840         ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
841
842         msg = talloc(ltdb_ac, struct ldb_message);
843         if (msg == NULL) {
844                 ret = LDB_ERR_OPERATIONS_ERROR;
845                 goto done;
846         }
847
848         /* in case any attribute of the message was indexed, we need
849            to fetch the old record */
850         tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
851         if (tret != 1) {
852                 /* not finding the old record is an error */
853                 req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
854                 goto done;
855         }
856
857         msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
858         if (!msg->dn) {
859                 ret = LDB_ERR_OPERATIONS_ERROR;
860                 goto done;
861         }
862
863         tret = ltdb_add_internal(module, msg);
864         if (tret != LDB_SUCCESS) {
865                 ret = LDB_ERR_OPERATIONS_ERROR;
866                 goto done;
867         }
868
869         tret = ltdb_delete_internal(module, req->op.rename.olddn);
870         if (tret != LDB_SUCCESS) {
871                 ltdb_delete_internal(module, req->op.rename.newdn);
872                 ret = LDB_ERR_OPERATIONS_ERROR;
873                 goto done;
874         }
875
876         if (ltdb_ac->callback) {
877                 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
878         }
879 done:
880         req->handle->state = LDB_ASYNC_DONE;
881         return ret;
882 }
883
884 static int ltdb_start_trans(struct ldb_module *module)
885 {
886         struct ltdb_private *ltdb = module->private_data;
887
888         if (tdb_transaction_start(ltdb->tdb) != 0) {
889                 return ltdb_err_map(tdb_error(ltdb->tdb));
890         }
891
892         return LDB_SUCCESS;
893 }
894
895 static int ltdb_end_trans(struct ldb_module *module)
896 {
897         struct ltdb_private *ltdb = module->private_data;
898
899         if (tdb_transaction_commit(ltdb->tdb) != 0) {
900                 return ltdb_err_map(tdb_error(ltdb->tdb));
901         }
902
903         return LDB_SUCCESS;
904 }
905
906 static int ltdb_del_trans(struct ldb_module *module)
907 {
908         struct ltdb_private *ltdb = module->private_data;
909
910         if (tdb_transaction_cancel(ltdb->tdb) != 0) {
911                 return ltdb_err_map(tdb_error(ltdb->tdb));
912         }
913
914         return LDB_SUCCESS;
915 }
916
917 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
918 {
919         return handle->status;
920 }
921
922 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
923 {
924         /* check for oustanding critical controls and return an error if found */
925         if (req->controls != NULL) {
926                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
927                 if (check_critical_controls(req->controls)) {
928                         return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
929                 }
930         }
931         
932         /* search, add, modify, delete, rename are handled by their own, no other op supported */
933         return LDB_ERR_OPERATIONS_ERROR;
934 }
935
936 /*
937   return sequenceNumber from @BASEINFO
938 */
939 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
940 {
941         TALLOC_CTX *tmp_ctx = talloc_new(req);
942         struct ldb_message *msg = NULL;
943         struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, LTDB_BASEINFO);
944         int tret;
945
946         if (tmp_ctx == NULL) {
947                 talloc_free(tmp_ctx);
948                 return LDB_ERR_OPERATIONS_ERROR;
949         }
950
951         msg = talloc(tmp_ctx, struct ldb_message);
952         if (msg == NULL) {
953                 talloc_free(tmp_ctx);
954                 return LDB_ERR_OPERATIONS_ERROR;
955         }
956
957         tret = ltdb_search_dn1(module, dn, msg);
958         if (tret != 1) {
959                 talloc_free(tmp_ctx);
960                 req->op.seq_num.seq_num = 0;
961                 /* zero is as good as anything when we don't know */
962                 return LDB_SUCCESS;
963         }
964
965         req->op.seq_num.seq_num = ldb_msg_find_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
966         talloc_free(tmp_ctx);
967         return LDB_SUCCESS;
968 }
969
970 static const struct ldb_module_ops ltdb_ops = {
971         .name              = "tdb",
972         .search            = ltdb_search,
973         .add               = ltdb_add,
974         .modify            = ltdb_modify,
975         .del               = ltdb_delete,
976         .rename            = ltdb_rename,
977         .request           = ltdb_request,
978         .start_transaction = ltdb_start_trans,
979         .end_transaction   = ltdb_end_trans,
980         .del_transaction   = ltdb_del_trans,
981         .wait              = ltdb_wait,
982         .sequence_number   = ltdb_sequence_number
983 };
984
985 /*
986   connect to the database
987 */
988 static int ltdb_connect(struct ldb_context *ldb, const char *url, 
989                         unsigned int flags, const char *options[],
990                         struct ldb_module **module)
991 {
992         const char *path;
993         int tdb_flags, open_flags;
994         struct ltdb_private *ltdb;
995
996         /* parse the url */
997         if (strchr(url, ':')) {
998                 if (strncmp(url, "tdb://", 6) != 0) {
999                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1000                         return -1;
1001                 }
1002                 path = url+6;
1003         } else {
1004                 path = url;
1005         }
1006
1007         tdb_flags = TDB_DEFAULT;
1008
1009         /* check for the 'nosync' option */
1010         if (flags & LDB_FLG_NOSYNC) {
1011                 tdb_flags |= TDB_NOSYNC;
1012         }
1013
1014         if (flags & LDB_FLG_RDONLY) {
1015                 open_flags = O_RDONLY;
1016         } else {
1017                 open_flags = O_CREAT | O_RDWR;
1018         }
1019
1020         ltdb = talloc_zero(ldb, struct ltdb_private);
1021         if (!ltdb) {
1022                 ldb_oom(ldb);
1023                 return -1;
1024         }
1025
1026         /* note that we use quite a large default hash size */
1027         ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, 
1028                                    tdb_flags, open_flags, 0666, ldb);
1029         if (!ltdb->tdb) {
1030                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1031                 talloc_free(ltdb);
1032                 return -1;
1033         }
1034
1035         ltdb->sequence_number = 0;
1036
1037         *module = talloc(ldb, struct ldb_module);
1038         if (!module) {
1039                 ldb_oom(ldb);
1040                 talloc_free(ltdb);
1041                 return -1;
1042         }
1043         (*module)->ldb = ldb;
1044         (*module)->prev = (*module)->next = NULL;
1045         (*module)->private_data = ltdb;
1046         (*module)->ops = &ltdb_ops;
1047
1048         return 0;
1049 }
1050
1051 int ldb_tdb_init(void)
1052 {
1053         return ldb_register_backend("tdb", ltdb_connect);
1054 }