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 (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, 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, 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 one level attribute */
381 ret = ltdb_index_one(module, msg, 0);
382 if (ret != LDB_SUCCESS) {
384 return LDB_ERR_OPERATIONS_ERROR;
387 /* remove any indexed attributes */
388 ret = ltdb_index_del(module, msg);
389 if (ret != LDB_SUCCESS) {
391 return LDB_ERR_OPERATIONS_ERROR;
394 ret = ltdb_modified(module, dn);
395 if (ret != LDB_SUCCESS) {
397 return LDB_ERR_OPERATIONS_ERROR;
405 delete a record from the database
407 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
409 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
410 struct ltdb_context *ltdb_ac;
411 int tret, ret = LDB_SUCCESS;
413 if (req->controls != NULL) {
414 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
415 if (check_critical_controls(req->controls)) {
416 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
422 if (ltdb_cache_load(module) != 0) {
423 return LDB_ERR_OPERATIONS_ERROR;
426 req->handle = init_ltdb_handle(ltdb, module, req);
427 if (req->handle == NULL) {
428 return LDB_ERR_OPERATIONS_ERROR;
430 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
432 tret = ltdb_delete_internal(module, req->op.del.dn);
433 if (tret != LDB_SUCCESS) {
434 req->handle->status = tret;
438 if (ltdb_ac->callback) {
439 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
442 req->handle->state = LDB_ASYNC_DONE;
447 find an element by attribute name. At the moment this does a linear search, it should
448 be re-coded to use a binary search once all places that modify records guarantee
451 return the index of the first matching element if found, otherwise -1
453 static int find_element(const struct ldb_message *msg, const char *name)
456 for (i=0;i<msg->num_elements;i++) {
457 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
466 add an element to an existing record. Assumes a elements array that we
467 can call re-alloc on, and assumed that we can re-use the data pointers from the
468 passed in additional values. Use with care!
470 returns 0 on success, -1 on failure (and sets errno)
472 static int msg_add_element(struct ldb_context *ldb,
473 struct ldb_message *msg, struct ldb_message_element *el)
475 struct ldb_message_element *e2;
478 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
479 msg->num_elements+1);
487 e2 = &msg->elements[msg->num_elements];
490 e2->flags = el->flags;
492 if (el->num_values != 0) {
493 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
499 for (i=0;i<el->num_values;i++) {
500 e2->values[i] = el->values[i];
502 e2->num_values = el->num_values;
510 delete all elements having a specified attribute name
512 static int msg_delete_attribute(struct ldb_module *module,
513 struct ldb_context *ldb,
514 struct ldb_message *msg, const char *name)
519 dn = ldb_dn_get_linearized(msg->dn);
524 for (i=0;i<msg->num_elements;i++) {
525 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
526 for (j=0;j<msg->elements[i].num_values;j++) {
527 ltdb_index_del_value(module, dn, &msg->elements[i], j);
529 talloc_free(msg->elements[i].values);
530 if (msg->num_elements > (i+1)) {
531 memmove(&msg->elements[i],
533 sizeof(struct ldb_message_element)*
534 (msg->num_elements - (i+1)));
538 msg->elements = talloc_realloc(msg, msg->elements,
539 struct ldb_message_element,
548 delete all elements matching an attribute name/value
550 return 0 on success, -1 on failure
552 static int msg_delete_element(struct ldb_module *module,
553 struct ldb_message *msg,
555 const struct ldb_val *val)
557 struct ldb_context *ldb = module->ldb;
560 struct ldb_message_element *el;
561 const struct ldb_attrib_handler *h;
563 found = find_element(msg, name);
568 el = &msg->elements[found];
570 h = ldb_attrib_handler(ldb, el->name);
572 for (i=0;i<el->num_values;i++) {
573 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
574 if (i<el->num_values-1) {
575 memmove(&el->values[i], &el->values[i+1],
576 sizeof(el->values[i])*(el->num_values-(i+1)));
579 if (el->num_values == 0) {
580 return msg_delete_attribute(module, ldb, msg, name);
591 modify a record - internal interface
593 yuck - this is O(n^2). Luckily n is usually small so we probably
594 get away with it, but if we ever have really large attribute lists
595 then we'll need to look at this again
597 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
599 struct ldb_context *ldb = module->ldb;
600 struct ltdb_private *ltdb =
601 talloc_get_type(module->private_data, struct ltdb_private);
602 TDB_DATA tdb_key, tdb_data;
603 struct ldb_message *msg2;
607 tdb_key = ltdb_key(module, msg->dn);
609 return LDB_ERR_OTHER;
612 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
613 if (!tdb_data.dptr) {
614 talloc_free(tdb_key.dptr);
615 return ltdb_err_map(tdb_error(ltdb->tdb));
618 msg2 = talloc(tdb_key.dptr, struct ldb_message);
620 talloc_free(tdb_key.dptr);
621 return LDB_ERR_OTHER;
624 ret = ltdb_unpack_data(module, &tdb_data, msg2);
634 for (i=0;i<msg->num_elements;i++) {
635 struct ldb_message_element *el = &msg->elements[i];
636 struct ldb_message_element *el2;
637 struct ldb_val *vals;
640 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
642 case LDB_FLAG_MOD_ADD:
643 /* add this element to the message. fail if it
645 ret = find_element(msg2, el->name);
648 if (msg_add_element(ldb, msg2, el) != 0) {
655 el2 = &msg2->elements[ret];
657 /* An attribute with this name already exists, add all
658 * values if they don't already exist. */
660 for (j=0;j<el->num_values;j++) {
661 if (ldb_msg_find_val(el2, &el->values[j])) {
662 ldb_set_errstring(module->ldb, "Type or value exists");
663 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
668 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
669 el2->num_values + el->num_values);
676 for (j=0;j<el->num_values;j++) {
677 vals[el2->num_values + j] =
678 ldb_val_dup(vals, &el->values[j]);
682 el2->num_values += el->num_values;
686 case LDB_FLAG_MOD_REPLACE:
687 /* replace all elements of this attribute name with the elements
688 listed. The attribute not existing is not an error */
689 msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
691 /* add the replacement element, if not empty */
692 if (msg->elements[i].num_values != 0 &&
693 msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
699 case LDB_FLAG_MOD_DELETE:
701 dn = ldb_dn_get_linearized(msg->dn);
707 /* we could be being asked to delete all
708 values or just some values */
709 if (msg->elements[i].num_values == 0) {
710 if (msg_delete_attribute(module, ldb, msg2,
711 msg->elements[i].name) != 0) {
712 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
713 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
718 for (j=0;j<msg->elements[i].num_values;j++) {
719 if (msg_delete_element(module,
721 msg->elements[i].name,
722 &msg->elements[i].values[j]) != 0) {
723 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
724 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
727 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
734 ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
735 msg->elements[i].name,
736 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
737 ret = LDB_ERR_PROTOCOL_ERROR;
742 /* we've made all the mods - save the modified record back into the database */
743 ret = ltdb_store(module, msg2, TDB_MODIFY);
744 if (ret != LDB_SUCCESS) {
748 if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
749 ret = LDB_ERR_OPERATIONS_ERROR;
753 talloc_free(tdb_key.dptr);
758 talloc_free(tdb_key.dptr);
766 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
768 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
769 struct ltdb_context *ltdb_ac;
770 int tret, ret = LDB_SUCCESS;
772 if (req->controls != NULL) {
773 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
774 if (check_critical_controls(req->controls)) {
775 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
781 req->handle = init_ltdb_handle(ltdb, module, req);
782 if (req->handle == NULL) {
783 return LDB_ERR_OPERATIONS_ERROR;
785 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
787 tret = ltdb_check_special_dn(module, req->op.mod.message);
788 if (tret != LDB_SUCCESS) {
789 req->handle->status = tret;
793 if (ltdb_cache_load(module) != 0) {
794 ret = LDB_ERR_OPERATIONS_ERROR;
798 tret = ltdb_modify_internal(module, req->op.mod.message);
799 if (tret != LDB_SUCCESS) {
800 req->handle->status = tret;
804 if (ltdb_ac->callback) {
805 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
808 req->handle->state = LDB_ASYNC_DONE;
815 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
817 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
818 struct ltdb_context *ltdb_ac;
819 struct ldb_message *msg;
820 int tret, ret = LDB_SUCCESS;
822 if (req->controls != NULL) {
823 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
824 if (check_critical_controls(req->controls)) {
825 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
831 if (ltdb_cache_load(module) != 0) {
832 return LDB_ERR_OPERATIONS_ERROR;
835 req->handle = init_ltdb_handle(ltdb, module, req);
836 if (req->handle == NULL) {
837 return LDB_ERR_OPERATIONS_ERROR;
839 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
841 msg = talloc(ltdb_ac, struct ldb_message);
843 ret = LDB_ERR_OPERATIONS_ERROR;
847 /* in case any attribute of the message was indexed, we need
848 to fetch the old record */
849 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
851 /* not finding the old record is an error */
852 req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
856 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
858 ret = LDB_ERR_OPERATIONS_ERROR;
862 tret = ltdb_add_internal(module, msg);
863 if (tret != LDB_SUCCESS) {
864 ret = LDB_ERR_OPERATIONS_ERROR;
868 tret = ltdb_delete_internal(module, req->op.rename.olddn);
869 if (tret != LDB_SUCCESS) {
870 ltdb_delete_internal(module, req->op.rename.newdn);
871 ret = LDB_ERR_OPERATIONS_ERROR;
875 if (ltdb_ac->callback) {
876 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
879 req->handle->state = LDB_ASYNC_DONE;
883 static int ltdb_start_trans(struct ldb_module *module)
885 struct ltdb_private *ltdb =
886 talloc_get_type(module->private_data, struct ltdb_private);
888 if (tdb_transaction_start(ltdb->tdb) != 0) {
889 return ltdb_err_map(tdb_error(ltdb->tdb));
895 static int ltdb_end_trans(struct ldb_module *module)
897 struct ltdb_private *ltdb =
898 talloc_get_type(module->private_data, struct ltdb_private);
900 if (tdb_transaction_commit(ltdb->tdb) != 0) {
901 return ltdb_err_map(tdb_error(ltdb->tdb));
907 static int ltdb_del_trans(struct ldb_module *module)
909 struct ltdb_private *ltdb =
910 talloc_get_type(module->private_data, struct ltdb_private);
912 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
913 return ltdb_err_map(tdb_error(ltdb->tdb));
919 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
921 return handle->status;
924 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
926 /* check for oustanding critical controls and return an error if found */
927 if (req->controls != NULL) {
928 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
929 if (check_critical_controls(req->controls)) {
930 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
934 /* search, add, modify, delete, rename are handled by their own, no other op supported */
935 return LDB_ERR_OPERATIONS_ERROR;
939 return sequenceNumber from @BASEINFO
941 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
943 TALLOC_CTX *tmp_ctx = talloc_new(req);
944 struct ldb_message *msg = NULL;
945 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
948 if (tmp_ctx == NULL) {
949 talloc_free(tmp_ctx);
950 return LDB_ERR_OPERATIONS_ERROR;
953 msg = talloc(tmp_ctx, struct ldb_message);
955 talloc_free(tmp_ctx);
956 return LDB_ERR_OPERATIONS_ERROR;
959 req->op.seq_num.flags = 0;
961 tret = ltdb_search_dn1(module, dn, msg);
963 talloc_free(tmp_ctx);
964 req->op.seq_num.seq_num = 0;
965 /* zero is as good as anything when we don't know */
969 switch (req->op.seq_num.type) {
970 case LDB_SEQ_HIGHEST_SEQ:
971 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
974 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
975 req->op.seq_num.seq_num++;
977 case LDB_SEQ_HIGHEST_TIMESTAMP:
979 const char *date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
981 req->op.seq_num.seq_num = ldb_string_to_time(date);
983 req->op.seq_num.seq_num = 0;
984 /* zero is as good as anything when we don't know */
989 talloc_free(tmp_ctx);
993 static const struct ldb_module_ops ltdb_ops = {
995 .search = ltdb_search,
997 .modify = ltdb_modify,
999 .rename = ltdb_rename,
1000 .request = ltdb_request,
1001 .start_transaction = ltdb_start_trans,
1002 .end_transaction = ltdb_end_trans,
1003 .del_transaction = ltdb_del_trans,
1005 .sequence_number = ltdb_sequence_number
1009 connect to the database
1011 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1012 unsigned int flags, const char *options[],
1013 struct ldb_module **module)
1016 int tdb_flags, open_flags;
1017 struct ltdb_private *ltdb;
1020 if (strchr(url, ':')) {
1021 if (strncmp(url, "tdb://", 6) != 0) {
1022 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1030 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1032 /* check for the 'nosync' option */
1033 if (flags & LDB_FLG_NOSYNC) {
1034 tdb_flags |= TDB_NOSYNC;
1037 if (flags & LDB_FLG_RDONLY) {
1038 open_flags = O_RDONLY;
1040 open_flags = O_CREAT | O_RDWR;
1043 ltdb = talloc_zero(ldb, struct ltdb_private);
1049 /* note that we use quite a large default hash size */
1050 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1051 tdb_flags, open_flags,
1052 ldb->create_perms, ldb);
1054 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1059 ltdb->sequence_number = 0;
1061 *module = talloc(ldb, struct ldb_module);
1067 talloc_set_name_const(*module, "ldb_tdb backend");
1068 (*module)->ldb = ldb;
1069 (*module)->prev = (*module)->next = NULL;
1070 (*module)->private_data = ltdb;
1071 (*module)->ops = <db_ops;
1073 if (ltdb_cache_load(*module) != 0) {
1074 talloc_free(*module);
1082 int ldb_tdb_init(void)
1084 return ldb_register_backend("tdb", ltdb_connect);