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);
276 TALLOC_CTX *mem_ctx = talloc_new(module);
278 dn = ldb_dn_linearize(mem_ctx, msg->dn);
282 ret = ltdb_modified(module, msg->dn);
283 if (ret != LDB_SUCCESS) {
284 return LDB_ERR_OPERATIONS_ERROR;
288 case LDB_ERR_ENTRY_ALREADY_EXISTS:
290 TALLOC_CTX *mem_ctx = talloc_new(module);
291 char *errstring, *dn;
295 dn = ldb_dn_linearize(mem_ctx, msg->dn);
299 errstring = talloc_asprintf(mem_ctx, "Entry %s already exists",
301 ldb_set_errstring(module->ldb, errstring);
302 talloc_free(mem_ctx);
312 add a record to the database
314 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
316 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
317 struct ltdb_context *ltdb_ac;
318 int tret, ret = LDB_SUCCESS;
320 if (req->controls != NULL) {
321 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
322 if (check_critical_controls(req->controls)) {
323 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
327 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
328 if (req->handle == NULL) {
329 return LDB_ERR_OPERATIONS_ERROR;
331 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
333 tret = ltdb_add_internal(module, req->op.add.message);
334 if (tret != LDB_SUCCESS) {
335 req->handle->status = tret;
339 if (ltdb_ac->callback) {
340 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
343 req->handle->state = LDB_ASYNC_DONE;
348 delete a record from the database, not updating indexes (used for deleting
351 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
353 struct ltdb_private *ltdb = module->private_data;
357 tdb_key = ltdb_key(module, dn);
359 return LDB_ERR_OTHER;
362 ret = tdb_delete(ltdb->tdb, tdb_key);
363 talloc_free(tdb_key.dptr);
366 ret = ltdb_err_map(tdb_error(ltdb->tdb));
372 static int ltdb_delete_internal(struct ldb_module *module, const struct ldb_dn *dn)
374 struct ldb_message *msg;
377 msg = talloc(module, struct ldb_message);
379 return LDB_ERR_OPERATIONS_ERROR;
382 /* in case any attribute of the message was indexed, we need
383 to fetch the old record */
384 ret = ltdb_search_dn1(module, dn, msg);
386 /* not finding the old record is an error */
388 return LDB_ERR_NO_SUCH_OBJECT;
391 ret = ltdb_delete_noindex(module, dn);
392 if (ret != LDB_SUCCESS) {
394 return LDB_ERR_NO_SUCH_OBJECT;
397 /* remove any indexed attributes */
398 ret = ltdb_index_del(module, msg);
399 if (ret != LDB_SUCCESS) {
401 return LDB_ERR_OPERATIONS_ERROR;
404 ret = ltdb_modified(module, dn);
405 if (ret != LDB_SUCCESS) {
406 return LDB_ERR_OPERATIONS_ERROR;
414 delete a record from the database
416 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
418 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
419 struct ltdb_context *ltdb_ac;
420 int tret, ret = LDB_SUCCESS;
422 if (req->controls != NULL) {
423 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
424 if (check_critical_controls(req->controls)) {
425 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
431 if (ltdb_cache_load(module) != 0) {
432 return LDB_ERR_OPERATIONS_ERROR;
435 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
436 if (req->handle == NULL) {
437 return LDB_ERR_OPERATIONS_ERROR;
439 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
441 tret = ltdb_delete_internal(module, req->op.del.dn);
442 if (tret != LDB_SUCCESS) {
443 req->handle->status = tret;
447 if (ltdb_ac->callback) {
448 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
451 req->handle->state = LDB_ASYNC_DONE;
456 find an element by attribute name. At the moment this does a linear search, it should
457 be re-coded to use a binary search once all places that modify records guarantee
460 return the index of the first matching element if found, otherwise -1
462 static int find_element(const struct ldb_message *msg, const char *name)
465 for (i=0;i<msg->num_elements;i++) {
466 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
475 add an element to an existing record. Assumes a elements array that we
476 can call re-alloc on, and assumed that we can re-use the data pointers from the
477 passed in additional values. Use with care!
479 returns 0 on success, -1 on failure (and sets errno)
481 static int msg_add_element(struct ldb_context *ldb,
482 struct ldb_message *msg, struct ldb_message_element *el)
484 struct ldb_message_element *e2;
487 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
488 msg->num_elements+1);
496 e2 = &msg->elements[msg->num_elements];
499 e2->flags = el->flags;
501 if (el->num_values != 0) {
502 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
508 for (i=0;i<el->num_values;i++) {
509 e2->values[i] = el->values[i];
511 e2->num_values = el->num_values;
519 delete all elements having a specified attribute name
521 static int msg_delete_attribute(struct ldb_module *module,
522 struct ldb_context *ldb,
523 struct ldb_message *msg, const char *name)
528 dn = ldb_dn_linearize(ldb, msg->dn);
533 for (i=0;i<msg->num_elements;i++) {
534 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
535 for (j=0;j<msg->elements[i].num_values;j++) {
536 ltdb_index_del_value(module, dn, &msg->elements[i], j);
538 talloc_free(msg->elements[i].values);
539 if (msg->num_elements > (i+1)) {
540 memmove(&msg->elements[i],
542 sizeof(struct ldb_message_element)*
543 (msg->num_elements - (i+1)));
547 msg->elements = talloc_realloc(msg, msg->elements,
548 struct ldb_message_element,
558 delete all elements matching an attribute name/value
560 return 0 on success, -1 on failure
562 static int msg_delete_element(struct ldb_module *module,
563 struct ldb_message *msg,
565 const struct ldb_val *val)
567 struct ldb_context *ldb = module->ldb;
570 struct ldb_message_element *el;
571 const struct ldb_attrib_handler *h;
573 found = find_element(msg, name);
578 el = &msg->elements[found];
580 h = ldb_attrib_handler(ldb, el->name);
582 for (i=0;i<el->num_values;i++) {
583 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
584 if (i<el->num_values-1) {
585 memmove(&el->values[i], &el->values[i+1],
586 sizeof(el->values[i])*(el->num_values-(i+1)));
589 if (el->num_values == 0) {
590 return msg_delete_attribute(module, ldb, msg, name);
601 modify a record - internal interface
603 yuck - this is O(n^2). Luckily n is usually small so we probably
604 get away with it, but if we ever have really large attribute lists
605 then we'll need to look at this again
607 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
609 struct ldb_context *ldb = module->ldb;
610 struct ltdb_private *ltdb = module->private_data;
611 TDB_DATA tdb_key, tdb_data;
612 struct ldb_message *msg2;
616 tdb_key = ltdb_key(module, msg->dn);
618 return LDB_ERR_OTHER;
621 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
622 if (!tdb_data.dptr) {
623 talloc_free(tdb_key.dptr);
624 return ltdb_err_map(tdb_error(ltdb->tdb));
627 msg2 = talloc(tdb_key.dptr, struct ldb_message);
629 talloc_free(tdb_key.dptr);
630 return LDB_ERR_OTHER;
633 ret = ltdb_unpack_data(module, &tdb_data, msg2);
643 for (i=0;i<msg->num_elements;i++) {
644 struct ldb_message_element *el = &msg->elements[i];
645 struct ldb_message_element *el2;
646 struct ldb_val *vals;
650 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
652 case LDB_FLAG_MOD_ADD:
653 /* add this element to the message. fail if it
655 ret = find_element(msg2, el->name);
658 if (msg_add_element(ldb, msg2, el) != 0) {
665 el2 = &msg2->elements[ret];
667 /* An attribute with this name already exists, add all
668 * values if they don't already exist. */
670 for (j=0;j<el->num_values;j++) {
671 if (ldb_msg_find_val(el2, &el->values[j])) {
672 err_string = talloc_strdup(module, "Type or value exists");
673 if (err_string) ldb_set_errstring(module->ldb, err_string);
674 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
679 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
680 el2->num_values + el->num_values);
687 for (j=0;j<el->num_values;j++) {
688 vals[el2->num_values + j] =
689 ldb_val_dup(vals, &el->values[j]);
693 el2->num_values += el->num_values;
697 case LDB_FLAG_MOD_REPLACE:
698 /* replace all elements of this attribute name with the elements
699 listed. The attribute not existing is not an error */
700 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
702 /* add the replacement element, if not empty */
703 if (msg->elements[i].num_values != 0 &&
704 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
710 case LDB_FLAG_MOD_DELETE:
712 dn = ldb_dn_linearize(msg2, msg->dn);
718 /* we could be being asked to delete all
719 values or just some values */
720 if (msg->elements[i].num_values == 0) {
721 if (msg_delete_attribute(module, ldb, msg2,
722 msg->elements[i].name) != 0) {
723 err_string = talloc_asprintf(module, "No such attribute: %s for delete on %s",
724 msg->elements[i].name, dn);
725 if (err_string) ldb_set_errstring(module->ldb, err_string);
726 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
731 for (j=0;j<msg->elements[i].num_values;j++) {
732 if (msg_delete_element(module,
734 msg->elements[i].name,
735 &msg->elements[i].values[j]) != 0) {
736 err_string = talloc_asprintf(module, "No matching attribute value when deleting attribute: %s on %s",
737 msg->elements[i].name, dn);
738 if (err_string) ldb_set_errstring(module->ldb, err_string);
739 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
742 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
749 err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x",
750 msg->elements[i].name,
751 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
752 if (err_string) ldb_set_errstring(module->ldb, err_string);
753 ret = LDB_ERR_PROTOCOL_ERROR;
758 /* we've made all the mods - save the modified record back into the database */
759 ret = ltdb_store(module, msg2, TDB_MODIFY);
760 if (ret != LDB_SUCCESS) {
764 if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
765 ret = LDB_ERR_OPERATIONS_ERROR;
769 talloc_free(tdb_key.dptr);
774 talloc_free(tdb_key.dptr);
782 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
784 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
785 struct ltdb_context *ltdb_ac;
786 int tret, ret = LDB_SUCCESS;
788 if (req->controls != NULL) {
789 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
790 if (check_critical_controls(req->controls)) {
791 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
797 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
798 if (req->handle == NULL) {
799 return LDB_ERR_OPERATIONS_ERROR;
801 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
803 tret = ltdb_check_special_dn(module, req->op.mod.message);
804 if (tret != LDB_SUCCESS) {
805 req->handle->status = tret;
809 if (ltdb_cache_load(module) != 0) {
810 ret = LDB_ERR_OPERATIONS_ERROR;
814 tret = ltdb_modify_internal(module, req->op.mod.message);
815 if (tret != LDB_SUCCESS) {
816 req->handle->status = tret;
820 if (ltdb_ac->callback) {
821 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
824 req->handle->state = LDB_ASYNC_DONE;
831 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
833 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
834 struct ltdb_context *ltdb_ac;
835 struct ldb_message *msg;
836 int tret, ret = LDB_SUCCESS;
838 if (req->controls != NULL) {
839 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
840 if (check_critical_controls(req->controls)) {
841 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
847 if (ltdb_cache_load(module) != 0) {
848 return LDB_ERR_OPERATIONS_ERROR;
851 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
852 if (req->handle == NULL) {
853 return LDB_ERR_OPERATIONS_ERROR;
855 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
857 msg = talloc(ltdb_ac, struct ldb_message);
859 ret = LDB_ERR_OPERATIONS_ERROR;
863 /* in case any attribute of the message was indexed, we need
864 to fetch the old record */
865 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
867 /* not finding the old record is an error */
868 req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
872 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
874 ret = LDB_ERR_OPERATIONS_ERROR;
878 tret = ltdb_add_internal(module, msg);
879 if (tret != LDB_SUCCESS) {
880 ret = LDB_ERR_OPERATIONS_ERROR;
884 tret = ltdb_delete_internal(module, req->op.rename.olddn);
885 if (tret != LDB_SUCCESS) {
886 ltdb_delete_internal(module, req->op.rename.newdn);
887 ret = LDB_ERR_OPERATIONS_ERROR;
891 if (ltdb_ac->callback) {
892 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
895 req->handle->state = LDB_ASYNC_DONE;
899 static int ltdb_start_trans(struct ldb_module *module)
901 struct ltdb_private *ltdb = module->private_data;
903 if (tdb_transaction_start(ltdb->tdb) != 0) {
904 return ltdb_err_map(tdb_error(ltdb->tdb));
910 static int ltdb_end_trans(struct ldb_module *module)
912 struct ltdb_private *ltdb = module->private_data;
914 if (tdb_transaction_commit(ltdb->tdb) != 0) {
915 return ltdb_err_map(tdb_error(ltdb->tdb));
921 static int ltdb_del_trans(struct ldb_module *module)
923 struct ltdb_private *ltdb = module->private_data;
925 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
926 return ltdb_err_map(tdb_error(ltdb->tdb));
932 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
934 return handle->status;
937 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
939 /* check for oustanding critical controls and return an error if found */
940 if (req->controls != NULL) {
941 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
942 if (check_critical_controls(req->controls)) {
943 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
947 /* search, add, modify, delete, rename are handled by their own, no other op supported */
948 return LDB_ERR_OPERATIONS_ERROR;
952 return sequenceNumber from @BASEINFO
954 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
956 TALLOC_CTX *tmp_ctx = talloc_new(req);
957 struct ldb_message *msg = NULL;
958 struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, LTDB_BASEINFO);
961 if (tmp_ctx == NULL) {
962 talloc_free(tmp_ctx);
963 return LDB_ERR_OPERATIONS_ERROR;
966 msg = talloc(tmp_ctx, struct ldb_message);
968 talloc_free(tmp_ctx);
969 return LDB_ERR_OPERATIONS_ERROR;
972 tret = ltdb_search_dn1(module, dn, msg);
974 talloc_free(tmp_ctx);
975 req->op.seq_num.seq_num = 0;
976 /* zero is as good as anything when we don't know */
980 req->op.seq_num.seq_num = ldb_msg_find_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
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;
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, 0666, ldb);
1045 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1050 ltdb->sequence_number = 0;
1052 *module = talloc(ldb, struct ldb_module);
1058 (*module)->ldb = ldb;
1059 (*module)->prev = (*module)->next = NULL;
1060 (*module)->private_data = ltdb;
1061 (*module)->ops = <db_ops;
1066 int ldb_tdb_init(void)
1068 return ldb_register_backend("tdb", ltdb_connect);