4 Copyright (C) Andrew Tridgell 2004
5 Copyright (C) Stefan Metzmacher 2004
6 Copyright (C) Simo Sorce 2006
9 ** NOTE! The following LGPL license applies to the ldb
10 ** library. This does NOT imply that all of Samba is released
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.
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.
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
31 * Component: ldb tdb backend
33 * Description: core functions for tdb backend
35 * Author: Andrew Tridgell
36 * Author: Stefan Metzmacher
40 * - description: make the module use asyncronous calls
46 #include "ldb/include/includes.h"
48 #include "ldb/ldb_tdb/ldb_tdb.h"
52 map a tdb error code to a ldb error code
54 static int ltdb_err_map(enum TDB_ERROR tdb_code)
62 return LDB_ERR_OPERATIONS_ERROR;
64 return LDB_ERR_PROTOCOL_ERROR;
68 case TDB_ERR_LOCK_TIMEOUT:
69 return LDB_ERR_TIME_LIMIT_EXCEEDED;
71 return LDB_ERR_ENTRY_ALREADY_EXISTS;
73 return LDB_ERR_NO_SUCH_OBJECT;
75 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
81 struct ldb_async_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,
83 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
86 struct ltdb_async_context *ac;
87 struct ldb_async_handle *h;
89 h = talloc_zero(ltdb, struct ldb_async_handle);
91 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
95 ac = talloc_zero(h, struct ltdb_async_context);
97 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
102 h->private_data = (void *)ac;
105 ac->context = context;
106 ac->callback = callback;
107 ac->timeout = timeout;
113 form a TDB_DATA for a record key
116 note that the key for a record can depend on whether the
117 dn refers to a case sensitive index record or not
119 struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn)
121 struct ldb_context *ldb = module->ldb;
123 char *key_str = NULL;
124 char *dn_folded = NULL;
127 most DNs are case insensitive. The exception is index DNs for
128 case sensitive attributes
130 there are 3 cases dealt with in this code:
132 1) if the dn doesn't start with @ then uppercase the attribute
133 names and the attributes values of case insensitive attributes
134 2) if the dn starts with @ then leave it alone - the indexing code handles
138 dn_folded = ldb_dn_linearize_casefold(ldb, dn);
143 key_str = talloc_asprintf(ldb, "DN=%s", dn_folded);
145 talloc_free(dn_folded);
151 key.dptr = (uint8_t *)key_str;
152 key.dsize = strlen(key_str) + 1;
164 check special dn's have valid attributes
165 currently only @ATTRIBUTES is checked
167 int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
171 if (! ldb_dn_is_special(msg->dn) ||
172 ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
176 /* we have @ATTRIBUTES, let's check attributes are fine */
177 /* should we check that we deny multivalued attributes ? */
178 for (i = 0; i < msg->num_elements; i++) {
179 for (j = 0; j < msg->elements[i].num_values; j++) {
180 if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
181 char *err_string = talloc_strdup(module, "Invalid attribute value in an @ATTRIBUTES entry");
183 ldb_set_errstring(module->ldb, err_string);
185 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
195 we've made a modification to a dn - possibly reindex and
196 update sequence number
198 static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn)
202 if (ldb_dn_is_special(dn) &&
203 (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
204 ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
205 ret = ltdb_reindex(module);
209 !(ldb_dn_is_special(dn) &&
210 ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
211 ret = ltdb_increase_sequence_number(module);
218 store a record into the db
220 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
222 struct ltdb_private *ltdb = module->private_data;
223 TDB_DATA tdb_key, tdb_data;
226 tdb_key = ltdb_key(module, msg->dn);
228 return LDB_ERR_OTHER;
231 ret = ltdb_pack_data(module, msg, &tdb_data);
233 talloc_free(tdb_key.dptr);
234 return LDB_ERR_OTHER;
237 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
239 ret = ltdb_err_map(tdb_error(ltdb->tdb));
243 ret = ltdb_index_add(module, msg);
245 tdb_delete(ltdb->tdb, tdb_key);
249 talloc_free(tdb_key.dptr);
250 talloc_free(tdb_data.dptr);
257 add a record to the database
259 static int ltdb_add_async(struct ldb_module *module, const struct ldb_message *msg,
261 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
263 struct ldb_async_handle **handle)
265 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
266 struct ltdb_async_context *ltdb_ac;
267 int ret = LDB_ERR_OPERATIONS_ERROR;
269 *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
270 if (*handle == NULL) {
273 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
274 (*handle)->state = LDB_ASYNC_DONE;
275 (*handle)->status = LDB_SUCCESS;
277 ret = ltdb_check_special_dn(module, msg);
278 if (ret != LDB_SUCCESS) {
279 talloc_free(*handle);
283 if (ltdb_cache_load(module) != 0) {
284 talloc_free(*handle);
285 return LDB_ERR_OTHER;
288 ret = ltdb_store(module, msg, TDB_INSERT);
290 if (ret != LDB_SUCCESS) {
291 (*handle)->status = ret;
295 ltdb_modified(module, msg->dn);
297 if (ltdb_ac->callback)
298 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
303 static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg)
305 struct ldb_async_handle *handle;
308 ret = ltdb_add_async(module, msg, NULL, NULL, 0, &handle);
310 if (ret != LDB_SUCCESS)
313 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
320 delete a record from the database, not updating indexes (used for deleting
323 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
325 struct ltdb_private *ltdb = module->private_data;
329 tdb_key = ltdb_key(module, dn);
331 return LDB_ERR_OTHER;
334 ret = tdb_delete(ltdb->tdb, tdb_key);
335 talloc_free(tdb_key.dptr);
338 ret = ltdb_err_map(tdb_error(ltdb->tdb));
345 delete a record from the database
347 static int ltdb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
349 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
351 struct ldb_async_handle **handle)
353 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
354 struct ltdb_async_context *ltdb_ac;
355 struct ldb_message *msg;
356 int ret = LDB_ERR_OPERATIONS_ERROR;
360 if (ltdb_cache_load(module) != 0) {
364 *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
365 if (*handle == NULL) {
368 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
369 (*handle)->state = LDB_ASYNC_DONE;
370 (*handle)->status = LDB_SUCCESS;
372 msg = talloc(ltdb_ac, struct ldb_message);
377 /* in case any attribute of the message was indexed, we need
378 to fetch the old record */
379 ret = ltdb_search_dn1(module, dn, msg);
381 /* not finding the old record is an error */
382 (*handle)->status = LDB_ERR_NO_SUCH_OBJECT;
386 ret = ltdb_delete_noindex(module, dn);
387 if (ret != LDB_SUCCESS) {
391 /* remove any indexed attributes */
392 ret = ltdb_index_del(module, msg);
396 ltdb_modified(module, dn);
398 if (ltdb_ac->callback)
399 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
404 talloc_free(*handle);
408 static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn)
410 struct ldb_async_handle *handle;
413 ret = ltdb_delete_async(module, dn,
414 NULL, NULL, 0, &handle);
416 if (ret != LDB_SUCCESS)
419 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
427 find an element by attribute name. At the moment this does a linear search, it should
428 be re-coded to use a binary search once all places that modify records guarantee
431 return the index of the first matching element if found, otherwise -1
433 static int find_element(const struct ldb_message *msg, const char *name)
436 for (i=0;i<msg->num_elements;i++) {
437 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
446 add an element to an existing record. Assumes a elements array that we
447 can call re-alloc on, and assumed that we can re-use the data pointers from the
448 passed in additional values. Use with care!
450 returns 0 on success, -1 on failure (and sets errno)
452 static int msg_add_element(struct ldb_context *ldb,
453 struct ldb_message *msg, struct ldb_message_element *el)
455 struct ldb_message_element *e2;
458 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
459 msg->num_elements+1);
467 e2 = &msg->elements[msg->num_elements];
470 e2->flags = el->flags;
472 if (el->num_values != 0) {
473 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
479 for (i=0;i<el->num_values;i++) {
480 e2->values[i] = el->values[i];
482 e2->num_values = el->num_values;
490 delete all elements having a specified attribute name
492 static int msg_delete_attribute(struct ldb_module *module,
493 struct ldb_context *ldb,
494 struct ldb_message *msg, const char *name)
499 dn = ldb_dn_linearize(ldb, msg->dn);
504 for (i=0;i<msg->num_elements;i++) {
505 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
506 for (j=0;j<msg->elements[i].num_values;j++) {
507 ltdb_index_del_value(module, dn, &msg->elements[i], j);
509 talloc_free(msg->elements[i].values);
510 if (msg->num_elements > (i+1)) {
511 memmove(&msg->elements[i],
513 sizeof(struct ldb_message_element)*
514 (msg->num_elements - (i+1)));
518 msg->elements = talloc_realloc(msg, msg->elements,
519 struct ldb_message_element,
529 delete all elements matching an attribute name/value
531 return 0 on success, -1 on failure
533 static int msg_delete_element(struct ldb_module *module,
534 struct ldb_message *msg,
536 const struct ldb_val *val)
538 struct ldb_context *ldb = module->ldb;
541 struct ldb_message_element *el;
542 const struct ldb_attrib_handler *h;
544 found = find_element(msg, name);
549 el = &msg->elements[found];
551 h = ldb_attrib_handler(ldb, el->name);
553 for (i=0;i<el->num_values;i++) {
554 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
555 if (i<el->num_values-1) {
556 memmove(&el->values[i], &el->values[i+1],
557 sizeof(el->values[i])*(el->num_values-(i+1)));
560 if (el->num_values == 0) {
561 return msg_delete_attribute(module, ldb, msg, name);
572 modify a record - internal interface
574 yuck - this is O(n^2). Luckily n is usually small so we probably
575 get away with it, but if we ever have really large attribute lists
576 then we'll need to look at this again
578 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
580 struct ldb_context *ldb = module->ldb;
581 struct ltdb_private *ltdb = module->private_data;
582 TDB_DATA tdb_key, tdb_data;
583 struct ldb_message *msg2;
587 tdb_key = ltdb_key(module, msg->dn);
589 return LDB_ERR_OTHER;
592 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
593 if (!tdb_data.dptr) {
594 talloc_free(tdb_key.dptr);
595 return ltdb_err_map(tdb_error(ltdb->tdb));
598 msg2 = talloc(tdb_key.dptr, struct ldb_message);
600 talloc_free(tdb_key.dptr);
601 return LDB_ERR_OTHER;
604 ret = ltdb_unpack_data(module, &tdb_data, msg2);
606 talloc_free(tdb_key.dptr);
608 return LDB_ERR_OTHER;
615 for (i=0;i<msg->num_elements;i++) {
616 struct ldb_message_element *el = &msg->elements[i];
617 struct ldb_message_element *el2;
618 struct ldb_val *vals;
622 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
624 case LDB_FLAG_MOD_ADD:
625 /* add this element to the message. fail if it
627 ret = find_element(msg2, el->name);
630 if (msg_add_element(ldb, msg2, el) != 0) {
637 el2 = &msg2->elements[ret];
639 /* An attribute with this name already exists, add all
640 * values if they don't already exist. */
642 for (j=0;j<el->num_values;j++) {
643 if (ldb_msg_find_val(el2, &el->values[j])) {
644 err_string = talloc_strdup(module, "Type or value exists");
645 if (err_string) ldb_set_errstring(module->ldb, err_string);
646 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
651 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
652 el2->num_values + el->num_values);
657 for (j=0;j<el->num_values;j++) {
658 vals[el2->num_values + j] =
659 ldb_val_dup(vals, &el->values[j]);
663 el2->num_values += el->num_values;
667 case LDB_FLAG_MOD_REPLACE:
668 /* replace all elements of this attribute name with the elements
669 listed. The attribute not existing is not an error */
670 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
672 /* add the replacement element, if not empty */
673 if (msg->elements[i].num_values != 0 &&
674 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
679 case LDB_FLAG_MOD_DELETE:
681 dn = ldb_dn_linearize(msg2, msg->dn);
682 if (dn == NULL) goto failed;
684 /* we could be being asked to delete all
685 values or just some values */
686 if (msg->elements[i].num_values == 0) {
687 if (msg_delete_attribute(module, ldb, msg2,
688 msg->elements[i].name) != 0) {
689 err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
690 if (err_string) ldb_set_errstring(module->ldb, err_string);
691 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
696 for (j=0;j<msg->elements[i].num_values;j++) {
697 if (msg_delete_element(module,
699 msg->elements[i].name,
700 &msg->elements[i].values[j]) != 0) {
701 err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
702 if (err_string) ldb_set_errstring(module->ldb, err_string);
703 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
706 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
712 err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x",
713 msg->elements[i].name,
714 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
715 if (err_string) ldb_set_errstring(module->ldb, err_string);
716 ret = LDB_ERR_PROTOCOL_ERROR;
721 /* we've made all the mods - save the modified record back into the database */
722 ret = ltdb_store(module, msg2, TDB_MODIFY);
724 talloc_free(tdb_key.dptr);
729 talloc_free(tdb_key.dptr);
737 static int ltdb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
739 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
741 struct ldb_async_handle **handle)
743 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
744 struct ltdb_async_context *ltdb_ac;
745 int ret = LDB_ERR_OPERATIONS_ERROR;
749 *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
750 if (*handle == NULL) {
753 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
754 (*handle)->state = LDB_ASYNC_DONE;
755 (*handle)->status = LDB_SUCCESS;
757 ret = ltdb_check_special_dn(module, msg);
758 if (ret != LDB_SUCCESS) {
759 talloc_free(*handle);
763 if (ltdb_cache_load(module) != 0) {
764 talloc_free(*handle);
765 return LDB_ERR_OTHER;
768 ret = ltdb_modify_internal(module, msg);
770 if (ret != LDB_SUCCESS) {
771 (*handle)->status = ret;
775 ltdb_modified(module, msg->dn);
777 if (ltdb_ac->callback)
778 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
783 static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg)
785 struct ldb_async_handle *handle;
788 ret = ltdb_modify_async(module, msg, NULL, NULL, 0, &handle);
790 if (ret != LDB_SUCCESS)
793 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
802 static int ltdb_rename_async(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn,
804 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
806 struct ldb_async_handle **handle)
808 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
809 struct ltdb_async_context *ltdb_ac;
810 struct ldb_message *msg;
811 int ret = LDB_ERR_OPERATIONS_ERROR;
815 if (ltdb_cache_load(module) != 0) {
819 *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
820 if (*handle == NULL) {
823 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
824 (*handle)->state = LDB_ASYNC_DONE;
825 (*handle)->status = LDB_SUCCESS;
827 msg = talloc(ltdb_ac, struct ldb_message);
832 /* in case any attribute of the message was indexed, we need
833 to fetch the old record */
834 ret = ltdb_search_dn1(module, olddn, msg);
836 /* not finding the old record is an error */
837 (*handle)->status = LDB_ERR_NO_SUCH_OBJECT;
841 msg->dn = ldb_dn_copy(msg, newdn);
843 ret = LDB_ERR_OPERATIONS_ERROR;
847 ret = ltdb_add(module, msg);
848 if (ret != LDB_SUCCESS) {
849 (*handle)->status = LDB_ERR_OPERATIONS_ERROR;
853 ret = ltdb_delete(module, olddn);
854 if (ret != LDB_SUCCESS) {
855 ltdb_delete(module, newdn);
856 (*handle)->status = ret;
860 if (ltdb_ac->callback)
861 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
866 talloc_free(*handle);
870 static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
872 struct ldb_async_handle *handle;
875 ret = ltdb_rename_async(module, olddn, newdn,
876 NULL, NULL, 0, &handle);
878 if (ret != LDB_SUCCESS)
881 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
887 static int ltdb_start_trans(struct ldb_module *module)
889 struct ltdb_private *ltdb = module->private_data;
891 if (tdb_transaction_start(ltdb->tdb) != 0) {
892 return ltdb_err_map(tdb_error(ltdb->tdb));
898 static int ltdb_end_trans(struct ldb_module *module)
900 struct ltdb_private *ltdb = module->private_data;
902 if (tdb_transaction_commit(ltdb->tdb) != 0) {
903 return ltdb_err_map(tdb_error(ltdb->tdb));
909 static int ltdb_del_trans(struct ldb_module *module)
911 struct ltdb_private *ltdb = module->private_data;
913 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
914 return ltdb_err_map(tdb_error(ltdb->tdb));
920 static int ltdb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
922 return handle->status;
925 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
927 /* check for oustanding critical controls and return an error if found */
929 if (req->controls != NULL) {
930 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
933 if (check_critical_controls(req->controls)) {
934 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
937 switch (req->operation) {
940 return ltdb_search_bytree(module,
942 req->op.search.scope,
944 req->op.search.attrs,
945 &req->op.search.res);
948 return ltdb_add(module, req->op.add.message);
951 return ltdb_modify(module, req->op.mod.message);
954 return ltdb_delete(module, req->op.del.dn);
957 return ltdb_rename(module,
958 req->op.rename.olddn,
959 req->op.rename.newdn);
961 case LDB_ASYNC_SEARCH:
962 return ltdb_search_async(module,
964 req->op.search.scope,
966 req->op.search.attrs,
973 return ltdb_add_async(module,
980 case LDB_ASYNC_MODIFY:
981 return ltdb_modify_async(module,
988 case LDB_ASYNC_DELETE:
989 return ltdb_delete_async(module,
996 case LDB_ASYNC_RENAME:
997 return ltdb_rename_async(module,
998 req->op.rename.olddn,
999 req->op.rename.newdn,
1001 req->async.callback,
1003 &req->async.handle);
1006 return LDB_ERR_OPERATIONS_ERROR;
1012 return sequenceNumber from @BASEINFO
1014 static uint64_t ltdb_sequence_number(struct ldb_context *ldb)
1016 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1017 const char *attrs[] = { "sequenceNumber", NULL };
1018 struct ldb_result *res = NULL;
1019 struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO");
1023 ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
1024 talloc_steal(tmp_ctx, res);
1025 if (ret != LDB_SUCCESS || res->count != 1) {
1026 talloc_free(tmp_ctx);
1027 /* zero is as good as anything when we don't know */
1031 seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0);
1032 talloc_free(tmp_ctx);
1036 static const struct ldb_module_ops ltdb_ops = {
1038 .request = ltdb_request,
1039 .start_transaction = ltdb_start_trans,
1040 .end_transaction = ltdb_end_trans,
1041 .del_transaction = ltdb_del_trans
1046 connect to the database
1048 int ltdb_connect(struct ldb_context *ldb, const char *url,
1049 unsigned int flags, const char *options[])
1052 int tdb_flags, open_flags;
1053 struct ltdb_private *ltdb;
1056 if (strchr(url, ':')) {
1057 if (strncmp(url, "tdb://", 6) != 0) {
1058 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1066 tdb_flags = TDB_DEFAULT;
1068 /* check for the 'nosync' option */
1069 if (flags & LDB_FLG_NOSYNC) {
1070 tdb_flags |= TDB_NOSYNC;
1073 if (flags & LDB_FLG_RDONLY) {
1074 open_flags = O_RDONLY;
1076 open_flags = O_CREAT | O_RDWR;
1079 ltdb = talloc_zero(ldb, struct ltdb_private);
1085 /* note that we use quite a large default hash size */
1086 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, tdb_flags, open_flags, 0666);
1088 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1093 ltdb->sequence_number = 0;
1095 ldb->modules = talloc(ldb, struct ldb_module);
1096 if (!ldb->modules) {
1101 ldb->modules->ldb = ldb;
1102 ldb->modules->prev = ldb->modules->next = NULL;
1103 ldb->modules->private_data = ltdb;
1104 ldb->modules->ops = <db_ops;
1105 ldb->sequence_number = ltdb_sequence_number;
1107 ldb->async_wait = <db_async_wait;