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_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,
83 int (*callback)(struct ldb_context *, void *, struct ldb_reply *))
85 struct ltdb_context *ac;
88 h = talloc_zero(ltdb, struct ldb_handle);
90 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
96 ac = talloc_zero(h, struct ltdb_context);
98 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
103 h->private_data = (void *)ac;
105 h->state = LDB_ASYNC_INIT;
106 h->status = LDB_SUCCESS;
109 ac->context = context;
110 ac->callback = callback;
116 form a TDB_DATA for a record key
119 note that the key for a record can depend on whether the
120 dn refers to a case sensitive index record or not
122 struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn)
124 struct ldb_context *ldb = module->ldb;
126 char *key_str = NULL;
127 char *dn_folded = NULL;
130 most DNs are case insensitive. The exception is index DNs for
131 case sensitive attributes
133 there are 3 cases dealt with in this code:
135 1) if the dn doesn't start with @ then uppercase the attribute
136 names and the attributes values of case insensitive attributes
137 2) if the dn starts with @ then leave it alone - the indexing code handles
141 dn_folded = ldb_dn_linearize_casefold(ldb, dn);
146 key_str = talloc_asprintf(ldb, "DN=%s", dn_folded);
148 talloc_free(dn_folded);
154 key.dptr = (uint8_t *)key_str;
155 key.dsize = strlen(key_str) + 1;
167 check special dn's have valid attributes
168 currently only @ATTRIBUTES is checked
170 int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
174 if (! ldb_dn_is_special(msg->dn) ||
175 ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
179 /* we have @ATTRIBUTES, let's check attributes are fine */
180 /* should we check that we deny multivalued attributes ? */
181 for (i = 0; i < msg->num_elements; i++) {
182 for (j = 0; j < msg->elements[i].num_values; j++) {
183 if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
184 char *err_string = talloc_strdup(module, "Invalid attribute value in an @ATTRIBUTES entry");
186 ldb_set_errstring(module->ldb, err_string);
188 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
198 we've made a modification to a dn - possibly reindex and
199 update sequence number
201 static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn)
205 if (ldb_dn_is_special(dn) &&
206 (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
207 ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
208 ret = ltdb_reindex(module);
212 !(ldb_dn_is_special(dn) &&
213 ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
214 ret = ltdb_increase_sequence_number(module);
221 store a record into the db
223 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
225 struct ltdb_private *ltdb = module->private_data;
226 TDB_DATA tdb_key, tdb_data;
229 tdb_key = ltdb_key(module, msg->dn);
231 return LDB_ERR_OTHER;
234 ret = ltdb_pack_data(module, msg, &tdb_data);
236 talloc_free(tdb_key.dptr);
237 return LDB_ERR_OTHER;
240 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
242 ret = ltdb_err_map(tdb_error(ltdb->tdb));
246 ret = ltdb_index_add(module, msg);
248 tdb_delete(ltdb->tdb, tdb_key);
252 talloc_free(tdb_key.dptr);
253 talloc_free(tdb_data.dptr);
259 static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg)
263 ret = ltdb_check_special_dn(module, msg);
264 if (ret != LDB_SUCCESS) {
268 if (ltdb_cache_load(module) != 0) {
269 return LDB_ERR_OPERATIONS_ERROR;
272 ret = ltdb_store(module, msg, TDB_INSERT);
274 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
277 dn = ldb_dn_linearize(module, msg->dn);
281 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Entry %s already exists", dn));
286 if (ret == LDB_SUCCESS) {
287 ret = ltdb_modified(module, msg->dn);
288 if (ret != LDB_SUCCESS) {
289 return LDB_ERR_OPERATIONS_ERROR;
297 add a record to the database
299 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
301 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
302 struct ltdb_context *ltdb_ac;
303 int tret, ret = LDB_SUCCESS;
305 if (req->controls != NULL) {
306 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
307 if (check_critical_controls(req->controls)) {
308 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
312 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
313 if (req->handle == NULL) {
314 return LDB_ERR_OPERATIONS_ERROR;
316 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
318 tret = ltdb_add_internal(module, req->op.add.message);
319 if (tret != LDB_SUCCESS) {
320 req->handle->status = tret;
324 if (ltdb_ac->callback) {
325 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
328 req->handle->state = LDB_ASYNC_DONE;
333 delete a record from the database, not updating indexes (used for deleting
336 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
338 struct ltdb_private *ltdb = module->private_data;
342 tdb_key = ltdb_key(module, dn);
344 return LDB_ERR_OTHER;
347 ret = tdb_delete(ltdb->tdb, tdb_key);
348 talloc_free(tdb_key.dptr);
351 ret = ltdb_err_map(tdb_error(ltdb->tdb));
357 static int ltdb_delete_internal(struct ldb_module *module, const struct ldb_dn *dn)
359 struct ldb_message *msg;
362 msg = talloc(module, struct ldb_message);
364 return LDB_ERR_OPERATIONS_ERROR;
367 /* in case any attribute of the message was indexed, we need
368 to fetch the old record */
369 ret = ltdb_search_dn1(module, dn, msg);
371 /* not finding the old record is an error */
373 return LDB_ERR_NO_SUCH_OBJECT;
376 ret = ltdb_delete_noindex(module, dn);
377 if (ret != LDB_SUCCESS) {
379 return LDB_ERR_NO_SUCH_OBJECT;
382 /* remove any indexed attributes */
383 ret = ltdb_index_del(module, msg);
384 if (ret != LDB_SUCCESS) {
386 return LDB_ERR_OPERATIONS_ERROR;
389 ret = ltdb_modified(module, dn);
390 if (ret != LDB_SUCCESS) {
391 return LDB_ERR_OPERATIONS_ERROR;
399 delete a record from the database
401 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
403 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
404 struct ltdb_context *ltdb_ac;
405 int tret, ret = LDB_SUCCESS;
407 if (req->controls != NULL) {
408 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
409 if (check_critical_controls(req->controls)) {
410 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
416 if (ltdb_cache_load(module) != 0) {
417 return LDB_ERR_OPERATIONS_ERROR;
420 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
421 if (req->handle == NULL) {
422 return LDB_ERR_OPERATIONS_ERROR;
424 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
426 tret = ltdb_delete_internal(module, req->op.del.dn);
427 if (tret != LDB_SUCCESS) {
428 req->handle->status = tret;
432 if (ltdb_ac->callback) {
433 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
436 req->handle->state = LDB_ASYNC_DONE;
441 find an element by attribute name. At the moment this does a linear search, it should
442 be re-coded to use a binary search once all places that modify records guarantee
445 return the index of the first matching element if found, otherwise -1
447 static int find_element(const struct ldb_message *msg, const char *name)
450 for (i=0;i<msg->num_elements;i++) {
451 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
460 add an element to an existing record. Assumes a elements array that we
461 can call re-alloc on, and assumed that we can re-use the data pointers from the
462 passed in additional values. Use with care!
464 returns 0 on success, -1 on failure (and sets errno)
466 static int msg_add_element(struct ldb_context *ldb,
467 struct ldb_message *msg, struct ldb_message_element *el)
469 struct ldb_message_element *e2;
472 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
473 msg->num_elements+1);
481 e2 = &msg->elements[msg->num_elements];
484 e2->flags = el->flags;
486 if (el->num_values != 0) {
487 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
493 for (i=0;i<el->num_values;i++) {
494 e2->values[i] = el->values[i];
496 e2->num_values = el->num_values;
504 delete all elements having a specified attribute name
506 static int msg_delete_attribute(struct ldb_module *module,
507 struct ldb_context *ldb,
508 struct ldb_message *msg, const char *name)
513 dn = ldb_dn_linearize(ldb, msg->dn);
518 for (i=0;i<msg->num_elements;i++) {
519 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
520 for (j=0;j<msg->elements[i].num_values;j++) {
521 ltdb_index_del_value(module, dn, &msg->elements[i], j);
523 talloc_free(msg->elements[i].values);
524 if (msg->num_elements > (i+1)) {
525 memmove(&msg->elements[i],
527 sizeof(struct ldb_message_element)*
528 (msg->num_elements - (i+1)));
532 msg->elements = talloc_realloc(msg, msg->elements,
533 struct ldb_message_element,
543 delete all elements matching an attribute name/value
545 return 0 on success, -1 on failure
547 static int msg_delete_element(struct ldb_module *module,
548 struct ldb_message *msg,
550 const struct ldb_val *val)
552 struct ldb_context *ldb = module->ldb;
555 struct ldb_message_element *el;
556 const struct ldb_attrib_handler *h;
558 found = find_element(msg, name);
563 el = &msg->elements[found];
565 h = ldb_attrib_handler(ldb, el->name);
567 for (i=0;i<el->num_values;i++) {
568 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
569 if (i<el->num_values-1) {
570 memmove(&el->values[i], &el->values[i+1],
571 sizeof(el->values[i])*(el->num_values-(i+1)));
574 if (el->num_values == 0) {
575 return msg_delete_attribute(module, ldb, msg, name);
586 modify a record - internal interface
588 yuck - this is O(n^2). Luckily n is usually small so we probably
589 get away with it, but if we ever have really large attribute lists
590 then we'll need to look at this again
592 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
594 struct ldb_context *ldb = module->ldb;
595 struct ltdb_private *ltdb = module->private_data;
596 TDB_DATA tdb_key, tdb_data;
597 struct ldb_message *msg2;
601 tdb_key = ltdb_key(module, msg->dn);
603 return LDB_ERR_OTHER;
606 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
607 if (!tdb_data.dptr) {
608 talloc_free(tdb_key.dptr);
609 return ltdb_err_map(tdb_error(ltdb->tdb));
612 msg2 = talloc(tdb_key.dptr, struct ldb_message);
614 talloc_free(tdb_key.dptr);
615 return LDB_ERR_OTHER;
618 ret = ltdb_unpack_data(module, &tdb_data, msg2);
628 for (i=0;i<msg->num_elements;i++) {
629 struct ldb_message_element *el = &msg->elements[i];
630 struct ldb_message_element *el2;
631 struct ldb_val *vals;
635 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
637 case LDB_FLAG_MOD_ADD:
638 /* add this element to the message. fail if it
640 ret = find_element(msg2, el->name);
643 if (msg_add_element(ldb, msg2, el) != 0) {
650 el2 = &msg2->elements[ret];
652 /* An attribute with this name already exists, add all
653 * values if they don't already exist. */
655 for (j=0;j<el->num_values;j++) {
656 if (ldb_msg_find_val(el2, &el->values[j])) {
657 err_string = talloc_strdup(module, "Type or value exists");
658 if (err_string) ldb_set_errstring(module->ldb, err_string);
659 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
664 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
665 el2->num_values + el->num_values);
672 for (j=0;j<el->num_values;j++) {
673 vals[el2->num_values + j] =
674 ldb_val_dup(vals, &el->values[j]);
678 el2->num_values += el->num_values;
682 case LDB_FLAG_MOD_REPLACE:
683 /* replace all elements of this attribute name with the elements
684 listed. The attribute not existing is not an error */
685 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
687 /* add the replacement element, if not empty */
688 if (msg->elements[i].num_values != 0 &&
689 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
695 case LDB_FLAG_MOD_DELETE:
697 dn = ldb_dn_linearize(msg2, msg->dn);
703 /* we could be being asked to delete all
704 values or just some values */
705 if (msg->elements[i].num_values == 0) {
706 if (msg_delete_attribute(module, ldb, msg2,
707 msg->elements[i].name) != 0) {
708 err_string = talloc_asprintf(module, "No such attribute: %s for delete on %s",
709 msg->elements[i].name, dn);
710 if (err_string) ldb_set_errstring(module->ldb, err_string);
711 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
716 for (j=0;j<msg->elements[i].num_values;j++) {
717 if (msg_delete_element(module,
719 msg->elements[i].name,
720 &msg->elements[i].values[j]) != 0) {
721 err_string = talloc_asprintf(module, "No matching attribute value when deleting attribute: %s on %s",
722 msg->elements[i].name, dn);
723 if (err_string) ldb_set_errstring(module->ldb, err_string);
724 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
727 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
734 err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x",
735 msg->elements[i].name,
736 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
737 if (err_string) ldb_set_errstring(module->ldb, err_string);
738 ret = LDB_ERR_PROTOCOL_ERROR;
743 /* we've made all the mods - save the modified record back into the database */
744 ret = ltdb_store(module, msg2, TDB_MODIFY);
745 if (ret != LDB_SUCCESS) {
749 if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
750 ret = LDB_ERR_OPERATIONS_ERROR;
754 talloc_free(tdb_key.dptr);
759 talloc_free(tdb_key.dptr);
767 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
769 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
770 struct ltdb_context *ltdb_ac;
771 int tret, ret = LDB_SUCCESS;
773 if (req->controls != NULL) {
774 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
775 if (check_critical_controls(req->controls)) {
776 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
782 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
783 if (req->handle == NULL) {
784 return LDB_ERR_OPERATIONS_ERROR;
786 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
788 tret = ltdb_check_special_dn(module, req->op.mod.message);
789 if (tret != LDB_SUCCESS) {
790 req->handle->status = tret;
794 if (ltdb_cache_load(module) != 0) {
795 ret = LDB_ERR_OPERATIONS_ERROR;
799 tret = ltdb_modify_internal(module, req->op.mod.message);
800 if (tret != LDB_SUCCESS) {
801 req->handle->status = tret;
805 if (ltdb_ac->callback) {
806 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
809 req->handle->state = LDB_ASYNC_DONE;
816 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
818 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
819 struct ltdb_context *ltdb_ac;
820 struct ldb_message *msg;
821 int tret, ret = LDB_SUCCESS;
823 if (req->controls != NULL) {
824 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
825 if (check_critical_controls(req->controls)) {
826 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
832 if (ltdb_cache_load(module) != 0) {
833 return LDB_ERR_OPERATIONS_ERROR;
836 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
837 if (req->handle == NULL) {
838 return LDB_ERR_OPERATIONS_ERROR;
840 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
842 msg = talloc(ltdb_ac, struct ldb_message);
844 ret = LDB_ERR_OPERATIONS_ERROR;
848 /* in case any attribute of the message was indexed, we need
849 to fetch the old record */
850 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
852 /* not finding the old record is an error */
853 req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
857 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
859 ret = LDB_ERR_OPERATIONS_ERROR;
863 tret = ltdb_add_internal(module, msg);
864 if (tret != LDB_SUCCESS) {
865 ret = LDB_ERR_OPERATIONS_ERROR;
869 tret = ltdb_delete_internal(module, req->op.rename.olddn);
870 if (tret != LDB_SUCCESS) {
871 ltdb_delete_internal(module, req->op.rename.newdn);
872 ret = LDB_ERR_OPERATIONS_ERROR;
876 if (ltdb_ac->callback) {
877 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
880 req->handle->state = LDB_ASYNC_DONE;
884 static int ltdb_start_trans(struct ldb_module *module)
886 struct ltdb_private *ltdb = module->private_data;
888 if (tdb_transaction_start(ltdb->tdb) != 0) {
889 return ltdb_err_map(tdb_error(ltdb->tdb));
895 static int ltdb_end_trans(struct ldb_module *module)
897 struct ltdb_private *ltdb = module->private_data;
899 if (tdb_transaction_commit(ltdb->tdb) != 0) {
900 return ltdb_err_map(tdb_error(ltdb->tdb));
906 static int ltdb_del_trans(struct ldb_module *module)
908 struct ltdb_private *ltdb = module->private_data;
910 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
911 return ltdb_err_map(tdb_error(ltdb->tdb));
917 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
919 return handle->status;
922 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
924 /* check for oustanding critical controls and return an error if found */
925 if (req->controls != NULL) {
926 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
927 if (check_critical_controls(req->controls)) {
928 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
932 /* search, add, modify, delete, rename are handled by their own, no other op supported */
933 return LDB_ERR_OPERATIONS_ERROR;
937 return sequenceNumber from @BASEINFO
939 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
941 TALLOC_CTX *tmp_ctx = talloc_new(req);
942 struct ldb_message *msg = NULL;
943 struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, LTDB_BASEINFO);
946 if (tmp_ctx == NULL) {
947 talloc_free(tmp_ctx);
948 return LDB_ERR_OPERATIONS_ERROR;
951 msg = talloc(tmp_ctx, struct ldb_message);
953 talloc_free(tmp_ctx);
954 return LDB_ERR_OPERATIONS_ERROR;
957 tret = ltdb_search_dn1(module, dn, msg);
959 talloc_free(tmp_ctx);
960 req->op.seq_num.seq_num = 0;
961 /* zero is as good as anything when we don't know */
965 req->op.seq_num.seq_num = ldb_msg_find_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
966 talloc_free(tmp_ctx);
970 static const struct ldb_module_ops ltdb_ops = {
972 .search = ltdb_search,
974 .modify = ltdb_modify,
976 .rename = ltdb_rename,
977 .request = ltdb_request,
978 .start_transaction = ltdb_start_trans,
979 .end_transaction = ltdb_end_trans,
980 .del_transaction = ltdb_del_trans,
982 .sequence_number = ltdb_sequence_number
986 connect to the database
988 static int ltdb_connect(struct ldb_context *ldb, const char *url,
989 unsigned int flags, const char *options[],
990 struct ldb_module **module)
993 int tdb_flags, open_flags;
994 struct ltdb_private *ltdb;
997 if (strchr(url, ':')) {
998 if (strncmp(url, "tdb://", 6) != 0) {
999 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1007 tdb_flags = TDB_DEFAULT;
1009 /* check for the 'nosync' option */
1010 if (flags & LDB_FLG_NOSYNC) {
1011 tdb_flags |= TDB_NOSYNC;
1014 if (flags & LDB_FLG_RDONLY) {
1015 open_flags = O_RDONLY;
1017 open_flags = O_CREAT | O_RDWR;
1020 ltdb = talloc_zero(ldb, struct ltdb_private);
1026 /* note that we use quite a large default hash size */
1027 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1028 tdb_flags, open_flags, 0666, ldb);
1030 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1035 ltdb->sequence_number = 0;
1037 *module = talloc(ldb, struct ldb_module);
1043 (*module)->ldb = ldb;
1044 (*module)->prev = (*module)->next = NULL;
1045 (*module)->private_data = ltdb;
1046 (*module)->ops = <db_ops;
1051 int ldb_tdb_init(void)
1053 return ldb_register_backend("tdb", ltdb_connect);