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 const 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_strdup(ldb, "DN=");
150 key_str = talloc_append_string(ldb, key_str, dn_folded);
155 key.dptr = (uint8_t *)key_str;
156 key.dsize = strlen(key_str) + 1;
168 check special dn's have valid attributes
169 currently only @ATTRIBUTES is checked
171 int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
175 if (! ldb_dn_is_special(msg->dn) ||
176 ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
180 /* we have @ATTRIBUTES, let's check attributes are fine */
181 /* should we check that we deny multivalued attributes ? */
182 for (i = 0; i < msg->num_elements; i++) {
183 for (j = 0; j < msg->elements[i].num_values; j++) {
184 if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
185 ldb_set_errstring(module->ldb, "Invalid attribute value in an @ATTRIBUTES entry");
186 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
196 we've made a modification to a dn - possibly reindex and
197 update sequence number
199 static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn)
203 if (ldb_dn_is_special(dn) &&
204 (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
205 ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
206 ret = ltdb_reindex(module);
210 !(ldb_dn_is_special(dn) &&
211 ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
212 ret = ltdb_increase_sequence_number(module);
219 store a record into the db
221 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
223 struct ltdb_private *ltdb =
224 talloc_get_type(module->private_data, struct ltdb_private);
225 TDB_DATA tdb_key, tdb_data;
228 tdb_key = ltdb_key(module, msg->dn);
230 return LDB_ERR_OTHER;
233 ret = ltdb_pack_data(module, msg, &tdb_data);
235 talloc_free(tdb_key.dptr);
236 return LDB_ERR_OTHER;
239 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
241 ret = ltdb_err_map(tdb_error(ltdb->tdb));
245 ret = ltdb_index_add(module, msg);
247 tdb_delete(ltdb->tdb, tdb_key);
251 talloc_free(tdb_key.dptr);
252 talloc_free(tdb_data.dptr);
258 static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg)
262 ret = ltdb_check_special_dn(module, msg);
263 if (ret != LDB_SUCCESS) {
267 if (ltdb_cache_load(module) != 0) {
268 return LDB_ERR_OPERATIONS_ERROR;
271 ret = ltdb_store(module, msg, TDB_INSERT);
273 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
274 ldb_asprintf_errstring(module->ldb, "Entry %s already exists", ldb_dn_get_linearized(msg->dn));
278 if (ret == LDB_SUCCESS) {
279 ret = ltdb_index_one(module, msg, 1);
280 if (ret != LDB_SUCCESS) {
281 return LDB_ERR_OPERATIONS_ERROR;
284 ret = ltdb_modified(module, msg->dn);
285 if (ret != LDB_SUCCESS) {
286 return LDB_ERR_OPERATIONS_ERROR;
294 add a record to the database
296 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
298 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
299 struct ltdb_context *ltdb_ac;
300 int tret, ret = LDB_SUCCESS;
302 if (check_critical_controls(req->controls)) {
303 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
306 req->handle = init_ltdb_handle(ltdb, module, req);
307 if (req->handle == NULL) {
308 return LDB_ERR_OPERATIONS_ERROR;
310 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
312 tret = ltdb_add_internal(module, req->op.add.message);
313 if (tret != LDB_SUCCESS) {
314 req->handle->status = tret;
318 if (ltdb_ac->callback) {
319 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
322 req->handle->state = LDB_ASYNC_DONE;
327 delete a record from the database, not updating indexes (used for deleting
330 int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn)
332 struct ltdb_private *ltdb =
333 talloc_get_type(module->private_data, struct ltdb_private);
337 tdb_key = ltdb_key(module, dn);
339 return LDB_ERR_OTHER;
342 ret = tdb_delete(ltdb->tdb, tdb_key);
343 talloc_free(tdb_key.dptr);
346 ret = ltdb_err_map(tdb_error(ltdb->tdb));
352 static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
354 struct ldb_message *msg;
357 msg = talloc(module, struct ldb_message);
359 return LDB_ERR_OPERATIONS_ERROR;
362 /* in case any attribute of the message was indexed, we need
363 to fetch the old record */
364 ret = ltdb_search_dn1(module, dn, msg);
366 /* not finding the old record is an error */
368 return LDB_ERR_NO_SUCH_OBJECT;
371 ret = ltdb_delete_noindex(module, dn);
372 if (ret != LDB_SUCCESS) {
374 return LDB_ERR_NO_SUCH_OBJECT;
377 /* remove one level attribute */
378 ret = ltdb_index_one(module, msg, 0);
379 if (ret != LDB_SUCCESS) {
381 return LDB_ERR_OPERATIONS_ERROR;
384 /* remove any indexed attributes */
385 ret = ltdb_index_del(module, msg);
386 if (ret != LDB_SUCCESS) {
388 return LDB_ERR_OPERATIONS_ERROR;
391 ret = ltdb_modified(module, dn);
392 if (ret != LDB_SUCCESS) {
394 return LDB_ERR_OPERATIONS_ERROR;
402 delete a record from the database
404 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
406 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
407 struct ltdb_context *ltdb_ac;
408 int tret, ret = LDB_SUCCESS;
410 if (check_critical_controls(req->controls)) {
411 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);
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_get_linearized(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,
542 delete all elements matching an attribute name/value
544 return 0 on success, -1 on failure
546 static int msg_delete_element(struct ldb_module *module,
547 struct ldb_message *msg,
549 const struct ldb_val *val)
551 struct ldb_context *ldb = module->ldb;
554 struct ldb_message_element *el;
555 const struct ldb_schema_attribute *a;
557 found = find_element(msg, name);
562 el = &msg->elements[found];
564 a = ldb_schema_attribute_by_name(ldb, el->name);
566 for (i=0;i<el->num_values;i++) {
567 if (a->syntax->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
568 if (i<el->num_values-1) {
569 memmove(&el->values[i], &el->values[i+1],
570 sizeof(el->values[i])*(el->num_values-(i+1)));
573 if (el->num_values == 0) {
574 return msg_delete_attribute(module, ldb, msg, name);
585 modify a record - internal interface
587 yuck - this is O(n^2). Luckily n is usually small so we probably
588 get away with it, but if we ever have really large attribute lists
589 then we'll need to look at this again
591 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
593 struct ldb_context *ldb = module->ldb;
594 struct ltdb_private *ltdb =
595 talloc_get_type(module->private_data, struct ltdb_private);
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;
634 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
636 case LDB_FLAG_MOD_ADD:
637 /* add this element to the message. fail if it
639 ret = find_element(msg2, el->name);
642 if (msg_add_element(ldb, msg2, el) != 0) {
649 el2 = &msg2->elements[ret];
651 /* An attribute with this name already exists, add all
652 * values if they don't already exist. */
654 for (j=0;j<el->num_values;j++) {
655 if (ldb_msg_find_val(el2, &el->values[j])) {
656 ldb_set_errstring(module->ldb, "Type or value exists");
657 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
662 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
663 el2->num_values + el->num_values);
670 for (j=0;j<el->num_values;j++) {
671 vals[el2->num_values + j] =
672 ldb_val_dup(vals, &el->values[j]);
676 el2->num_values += el->num_values;
680 case LDB_FLAG_MOD_REPLACE:
681 /* replace all elements of this attribute name with the elements
682 listed. The attribute not existing is not an error */
683 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
685 /* add the replacement element, if not empty */
686 if (msg->elements[i].num_values != 0 &&
687 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
693 case LDB_FLAG_MOD_DELETE:
695 dn = ldb_dn_get_linearized(msg->dn);
701 /* we could be being asked to delete all
702 values or just some values */
703 if (msg->elements[i].num_values == 0) {
704 if (msg_delete_attribute(module, ldb, msg2,
705 msg->elements[i].name) != 0) {
706 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
707 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
712 for (j=0;j<msg->elements[i].num_values;j++) {
713 if (msg_delete_element(module,
715 msg->elements[i].name,
716 &msg->elements[i].values[j]) != 0) {
717 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
718 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
721 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
728 ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
729 msg->elements[i].name,
730 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
731 ret = LDB_ERR_PROTOCOL_ERROR;
736 /* we've made all the mods - save the modified record back into the database */
737 ret = ltdb_store(module, msg2, TDB_MODIFY);
738 if (ret != LDB_SUCCESS) {
742 if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
743 ret = LDB_ERR_OPERATIONS_ERROR;
747 talloc_free(tdb_key.dptr);
752 talloc_free(tdb_key.dptr);
760 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
762 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
763 struct ltdb_context *ltdb_ac;
764 int tret, ret = LDB_SUCCESS;
766 if (check_critical_controls(req->controls)) {
767 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
772 req->handle = init_ltdb_handle(ltdb, module, req);
773 if (req->handle == NULL) {
774 return LDB_ERR_OPERATIONS_ERROR;
776 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
778 tret = ltdb_check_special_dn(module, req->op.mod.message);
779 if (tret != LDB_SUCCESS) {
780 req->handle->status = tret;
784 if (ltdb_cache_load(module) != 0) {
785 ret = LDB_ERR_OPERATIONS_ERROR;
789 tret = ltdb_modify_internal(module, req->op.mod.message);
790 if (tret != LDB_SUCCESS) {
791 req->handle->status = tret;
795 if (ltdb_ac->callback) {
796 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
799 req->handle->state = LDB_ASYNC_DONE;
806 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
808 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
809 struct ltdb_context *ltdb_ac;
810 struct ldb_message *msg;
811 int tret, ret = LDB_SUCCESS;
813 if (check_critical_controls(req->controls)) {
814 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
819 if (ltdb_cache_load(module) != 0) {
820 return LDB_ERR_OPERATIONS_ERROR;
823 req->handle = init_ltdb_handle(ltdb, module, req);
824 if (req->handle == NULL) {
825 return LDB_ERR_OPERATIONS_ERROR;
827 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
829 msg = talloc(ltdb_ac, struct ldb_message);
831 ret = LDB_ERR_OPERATIONS_ERROR;
835 /* in case any attribute of the message was indexed, we need
836 to fetch the old record */
837 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
839 /* not finding the old record is an error */
840 req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
844 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
846 ret = LDB_ERR_OPERATIONS_ERROR;
850 tret = ltdb_add_internal(module, msg);
851 if (tret != LDB_SUCCESS) {
852 ret = LDB_ERR_OPERATIONS_ERROR;
856 tret = ltdb_delete_internal(module, req->op.rename.olddn);
857 if (tret != LDB_SUCCESS) {
858 ltdb_delete_internal(module, req->op.rename.newdn);
859 ret = LDB_ERR_OPERATIONS_ERROR;
863 if (ltdb_ac->callback) {
864 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
867 req->handle->state = LDB_ASYNC_DONE;
871 static int ltdb_start_trans(struct ldb_module *module)
873 struct ltdb_private *ltdb =
874 talloc_get_type(module->private_data, struct ltdb_private);
876 if (tdb_transaction_start(ltdb->tdb) != 0) {
877 return ltdb_err_map(tdb_error(ltdb->tdb));
883 static int ltdb_end_trans(struct ldb_module *module)
885 struct ltdb_private *ltdb =
886 talloc_get_type(module->private_data, struct ltdb_private);
888 if (tdb_transaction_commit(ltdb->tdb) != 0) {
889 return ltdb_err_map(tdb_error(ltdb->tdb));
895 static int ltdb_del_trans(struct ldb_module *module)
897 struct ltdb_private *ltdb =
898 talloc_get_type(module->private_data, struct ltdb_private);
900 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
901 return ltdb_err_map(tdb_error(ltdb->tdb));
907 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
909 return handle->status;
912 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
914 /* check for oustanding critical controls and return an error if found */
915 if (check_critical_controls(req->controls)) {
916 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
919 /* search, add, modify, delete, rename are handled by their own, no other op supported */
920 return LDB_ERR_OPERATIONS_ERROR;
924 return sequenceNumber from @BASEINFO
926 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
928 TALLOC_CTX *tmp_ctx = talloc_new(req);
929 struct ldb_message *msg = NULL;
930 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
933 if (tmp_ctx == NULL) {
934 talloc_free(tmp_ctx);
935 return LDB_ERR_OPERATIONS_ERROR;
938 msg = talloc(tmp_ctx, struct ldb_message);
940 talloc_free(tmp_ctx);
941 return LDB_ERR_OPERATIONS_ERROR;
944 req->op.seq_num.flags = 0;
946 tret = ltdb_search_dn1(module, dn, msg);
948 talloc_free(tmp_ctx);
949 req->op.seq_num.seq_num = 0;
950 /* zero is as good as anything when we don't know */
954 switch (req->op.seq_num.type) {
955 case LDB_SEQ_HIGHEST_SEQ:
956 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
959 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
960 req->op.seq_num.seq_num++;
962 case LDB_SEQ_HIGHEST_TIMESTAMP:
964 const char *date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
966 req->op.seq_num.seq_num = ldb_string_to_time(date);
968 req->op.seq_num.seq_num = 0;
969 /* zero is as good as anything when we don't know */
974 talloc_free(tmp_ctx);
978 static const struct ldb_module_ops ltdb_ops = {
980 .search = ltdb_search,
982 .modify = ltdb_modify,
984 .rename = ltdb_rename,
985 .request = ltdb_request,
986 .start_transaction = ltdb_start_trans,
987 .end_transaction = ltdb_end_trans,
988 .del_transaction = ltdb_del_trans,
990 .sequence_number = ltdb_sequence_number
994 connect to the database
996 static int ltdb_connect(struct ldb_context *ldb, const char *url,
997 unsigned int flags, const char *options[],
998 struct ldb_module **module)
1001 int tdb_flags, open_flags;
1002 struct ltdb_private *ltdb;
1005 if (strchr(url, ':')) {
1006 if (strncmp(url, "tdb://", 6) != 0) {
1007 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1015 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1017 /* check for the 'nosync' option */
1018 if (flags & LDB_FLG_NOSYNC) {
1019 tdb_flags |= TDB_NOSYNC;
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);