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);
273 if (ret != LDB_SUCCESS) {
277 ret = ltdb_modified(module, msg->dn);
278 if (ret != LDB_SUCCESS) {
279 return LDB_ERR_OPERATIONS_ERROR;
286 add a record to the database
288 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
290 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
291 struct ltdb_context *ltdb_ac;
292 int tret, ret = LDB_SUCCESS;
294 if (req->controls != NULL) {
295 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
296 if (check_critical_controls(req->controls)) {
297 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
301 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
302 if (req->handle == NULL) {
303 return LDB_ERR_OPERATIONS_ERROR;
305 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
307 tret = ltdb_add_internal(module, req->op.add.message);
308 if (tret != LDB_SUCCESS) {
309 req->handle->status = tret;
313 if (ltdb_ac->callback) {
314 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
317 req->handle->state = LDB_ASYNC_DONE;
322 delete a record from the database, not updating indexes (used for deleting
325 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
327 struct ltdb_private *ltdb = module->private_data;
331 tdb_key = ltdb_key(module, dn);
333 return LDB_ERR_OTHER;
336 ret = tdb_delete(ltdb->tdb, tdb_key);
337 talloc_free(tdb_key.dptr);
340 ret = ltdb_err_map(tdb_error(ltdb->tdb));
346 static int ltdb_delete_internal(struct ldb_module *module, const struct ldb_dn *dn)
348 struct ldb_message *msg;
351 msg = talloc(module, struct ldb_message);
353 return LDB_ERR_OPERATIONS_ERROR;
356 /* in case any attribute of the message was indexed, we need
357 to fetch the old record */
358 ret = ltdb_search_dn1(module, dn, msg);
360 /* not finding the old record is an error */
362 return LDB_ERR_NO_SUCH_OBJECT;
365 ret = ltdb_delete_noindex(module, dn);
366 if (ret != LDB_SUCCESS) {
368 return LDB_ERR_NO_SUCH_OBJECT;
371 /* remove any indexed attributes */
372 ret = ltdb_index_del(module, msg);
373 if (ret != LDB_SUCCESS) {
375 return LDB_ERR_OPERATIONS_ERROR;
378 ret = ltdb_modified(module, dn);
379 if (ret != LDB_SUCCESS) {
380 return LDB_ERR_OPERATIONS_ERROR;
388 delete a record from the database
390 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
392 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
393 struct ltdb_context *ltdb_ac;
394 int tret, ret = LDB_SUCCESS;
396 if (req->controls != NULL) {
397 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
398 if (check_critical_controls(req->controls)) {
399 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
405 if (ltdb_cache_load(module) != 0) {
406 return LDB_ERR_OPERATIONS_ERROR;
409 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
410 if (req->handle == NULL) {
411 return LDB_ERR_OPERATIONS_ERROR;
413 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
415 tret = ltdb_delete_internal(module, req->op.del.dn);
416 if (tret != LDB_SUCCESS) {
417 req->handle->status = tret;
421 if (ltdb_ac->callback) {
422 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
425 req->handle->state = LDB_ASYNC_DONE;
430 find an element by attribute name. At the moment this does a linear search, it should
431 be re-coded to use a binary search once all places that modify records guarantee
434 return the index of the first matching element if found, otherwise -1
436 static int find_element(const struct ldb_message *msg, const char *name)
439 for (i=0;i<msg->num_elements;i++) {
440 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
449 add an element to an existing record. Assumes a elements array that we
450 can call re-alloc on, and assumed that we can re-use the data pointers from the
451 passed in additional values. Use with care!
453 returns 0 on success, -1 on failure (and sets errno)
455 static int msg_add_element(struct ldb_context *ldb,
456 struct ldb_message *msg, struct ldb_message_element *el)
458 struct ldb_message_element *e2;
461 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
462 msg->num_elements+1);
470 e2 = &msg->elements[msg->num_elements];
473 e2->flags = el->flags;
475 if (el->num_values != 0) {
476 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
482 for (i=0;i<el->num_values;i++) {
483 e2->values[i] = el->values[i];
485 e2->num_values = el->num_values;
493 delete all elements having a specified attribute name
495 static int msg_delete_attribute(struct ldb_module *module,
496 struct ldb_context *ldb,
497 struct ldb_message *msg, const char *name)
502 dn = ldb_dn_linearize(ldb, msg->dn);
507 for (i=0;i<msg->num_elements;i++) {
508 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
509 for (j=0;j<msg->elements[i].num_values;j++) {
510 ltdb_index_del_value(module, dn, &msg->elements[i], j);
512 talloc_free(msg->elements[i].values);
513 if (msg->num_elements > (i+1)) {
514 memmove(&msg->elements[i],
516 sizeof(struct ldb_message_element)*
517 (msg->num_elements - (i+1)));
521 msg->elements = talloc_realloc(msg, msg->elements,
522 struct ldb_message_element,
532 delete all elements matching an attribute name/value
534 return 0 on success, -1 on failure
536 static int msg_delete_element(struct ldb_module *module,
537 struct ldb_message *msg,
539 const struct ldb_val *val)
541 struct ldb_context *ldb = module->ldb;
544 struct ldb_message_element *el;
545 const struct ldb_attrib_handler *h;
547 found = find_element(msg, name);
552 el = &msg->elements[found];
554 h = ldb_attrib_handler(ldb, el->name);
556 for (i=0;i<el->num_values;i++) {
557 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
558 if (i<el->num_values-1) {
559 memmove(&el->values[i], &el->values[i+1],
560 sizeof(el->values[i])*(el->num_values-(i+1)));
563 if (el->num_values == 0) {
564 return msg_delete_attribute(module, ldb, msg, name);
575 modify a record - internal interface
577 yuck - this is O(n^2). Luckily n is usually small so we probably
578 get away with it, but if we ever have really large attribute lists
579 then we'll need to look at this again
581 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
583 struct ldb_context *ldb = module->ldb;
584 struct ltdb_private *ltdb = module->private_data;
585 TDB_DATA tdb_key, tdb_data;
586 struct ldb_message *msg2;
590 tdb_key = ltdb_key(module, msg->dn);
592 return LDB_ERR_OTHER;
595 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
596 if (!tdb_data.dptr) {
597 talloc_free(tdb_key.dptr);
598 return ltdb_err_map(tdb_error(ltdb->tdb));
601 msg2 = talloc(tdb_key.dptr, struct ldb_message);
603 talloc_free(tdb_key.dptr);
604 return LDB_ERR_OTHER;
607 ret = ltdb_unpack_data(module, &tdb_data, msg2);
617 for (i=0;i<msg->num_elements;i++) {
618 struct ldb_message_element *el = &msg->elements[i];
619 struct ldb_message_element *el2;
620 struct ldb_val *vals;
624 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
626 case LDB_FLAG_MOD_ADD:
627 /* add this element to the message. fail if it
629 ret = find_element(msg2, el->name);
632 if (msg_add_element(ldb, msg2, el) != 0) {
639 el2 = &msg2->elements[ret];
641 /* An attribute with this name already exists, add all
642 * values if they don't already exist. */
644 for (j=0;j<el->num_values;j++) {
645 if (ldb_msg_find_val(el2, &el->values[j])) {
646 err_string = talloc_strdup(module, "Type or value exists");
647 if (err_string) ldb_set_errstring(module->ldb, err_string);
648 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
653 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
654 el2->num_values + el->num_values);
661 for (j=0;j<el->num_values;j++) {
662 vals[el2->num_values + j] =
663 ldb_val_dup(vals, &el->values[j]);
667 el2->num_values += el->num_values;
671 case LDB_FLAG_MOD_REPLACE:
672 /* replace all elements of this attribute name with the elements
673 listed. The attribute not existing is not an error */
674 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
676 /* add the replacement element, if not empty */
677 if (msg->elements[i].num_values != 0 &&
678 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
684 case LDB_FLAG_MOD_DELETE:
686 dn = ldb_dn_linearize(msg2, msg->dn);
692 /* we could be being asked to delete all
693 values or just some values */
694 if (msg->elements[i].num_values == 0) {
695 if (msg_delete_attribute(module, ldb, msg2,
696 msg->elements[i].name) != 0) {
697 err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
698 if (err_string) ldb_set_errstring(module->ldb, err_string);
699 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
704 for (j=0;j<msg->elements[i].num_values;j++) {
705 if (msg_delete_element(module,
707 msg->elements[i].name,
708 &msg->elements[i].values[j]) != 0) {
709 err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
710 if (err_string) ldb_set_errstring(module->ldb, err_string);
711 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
714 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
721 err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x",
722 msg->elements[i].name,
723 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
724 if (err_string) ldb_set_errstring(module->ldb, err_string);
725 ret = LDB_ERR_PROTOCOL_ERROR;
730 /* we've made all the mods - save the modified record back into the database */
731 ret = ltdb_store(module, msg2, TDB_MODIFY);
732 if (ret != LDB_SUCCESS) {
736 if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
737 ret = LDB_ERR_OPERATIONS_ERROR;
741 talloc_free(tdb_key.dptr);
746 talloc_free(tdb_key.dptr);
754 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
756 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
757 struct ltdb_context *ltdb_ac;
758 int tret, ret = LDB_SUCCESS;
760 if (req->controls != NULL) {
761 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
762 if (check_critical_controls(req->controls)) {
763 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
769 req->handle = init_ltdb_handle(ltdb, module, req->context, req->callback);
770 if (req->handle == NULL) {
771 return LDB_ERR_OPERATIONS_ERROR;
773 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
775 tret = ltdb_check_special_dn(module, req->op.mod.message);
776 if (tret != LDB_SUCCESS) {
777 req->handle->status = tret;
781 if (ltdb_cache_load(module) != 0) {
782 ret = LDB_ERR_OPERATIONS_ERROR;
786 tret = ltdb_modify_internal(module, req->op.mod.message);
787 if (tret != LDB_SUCCESS) {
788 req->handle->status = tret;
792 if (ltdb_ac->callback) {
793 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
796 req->handle->state = LDB_ASYNC_DONE;
803 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
805 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
806 struct ltdb_context *ltdb_ac;
807 struct ldb_message *msg;
808 int tret, ret = LDB_SUCCESS;
810 if (req->controls != NULL) {
811 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
812 if (check_critical_controls(req->controls)) {
813 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->context, req->callback);
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 = module->private_data;
875 if (tdb_transaction_start(ltdb->tdb) != 0) {
876 return ltdb_err_map(tdb_error(ltdb->tdb));
882 static int ltdb_end_trans(struct ldb_module *module)
884 struct ltdb_private *ltdb = module->private_data;
886 if (tdb_transaction_commit(ltdb->tdb) != 0) {
887 return ltdb_err_map(tdb_error(ltdb->tdb));
893 static int ltdb_del_trans(struct ldb_module *module)
895 struct ltdb_private *ltdb = module->private_data;
897 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
898 return ltdb_err_map(tdb_error(ltdb->tdb));
904 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
906 return handle->status;
909 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
911 /* check for oustanding critical controls and return an error if found */
912 if (req->controls != NULL) {
913 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
914 if (check_critical_controls(req->controls)) {
915 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_explode(tmp_ctx, 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 tret = ltdb_search_dn1(module, dn, msg);
946 talloc_free(tmp_ctx);
947 req->op.seq_num.seq_num = 0;
948 /* zero is as good as anything when we don't know */
952 req->op.seq_num.seq_num = ldb_msg_find_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
953 talloc_free(tmp_ctx);
957 static const struct ldb_module_ops ltdb_ops = {
959 .search = ltdb_search,
961 .modify = ltdb_modify,
963 .rename = ltdb_rename,
964 .request = ltdb_request,
965 .start_transaction = ltdb_start_trans,
966 .end_transaction = ltdb_end_trans,
967 .del_transaction = ltdb_del_trans,
969 .sequence_number = ltdb_sequence_number
973 connect to the database
975 static int ltdb_connect(struct ldb_context *ldb, const char *url,
976 unsigned int flags, const char *options[],
977 struct ldb_module **module)
980 int tdb_flags, open_flags;
981 struct ltdb_private *ltdb;
984 if (strchr(url, ':')) {
985 if (strncmp(url, "tdb://", 6) != 0) {
986 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
994 tdb_flags = TDB_DEFAULT;
996 /* check for the 'nosync' option */
997 if (flags & LDB_FLG_NOSYNC) {
998 tdb_flags |= TDB_NOSYNC;
1001 if (flags & LDB_FLG_RDONLY) {
1002 open_flags = O_RDONLY;
1004 open_flags = O_CREAT | O_RDWR;
1007 ltdb = talloc_zero(ldb, struct ltdb_private);
1013 /* note that we use quite a large default hash size */
1014 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1015 tdb_flags, open_flags, 0666, ldb);
1017 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1022 ltdb->sequence_number = 0;
1024 *module = talloc(ldb, struct ldb_module);
1030 (*module)->ldb = ldb;
1031 (*module)->prev = (*module)->next = NULL;
1032 (*module)->private_data = ltdb;
1033 (*module)->ops = <db_ops;
1038 int ldb_tdb_init(void)
1040 return ldb_register_backend("tdb", ltdb_connect);