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 ret = find_element(msg2, el->name);
637 if (msg_add_element(ldb, msg2, el) != 0) {
644 el2 = &msg2->elements[ret];
646 /* An attribute with this name already exists, add all
647 * values if they don't already exist. */
649 for (j=0;j<el->num_values;j++) {
650 if (ldb_msg_find_val(el2, &el->values[j])) {
651 ldb_set_errstring(module->ldb, "Type or value exists");
652 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
657 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
658 el2->num_values + el->num_values);
665 for (j=0;j<el->num_values;j++) {
666 vals[el2->num_values + j] =
667 ldb_val_dup(vals, &el->values[j]);
671 el2->num_values += el->num_values;
675 case LDB_FLAG_MOD_REPLACE:
676 /* replace all elements of this attribute name with the elements
677 listed. The attribute not existing is not an error */
678 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
680 /* add the replacement element, if not empty */
681 if (msg->elements[i].num_values != 0 &&
682 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
688 case LDB_FLAG_MOD_DELETE:
690 dn = ldb_dn_get_linearized(msg->dn);
696 /* we could be being asked to delete all
697 values or just some values */
698 if (msg->elements[i].num_values == 0) {
699 if (msg_delete_attribute(module, ldb, msg2,
700 msg->elements[i].name) != 0) {
701 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
702 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
707 for (j=0;j<msg->elements[i].num_values;j++) {
708 if (msg_delete_element(module,
710 msg->elements[i].name,
711 &msg->elements[i].values[j]) != 0) {
712 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
713 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
716 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
717 if (ret != LDB_SUCCESS) {
723 ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
724 msg->elements[i].name,
725 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
726 ret = LDB_ERR_PROTOCOL_ERROR;
731 /* we've made all the mods - save the modified record back into the database */
732 ret = ltdb_store(module, msg2, TDB_MODIFY);
733 if (ret != LDB_SUCCESS) {
737 ret = ltdb_modified(module, msg->dn);
738 if (ret != LDB_SUCCESS) {
742 talloc_free(tdb_key.dptr);
747 talloc_free(tdb_key.dptr);
755 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
757 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
758 struct ltdb_context *ltdb_ac;
759 int tret, ret = LDB_SUCCESS;
761 if (check_critical_controls(req->controls)) {
762 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
767 req->handle = init_ltdb_handle(ltdb, module, req);
768 if (req->handle == NULL) {
769 return LDB_ERR_OPERATIONS_ERROR;
771 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
773 tret = ltdb_check_special_dn(module, req->op.mod.message);
774 if (tret != LDB_SUCCESS) {
775 req->handle->status = tret;
779 if (ltdb_cache_load(module) != 0) {
780 ret = LDB_ERR_OPERATIONS_ERROR;
784 tret = ltdb_modify_internal(module, req->op.mod.message);
785 if (tret != LDB_SUCCESS) {
786 req->handle->status = tret;
790 if (ltdb_ac->callback) {
791 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
794 req->handle->state = LDB_ASYNC_DONE;
801 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
803 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
804 struct ltdb_context *ltdb_ac;
805 struct ldb_message *msg;
806 int tret, ret = LDB_SUCCESS;
808 if (check_critical_controls(req->controls)) {
809 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
814 if (ltdb_cache_load(module) != 0) {
815 return LDB_ERR_OPERATIONS_ERROR;
818 req->handle = init_ltdb_handle(ltdb, module, req);
819 if (req->handle == NULL) {
820 return LDB_ERR_OPERATIONS_ERROR;
822 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
824 msg = talloc(ltdb_ac, struct ldb_message);
826 ret = LDB_ERR_OPERATIONS_ERROR;
830 /* in case any attribute of the message was indexed, we need
831 to fetch the old record */
832 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
833 if (tret != LDB_SUCCESS) {
834 /* not finding the old record is an error */
835 req->handle->status = tret;
839 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
841 ret = LDB_ERR_OPERATIONS_ERROR;
845 tret = ltdb_add_internal(module, msg);
846 if (tret != LDB_SUCCESS) {
847 ret = LDB_ERR_OPERATIONS_ERROR;
851 tret = ltdb_delete_internal(module, req->op.rename.olddn);
852 if (tret != LDB_SUCCESS) {
853 ltdb_delete_internal(module, req->op.rename.newdn);
854 ret = LDB_ERR_OPERATIONS_ERROR;
858 if (ltdb_ac->callback) {
859 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
862 req->handle->state = LDB_ASYNC_DONE;
866 static int ltdb_start_trans(struct ldb_module *module)
868 struct ltdb_private *ltdb =
869 talloc_get_type(module->private_data, struct ltdb_private);
871 if (tdb_transaction_start(ltdb->tdb) != 0) {
872 return ltdb_err_map(tdb_error(ltdb->tdb));
878 static int ltdb_end_trans(struct ldb_module *module)
880 struct ltdb_private *ltdb =
881 talloc_get_type(module->private_data, struct ltdb_private);
883 if (tdb_transaction_commit(ltdb->tdb) != 0) {
884 return ltdb_err_map(tdb_error(ltdb->tdb));
890 static int ltdb_del_trans(struct ldb_module *module)
892 struct ltdb_private *ltdb =
893 talloc_get_type(module->private_data, struct ltdb_private);
895 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
896 return ltdb_err_map(tdb_error(ltdb->tdb));
902 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
904 return handle->status;
907 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
909 /* check for oustanding critical controls and return an error if found */
910 if (check_critical_controls(req->controls)) {
911 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
914 /* search, add, modify, delete, rename are handled by their own, no other op supported */
915 return LDB_ERR_OPERATIONS_ERROR;
919 return sequenceNumber from @BASEINFO
921 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
923 TALLOC_CTX *tmp_ctx = talloc_new(req);
924 struct ldb_message *msg = NULL;
925 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
928 if (tmp_ctx == NULL) {
929 talloc_free(tmp_ctx);
930 return LDB_ERR_OPERATIONS_ERROR;
933 msg = talloc(tmp_ctx, struct ldb_message);
935 talloc_free(tmp_ctx);
936 return LDB_ERR_OPERATIONS_ERROR;
939 req->op.seq_num.flags = 0;
941 tret = ltdb_search_dn1(module, dn, msg);
942 if (tret != LDB_SUCCESS) {
943 talloc_free(tmp_ctx);
944 /* zero is as good as anything when we don't know */
945 req->op.seq_num.seq_num = 0;
949 switch (req->op.seq_num.type) {
950 case LDB_SEQ_HIGHEST_SEQ:
951 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
954 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
955 req->op.seq_num.seq_num++;
957 case LDB_SEQ_HIGHEST_TIMESTAMP:
959 const char *date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
961 req->op.seq_num.seq_num = ldb_string_to_time(date);
963 req->op.seq_num.seq_num = 0;
964 /* zero is as good as anything when we don't know */
969 talloc_free(tmp_ctx);
973 static const struct ldb_module_ops ltdb_ops = {
975 .search = ltdb_search,
977 .modify = ltdb_modify,
979 .rename = ltdb_rename,
980 .request = ltdb_request,
981 .start_transaction = ltdb_start_trans,
982 .end_transaction = ltdb_end_trans,
983 .del_transaction = ltdb_del_trans,
985 .sequence_number = ltdb_sequence_number
989 connect to the database
991 static int ltdb_connect(struct ldb_context *ldb, const char *url,
992 unsigned int flags, const char *options[],
993 struct ldb_module **module)
996 int tdb_flags, open_flags;
997 struct ltdb_private *ltdb;
1000 if (strchr(url, ':')) {
1001 if (strncmp(url, "tdb://", 6) != 0) {
1002 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1010 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1012 /* check for the 'nosync' option */
1013 if (flags & LDB_FLG_NOSYNC) {
1014 tdb_flags |= TDB_NOSYNC;
1017 /* and nommap option */
1018 if (flags & LDB_FLG_NOMMAP) {
1019 tdb_flags |= TDB_NOMMAP;
1022 if (flags & LDB_FLG_RDONLY) {
1023 open_flags = O_RDONLY;
1025 open_flags = O_CREAT | O_RDWR;
1028 ltdb = talloc_zero(ldb, struct ltdb_private);
1034 /* note that we use quite a large default hash size */
1035 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1036 tdb_flags, open_flags,
1037 ldb->create_perms, ldb);
1039 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1044 ltdb->sequence_number = 0;
1046 *module = talloc(ldb, struct ldb_module);
1052 talloc_set_name_const(*module, "ldb_tdb backend");
1053 (*module)->ldb = ldb;
1054 (*module)->prev = (*module)->next = NULL;
1055 (*module)->private_data = ltdb;
1056 (*module)->ops = <db_ops;
1058 if (ltdb_cache_load(*module) != 0) {
1059 talloc_free(*module);
1067 int ldb_tdb_init(void)
1069 return ldb_register_backend("tdb", ltdb_connect);