r13700: added highestCommittedUSN, uSNChanged and uSNCreated support, using
[kai/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/includes.h"
40
41 #include "ldb/ldb_tdb/ldb_tdb.h"
42
43
44 /*
45   map a tdb error code to a ldb error code
46 */
47 static int ltdb_err_map(enum TDB_ERROR tdb_code)
48 {
49         switch (tdb_code) {
50         case TDB_SUCCESS:
51                 return LDB_SUCCESS;
52         case TDB_ERR_CORRUPT:
53         case TDB_ERR_OOM:
54         case TDB_ERR_EINVAL:
55                 return LDB_ERR_OPERATIONS_ERROR;
56         case TDB_ERR_IO:
57                 return LDB_ERR_PROTOCOL_ERROR;
58         case TDB_ERR_LOCK:
59         case TDB_ERR_NOLOCK:
60                 return LDB_ERR_BUSY;
61         case TDB_ERR_LOCK_TIMEOUT:
62                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
63         case TDB_ERR_EXISTS:
64                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
65         case TDB_ERR_NOEXIST:
66                 return LDB_ERR_NO_SUCH_OBJECT;
67         case TDB_ERR_RDONLY:
68                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
69         }
70         return LDB_ERR_OTHER;
71 }
72
73
74 /*
75   form a TDB_DATA for a record key
76   caller frees
77
78   note that the key for a record can depend on whether the 
79   dn refers to a case sensitive index record or not
80 */
81 struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn)
82 {
83         struct ldb_context *ldb = module->ldb;
84         TDB_DATA key;
85         char *key_str = NULL;
86         char *dn_folded = NULL;
87
88         /*
89           most DNs are case insensitive. The exception is index DNs for
90           case sensitive attributes
91
92           there are 3 cases dealt with in this code:
93
94           1) if the dn doesn't start with @ then uppercase the attribute
95              names and the attributes values of case insensitive attributes
96           2) if the dn starts with @ then leave it alone - the indexing code handles
97              the rest
98         */
99
100         dn_folded = ldb_dn_linearize_casefold(ldb, dn);
101         if (!dn_folded) {
102                 goto failed;
103         }
104
105         key_str = talloc_asprintf(ldb, "DN=%s", dn_folded);
106
107         talloc_free(dn_folded);
108
109         if (!key_str) {
110                 goto failed;
111         }
112
113         key.dptr = (uint8_t *)key_str;
114         key.dsize = strlen(key_str) + 1;
115
116         return key;
117
118 failed:
119         errno = ENOMEM;
120         key.dptr = NULL;
121         key.dsize = 0;
122         return key;
123 }
124
125 /*
126   check special dn's have valid attributes
127   currently only @ATTRIBUTES is checked
128 */
129 int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
130 {
131         int i, j;
132  
133         if (! ldb_dn_is_special(msg->dn) ||
134             ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
135                 return 0;
136         }
137
138         /* we have @ATTRIBUTES, let's check attributes are fine */
139         /* should we check that we deny multivalued attributes ? */
140         for (i = 0; i < msg->num_elements; i++) {
141                 for (j = 0; j < msg->elements[i].num_values; j++) {
142                         if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
143                                 char *err_string = talloc_strdup(module, "Invalid attribute value in an @ATTRIBUTES entry");
144                                 if (err_string) {
145                                         ldb_set_errstring(module->ldb, err_string);
146                                 }
147                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
148                         }
149                 }
150         }
151
152         return 0;
153 }
154
155
156 /*
157   we've made a modification to a dn - possibly reindex and 
158   update sequence number
159 */
160 static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn)
161 {
162         int ret = 0;
163
164         if (ldb_dn_is_special(dn) &&
165             (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
166              ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
167                 ret = ltdb_reindex(module);
168         }
169
170         if (ret == 0 &&
171             !(ldb_dn_is_special(dn) &&
172               ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
173                 ret = ltdb_increase_sequence_number(module);
174         }
175
176         return ret;
177 }
178
179 /*
180   store a record into the db
181 */
182 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
183 {
184         struct ltdb_private *ltdb = module->private_data;
185         TDB_DATA tdb_key, tdb_data;
186         int ret;
187
188         tdb_key = ltdb_key(module, msg->dn);
189         if (!tdb_key.dptr) {
190                 return LDB_ERR_OTHER;
191         }
192
193         ret = ltdb_pack_data(module, msg, &tdb_data);
194         if (ret == -1) {
195                 talloc_free(tdb_key.dptr);
196                 return LDB_ERR_OTHER;
197         }
198
199         ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
200         if (ret == -1) {
201                 ret = ltdb_err_map(tdb_error(ltdb->tdb));
202                 goto done;
203         }
204         
205         ret = ltdb_index_add(module, msg);
206         if (ret == -1) {
207                 tdb_delete(ltdb->tdb, tdb_key);
208         }
209
210 done:
211         talloc_free(tdb_key.dptr);
212         talloc_free(tdb_data.dptr);
213
214         return ret;
215 }
216
217
218 /*
219   add a record to the database
220 */
221 static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg)
222 {
223         int ret;
224
225         ret = ltdb_check_special_dn(module, msg);
226         if (ret != LDB_SUCCESS) {
227                 return ret;
228         }
229         
230         if (ltdb_cache_load(module) != 0) {
231                 return LDB_ERR_OTHER;
232         }
233
234         ret = ltdb_store(module, msg, TDB_INSERT);
235
236         if (ret == LDB_SUCCESS) {
237                 ltdb_modified(module, msg->dn);
238         }
239
240         return ret;
241 }
242
243
244 /*
245   delete a record from the database, not updating indexes (used for deleting
246   index records)
247 */
248 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
249 {
250         struct ltdb_private *ltdb = module->private_data;
251         TDB_DATA tdb_key;
252         int ret;
253
254         tdb_key = ltdb_key(module, dn);
255         if (!tdb_key.dptr) {
256                 return LDB_ERR_OTHER;
257         }
258
259         ret = tdb_delete(ltdb->tdb, tdb_key);
260         talloc_free(tdb_key.dptr);
261
262         if (ret != 0) {
263                 ret = ltdb_err_map(tdb_error(ltdb->tdb));
264         }
265
266         return ret;
267 }
268
269 /*
270   delete a record from the database
271 */
272 static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn)
273 {
274         struct ldb_message *msg = NULL;
275         int ret = LDB_ERR_OTHER;
276
277         if (ltdb_cache_load(module) != 0) {
278                 goto failed;
279         }
280
281         msg = talloc(module, struct ldb_message);
282         if (msg == NULL) {
283                 goto failed;
284         }
285
286         /* in case any attribute of the message was indexed, we need
287            to fetch the old record */
288         ret = ltdb_search_dn1(module, dn, msg);
289         if (ret != 1) {
290                 /* not finding the old record is an error */
291                 ret = LDB_ERR_NO_SUCH_OBJECT;
292                 goto failed;
293         }
294
295         ret = ltdb_delete_noindex(module, dn);
296         if (ret != LDB_SUCCESS) {
297                 goto failed;
298         }
299
300         /* remove any indexed attributes */
301         ret = ltdb_index_del(module, msg);
302         if (ret == LDB_SUCCESS) {
303                 ltdb_modified(module, dn);
304         } else
305                 ret = LDB_ERR_OTHER;
306
307         talloc_free(msg);
308         return ret;
309
310 failed:
311         talloc_free(msg);
312         return ret;
313 }
314
315
316 /*
317   find an element by attribute name. At the moment this does a linear search, it should
318   be re-coded to use a binary search once all places that modify records guarantee
319   sorted order
320
321   return the index of the first matching element if found, otherwise -1
322 */
323 static int find_element(const struct ldb_message *msg, const char *name)
324 {
325         unsigned int i;
326         for (i=0;i<msg->num_elements;i++) {
327                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
328                         return i;
329                 }
330         }
331         return -1;
332 }
333
334
335 /*
336   add an element to an existing record. Assumes a elements array that we
337   can call re-alloc on, and assumed that we can re-use the data pointers from the 
338   passed in additional values. Use with care!
339
340   returns 0 on success, -1 on failure (and sets errno)
341 */
342 static int msg_add_element(struct ldb_context *ldb,
343                            struct ldb_message *msg, struct ldb_message_element *el)
344 {
345         struct ldb_message_element *e2;
346         unsigned int i;
347
348         e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
349                               msg->num_elements+1);
350         if (!e2) {
351                 errno = ENOMEM;
352                 return -1;
353         }
354
355         msg->elements = e2;
356
357         e2 = &msg->elements[msg->num_elements];
358
359         e2->name = el->name;
360         e2->flags = el->flags;
361         e2->values = NULL;
362         if (el->num_values != 0) {
363                 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
364                 if (!e2->values) {
365                         errno = ENOMEM;
366                         return -1;
367                 }
368         }
369         for (i=0;i<el->num_values;i++) {
370                 e2->values[i] = el->values[i];
371         }
372         e2->num_values = el->num_values;
373
374         msg->num_elements++;
375
376         return 0;
377 }
378
379 /*
380   delete all elements having a specified attribute name
381 */
382 static int msg_delete_attribute(struct ldb_module *module,
383                                 struct ldb_context *ldb,
384                                 struct ldb_message *msg, const char *name)
385 {
386         char *dn;
387         unsigned int i, j;
388
389         dn = ldb_dn_linearize(ldb, msg->dn);
390         if (dn == NULL) {
391                 return -1;
392         }
393
394         for (i=0;i<msg->num_elements;i++) {
395                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
396                         for (j=0;j<msg->elements[i].num_values;j++) {
397                                 ltdb_index_del_value(module, dn, &msg->elements[i], j);
398                         }
399                         talloc_free(msg->elements[i].values);
400                         if (msg->num_elements > (i+1)) {
401                                 memmove(&msg->elements[i], 
402                                         &msg->elements[i+1], 
403                                         sizeof(struct ldb_message_element)*
404                                         (msg->num_elements - (i+1)));
405                         }
406                         msg->num_elements--;
407                         i--;
408                         msg->elements = talloc_realloc(msg, msg->elements, 
409                                                          struct ldb_message_element, 
410                                                          msg->num_elements);
411                 }
412         }
413
414         talloc_free(dn);
415         return 0;
416 }
417
418 /*
419   delete all elements matching an attribute name/value 
420
421   return 0 on success, -1 on failure
422 */
423 static int msg_delete_element(struct ldb_module *module,
424                               struct ldb_message *msg, 
425                               const char *name,
426                               const struct ldb_val *val)
427 {
428         struct ldb_context *ldb = module->ldb;
429         unsigned int i;
430         int found;
431         struct ldb_message_element *el;
432         const struct ldb_attrib_handler *h;
433
434         found = find_element(msg, name);
435         if (found == -1) {
436                 return -1;
437         }
438
439         el = &msg->elements[found];
440
441         h = ldb_attrib_handler(ldb, el->name);
442
443         for (i=0;i<el->num_values;i++) {
444                 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
445                         if (i<el->num_values-1) {
446                                 memmove(&el->values[i], &el->values[i+1],
447                                         sizeof(el->values[i])*(el->num_values-(i+1)));
448                         }
449                         el->num_values--;
450                         if (el->num_values == 0) {
451                                 return msg_delete_attribute(module, ldb, msg, name);
452                         }
453                         return 0;
454                 }
455         }
456
457         return -1;
458 }
459
460
461 /*
462   modify a record - internal interface
463
464   yuck - this is O(n^2). Luckily n is usually small so we probably
465   get away with it, but if we ever have really large attribute lists 
466   then we'll need to look at this again
467 */
468 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
469 {
470         struct ldb_context *ldb = module->ldb;
471         struct ltdb_private *ltdb = module->private_data;
472         TDB_DATA tdb_key, tdb_data;
473         struct ldb_message *msg2;
474         unsigned i, j;
475         int ret;
476
477         tdb_key = ltdb_key(module, msg->dn);
478         if (!tdb_key.dptr) {
479                 return LDB_ERR_OTHER;
480         }
481
482         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
483         if (!tdb_data.dptr) {
484                 talloc_free(tdb_key.dptr);
485                 return ltdb_err_map(tdb_error(ltdb->tdb));
486         }
487
488         msg2 = talloc(tdb_key.dptr, struct ldb_message);
489         if (msg2 == NULL) {
490                 talloc_free(tdb_key.dptr);
491                 return LDB_ERR_OTHER;
492         }
493
494         ret = ltdb_unpack_data(module, &tdb_data, msg2);
495         if (ret == -1) {
496                 talloc_free(tdb_key.dptr);
497                 free(tdb_data.dptr);
498                 return LDB_ERR_OTHER;
499         }
500
501         if (!msg2->dn) {
502                 msg2->dn = msg->dn;
503         }
504
505         for (i=0;i<msg->num_elements;i++) {
506                 struct ldb_message_element *el = &msg->elements[i];
507                 struct ldb_message_element *el2;
508                 struct ldb_val *vals;
509                 char *err_string;
510                 char *dn;
511
512                 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
513
514                 case LDB_FLAG_MOD_ADD:
515                         /* add this element to the message. fail if it
516                            already exists */
517                         ret = find_element(msg2, el->name);
518
519                         if (ret == -1) {
520                                 if (msg_add_element(ldb, msg2, el) != 0) {
521                                         ret = LDB_ERR_OTHER;
522                                         goto failed;
523                                 }
524                                 continue;
525                         }
526
527                         el2 = &msg2->elements[ret];
528
529                         /* An attribute with this name already exists, add all
530                          * values if they don't already exist. */
531
532                         for (j=0;j<el->num_values;j++) {
533                                 if (ldb_msg_find_val(el2, &el->values[j])) {
534                                         err_string = talloc_strdup(module, "Type or value exists");
535                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
536                                         ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
537                                         goto failed;
538                                 }
539                         }
540
541                         vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
542                                                 el2->num_values + el->num_values);
543
544                         if (vals == NULL)
545                                 goto failed;
546
547                         for (j=0;j<el->num_values;j++) {
548                                 vals[el2->num_values + j] =
549                                         ldb_val_dup(vals, &el->values[j]);
550                         }
551
552                         el2->values = vals;
553                         el2->num_values += el->num_values;
554
555                         break;
556
557                 case LDB_FLAG_MOD_REPLACE:
558                         /* replace all elements of this attribute name with the elements
559                            listed. The attribute not existing is not an error */
560                         msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
561
562                         /* add the replacement element, if not empty */
563                         if (msg->elements[i].num_values != 0 &&
564                             msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
565                                 goto failed;
566                         }
567                         break;
568
569                 case LDB_FLAG_MOD_DELETE:
570
571                         dn = ldb_dn_linearize(msg2, msg->dn);
572                         if (dn == NULL) goto failed;
573
574                         /* we could be being asked to delete all
575                            values or just some values */
576                         if (msg->elements[i].num_values == 0) {
577                                 if (msg_delete_attribute(module, ldb, msg2, 
578                                                          msg->elements[i].name) != 0) {
579                                         err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
580                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
581                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
582                                         goto failed;
583                                 }
584                                 break;
585                         }
586                         for (j=0;j<msg->elements[i].num_values;j++) {
587                                 if (msg_delete_element(module,
588                                                        msg2, 
589                                                        msg->elements[i].name,
590                                                        &msg->elements[i].values[j]) != 0) {
591                                         err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
592                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
593                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
594                                         goto failed;
595                                 }
596                                 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
597                                         goto failed;
598                                 }
599                         }
600                         break;
601                 default:
602                         err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x", 
603                                                      msg->elements[i].name, 
604                                                      msg->elements[i].flags & LDB_FLAG_MOD_MASK);
605                         if (err_string) ldb_set_errstring(module->ldb, err_string);
606                         ret = LDB_ERR_PROTOCOL_ERROR;
607                         goto failed;
608                 }
609         }
610
611         /* we've made all the mods - save the modified record back into the database */
612         ret = ltdb_store(module, msg2, TDB_MODIFY);
613
614         talloc_free(tdb_key.dptr);
615         free(tdb_data.dptr);
616         return ret;
617
618 failed:
619         talloc_free(tdb_key.dptr);
620         free(tdb_data.dptr);
621         return ret;
622 }
623
624 /*
625   modify a record
626 */
627 static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg)
628 {
629         int ret;
630
631         ret = ltdb_check_special_dn(module, msg);
632         if (ret != 0) {
633                 return ret;
634         }
635         
636         if (ltdb_cache_load(module) != 0) {
637                 return -1;
638         }
639
640         ret = ltdb_modify_internal(module, msg);
641
642         if (ret == LDB_SUCCESS) {
643                 ltdb_modified(module, msg->dn);
644         }
645
646         return ret;
647 }
648
649 /*
650   rename a record
651 */
652 static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
653 {
654         struct ldb_message *msg;
655         char *error_str;
656         int ret = LDB_ERR_OTHER;
657
658         if (ltdb_cache_load(module) != 0) {
659                 return ret;
660         }
661
662         msg = talloc(module, struct ldb_message);
663         if (msg == NULL) {
664                 goto failed;
665         }
666
667         /* in case any attribute of the message was indexed, we need
668            to fetch the old record */
669         ret = ltdb_search_dn1(module, olddn, msg);
670         if (ret != 1) {
671                 /* not finding the old record is an error */
672                 ret = LDB_ERR_NO_SUCH_OBJECT;
673                 goto failed;
674         }
675
676         msg->dn = ldb_dn_copy(msg, newdn);
677         if (!msg->dn) {
678                 ret = LDB_ERR_OTHER;
679                 goto failed;
680         }
681
682         ret = ltdb_add(module, msg);
683         if (ret != LDB_SUCCESS) {
684                 goto failed;
685         }
686
687         ret = ltdb_delete(module, olddn);
688         error_str = talloc_strdup(module, ldb_errstring(module->ldb));
689         if (ret != LDB_SUCCESS) {
690                 ltdb_delete(module, newdn);
691         }
692
693         ldb_set_errstring(module->ldb, error_str);
694
695         talloc_free(msg);
696
697         return ret;
698
699 failed:
700         talloc_free(msg);
701         return ret;
702 }
703
704 static int ltdb_start_trans(struct ldb_module *module)
705 {
706         struct ltdb_private *ltdb = module->private_data;
707
708         if (tdb_transaction_start(ltdb->tdb) != 0) {
709                 return ltdb_err_map(tdb_error(ltdb->tdb));
710         }
711
712         return LDB_SUCCESS;
713 }
714
715 static int ltdb_end_trans(struct ldb_module *module)
716 {
717         struct ltdb_private *ltdb = module->private_data;
718
719         if (tdb_transaction_commit(ltdb->tdb) != 0) {
720                 return ltdb_err_map(tdb_error(ltdb->tdb));
721         }
722
723         return LDB_SUCCESS;
724 }
725
726 static int ltdb_del_trans(struct ldb_module *module)
727 {
728         struct ltdb_private *ltdb = module->private_data;
729
730         if (tdb_transaction_cancel(ltdb->tdb) != 0) {
731                 return ltdb_err_map(tdb_error(ltdb->tdb));
732         }
733
734         return LDB_SUCCESS;
735 }
736
737 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
738 {
739         /* check for oustanding critical controls and return an error if found */
740
741         if (check_critical_controls(req->controls)) {
742                 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
743         }
744         
745         switch (req->operation) {
746
747         case LDB_REQ_SEARCH:
748                 return ltdb_search_bytree(module,
749                                           req->op.search.base,
750                                           req->op.search.scope, 
751                                           req->op.search.tree, 
752                                           req->op.search.attrs, 
753                                           &req->op.search.res);
754
755         case LDB_REQ_ADD:
756                 return ltdb_add(module, req->op.add.message);
757
758         case LDB_REQ_MODIFY:
759                 return ltdb_modify(module, req->op.mod.message);
760
761         case LDB_REQ_DELETE:
762                 return ltdb_delete(module, req->op.del.dn);
763
764         case LDB_REQ_RENAME:
765                 return ltdb_rename(module,
766                                         req->op.rename.olddn,
767                                         req->op.rename.newdn);
768
769         default:
770                 return LDB_ERR_OPERATIONS_ERROR;
771
772         }
773 }
774
775 /*
776   return sequenceNumber from @BASEINFO
777 */
778 static uint64_t ltdb_sequence_number(struct ldb_context *ldb)
779 {
780         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
781         const char *attrs[] = { "sequenceNumber", NULL };
782         struct ldb_result *res = NULL;
783         struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO");
784         int ret;
785         uint64_t seq_num;
786
787         ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
788         talloc_steal(tmp_ctx, res);
789         if (ret != LDB_SUCCESS || res->count != 1) {
790                 talloc_free(tmp_ctx);
791                 /* zero is as good as anything when we don't know */
792                 return 0;
793         }
794
795         seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0);
796         talloc_free(tmp_ctx);
797         return seq_num; 
798 }
799
800 static int ltdb_init_2(struct ldb_module *module)
801 {
802         return LDB_SUCCESS;
803 }
804
805 static const struct ldb_module_ops ltdb_ops = {
806         .name              = "tdb",
807         .request           = ltdb_request,
808         .start_transaction = ltdb_start_trans,
809         .end_transaction   = ltdb_end_trans,
810         .del_transaction   = ltdb_del_trans,
811         .second_stage_init = ltdb_init_2
812 };
813
814
815 /*
816   connect to the database
817 */
818 int ltdb_connect(struct ldb_context *ldb, const char *url, 
819                  unsigned int flags, const char *options[])
820 {
821         const char *path;
822         int tdb_flags, open_flags;
823         struct ltdb_private *ltdb;
824
825         /* parse the url */
826         if (strchr(url, ':')) {
827                 if (strncmp(url, "tdb://", 6) != 0) {
828                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
829                         return -1;
830                 }
831                 path = url+6;
832         } else {
833                 path = url;
834         }
835
836         tdb_flags = TDB_DEFAULT;
837
838         /* check for the 'nosync' option */
839         if (flags & LDB_FLG_NOSYNC) {
840                 tdb_flags |= TDB_NOSYNC;
841         }
842
843         if (flags & LDB_FLG_RDONLY) {
844                 open_flags = O_RDONLY;
845         } else {
846                 open_flags = O_CREAT | O_RDWR;
847         }
848
849         ltdb = talloc_zero(ldb, struct ltdb_private);
850         if (!ltdb) {
851                 ldb_oom(ldb);
852                 return -1;
853         }
854
855         /* note that we use quite a large default hash size */
856         ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, tdb_flags, open_flags, 0666);
857         if (!ltdb->tdb) {
858                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
859                 talloc_free(ltdb);
860                 return -1;
861         }
862
863         ltdb->sequence_number = 0;
864
865         ldb->modules = talloc(ldb, struct ldb_module);
866         if (!ldb->modules) {
867                 ldb_oom(ldb);
868                 talloc_free(ltdb);
869                 return -1;
870         }
871         ldb->modules->ldb = ldb;
872         ldb->modules->prev = ldb->modules->next = NULL;
873         ldb->modules->private_data = ltdb;
874         ldb->modules->ops = &ltdb_ops;
875         ldb->sequence_number = ltdb_sequence_number;
876
877         return 0;
878 }