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
45 #include "ldb_includes.h"
51 map a tdb error code to a ldb error code
53 static int ltdb_err_map(enum TDB_ERROR tdb_code)
61 return LDB_ERR_OPERATIONS_ERROR;
63 return LDB_ERR_PROTOCOL_ERROR;
67 case TDB_ERR_LOCK_TIMEOUT:
68 return LDB_ERR_TIME_LIMIT_EXCEEDED;
70 return LDB_ERR_ENTRY_ALREADY_EXISTS;
72 return LDB_ERR_NO_SUCH_OBJECT;
74 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
80 struct ldb_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,
81 struct ldb_request *req)
83 struct ltdb_context *ac;
86 h = talloc_zero(req, struct ldb_handle);
88 ldb_set_errstring(module->ldb, "Out of Memory");
94 ac = talloc_zero(h, struct ltdb_context);
96 ldb_set_errstring(module->ldb, "Out of Memory");
101 h->private_data = (void *)ac;
103 h->state = LDB_ASYNC_INIT;
104 h->status = LDB_SUCCESS;
107 ac->context = req->context;
108 ac->callback = req->callback;
114 form a TDB_DATA for a record key
117 note that the key for a record can depend on whether the
118 dn refers to a case sensitive index record or not
120 struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn)
122 struct ldb_context *ldb = module->ldb;
124 char *key_str = NULL;
125 const char *dn_folded = NULL;
128 most DNs are case insensitive. The exception is index DNs for
129 case sensitive attributes
131 there are 3 cases dealt with in this code:
133 1) if the dn doesn't start with @ then uppercase the attribute
134 names and the attributes values of case insensitive attributes
135 2) if the dn starts with @ then leave it alone - the indexing code handles
139 dn_folded = ldb_dn_get_casefold(dn);
144 key_str = talloc_strdup(ldb, "DN=");
149 key_str = talloc_append_string(ldb, key_str, 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 ldb_set_errstring(module->ldb, "Invalid attribute value in an @ATTRIBUTES entry");
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, struct ldb_dn *dn)
200 int ret = LDB_SUCCESS;
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);
208 if (ret == LDB_SUCCESS &&
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 =
223 talloc_get_type(module->private_data, struct ltdb_private);
224 TDB_DATA tdb_key, tdb_data;
227 tdb_key = ltdb_key(module, msg->dn);
229 return LDB_ERR_OTHER;
232 ret = ltdb_pack_data(module, msg, &tdb_data);
234 talloc_free(tdb_key.dptr);
235 return LDB_ERR_OTHER;
238 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
240 ret = ltdb_err_map(tdb_error(ltdb->tdb));
244 ret = ltdb_index_add(module, msg);
245 if (ret != LDB_SUCCESS) {
246 tdb_delete(ltdb->tdb, tdb_key);
250 talloc_free(tdb_key.dptr);
251 talloc_free(tdb_data.dptr);
257 static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg)
261 ret = ltdb_check_special_dn(module, msg);
262 if (ret != LDB_SUCCESS) {
266 if (ltdb_cache_load(module) != 0) {
267 return LDB_ERR_OPERATIONS_ERROR;
270 ret = ltdb_store(module, msg, TDB_INSERT);
272 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
273 ldb_asprintf_errstring(module->ldb, "Entry %s already exists", ldb_dn_get_linearized(msg->dn));
277 if (ret == LDB_SUCCESS) {
278 ret = ltdb_index_one(module, msg, 1);
279 if (ret != LDB_SUCCESS) {
283 ret = ltdb_modified(module, msg->dn);
284 if (ret != LDB_SUCCESS) {
293 add a record to the database
295 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
297 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
298 struct ltdb_context *ltdb_ac;
299 int tret, ret = LDB_SUCCESS;
301 if (check_critical_controls(req->controls)) {
302 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
305 req->handle = init_ltdb_handle(ltdb, module, req);
306 if (req->handle == NULL) {
307 return LDB_ERR_OPERATIONS_ERROR;
309 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
311 tret = ltdb_add_internal(module, req->op.add.message);
312 if (tret != LDB_SUCCESS) {
313 req->handle->status = tret;
317 if (ltdb_ac->callback) {
318 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
321 req->handle->state = LDB_ASYNC_DONE;
326 delete a record from the database, not updating indexes (used for deleting
329 int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn)
331 struct ltdb_private *ltdb =
332 talloc_get_type(module->private_data, struct ltdb_private);
336 tdb_key = ltdb_key(module, dn);
338 return LDB_ERR_OTHER;
341 ret = tdb_delete(ltdb->tdb, tdb_key);
342 talloc_free(tdb_key.dptr);
345 ret = ltdb_err_map(tdb_error(ltdb->tdb));
351 static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
353 struct ldb_message *msg;
356 msg = talloc(module, struct ldb_message);
358 return LDB_ERR_OPERATIONS_ERROR;
361 /* in case any attribute of the message was indexed, we need
362 to fetch the old record */
363 ret = ltdb_search_dn1(module, dn, msg);
364 if (ret != LDB_SUCCESS) {
365 /* not finding the old record is an error */
369 ret = ltdb_delete_noindex(module, dn);
370 if (ret != LDB_SUCCESS) {
374 /* remove one level attribute */
375 ret = ltdb_index_one(module, msg, 0);
376 if (ret != LDB_SUCCESS) {
380 /* remove any indexed attributes */
381 ret = ltdb_index_del(module, msg);
382 if (ret != LDB_SUCCESS) {
386 ret = ltdb_modified(module, dn);
387 if (ret != LDB_SUCCESS) {
397 delete a record from the database
399 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
401 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
402 struct ltdb_context *ltdb_ac;
403 int tret, ret = LDB_SUCCESS;
405 if (check_critical_controls(req->controls)) {
406 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
411 if (ltdb_cache_load(module) != 0) {
412 return LDB_ERR_OPERATIONS_ERROR;
415 req->handle = init_ltdb_handle(ltdb, module, req);
416 if (req->handle == NULL) {
417 return LDB_ERR_OPERATIONS_ERROR;
419 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
421 tret = ltdb_delete_internal(module, req->op.del.dn);
422 if (tret != LDB_SUCCESS) {
423 req->handle->status = tret;
427 if (ltdb_ac->callback) {
428 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
431 req->handle->state = LDB_ASYNC_DONE;
436 find an element by attribute name. At the moment this does a linear search, it should
437 be re-coded to use a binary search once all places that modify records guarantee
440 return the index of the first matching element if found, otherwise -1
442 static int find_element(const struct ldb_message *msg, const char *name)
445 for (i=0;i<msg->num_elements;i++) {
446 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
455 add an element to an existing record. Assumes a elements array that we
456 can call re-alloc on, and assumed that we can re-use the data pointers from the
457 passed in additional values. Use with care!
459 returns 0 on success, -1 on failure (and sets errno)
461 static int msg_add_element(struct ldb_context *ldb,
462 struct ldb_message *msg, struct ldb_message_element *el)
464 struct ldb_message_element *e2;
467 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
468 msg->num_elements+1);
476 e2 = &msg->elements[msg->num_elements];
479 e2->flags = el->flags;
481 if (el->num_values != 0) {
482 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
488 for (i=0;i<el->num_values;i++) {
489 e2->values[i] = el->values[i];
491 e2->num_values = el->num_values;
499 delete all elements having a specified attribute name
501 static int msg_delete_attribute(struct ldb_module *module,
502 struct ldb_context *ldb,
503 struct ldb_message *msg, const char *name)
508 dn = ldb_dn_get_linearized(msg->dn);
513 for (i=0;i<msg->num_elements;i++) {
514 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
515 for (j=0;j<msg->elements[i].num_values;j++) {
516 ltdb_index_del_value(module, dn, &msg->elements[i], j);
518 talloc_free(msg->elements[i].values);
519 if (msg->num_elements > (i+1)) {
520 memmove(&msg->elements[i],
522 sizeof(struct ldb_message_element)*
523 (msg->num_elements - (i+1)));
527 msg->elements = talloc_realloc(msg, msg->elements,
528 struct ldb_message_element,
537 delete all elements matching an attribute name/value
539 return 0 on success, -1 on failure
541 static int msg_delete_element(struct ldb_module *module,
542 struct ldb_message *msg,
544 const struct ldb_val *val)
546 struct ldb_context *ldb = module->ldb;
549 struct ldb_message_element *el;
550 const struct ldb_schema_attribute *a;
552 found = find_element(msg, name);
557 el = &msg->elements[found];
559 a = ldb_schema_attribute_by_name(ldb, el->name);
561 for (i=0;i<el->num_values;i++) {
562 if (a->syntax->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
563 if (i<el->num_values-1) {
564 memmove(&el->values[i], &el->values[i+1],
565 sizeof(el->values[i])*(el->num_values-(i+1)));
568 if (el->num_values == 0) {
569 return msg_delete_attribute(module, ldb, msg, name);
580 modify a record - internal interface
582 yuck - this is O(n^2). Luckily n is usually small so we probably
583 get away with it, but if we ever have really large attribute lists
584 then we'll need to look at this again
586 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
588 struct ldb_context *ldb = module->ldb;
589 struct ltdb_private *ltdb =
590 talloc_get_type(module->private_data, struct ltdb_private);
591 TDB_DATA tdb_key, tdb_data;
592 struct ldb_message *msg2;
596 tdb_key = ltdb_key(module, msg->dn);
598 return LDB_ERR_OTHER;
601 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
602 if (!tdb_data.dptr) {
603 talloc_free(tdb_key.dptr);
604 return ltdb_err_map(tdb_error(ltdb->tdb));
607 msg2 = talloc(tdb_key.dptr, struct ldb_message);
609 talloc_free(tdb_key.dptr);
610 return LDB_ERR_OTHER;
613 ret = ltdb_unpack_data(module, &tdb_data, msg2);
623 for (i=0;i<msg->num_elements;i++) {
624 struct ldb_message_element *el = &msg->elements[i];
625 struct ldb_message_element *el2;
626 struct ldb_val *vals;
629 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
631 case LDB_FLAG_MOD_ADD:
632 /* add this element to the message. fail if it
634 idx = find_element(msg2, el->name);
637 if (msg_add_element(ldb, msg2, el) != 0) {
644 el2 = &msg2->elements[idx];
646 /* An attribute with this name already exists,
647 * add all values if they don't already exist
648 * (check both the other elements to be added,
649 * and those already in the db). */
651 for (j=0;j<el->num_values;j++) {
652 if (ldb_msg_find_val(el2, &el->values[j])) {
653 ldb_asprintf_errstring(module->ldb, "%s: value #%d already exists", el->name, j);
654 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
657 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
658 ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
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, el->name);
687 for (j=0;j<el->num_values;j++) {
688 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
689 ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
690 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
695 /* add the replacement element, if not empty */
696 if (el->num_values != 0 &&
697 msg_add_element(ldb, msg2, el) != 0) {
703 case LDB_FLAG_MOD_DELETE:
705 dn = ldb_dn_get_linearized(msg->dn);
711 /* we could be being asked to delete all
712 values or just some values */
713 if (msg->elements[i].num_values == 0) {
714 if (msg_delete_attribute(module, ldb, msg2,
715 msg->elements[i].name) != 0) {
716 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
717 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
722 for (j=0;j<msg->elements[i].num_values;j++) {
723 if (msg_delete_element(module,
725 msg->elements[i].name,
726 &msg->elements[i].values[j]) != 0) {
727 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
728 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
731 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
732 if (ret != LDB_SUCCESS) {
738 ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
739 msg->elements[i].name,
740 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
741 ret = LDB_ERR_PROTOCOL_ERROR;
746 /* we've made all the mods - save the modified record back into the database */
747 ret = ltdb_store(module, msg2, TDB_MODIFY);
748 if (ret != LDB_SUCCESS) {
752 ret = ltdb_modified(module, msg->dn);
753 if (ret != LDB_SUCCESS) {
757 talloc_free(tdb_key.dptr);
762 talloc_free(tdb_key.dptr);
770 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
772 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
773 struct ltdb_context *ltdb_ac;
774 int tret, ret = LDB_SUCCESS;
776 if (check_critical_controls(req->controls)) {
777 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
782 req->handle = init_ltdb_handle(ltdb, module, req);
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 (check_critical_controls(req->controls)) {
824 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
829 if (ltdb_cache_load(module) != 0) {
830 return LDB_ERR_OPERATIONS_ERROR;
833 req->handle = init_ltdb_handle(ltdb, module, req);
834 if (req->handle == NULL) {
835 return LDB_ERR_OPERATIONS_ERROR;
837 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
839 msg = talloc(ltdb_ac, struct ldb_message);
841 ret = LDB_ERR_OPERATIONS_ERROR;
845 /* in case any attribute of the message was indexed, we need
846 to fetch the old record */
847 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
848 if (tret != LDB_SUCCESS) {
849 /* not finding the old record is an error */
850 req->handle->status = tret;
854 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
856 ret = LDB_ERR_OPERATIONS_ERROR;
860 ret = ltdb_add_internal(module, msg);
861 if (ret != LDB_SUCCESS) {
865 tret = ltdb_delete_internal(module, req->op.rename.olddn);
866 if (tret != LDB_SUCCESS) {
867 ltdb_delete_internal(module, req->op.rename.newdn);
868 ret = LDB_ERR_OPERATIONS_ERROR;
872 if (ltdb_ac->callback) {
873 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
876 req->handle->state = LDB_ASYNC_DONE;
880 static int ltdb_start_trans(struct ldb_module *module)
882 struct ltdb_private *ltdb =
883 talloc_get_type(module->private_data, struct ltdb_private);
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 =
895 talloc_get_type(module->private_data, struct ltdb_private);
897 if (tdb_transaction_commit(ltdb->tdb) != 0) {
898 return ltdb_err_map(tdb_error(ltdb->tdb));
904 static int ltdb_del_trans(struct ldb_module *module)
906 struct ltdb_private *ltdb =
907 talloc_get_type(module->private_data, struct ltdb_private);
909 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
910 return ltdb_err_map(tdb_error(ltdb->tdb));
916 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
918 return handle->status;
921 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
923 /* check for oustanding critical controls and return an error if found */
924 if (check_critical_controls(req->controls)) {
925 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
928 /* search, add, modify, delete, rename are handled by their own, no other op supported */
929 return LDB_ERR_OPERATIONS_ERROR;
933 return sequenceNumber from @BASEINFO
935 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
937 TALLOC_CTX *tmp_ctx = talloc_new(req);
938 struct ldb_message *msg = NULL;
939 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
942 if (tmp_ctx == NULL) {
943 talloc_free(tmp_ctx);
944 return LDB_ERR_OPERATIONS_ERROR;
947 msg = talloc(tmp_ctx, struct ldb_message);
949 talloc_free(tmp_ctx);
950 return LDB_ERR_OPERATIONS_ERROR;
953 req->op.seq_num.flags = 0;
955 tret = ltdb_search_dn1(module, dn, msg);
956 if (tret != LDB_SUCCESS) {
957 talloc_free(tmp_ctx);
958 /* zero is as good as anything when we don't know */
959 req->op.seq_num.seq_num = 0;
963 switch (req->op.seq_num.type) {
964 case LDB_SEQ_HIGHEST_SEQ:
965 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
968 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
969 req->op.seq_num.seq_num++;
971 case LDB_SEQ_HIGHEST_TIMESTAMP:
973 const char *date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
975 req->op.seq_num.seq_num = ldb_string_to_time(date);
977 req->op.seq_num.seq_num = 0;
978 /* zero is as good as anything when we don't know */
983 talloc_free(tmp_ctx);
987 static const struct ldb_module_ops ltdb_ops = {
989 .search = ltdb_search,
991 .modify = ltdb_modify,
993 .rename = ltdb_rename,
994 .request = ltdb_request,
995 .start_transaction = ltdb_start_trans,
996 .end_transaction = ltdb_end_trans,
997 .del_transaction = ltdb_del_trans,
999 .sequence_number = ltdb_sequence_number
1003 connect to the database
1005 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1006 unsigned int flags, const char *options[],
1007 struct ldb_module **module)
1010 int tdb_flags, open_flags;
1011 struct ltdb_private *ltdb;
1014 if (strchr(url, ':')) {
1015 if (strncmp(url, "tdb://", 6) != 0) {
1016 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1024 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1026 /* check for the 'nosync' option */
1027 if (flags & LDB_FLG_NOSYNC) {
1028 tdb_flags |= TDB_NOSYNC;
1031 /* and nommap option */
1032 if (flags & LDB_FLG_NOMMAP) {
1033 tdb_flags |= TDB_NOMMAP;
1036 if (flags & LDB_FLG_RDONLY) {
1037 open_flags = O_RDONLY;
1039 open_flags = O_CREAT | O_RDWR;
1042 ltdb = talloc_zero(ldb, struct ltdb_private);
1048 /* note that we use quite a large default hash size */
1049 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1050 tdb_flags, open_flags,
1051 ldb->create_perms, ldb);
1053 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1058 ltdb->sequence_number = 0;
1060 *module = talloc(ldb, struct ldb_module);
1066 talloc_set_name_const(*module, "ldb_tdb backend");
1067 (*module)->ldb = ldb;
1068 (*module)->prev = (*module)->next = NULL;
1069 (*module)->private_data = ltdb;
1070 (*module)->ops = <db_ops;
1072 if (ltdb_cache_load(*module) != 0) {
1073 talloc_free(*module);
1081 int ldb_tdb_init(void)
1083 return ldb_register_backend("tdb", ltdb_connect);