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,
82 struct ldb_request *req)
84 struct ltdb_context *ac;
87 h = talloc_zero(req, struct ldb_handle);
89 ldb_set_errstring(module->ldb, "Out of Memory");
95 ac = talloc_zero(h, struct ltdb_context);
97 ldb_set_errstring(module->ldb, "Out of Memory");
102 h->private_data = (void *)ac;
104 h->state = LDB_ASYNC_INIT;
105 h->status = LDB_SUCCESS;
108 ac->context = req->context;
109 ac->callback = req->callback;
115 form a TDB_DATA for a record key
118 note that the key for a record can depend on whether the
119 dn refers to a case sensitive index record or not
121 struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn)
123 struct ldb_context *ldb = module->ldb;
125 char *key_str = NULL;
126 char *dn_folded = NULL;
129 most DNs are case insensitive. The exception is index DNs for
130 case sensitive attributes
132 there are 3 cases dealt with in this code:
134 1) if the dn doesn't start with @ then uppercase the attribute
135 names and the attributes values of case insensitive attributes
136 2) if the dn starts with @ then leave it alone - the indexing code handles
140 dn_folded = ldb_dn_get_casefold(dn);
145 key_str = talloc_asprintf(ldb, "DN=%s", 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 ldb_set_errstring(module->ldb, "Invalid attribute value in an @ATTRIBUTES entry");
182 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
192 we've made a modification to a dn - possibly reindex and
193 update sequence number
195 static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn)
199 if (ldb_dn_is_special(dn) &&
200 (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
201 ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
202 ret = ltdb_reindex(module);
206 !(ldb_dn_is_special(dn) &&
207 ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
208 ret = ltdb_increase_sequence_number(module);
215 store a record into the db
217 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
219 struct ltdb_private *ltdb =
220 talloc_get_type(module->private_data, struct ltdb_private);
221 TDB_DATA tdb_key, tdb_data;
224 tdb_key = ltdb_key(module, msg->dn);
226 return LDB_ERR_OTHER;
229 ret = ltdb_pack_data(module, msg, &tdb_data);
231 talloc_free(tdb_key.dptr);
232 return LDB_ERR_OTHER;
235 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
237 ret = ltdb_err_map(tdb_error(ltdb->tdb));
241 ret = ltdb_index_add(module, msg);
243 tdb_delete(ltdb->tdb, tdb_key);
247 talloc_free(tdb_key.dptr);
248 talloc_free(tdb_data.dptr);
254 static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg)
258 ret = ltdb_check_special_dn(module, msg);
259 if (ret != LDB_SUCCESS) {
263 if (ltdb_cache_load(module) != 0) {
264 return LDB_ERR_OPERATIONS_ERROR;
267 ret = ltdb_store(module, msg, TDB_INSERT);
269 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
272 dn = ldb_dn_linearize(module, msg->dn);
276 ldb_asprintf_errstring(module->ldb, "Entry %s already exists", dn);
281 if (ret == LDB_SUCCESS) {
282 ret = ltdb_modified(module, msg->dn);
283 if (ret != LDB_SUCCESS) {
284 return LDB_ERR_OPERATIONS_ERROR;
292 add a record to the database
294 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
296 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
297 struct ltdb_context *ltdb_ac;
298 int tret, ret = LDB_SUCCESS;
300 if (req->controls != NULL) {
301 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
302 if (check_critical_controls(req->controls)) {
303 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
307 req->handle = init_ltdb_handle(ltdb, module, req);
308 if (req->handle == NULL) {
309 return LDB_ERR_OPERATIONS_ERROR;
311 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
313 tret = ltdb_add_internal(module, req->op.add.message);
314 if (tret != LDB_SUCCESS) {
315 req->handle->status = tret;
319 if (ltdb_ac->callback) {
320 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
323 req->handle->state = LDB_ASYNC_DONE;
328 delete a record from the database, not updating indexes (used for deleting
331 int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn)
333 struct ltdb_private *ltdb =
334 talloc_get_type(module->private_data, struct ltdb_private);
338 tdb_key = ltdb_key(module, dn);
340 return LDB_ERR_OTHER;
343 ret = tdb_delete(ltdb->tdb, tdb_key);
344 talloc_free(tdb_key.dptr);
347 ret = ltdb_err_map(tdb_error(ltdb->tdb));
353 static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
355 struct ldb_message *msg;
358 msg = talloc(module, struct ldb_message);
360 return LDB_ERR_OPERATIONS_ERROR;
363 /* in case any attribute of the message was indexed, we need
364 to fetch the old record */
365 ret = ltdb_search_dn1(module, dn, msg);
367 /* not finding the old record is an error */
369 return LDB_ERR_NO_SUCH_OBJECT;
372 ret = ltdb_delete_noindex(module, dn);
373 if (ret != LDB_SUCCESS) {
375 return LDB_ERR_NO_SUCH_OBJECT;
378 /* remove any indexed attributes */
379 ret = ltdb_index_del(module, msg);
380 if (ret != LDB_SUCCESS) {
382 return LDB_ERR_OPERATIONS_ERROR;
385 ret = ltdb_modified(module, dn);
386 if (ret != LDB_SUCCESS) {
388 return LDB_ERR_OPERATIONS_ERROR;
396 delete a record from the database
398 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
400 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
401 struct ltdb_context *ltdb_ac;
402 int tret, ret = LDB_SUCCESS;
404 if (req->controls != NULL) {
405 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
406 if (check_critical_controls(req->controls)) {
407 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
413 if (ltdb_cache_load(module) != 0) {
414 return LDB_ERR_OPERATIONS_ERROR;
417 req->handle = init_ltdb_handle(ltdb, module, req);
418 if (req->handle == NULL) {
419 return LDB_ERR_OPERATIONS_ERROR;
421 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
423 tret = ltdb_delete_internal(module, req->op.del.dn);
424 if (tret != LDB_SUCCESS) {
425 req->handle->status = tret;
429 if (ltdb_ac->callback) {
430 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
433 req->handle->state = LDB_ASYNC_DONE;
438 find an element by attribute name. At the moment this does a linear search, it should
439 be re-coded to use a binary search once all places that modify records guarantee
442 return the index of the first matching element if found, otherwise -1
444 static int find_element(const struct ldb_message *msg, const char *name)
447 for (i=0;i<msg->num_elements;i++) {
448 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
457 add an element to an existing record. Assumes a elements array that we
458 can call re-alloc on, and assumed that we can re-use the data pointers from the
459 passed in additional values. Use with care!
461 returns 0 on success, -1 on failure (and sets errno)
463 static int msg_add_element(struct ldb_context *ldb,
464 struct ldb_message *msg, struct ldb_message_element *el)
466 struct ldb_message_element *e2;
469 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
470 msg->num_elements+1);
478 e2 = &msg->elements[msg->num_elements];
481 e2->flags = el->flags;
483 if (el->num_values != 0) {
484 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
490 for (i=0;i<el->num_values;i++) {
491 e2->values[i] = el->values[i];
493 e2->num_values = el->num_values;
501 delete all elements having a specified attribute name
503 static int msg_delete_attribute(struct ldb_module *module,
504 struct ldb_context *ldb,
505 struct ldb_message *msg, const char *name)
510 dn = ldb_dn_linearize(ldb, msg->dn);
515 for (i=0;i<msg->num_elements;i++) {
516 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
517 for (j=0;j<msg->elements[i].num_values;j++) {
518 ltdb_index_del_value(module, dn, &msg->elements[i], j);
520 talloc_free(msg->elements[i].values);
521 if (msg->num_elements > (i+1)) {
522 memmove(&msg->elements[i],
524 sizeof(struct ldb_message_element)*
525 (msg->num_elements - (i+1)));
529 msg->elements = talloc_realloc(msg, msg->elements,
530 struct ldb_message_element,
540 delete all elements matching an attribute name/value
542 return 0 on success, -1 on failure
544 static int msg_delete_element(struct ldb_module *module,
545 struct ldb_message *msg,
547 const struct ldb_val *val)
549 struct ldb_context *ldb = module->ldb;
552 struct ldb_message_element *el;
553 const struct ldb_attrib_handler *h;
555 found = find_element(msg, name);
560 el = &msg->elements[found];
562 h = ldb_attrib_handler(ldb, el->name);
564 for (i=0;i<el->num_values;i++) {
565 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
566 if (i<el->num_values-1) {
567 memmove(&el->values[i], &el->values[i+1],
568 sizeof(el->values[i])*(el->num_values-(i+1)));
571 if (el->num_values == 0) {
572 return msg_delete_attribute(module, ldb, msg, name);
583 modify a record - internal interface
585 yuck - this is O(n^2). Luckily n is usually small so we probably
586 get away with it, but if we ever have really large attribute lists
587 then we'll need to look at this again
589 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
591 struct ldb_context *ldb = module->ldb;
592 struct ltdb_private *ltdb =
593 talloc_get_type(module->private_data, struct ltdb_private);
594 TDB_DATA tdb_key, tdb_data;
595 struct ldb_message *msg2;
599 tdb_key = ltdb_key(module, msg->dn);
601 return LDB_ERR_OTHER;
604 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
605 if (!tdb_data.dptr) {
606 talloc_free(tdb_key.dptr);
607 return ltdb_err_map(tdb_error(ltdb->tdb));
610 msg2 = talloc(tdb_key.dptr, struct ldb_message);
612 talloc_free(tdb_key.dptr);
613 return LDB_ERR_OTHER;
616 ret = ltdb_unpack_data(module, &tdb_data, msg2);
626 for (i=0;i<msg->num_elements;i++) {
627 struct ldb_message_element *el = &msg->elements[i];
628 struct ldb_message_element *el2;
629 struct ldb_val *vals;
632 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
634 case LDB_FLAG_MOD_ADD:
635 /* add this element to the message. fail if it
637 ret = find_element(msg2, el->name);
640 if (msg_add_element(ldb, msg2, el) != 0) {
647 el2 = &msg2->elements[ret];
649 /* An attribute with this name already exists, add all
650 * values if they don't already exist. */
652 for (j=0;j<el->num_values;j++) {
653 if (ldb_msg_find_val(el2, &el->values[j])) {
654 ldb_set_errstring(module->ldb, "Type or value exists");
655 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
660 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
661 el2->num_values + el->num_values);
668 for (j=0;j<el->num_values;j++) {
669 vals[el2->num_values + j] =
670 ldb_val_dup(vals, &el->values[j]);
674 el2->num_values += el->num_values;
678 case LDB_FLAG_MOD_REPLACE:
679 /* replace all elements of this attribute name with the elements
680 listed. The attribute not existing is not an error */
681 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
683 /* add the replacement element, if not empty */
684 if (msg->elements[i].num_values != 0 &&
685 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
691 case LDB_FLAG_MOD_DELETE:
693 dn = ldb_dn_linearize(msg2, msg->dn);
699 /* we could be being asked to delete all
700 values or just some values */
701 if (msg->elements[i].num_values == 0) {
702 if (msg_delete_attribute(module, ldb, msg2,
703 msg->elements[i].name) != 0) {
704 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
705 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
710 for (j=0;j<msg->elements[i].num_values;j++) {
711 if (msg_delete_element(module,
713 msg->elements[i].name,
714 &msg->elements[i].values[j]) != 0) {
715 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
716 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
719 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
726 ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
727 msg->elements[i].name,
728 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
729 ret = LDB_ERR_PROTOCOL_ERROR;
734 /* we've made all the mods - save the modified record back into the database */
735 ret = ltdb_store(module, msg2, TDB_MODIFY);
736 if (ret != LDB_SUCCESS) {
740 if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
741 ret = LDB_ERR_OPERATIONS_ERROR;
745 talloc_free(tdb_key.dptr);
750 talloc_free(tdb_key.dptr);
758 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
760 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
761 struct ltdb_context *ltdb_ac;
762 int tret, ret = LDB_SUCCESS;
764 if (req->controls != NULL) {
765 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
766 if (check_critical_controls(req->controls)) {
767 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
773 req->handle = init_ltdb_handle(ltdb, module, req);
774 if (req->handle == NULL) {
775 return LDB_ERR_OPERATIONS_ERROR;
777 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
779 tret = ltdb_check_special_dn(module, req->op.mod.message);
780 if (tret != LDB_SUCCESS) {
781 req->handle->status = tret;
785 if (ltdb_cache_load(module) != 0) {
786 ret = LDB_ERR_OPERATIONS_ERROR;
790 tret = ltdb_modify_internal(module, req->op.mod.message);
791 if (tret != LDB_SUCCESS) {
792 req->handle->status = tret;
796 if (ltdb_ac->callback) {
797 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
800 req->handle->state = LDB_ASYNC_DONE;
807 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
809 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
810 struct ltdb_context *ltdb_ac;
811 struct ldb_message *msg;
812 int tret, ret = LDB_SUCCESS;
814 if (req->controls != NULL) {
815 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
816 if (check_critical_controls(req->controls)) {
817 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
823 if (ltdb_cache_load(module) != 0) {
824 return LDB_ERR_OPERATIONS_ERROR;
827 req->handle = init_ltdb_handle(ltdb, module, req);
828 if (req->handle == NULL) {
829 return LDB_ERR_OPERATIONS_ERROR;
831 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
833 msg = talloc(ltdb_ac, struct ldb_message);
835 ret = LDB_ERR_OPERATIONS_ERROR;
839 /* in case any attribute of the message was indexed, we need
840 to fetch the old record */
841 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
843 /* not finding the old record is an error */
844 req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
848 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
850 ret = LDB_ERR_OPERATIONS_ERROR;
854 tret = ltdb_add_internal(module, msg);
855 if (tret != LDB_SUCCESS) {
856 ret = LDB_ERR_OPERATIONS_ERROR;
860 tret = ltdb_delete_internal(module, req->op.rename.olddn);
861 if (tret != LDB_SUCCESS) {
862 ltdb_delete_internal(module, req->op.rename.newdn);
863 ret = LDB_ERR_OPERATIONS_ERROR;
867 if (ltdb_ac->callback) {
868 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
871 req->handle->state = LDB_ASYNC_DONE;
875 static int ltdb_start_trans(struct ldb_module *module)
877 struct ltdb_private *ltdb =
878 talloc_get_type(module->private_data, struct ltdb_private);
880 if (tdb_transaction_start(ltdb->tdb) != 0) {
881 return ltdb_err_map(tdb_error(ltdb->tdb));
887 static int ltdb_end_trans(struct ldb_module *module)
889 struct ltdb_private *ltdb =
890 talloc_get_type(module->private_data, struct ltdb_private);
892 if (tdb_transaction_commit(ltdb->tdb) != 0) {
893 return ltdb_err_map(tdb_error(ltdb->tdb));
899 static int ltdb_del_trans(struct ldb_module *module)
901 struct ltdb_private *ltdb =
902 talloc_get_type(module->private_data, struct ltdb_private);
904 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
905 return ltdb_err_map(tdb_error(ltdb->tdb));
911 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
913 return handle->status;
916 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
918 /* check for oustanding critical controls and return an error if found */
919 if (req->controls != NULL) {
920 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
921 if (check_critical_controls(req->controls)) {
922 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
926 /* search, add, modify, delete, rename are handled by their own, no other op supported */
927 return LDB_ERR_OPERATIONS_ERROR;
931 return sequenceNumber from @BASEINFO
933 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
935 TALLOC_CTX *tmp_ctx = talloc_new(req);
936 struct ldb_message *msg = NULL;
937 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
940 if (tmp_ctx == NULL) {
941 talloc_free(tmp_ctx);
942 return LDB_ERR_OPERATIONS_ERROR;
945 msg = talloc(tmp_ctx, struct ldb_message);
947 talloc_free(tmp_ctx);
948 return LDB_ERR_OPERATIONS_ERROR;
951 req->op.seq_num.flags = 0;
953 tret = ltdb_search_dn1(module, dn, msg);
955 talloc_free(tmp_ctx);
956 req->op.seq_num.seq_num = 0;
957 /* zero is as good as anything when we don't know */
961 switch (req->op.seq_num.type) {
962 case LDB_SEQ_HIGHEST_SEQ:
963 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
966 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
967 req->op.seq_num.seq_num++;
969 case LDB_SEQ_HIGHEST_TIMESTAMP:
971 const char *date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
973 req->op.seq_num.seq_num = ldb_string_to_time(date);
975 req->op.seq_num.seq_num = 0;
976 /* zero is as good as anything when we don't know */
981 talloc_free(tmp_ctx);
985 static const struct ldb_module_ops ltdb_ops = {
987 .search = ltdb_search,
989 .modify = ltdb_modify,
991 .rename = ltdb_rename,
992 .request = ltdb_request,
993 .start_transaction = ltdb_start_trans,
994 .end_transaction = ltdb_end_trans,
995 .del_transaction = ltdb_del_trans,
997 .sequence_number = ltdb_sequence_number
1001 connect to the database
1003 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1004 unsigned int flags, const char *options[],
1005 struct ldb_module **module)
1008 int tdb_flags, open_flags;
1009 struct ltdb_private *ltdb;
1012 if (strchr(url, ':')) {
1013 if (strncmp(url, "tdb://", 6) != 0) {
1014 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1022 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1024 /* check for the 'nosync' option */
1025 if (flags & LDB_FLG_NOSYNC) {
1026 tdb_flags |= TDB_NOSYNC;
1029 if (flags & LDB_FLG_RDONLY) {
1030 open_flags = O_RDONLY;
1032 open_flags = O_CREAT | O_RDWR;
1035 ltdb = talloc_zero(ldb, struct ltdb_private);
1041 /* note that we use quite a large default hash size */
1042 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1043 tdb_flags, open_flags,
1044 ldb->create_perms, ldb);
1046 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1051 ltdb->sequence_number = 0;
1053 *module = talloc(ldb, struct ldb_module);
1059 talloc_set_name_const(*module, "ldb_tdb backend");
1060 (*module)->ldb = ldb;
1061 (*module)->prev = (*module)->next = NULL;
1062 (*module)->private_data = ltdb;
1063 (*module)->ops = <db_ops;
1065 if (ltdb_cache_load(*module) != 0) {
1066 talloc_free(*module);
1074 int ldb_tdb_init(void)
1076 return ldb_register_backend("tdb", ltdb_connect);