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 *))
85 struct ltdb_async_context *ac;
86 struct ldb_async_handle *h;
88 h = talloc_zero(ltdb, struct ldb_async_handle);
90 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
96 ac = talloc_zero(h, struct ltdb_async_context);
98 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
103 h->private_data = (void *)ac;
106 ac->context = context;
107 ac->callback = callback;
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 *),
262 struct ldb_async_handle **handle)
264 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
265 struct ltdb_async_context *ltdb_ac;
266 int ret = LDB_ERR_OPERATIONS_ERROR;
268 *handle = init_ltdb_handle(ltdb, module, context, callback);
269 if (*handle == NULL) {
272 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
273 (*handle)->state = LDB_ASYNC_DONE;
274 (*handle)->status = LDB_SUCCESS;
276 ret = ltdb_check_special_dn(module, msg);
277 if (ret != LDB_SUCCESS) {
278 talloc_free(*handle);
282 if (ltdb_cache_load(module) != 0) {
283 talloc_free(*handle);
284 return LDB_ERR_OTHER;
287 ret = ltdb_store(module, msg, TDB_INSERT);
289 if (ret != LDB_SUCCESS) {
290 (*handle)->status = ret;
294 ltdb_modified(module, msg->dn);
296 if (ltdb_ac->callback)
297 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
302 static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg)
304 struct ldb_async_handle *handle;
307 ret = ltdb_add_async(module, msg, NULL, NULL, &handle);
309 if (ret != LDB_SUCCESS)
312 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
319 delete a record from the database, not updating indexes (used for deleting
322 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
324 struct ltdb_private *ltdb = module->private_data;
328 tdb_key = ltdb_key(module, dn);
330 return LDB_ERR_OTHER;
333 ret = tdb_delete(ltdb->tdb, tdb_key);
334 talloc_free(tdb_key.dptr);
337 ret = ltdb_err_map(tdb_error(ltdb->tdb));
344 delete a record from the database
346 static int ltdb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
348 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
349 struct ldb_async_handle **handle)
351 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
352 struct ltdb_async_context *ltdb_ac;
353 struct ldb_message *msg;
354 int ret = LDB_ERR_OPERATIONS_ERROR;
358 if (ltdb_cache_load(module) != 0) {
362 *handle = init_ltdb_handle(ltdb, module, context, callback);
363 if (*handle == NULL) {
366 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
367 (*handle)->state = LDB_ASYNC_DONE;
368 (*handle)->status = LDB_SUCCESS;
370 msg = talloc(ltdb_ac, struct ldb_message);
375 /* in case any attribute of the message was indexed, we need
376 to fetch the old record */
377 ret = ltdb_search_dn1(module, dn, msg);
379 /* not finding the old record is an error */
380 (*handle)->status = LDB_ERR_NO_SUCH_OBJECT;
384 ret = ltdb_delete_noindex(module, dn);
385 if (ret != LDB_SUCCESS) {
389 /* remove any indexed attributes */
390 ret = ltdb_index_del(module, msg);
394 ltdb_modified(module, dn);
396 if (ltdb_ac->callback)
397 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
402 talloc_free(*handle);
406 static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn)
408 struct ldb_async_handle *handle;
411 ret = ltdb_delete_async(module, dn, NULL, NULL, &handle);
413 if (ret != LDB_SUCCESS)
416 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
424 find an element by attribute name. At the moment this does a linear search, it should
425 be re-coded to use a binary search once all places that modify records guarantee
428 return the index of the first matching element if found, otherwise -1
430 static int find_element(const struct ldb_message *msg, const char *name)
433 for (i=0;i<msg->num_elements;i++) {
434 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
443 add an element to an existing record. Assumes a elements array that we
444 can call re-alloc on, and assumed that we can re-use the data pointers from the
445 passed in additional values. Use with care!
447 returns 0 on success, -1 on failure (and sets errno)
449 static int msg_add_element(struct ldb_context *ldb,
450 struct ldb_message *msg, struct ldb_message_element *el)
452 struct ldb_message_element *e2;
455 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
456 msg->num_elements+1);
464 e2 = &msg->elements[msg->num_elements];
467 e2->flags = el->flags;
469 if (el->num_values != 0) {
470 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
476 for (i=0;i<el->num_values;i++) {
477 e2->values[i] = el->values[i];
479 e2->num_values = el->num_values;
487 delete all elements having a specified attribute name
489 static int msg_delete_attribute(struct ldb_module *module,
490 struct ldb_context *ldb,
491 struct ldb_message *msg, const char *name)
496 dn = ldb_dn_linearize(ldb, msg->dn);
501 for (i=0;i<msg->num_elements;i++) {
502 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
503 for (j=0;j<msg->elements[i].num_values;j++) {
504 ltdb_index_del_value(module, dn, &msg->elements[i], j);
506 talloc_free(msg->elements[i].values);
507 if (msg->num_elements > (i+1)) {
508 memmove(&msg->elements[i],
510 sizeof(struct ldb_message_element)*
511 (msg->num_elements - (i+1)));
515 msg->elements = talloc_realloc(msg, msg->elements,
516 struct ldb_message_element,
526 delete all elements matching an attribute name/value
528 return 0 on success, -1 on failure
530 static int msg_delete_element(struct ldb_module *module,
531 struct ldb_message *msg,
533 const struct ldb_val *val)
535 struct ldb_context *ldb = module->ldb;
538 struct ldb_message_element *el;
539 const struct ldb_attrib_handler *h;
541 found = find_element(msg, name);
546 el = &msg->elements[found];
548 h = ldb_attrib_handler(ldb, el->name);
550 for (i=0;i<el->num_values;i++) {
551 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
552 if (i<el->num_values-1) {
553 memmove(&el->values[i], &el->values[i+1],
554 sizeof(el->values[i])*(el->num_values-(i+1)));
557 if (el->num_values == 0) {
558 return msg_delete_attribute(module, ldb, msg, name);
569 modify a record - internal interface
571 yuck - this is O(n^2). Luckily n is usually small so we probably
572 get away with it, but if we ever have really large attribute lists
573 then we'll need to look at this again
575 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
577 struct ldb_context *ldb = module->ldb;
578 struct ltdb_private *ltdb = module->private_data;
579 TDB_DATA tdb_key, tdb_data;
580 struct ldb_message *msg2;
584 tdb_key = ltdb_key(module, msg->dn);
586 return LDB_ERR_OTHER;
589 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
590 if (!tdb_data.dptr) {
591 talloc_free(tdb_key.dptr);
592 return ltdb_err_map(tdb_error(ltdb->tdb));
595 msg2 = talloc(tdb_key.dptr, struct ldb_message);
597 talloc_free(tdb_key.dptr);
598 return LDB_ERR_OTHER;
601 ret = ltdb_unpack_data(module, &tdb_data, msg2);
603 talloc_free(tdb_key.dptr);
605 return LDB_ERR_OTHER;
612 for (i=0;i<msg->num_elements;i++) {
613 struct ldb_message_element *el = &msg->elements[i];
614 struct ldb_message_element *el2;
615 struct ldb_val *vals;
619 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
621 case LDB_FLAG_MOD_ADD:
622 /* add this element to the message. fail if it
624 ret = find_element(msg2, el->name);
627 if (msg_add_element(ldb, msg2, el) != 0) {
634 el2 = &msg2->elements[ret];
636 /* An attribute with this name already exists, add all
637 * values if they don't already exist. */
639 for (j=0;j<el->num_values;j++) {
640 if (ldb_msg_find_val(el2, &el->values[j])) {
641 err_string = talloc_strdup(module, "Type or value exists");
642 if (err_string) ldb_set_errstring(module->ldb, err_string);
643 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
648 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
649 el2->num_values + el->num_values);
654 for (j=0;j<el->num_values;j++) {
655 vals[el2->num_values + j] =
656 ldb_val_dup(vals, &el->values[j]);
660 el2->num_values += el->num_values;
664 case LDB_FLAG_MOD_REPLACE:
665 /* replace all elements of this attribute name with the elements
666 listed. The attribute not existing is not an error */
667 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
669 /* add the replacement element, if not empty */
670 if (msg->elements[i].num_values != 0 &&
671 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
676 case LDB_FLAG_MOD_DELETE:
678 dn = ldb_dn_linearize(msg2, msg->dn);
679 if (dn == NULL) goto failed;
681 /* we could be being asked to delete all
682 values or just some values */
683 if (msg->elements[i].num_values == 0) {
684 if (msg_delete_attribute(module, ldb, msg2,
685 msg->elements[i].name) != 0) {
686 err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
687 if (err_string) ldb_set_errstring(module->ldb, err_string);
688 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
693 for (j=0;j<msg->elements[i].num_values;j++) {
694 if (msg_delete_element(module,
696 msg->elements[i].name,
697 &msg->elements[i].values[j]) != 0) {
698 err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
699 if (err_string) ldb_set_errstring(module->ldb, err_string);
700 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
703 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
709 err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x",
710 msg->elements[i].name,
711 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
712 if (err_string) ldb_set_errstring(module->ldb, err_string);
713 ret = LDB_ERR_PROTOCOL_ERROR;
718 /* we've made all the mods - save the modified record back into the database */
719 ret = ltdb_store(module, msg2, TDB_MODIFY);
721 talloc_free(tdb_key.dptr);
726 talloc_free(tdb_key.dptr);
734 static int ltdb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
736 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
737 struct ldb_async_handle **handle)
739 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
740 struct ltdb_async_context *ltdb_ac;
741 int ret = LDB_ERR_OPERATIONS_ERROR;
745 *handle = init_ltdb_handle(ltdb, module, context, callback);
746 if (*handle == NULL) {
749 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
750 (*handle)->state = LDB_ASYNC_DONE;
751 (*handle)->status = LDB_SUCCESS;
753 ret = ltdb_check_special_dn(module, msg);
754 if (ret != LDB_SUCCESS) {
755 talloc_free(*handle);
759 if (ltdb_cache_load(module) != 0) {
760 talloc_free(*handle);
761 return LDB_ERR_OTHER;
764 ret = ltdb_modify_internal(module, msg);
766 if (ret != LDB_SUCCESS) {
767 (*handle)->status = ret;
771 ltdb_modified(module, msg->dn);
773 if (ltdb_ac->callback)
774 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
779 static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg)
781 struct ldb_async_handle *handle;
784 ret = ltdb_modify_async(module, msg, NULL, NULL, &handle);
786 if (ret != LDB_SUCCESS)
789 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
798 static int ltdb_rename_async(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn,
800 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
801 struct ldb_async_handle **handle)
803 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
804 struct ltdb_async_context *ltdb_ac;
805 struct ldb_message *msg;
806 int ret = LDB_ERR_OPERATIONS_ERROR;
810 if (ltdb_cache_load(module) != 0) {
814 *handle = init_ltdb_handle(ltdb, module, context, callback);
815 if (*handle == NULL) {
818 ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
819 (*handle)->state = LDB_ASYNC_DONE;
820 (*handle)->status = LDB_SUCCESS;
822 msg = talloc(ltdb_ac, struct ldb_message);
827 /* in case any attribute of the message was indexed, we need
828 to fetch the old record */
829 ret = ltdb_search_dn1(module, olddn, msg);
831 /* not finding the old record is an error */
832 (*handle)->status = LDB_ERR_NO_SUCH_OBJECT;
836 msg->dn = ldb_dn_copy(msg, newdn);
838 ret = LDB_ERR_OPERATIONS_ERROR;
842 ret = ltdb_add(module, msg);
843 if (ret != LDB_SUCCESS) {
844 (*handle)->status = LDB_ERR_OPERATIONS_ERROR;
848 ret = ltdb_delete(module, olddn);
849 if (ret != LDB_SUCCESS) {
850 ltdb_delete(module, newdn);
851 (*handle)->status = ret;
855 if (ltdb_ac->callback)
856 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
861 talloc_free(*handle);
865 static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
867 struct ldb_async_handle *handle;
870 ret = ltdb_rename_async(module, olddn, newdn, NULL, NULL, &handle);
872 if (ret != LDB_SUCCESS)
875 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
881 static int ltdb_start_trans(struct ldb_module *module)
883 struct ltdb_private *ltdb = module->private_data;
885 if (tdb_transaction_start(ltdb->tdb) != 0) {
886 return ltdb_err_map(tdb_error(ltdb->tdb));
892 static int ltdb_end_trans(struct ldb_module *module)
894 struct ltdb_private *ltdb = module->private_data;
896 if (tdb_transaction_commit(ltdb->tdb) != 0) {
897 return ltdb_err_map(tdb_error(ltdb->tdb));
903 static int ltdb_del_trans(struct ldb_module *module)
905 struct ltdb_private *ltdb = module->private_data;
907 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
908 return ltdb_err_map(tdb_error(ltdb->tdb));
914 static int ltdb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
916 return handle->status;
919 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
921 /* check for oustanding critical controls and return an error if found */
923 if (req->controls != NULL) {
924 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;
931 switch (req->operation) {
934 return ltdb_search_bytree(module,
936 req->op.search.scope,
938 req->op.search.attrs,
939 &req->op.search.res);
942 return ltdb_add(module, req->op.add.message);
945 return ltdb_modify(module, req->op.mod.message);
948 return ltdb_delete(module, req->op.del.dn);
951 return ltdb_rename(module,
952 req->op.rename.olddn,
953 req->op.rename.newdn);
955 case LDB_ASYNC_SEARCH:
956 return ltdb_search_async(module,
958 req->op.search.scope,
960 req->op.search.attrs,
966 return ltdb_add_async(module,
972 case LDB_ASYNC_MODIFY:
973 return ltdb_modify_async(module,
979 case LDB_ASYNC_DELETE:
980 return ltdb_delete_async(module,
986 case LDB_ASYNC_RENAME:
987 return ltdb_rename_async(module,
988 req->op.rename.olddn,
989 req->op.rename.newdn,
995 return LDB_ERR_OPERATIONS_ERROR;
1001 return sequenceNumber from @BASEINFO
1003 static uint64_t ltdb_sequence_number(struct ldb_context *ldb)
1005 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1006 const char *attrs[] = { "sequenceNumber", NULL };
1007 struct ldb_result *res = NULL;
1008 struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO");
1012 ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
1013 talloc_steal(tmp_ctx, res);
1014 if (ret != LDB_SUCCESS || res->count != 1) {
1015 talloc_free(tmp_ctx);
1016 /* zero is as good as anything when we don't know */
1020 seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0);
1021 talloc_free(tmp_ctx);
1025 static const struct ldb_module_ops ltdb_ops = {
1027 .request = ltdb_request,
1028 .start_transaction = ltdb_start_trans,
1029 .end_transaction = ltdb_end_trans,
1030 .del_transaction = ltdb_del_trans,
1031 .async_wait = ltdb_async_wait
1036 connect to the database
1038 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1039 unsigned int flags, const char *options[])
1042 int tdb_flags, open_flags;
1043 struct ltdb_private *ltdb;
1046 if (strchr(url, ':')) {
1047 if (strncmp(url, "tdb://", 6) != 0) {
1048 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1056 tdb_flags = TDB_DEFAULT;
1058 /* check for the 'nosync' option */
1059 if (flags & LDB_FLG_NOSYNC) {
1060 tdb_flags |= TDB_NOSYNC;
1063 if (flags & LDB_FLG_RDONLY) {
1064 open_flags = O_RDONLY;
1066 open_flags = O_CREAT | O_RDWR;
1069 ltdb = talloc_zero(ldb, struct ltdb_private);
1075 /* note that we use quite a large default hash size */
1076 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, tdb_flags, open_flags, 0666);
1078 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1083 ltdb->sequence_number = 0;
1085 ldb->modules = talloc(ldb, struct ldb_module);
1086 if (!ldb->modules) {
1091 ldb->modules->ldb = ldb;
1092 ldb->modules->prev = ldb->modules->next = NULL;
1093 ldb->modules->private_data = ltdb;
1094 ldb->modules->ops = <db_ops;
1095 ldb->sequence_number = ltdb_sequence_number;
1100 int ldb_tdb_init(void)
1102 return ldb_register_backend("tdb:", ltdb_connect);