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, const struct ldb_dn *dn)
123 struct ldb_context *ldb = module->ldb;
125 char *key_str = NULL;
126 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_linearize_casefold(ldb, ldb, dn);
145 key_str = talloc_asprintf(ldb, "DN=%s", dn_folded);
147 talloc_free(dn_folded);
153 key.dptr = (uint8_t *)key_str;
154 key.dsize = strlen(key_str) + 1;
166 check special dn's have valid attributes
167 currently only @ATTRIBUTES is checked
169 int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
173 if (! ldb_dn_is_special(msg->dn) ||
174 ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
178 /* we have @ATTRIBUTES, let's check attributes are fine */
179 /* should we check that we deny multivalued attributes ? */
180 for (i = 0; i < msg->num_elements; i++) {
181 for (j = 0; j < msg->elements[i].num_values; j++) {
182 if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
183 ldb_set_errstring(module->ldb, "Invalid attribute value in an @ATTRIBUTES entry");
184 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
194 we've made a modification to a dn - possibly reindex and
195 update sequence number
197 static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn)
201 if (ldb_dn_is_special(dn) &&
202 (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
203 ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
204 ret = ltdb_reindex(module);
208 !(ldb_dn_is_special(dn) &&
209 ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
210 ret = ltdb_increase_sequence_number(module);
217 store a record into the db
219 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
221 struct ltdb_private *ltdb =
222 talloc_get_type(module->private_data, struct ltdb_private);
223 TDB_DATA tdb_key, tdb_data;
226 tdb_key = ltdb_key(module, msg->dn);
228 return LDB_ERR_OTHER;
231 ret = ltdb_pack_data(module, msg, &tdb_data);
233 talloc_free(tdb_key.dptr);
234 return LDB_ERR_OTHER;
237 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
239 ret = ltdb_err_map(tdb_error(ltdb->tdb));
243 ret = ltdb_index_add(module, msg);
245 tdb_delete(ltdb->tdb, tdb_key);
249 talloc_free(tdb_key.dptr);
250 talloc_free(tdb_data.dptr);
256 static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg)
260 ret = ltdb_check_special_dn(module, msg);
261 if (ret != LDB_SUCCESS) {
265 if (ltdb_cache_load(module) != 0) {
266 return LDB_ERR_OPERATIONS_ERROR;
269 ret = ltdb_store(module, msg, TDB_INSERT);
271 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
274 dn = ldb_dn_linearize(module, msg->dn);
278 ldb_asprintf_errstring(module->ldb, "Entry %s already exists", dn);
283 if (ret == LDB_SUCCESS) {
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 (req->controls != NULL) {
303 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
304 if (check_critical_controls(req->controls)) {
305 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
309 req->handle = init_ltdb_handle(ltdb, module, req);
310 if (req->handle == NULL) {
311 return LDB_ERR_OPERATIONS_ERROR;
313 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
315 tret = ltdb_add_internal(module, req->op.add.message);
316 if (tret != LDB_SUCCESS) {
317 req->handle->status = tret;
321 if (ltdb_ac->callback) {
322 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
325 req->handle->state = LDB_ASYNC_DONE;
330 delete a record from the database, not updating indexes (used for deleting
333 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
335 struct ltdb_private *ltdb =
336 talloc_get_type(module->private_data, struct ltdb_private);
340 tdb_key = ltdb_key(module, dn);
342 return LDB_ERR_OTHER;
345 ret = tdb_delete(ltdb->tdb, tdb_key);
346 talloc_free(tdb_key.dptr);
349 ret = ltdb_err_map(tdb_error(ltdb->tdb));
355 static int ltdb_delete_internal(struct ldb_module *module, const struct ldb_dn *dn)
357 struct ldb_message *msg;
360 msg = talloc(module, struct ldb_message);
362 return LDB_ERR_OPERATIONS_ERROR;
365 /* in case any attribute of the message was indexed, we need
366 to fetch the old record */
367 ret = ltdb_search_dn1(module, dn, msg);
369 /* not finding the old record is an error */
371 return LDB_ERR_NO_SUCH_OBJECT;
374 ret = ltdb_delete_noindex(module, dn);
375 if (ret != LDB_SUCCESS) {
377 return LDB_ERR_NO_SUCH_OBJECT;
380 /* remove any indexed attributes */
381 ret = ltdb_index_del(module, msg);
382 if (ret != LDB_SUCCESS) {
384 return LDB_ERR_OPERATIONS_ERROR;
387 ret = ltdb_modified(module, dn);
388 if (ret != LDB_SUCCESS) {
389 return LDB_ERR_OPERATIONS_ERROR;
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 (req->controls != NULL) {
406 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
407 if (check_critical_controls(req->controls)) {
408 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
414 if (ltdb_cache_load(module) != 0) {
415 return LDB_ERR_OPERATIONS_ERROR;
418 req->handle = init_ltdb_handle(ltdb, module, req);
419 if (req->handle == NULL) {
420 return LDB_ERR_OPERATIONS_ERROR;
422 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
424 tret = ltdb_delete_internal(module, req->op.del.dn);
425 if (tret != LDB_SUCCESS) {
426 req->handle->status = tret;
430 if (ltdb_ac->callback) {
431 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
434 req->handle->state = LDB_ASYNC_DONE;
439 find an element by attribute name. At the moment this does a linear search, it should
440 be re-coded to use a binary search once all places that modify records guarantee
443 return the index of the first matching element if found, otherwise -1
445 static int find_element(const struct ldb_message *msg, const char *name)
448 for (i=0;i<msg->num_elements;i++) {
449 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
458 add an element to an existing record. Assumes a elements array that we
459 can call re-alloc on, and assumed that we can re-use the data pointers from the
460 passed in additional values. Use with care!
462 returns 0 on success, -1 on failure (and sets errno)
464 static int msg_add_element(struct ldb_context *ldb,
465 struct ldb_message *msg, struct ldb_message_element *el)
467 struct ldb_message_element *e2;
470 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
471 msg->num_elements+1);
479 e2 = &msg->elements[msg->num_elements];
482 e2->flags = el->flags;
484 if (el->num_values != 0) {
485 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
491 for (i=0;i<el->num_values;i++) {
492 e2->values[i] = el->values[i];
494 e2->num_values = el->num_values;
502 delete all elements having a specified attribute name
504 static int msg_delete_attribute(struct ldb_module *module,
505 struct ldb_context *ldb,
506 struct ldb_message *msg, const char *name)
511 dn = ldb_dn_linearize(ldb, msg->dn);
516 for (i=0;i<msg->num_elements;i++) {
517 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
518 for (j=0;j<msg->elements[i].num_values;j++) {
519 ltdb_index_del_value(module, dn, &msg->elements[i], j);
521 talloc_free(msg->elements[i].values);
522 if (msg->num_elements > (i+1)) {
523 memmove(&msg->elements[i],
525 sizeof(struct ldb_message_element)*
526 (msg->num_elements - (i+1)));
530 msg->elements = talloc_realloc(msg, msg->elements,
531 struct ldb_message_element,
541 delete all elements matching an attribute name/value
543 return 0 on success, -1 on failure
545 static int msg_delete_element(struct ldb_module *module,
546 struct ldb_message *msg,
548 const struct ldb_val *val)
550 struct ldb_context *ldb = module->ldb;
553 struct ldb_message_element *el;
554 const struct ldb_attrib_handler *h;
556 found = find_element(msg, name);
561 el = &msg->elements[found];
563 h = ldb_attrib_handler(ldb, el->name);
565 for (i=0;i<el->num_values;i++) {
566 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
567 if (i<el->num_values-1) {
568 memmove(&el->values[i], &el->values[i+1],
569 sizeof(el->values[i])*(el->num_values-(i+1)));
572 if (el->num_values == 0) {
573 return msg_delete_attribute(module, ldb, msg, name);
584 modify a record - internal interface
586 yuck - this is O(n^2). Luckily n is usually small so we probably
587 get away with it, but if we ever have really large attribute lists
588 then we'll need to look at this again
590 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
592 struct ldb_context *ldb = module->ldb;
593 struct ltdb_private *ltdb =
594 talloc_get_type(module->private_data, struct ltdb_private);
595 TDB_DATA tdb_key, tdb_data;
596 struct ldb_message *msg2;
600 tdb_key = ltdb_key(module, msg->dn);
602 return LDB_ERR_OTHER;
605 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
606 if (!tdb_data.dptr) {
607 talloc_free(tdb_key.dptr);
608 return ltdb_err_map(tdb_error(ltdb->tdb));
611 msg2 = talloc(tdb_key.dptr, struct ldb_message);
613 talloc_free(tdb_key.dptr);
614 return LDB_ERR_OTHER;
617 ret = ltdb_unpack_data(module, &tdb_data, msg2);
627 for (i=0;i<msg->num_elements;i++) {
628 struct ldb_message_element *el = &msg->elements[i];
629 struct ldb_message_element *el2;
630 struct ldb_val *vals;
633 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
635 case LDB_FLAG_MOD_ADD:
636 /* add this element to the message. fail if it
638 ret = find_element(msg2, el->name);
641 if (msg_add_element(ldb, msg2, el) != 0) {
648 el2 = &msg2->elements[ret];
650 /* An attribute with this name already exists, add all
651 * values if they don't already exist. */
653 for (j=0;j<el->num_values;j++) {
654 if (ldb_msg_find_val(el2, &el->values[j])) {
655 ldb_set_errstring(module->ldb, "Type or value exists");
656 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
661 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
662 el2->num_values + el->num_values);
669 for (j=0;j<el->num_values;j++) {
670 vals[el2->num_values + j] =
671 ldb_val_dup(vals, &el->values[j]);
675 el2->num_values += el->num_values;
679 case LDB_FLAG_MOD_REPLACE:
680 /* replace all elements of this attribute name with the elements
681 listed. The attribute not existing is not an error */
682 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
684 /* add the replacement element, if not empty */
685 if (msg->elements[i].num_values != 0 &&
686 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
692 case LDB_FLAG_MOD_DELETE:
694 dn = ldb_dn_linearize(msg2, msg->dn);
700 /* we could be being asked to delete all
701 values or just some values */
702 if (msg->elements[i].num_values == 0) {
703 if (msg_delete_attribute(module, ldb, msg2,
704 msg->elements[i].name) != 0) {
705 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
706 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
711 for (j=0;j<msg->elements[i].num_values;j++) {
712 if (msg_delete_element(module,
714 msg->elements[i].name,
715 &msg->elements[i].values[j]) != 0) {
716 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
717 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
720 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
727 ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
728 msg->elements[i].name,
729 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
730 ret = LDB_ERR_PROTOCOL_ERROR;
735 /* we've made all the mods - save the modified record back into the database */
736 ret = ltdb_store(module, msg2, TDB_MODIFY);
737 if (ret != LDB_SUCCESS) {
741 if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
742 ret = LDB_ERR_OPERATIONS_ERROR;
746 talloc_free(tdb_key.dptr);
751 talloc_free(tdb_key.dptr);
759 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
761 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
762 struct ltdb_context *ltdb_ac;
763 int tret, ret = LDB_SUCCESS;
765 if (req->controls != NULL) {
766 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
767 if (check_critical_controls(req->controls)) {
768 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
774 req->handle = init_ltdb_handle(ltdb, module, req);
775 if (req->handle == NULL) {
776 return LDB_ERR_OPERATIONS_ERROR;
778 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
780 tret = ltdb_check_special_dn(module, req->op.mod.message);
781 if (tret != LDB_SUCCESS) {
782 req->handle->status = tret;
786 if (ltdb_cache_load(module) != 0) {
787 ret = LDB_ERR_OPERATIONS_ERROR;
791 tret = ltdb_modify_internal(module, req->op.mod.message);
792 if (tret != LDB_SUCCESS) {
793 req->handle->status = tret;
797 if (ltdb_ac->callback) {
798 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
801 req->handle->state = LDB_ASYNC_DONE;
808 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
810 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
811 struct ltdb_context *ltdb_ac;
812 struct ldb_message *msg;
813 int tret, ret = LDB_SUCCESS;
815 if (req->controls != NULL) {
816 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
817 if (check_critical_controls(req->controls)) {
818 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
824 if (ltdb_cache_load(module) != 0) {
825 return LDB_ERR_OPERATIONS_ERROR;
828 req->handle = init_ltdb_handle(ltdb, module, req);
829 if (req->handle == NULL) {
830 return LDB_ERR_OPERATIONS_ERROR;
832 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
834 msg = talloc(ltdb_ac, struct ldb_message);
836 ret = LDB_ERR_OPERATIONS_ERROR;
840 /* in case any attribute of the message was indexed, we need
841 to fetch the old record */
842 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
844 /* not finding the old record is an error */
845 req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
849 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
851 ret = LDB_ERR_OPERATIONS_ERROR;
855 tret = ltdb_add_internal(module, msg);
856 if (tret != LDB_SUCCESS) {
857 ret = LDB_ERR_OPERATIONS_ERROR;
861 tret = ltdb_delete_internal(module, req->op.rename.olddn);
862 if (tret != LDB_SUCCESS) {
863 ltdb_delete_internal(module, req->op.rename.newdn);
864 ret = LDB_ERR_OPERATIONS_ERROR;
868 if (ltdb_ac->callback) {
869 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
872 req->handle->state = LDB_ASYNC_DONE;
876 static int ltdb_start_trans(struct ldb_module *module)
878 struct ltdb_private *ltdb =
879 talloc_get_type(module->private_data, struct ltdb_private);
881 if (tdb_transaction_start(ltdb->tdb) != 0) {
882 return ltdb_err_map(tdb_error(ltdb->tdb));
888 static int ltdb_end_trans(struct ldb_module *module)
890 struct ltdb_private *ltdb =
891 talloc_get_type(module->private_data, struct ltdb_private);
893 if (tdb_transaction_commit(ltdb->tdb) != 0) {
894 return ltdb_err_map(tdb_error(ltdb->tdb));
900 static int ltdb_del_trans(struct ldb_module *module)
902 struct ltdb_private *ltdb =
903 talloc_get_type(module->private_data, struct ltdb_private);
905 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
906 return ltdb_err_map(tdb_error(ltdb->tdb));
912 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
914 return handle->status;
917 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
919 /* check for oustanding critical controls and return an error if found */
920 if (req->controls != NULL) {
921 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
922 if (check_critical_controls(req->controls)) {
923 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
927 /* search, add, modify, delete, rename are handled by their own, no other op supported */
928 return LDB_ERR_OPERATIONS_ERROR;
932 return sequenceNumber from @BASEINFO
934 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
936 TALLOC_CTX *tmp_ctx = talloc_new(req);
937 struct ldb_message *msg = NULL;
938 struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, LTDB_BASEINFO);
941 if (tmp_ctx == NULL) {
942 talloc_free(tmp_ctx);
943 return LDB_ERR_OPERATIONS_ERROR;
946 msg = talloc(tmp_ctx, struct ldb_message);
948 talloc_free(tmp_ctx);
949 return LDB_ERR_OPERATIONS_ERROR;
952 req->op.seq_num.flags = 0;
954 tret = ltdb_search_dn1(module, dn, msg);
956 talloc_free(tmp_ctx);
957 req->op.seq_num.seq_num = 0;
958 /* zero is as good as anything when we don't know */
962 switch (req->op.seq_num.type) {
963 case LDB_SEQ_HIGHEST_SEQ:
964 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
967 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
968 req->op.seq_num.seq_num++;
970 case LDB_SEQ_HIGHEST_TIMESTAMP:
972 const char *date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
974 req->op.seq_num.seq_num = ldb_string_to_time(date);
976 req->op.seq_num.seq_num = 0;
977 /* zero is as good as anything when we don't know */
982 talloc_free(tmp_ctx);
986 static const struct ldb_module_ops ltdb_ops = {
988 .search = ltdb_search,
990 .modify = ltdb_modify,
992 .rename = ltdb_rename,
993 .request = ltdb_request,
994 .start_transaction = ltdb_start_trans,
995 .end_transaction = ltdb_end_trans,
996 .del_transaction = ltdb_del_trans,
998 .sequence_number = ltdb_sequence_number
1002 connect to the database
1004 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1005 unsigned int flags, const char *options[],
1006 struct ldb_module **module)
1009 int tdb_flags, open_flags;
1010 struct ltdb_private *ltdb;
1013 if (strchr(url, ':')) {
1014 if (strncmp(url, "tdb://", 6) != 0) {
1015 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1023 tdb_flags = TDB_DEFAULT;
1025 /* check for the 'nosync' option */
1026 if (flags & LDB_FLG_NOSYNC) {
1027 tdb_flags |= TDB_NOSYNC;
1030 if (flags & LDB_FLG_RDONLY) {
1031 open_flags = O_RDONLY;
1033 open_flags = O_CREAT | O_RDWR;
1036 ltdb = talloc_zero(ldb, struct ltdb_private);
1042 /* note that we use quite a large default hash size */
1043 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1044 tdb_flags, open_flags,
1045 ldb->create_perms, ldb);
1047 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1052 ltdb->sequence_number = 0;
1054 *module = talloc(ldb, struct ldb_module);
1060 (*module)->ldb = ldb;
1061 (*module)->prev = (*module)->next = NULL;
1062 (*module)->private_data = ltdb;
1063 (*module)->ops = <db_ops;
1068 int ldb_tdb_init(void)
1070 return ldb_register_backend("tdb", ltdb_connect);