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