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 3 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, see <http://www.gnu.org/licenses/>.
30 * Component: ldb tdb backend
32 * Description: core functions for tdb backend
34 * Author: Andrew Tridgell
35 * Author: Stefan Metzmacher
39 * - description: make the module use asyncronous calls
44 #include "ldb_includes.h"
50 map a tdb error code to a ldb error code
52 static int ltdb_err_map(enum TDB_ERROR tdb_code)
60 return LDB_ERR_OPERATIONS_ERROR;
62 return LDB_ERR_PROTOCOL_ERROR;
66 case TDB_ERR_LOCK_TIMEOUT:
67 return LDB_ERR_TIME_LIMIT_EXCEEDED;
69 return LDB_ERR_ENTRY_ALREADY_EXISTS;
71 return LDB_ERR_NO_SUCH_OBJECT;
73 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
79 struct ldb_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,
80 struct ldb_request *req)
82 struct ltdb_context *ac;
85 h = talloc_zero(req, struct ldb_handle);
87 ldb_set_errstring(module->ldb, "Out of Memory");
93 ac = talloc_zero(h, struct ltdb_context);
95 ldb_set_errstring(module->ldb, "Out of Memory");
100 h->private_data = (void *)ac;
102 h->state = LDB_ASYNC_INIT;
103 h->status = LDB_SUCCESS;
106 ac->context = req->context;
107 ac->callback = req->callback;
113 form a TDB_DATA for a record key
116 note that the key for a record can depend on whether the
117 dn refers to a case sensitive index record or not
119 struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn)
121 struct ldb_context *ldb = module->ldb;
123 char *key_str = NULL;
124 const char *dn_folded = NULL;
127 most DNs are case insensitive. The exception is index DNs for
128 case sensitive attributes
130 there are 3 cases dealt with in this code:
132 1) if the dn doesn't start with @ then uppercase the attribute
133 names and the attributes values of case insensitive attributes
134 2) if the dn starts with @ then leave it alone - the indexing code handles
138 dn_folded = ldb_dn_get_casefold(dn);
143 key_str = talloc_strdup(ldb, "DN=");
148 key_str = talloc_strdup_append_buffer(key_str, 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, struct ldb_dn *dn)
199 int ret = LDB_SUCCESS;
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);
207 if (ret == LDB_SUCCESS &&
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);
244 if (ret != LDB_SUCCESS) {
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) {
272 ldb_asprintf_errstring(module->ldb, "Entry %s already exists", ldb_dn_get_linearized(msg->dn));
276 if (ret == LDB_SUCCESS) {
277 ret = ltdb_index_one(module, msg, 1);
278 if (ret != LDB_SUCCESS) {
282 ret = ltdb_modified(module, msg->dn);
283 if (ret != LDB_SUCCESS) {
292 add a record to the database
294 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
296 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
297 struct ltdb_context *ltdb_ac;
298 int tret, ret = LDB_SUCCESS;
300 if (check_critical_controls(req->controls)) {
301 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
304 req->handle = init_ltdb_handle(ltdb, module, req);
305 if (req->handle == NULL) {
306 return LDB_ERR_OPERATIONS_ERROR;
308 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
310 tret = ltdb_add_internal(module, req->op.add.message);
311 if (tret != LDB_SUCCESS) {
312 req->handle->status = tret;
316 if (ltdb_ac->callback) {
317 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
320 req->handle->state = LDB_ASYNC_DONE;
325 delete a record from the database, not updating indexes (used for deleting
328 int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn)
330 struct ltdb_private *ltdb =
331 talloc_get_type(module->private_data, struct ltdb_private);
335 tdb_key = ltdb_key(module, dn);
337 return LDB_ERR_OTHER;
340 ret = tdb_delete(ltdb->tdb, tdb_key);
341 talloc_free(tdb_key.dptr);
344 ret = ltdb_err_map(tdb_error(ltdb->tdb));
350 static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
352 struct ldb_message *msg;
355 msg = talloc(module, struct ldb_message);
357 return LDB_ERR_OPERATIONS_ERROR;
360 /* in case any attribute of the message was indexed, we need
361 to fetch the old record */
362 ret = ltdb_search_dn1(module, dn, msg);
363 if (ret != LDB_SUCCESS) {
364 /* not finding the old record is an error */
368 ret = ltdb_delete_noindex(module, dn);
369 if (ret != LDB_SUCCESS) {
373 /* remove one level attribute */
374 ret = ltdb_index_one(module, msg, 0);
375 if (ret != LDB_SUCCESS) {
379 /* remove any indexed attributes */
380 ret = ltdb_index_del(module, msg);
381 if (ret != LDB_SUCCESS) {
385 ret = ltdb_modified(module, dn);
386 if (ret != LDB_SUCCESS) {
396 delete a record from the database
398 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
400 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
401 struct ltdb_context *ltdb_ac;
402 int tret, ret = LDB_SUCCESS;
404 if (check_critical_controls(req->controls)) {
405 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
410 if (ltdb_cache_load(module) != 0) {
411 return LDB_ERR_OPERATIONS_ERROR;
414 req->handle = init_ltdb_handle(ltdb, module, req);
415 if (req->handle == NULL) {
416 return LDB_ERR_OPERATIONS_ERROR;
418 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
420 tret = ltdb_delete_internal(module, req->op.del.dn);
421 if (tret != LDB_SUCCESS) {
422 req->handle->status = tret;
426 if (ltdb_ac->callback) {
427 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
430 req->handle->state = LDB_ASYNC_DONE;
435 find an element by attribute name. At the moment this does a linear search, it should
436 be re-coded to use a binary search once all places that modify records guarantee
439 return the index of the first matching element if found, otherwise -1
441 static int find_element(const struct ldb_message *msg, const char *name)
444 for (i=0;i<msg->num_elements;i++) {
445 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
454 add an element to an existing record. Assumes a elements array that we
455 can call re-alloc on, and assumed that we can re-use the data pointers from the
456 passed in additional values. Use with care!
458 returns 0 on success, -1 on failure (and sets errno)
460 static int msg_add_element(struct ldb_context *ldb,
461 struct ldb_message *msg, struct ldb_message_element *el)
463 struct ldb_message_element *e2;
466 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
467 msg->num_elements+1);
475 e2 = &msg->elements[msg->num_elements];
478 e2->flags = el->flags;
480 if (el->num_values != 0) {
481 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
487 for (i=0;i<el->num_values;i++) {
488 e2->values[i] = el->values[i];
490 e2->num_values = el->num_values;
498 delete all elements having a specified attribute name
500 static int msg_delete_attribute(struct ldb_module *module,
501 struct ldb_context *ldb,
502 struct ldb_message *msg, const char *name)
507 dn = ldb_dn_get_linearized(msg->dn);
512 for (i=0;i<msg->num_elements;i++) {
513 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
514 for (j=0;j<msg->elements[i].num_values;j++) {
515 ltdb_index_del_value(module, dn, &msg->elements[i], j);
517 talloc_free(msg->elements[i].values);
518 if (msg->num_elements > (i+1)) {
519 memmove(&msg->elements[i],
521 sizeof(struct ldb_message_element)*
522 (msg->num_elements - (i+1)));
526 msg->elements = talloc_realloc(msg, msg->elements,
527 struct ldb_message_element,
536 delete all elements matching an attribute name/value
538 return 0 on success, -1 on failure
540 static int msg_delete_element(struct ldb_module *module,
541 struct ldb_message *msg,
543 const struct ldb_val *val)
545 struct ldb_context *ldb = module->ldb;
548 struct ldb_message_element *el;
549 const struct ldb_schema_attribute *a;
551 found = find_element(msg, name);
556 el = &msg->elements[found];
558 a = ldb_schema_attribute_by_name(ldb, el->name);
560 for (i=0;i<el->num_values;i++) {
561 if (a->syntax->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
562 if (i<el->num_values-1) {
563 memmove(&el->values[i], &el->values[i+1],
564 sizeof(el->values[i])*(el->num_values-(i+1)));
567 if (el->num_values == 0) {
568 return msg_delete_attribute(module, ldb, msg, name);
579 modify a record - internal interface
581 yuck - this is O(n^2). Luckily n is usually small so we probably
582 get away with it, but if we ever have really large attribute lists
583 then we'll need to look at this again
585 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
587 struct ldb_context *ldb = module->ldb;
588 struct ltdb_private *ltdb =
589 talloc_get_type(module->private_data, struct ltdb_private);
590 TDB_DATA tdb_key, tdb_data;
591 struct ldb_message *msg2;
595 tdb_key = ltdb_key(module, msg->dn);
597 return LDB_ERR_OTHER;
600 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
601 if (!tdb_data.dptr) {
602 talloc_free(tdb_key.dptr);
603 return ltdb_err_map(tdb_error(ltdb->tdb));
606 msg2 = talloc(tdb_key.dptr, struct ldb_message);
608 talloc_free(tdb_key.dptr);
609 return LDB_ERR_OTHER;
612 ret = ltdb_unpack_data(module, &tdb_data, msg2);
622 for (i=0;i<msg->num_elements;i++) {
623 struct ldb_message_element *el = &msg->elements[i];
624 struct ldb_message_element *el2;
625 struct ldb_val *vals;
628 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
630 case LDB_FLAG_MOD_ADD:
631 /* add this element to the message. fail if it
633 idx = find_element(msg2, el->name);
636 if (msg_add_element(ldb, msg2, el) != 0) {
643 el2 = &msg2->elements[idx];
645 /* An attribute with this name already exists,
646 * add all values if they don't already exist
647 * (check both the other elements to be added,
648 * and those already in the db). */
650 for (j=0;j<el->num_values;j++) {
651 if (ldb_msg_find_val(el2, &el->values[j])) {
652 ldb_asprintf_errstring(module->ldb, "%s: value #%d already exists", el->name, j);
653 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
656 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
657 ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
658 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
663 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
664 el2->num_values + el->num_values);
671 for (j=0;j<el->num_values;j++) {
672 vals[el2->num_values + j] =
673 ldb_val_dup(vals, &el->values[j]);
677 el2->num_values += el->num_values;
681 case LDB_FLAG_MOD_REPLACE:
682 /* replace all elements of this attribute name with the elements
683 listed. The attribute not existing is not an error */
684 msg_delete_attribute(module, ldb, msg2, el->name);
686 for (j=0;j<el->num_values;j++) {
687 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
688 ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
689 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
694 /* add the replacement element, if not empty */
695 if (el->num_values != 0 &&
696 msg_add_element(ldb, msg2, el) != 0) {
702 case LDB_FLAG_MOD_DELETE:
704 dn = ldb_dn_get_linearized(msg->dn);
710 /* we could be being asked to delete all
711 values or just some values */
712 if (msg->elements[i].num_values == 0) {
713 if (msg_delete_attribute(module, ldb, msg2,
714 msg->elements[i].name) != 0) {
715 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
716 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
721 for (j=0;j<msg->elements[i].num_values;j++) {
722 if (msg_delete_element(module,
724 msg->elements[i].name,
725 &msg->elements[i].values[j]) != 0) {
726 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
727 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
730 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
731 if (ret != LDB_SUCCESS) {
737 ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
738 msg->elements[i].name,
739 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
740 ret = LDB_ERR_PROTOCOL_ERROR;
745 /* we've made all the mods - save the modified record back into the database */
746 ret = ltdb_store(module, msg2, TDB_MODIFY);
747 if (ret != LDB_SUCCESS) {
751 ret = ltdb_modified(module, msg->dn);
752 if (ret != LDB_SUCCESS) {
756 talloc_free(tdb_key.dptr);
761 talloc_free(tdb_key.dptr);
769 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
771 struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
772 struct ltdb_context *ltdb_ac;
773 int tret, ret = LDB_SUCCESS;
775 if (check_critical_controls(req->controls)) {
776 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 (check_critical_controls(req->controls)) {
823 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
828 if (ltdb_cache_load(module) != 0) {
829 return LDB_ERR_OPERATIONS_ERROR;
832 req->handle = init_ltdb_handle(ltdb, module, req);
833 if (req->handle == NULL) {
834 return LDB_ERR_OPERATIONS_ERROR;
836 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
838 msg = talloc(ltdb_ac, struct ldb_message);
840 ret = LDB_ERR_OPERATIONS_ERROR;
844 /* in case any attribute of the message was indexed, we need
845 to fetch the old record */
846 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
847 if (tret != LDB_SUCCESS) {
848 /* not finding the old record is an error */
849 req->handle->status = tret;
853 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
855 ret = LDB_ERR_OPERATIONS_ERROR;
859 if (ldb_dn_compare(req->op.rename.olddn, req->op.rename.newdn) == 0) {
860 /* The rename operation is apparently only changing case -
861 the DNs are the same. Delete the old DN before adding
862 the new one to avoid a TDB_ERR_EXISTS error.
864 The only drawback to this is that if the delete
865 succeeds but the add fails, we rely on the
866 transaction to roll this all back. */
867 ret = ltdb_delete_internal(module, req->op.rename.olddn);
868 if (ret != LDB_SUCCESS) {
872 ret = ltdb_add_internal(module, msg);
873 if (ret != LDB_SUCCESS) {
877 /* The rename operation is changing DNs. Try to add the new
878 DN first to avoid clobbering another DN not related to
879 this rename operation. */
880 ret = ltdb_add_internal(module, msg);
881 if (ret != LDB_SUCCESS) {
885 tret = ltdb_delete_internal(module, req->op.rename.olddn);
886 if (tret != LDB_SUCCESS) {
887 ltdb_delete_internal(module, req->op.rename.newdn);
888 ret = LDB_ERR_OPERATIONS_ERROR;
893 if (ltdb_ac->callback) {
894 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
897 req->handle->state = LDB_ASYNC_DONE;
901 static int ltdb_start_trans(struct ldb_module *module)
903 struct ltdb_private *ltdb =
904 talloc_get_type(module->private_data, struct ltdb_private);
906 if (tdb_transaction_start(ltdb->tdb) != 0) {
907 return ltdb_err_map(tdb_error(ltdb->tdb));
910 ltdb->in_transaction++;
915 static int ltdb_end_trans(struct ldb_module *module)
917 struct ltdb_private *ltdb =
918 talloc_get_type(module->private_data, struct ltdb_private);
920 ltdb->in_transaction--;
922 if (tdb_transaction_commit(ltdb->tdb) != 0) {
923 return ltdb_err_map(tdb_error(ltdb->tdb));
929 static int ltdb_del_trans(struct ldb_module *module)
931 struct ltdb_private *ltdb =
932 talloc_get_type(module->private_data, struct ltdb_private);
934 ltdb->in_transaction--;
936 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
937 return ltdb_err_map(tdb_error(ltdb->tdb));
943 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
945 return handle->status;
948 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
950 /* check for oustanding critical controls and return an error if found */
951 if (check_critical_controls(req->controls)) {
952 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
955 /* search, add, modify, delete, rename are handled by their own, no other op supported */
956 return LDB_ERR_OPERATIONS_ERROR;
960 return sequenceNumber from @BASEINFO
962 static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
965 struct ldb_message *msg = NULL;
970 tmp_ctx = talloc_new(req);
971 if (tmp_ctx == NULL) {
972 talloc_free(tmp_ctx);
973 return LDB_ERR_OPERATIONS_ERROR;
976 dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
978 msg = talloc(tmp_ctx, struct ldb_message);
980 talloc_free(tmp_ctx);
981 return LDB_ERR_OPERATIONS_ERROR;
984 req->op.seq_num.flags = 0;
986 tret = ltdb_search_dn1(module, dn, msg);
987 if (tret != LDB_SUCCESS) {
988 talloc_free(tmp_ctx);
989 /* zero is as good as anything when we don't know */
990 req->op.seq_num.seq_num = 0;
994 switch (req->op.seq_num.type) {
995 case LDB_SEQ_HIGHEST_SEQ:
996 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
999 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
1000 req->op.seq_num.seq_num++;
1002 case LDB_SEQ_HIGHEST_TIMESTAMP:
1003 date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
1005 req->op.seq_num.seq_num = ldb_string_to_time(date);
1007 req->op.seq_num.seq_num = 0;
1008 /* zero is as good as anything when we don't know */
1012 talloc_free(tmp_ctx);
1016 static const struct ldb_module_ops ltdb_ops = {
1018 .search = ltdb_search,
1020 .modify = ltdb_modify,
1022 .rename = ltdb_rename,
1023 .request = ltdb_request,
1024 .start_transaction = ltdb_start_trans,
1025 .end_transaction = ltdb_end_trans,
1026 .del_transaction = ltdb_del_trans,
1028 .sequence_number = ltdb_sequence_number
1032 connect to the database
1034 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1035 unsigned int flags, const char *options[],
1036 struct ldb_module **module)
1039 int tdb_flags, open_flags;
1040 struct ltdb_private *ltdb;
1043 if (strchr(url, ':')) {
1044 if (strncmp(url, "tdb://", 6) != 0) {
1045 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1053 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1055 /* check for the 'nosync' option */
1056 if (flags & LDB_FLG_NOSYNC) {
1057 tdb_flags |= TDB_NOSYNC;
1060 /* and nommap option */
1061 if (flags & LDB_FLG_NOMMAP) {
1062 tdb_flags |= TDB_NOMMAP;
1065 if (flags & LDB_FLG_RDONLY) {
1066 open_flags = O_RDONLY;
1068 open_flags = O_CREAT | O_RDWR;
1071 ltdb = talloc_zero(ldb, struct ltdb_private);
1077 /* note that we use quite a large default hash size */
1078 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1079 tdb_flags, open_flags,
1080 ldb->create_perms, ldb);
1082 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1087 ltdb->sequence_number = 0;
1089 *module = talloc(ldb, struct ldb_module);
1095 talloc_set_name_const(*module, "ldb_tdb backend");
1096 (*module)->ldb = ldb;
1097 (*module)->prev = (*module)->next = NULL;
1098 (*module)->private_data = ltdb;
1099 (*module)->ops = <db_ops;
1101 if (ltdb_cache_load(*module) != 0) {
1102 talloc_free(*module);
1110 int ldb_tdb_init(void)
1112 return ldb_register_backend("tdb", ltdb_connect);