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,
80 struct ldb_module *module,
81 struct ldb_request *req)
83 struct ltdb_context *ac;
86 h = talloc_zero(req, struct ldb_handle);
88 ldb_set_errstring(module->ldb, "Out of Memory");
94 ac = talloc_zero(h, struct ltdb_context);
96 ldb_set_errstring(module->ldb, "Out of Memory");
101 h->private_data = (void *)ac;
103 h->state = LDB_ASYNC_INIT;
104 h->status = LDB_SUCCESS;
107 ac->context = req->context;
108 ac->callback = req->callback;
114 form a TDB_DATA for a record key
117 note that the key for a record can depend on whether the
118 dn refers to a case sensitive index record or not
120 struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn)
122 struct ldb_context *ldb = module->ldb;
124 char *key_str = NULL;
125 const char *dn_folded = NULL;
128 most DNs are case insensitive. The exception is index DNs for
129 case sensitive attributes
131 there are 3 cases dealt with in this code:
133 1) if the dn doesn't start with @ then uppercase the attribute
134 names and the attributes values of case insensitive attributes
135 2) if the dn starts with @ then leave it alone -
136 the indexing code handles the rest
139 dn_folded = ldb_dn_get_casefold(dn);
144 key_str = talloc_strdup(ldb, "DN=");
149 key_str = talloc_strdup_append_buffer(key_str, 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,
171 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)
201 int ret = LDB_SUCCESS;
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);
209 if (ret == LDB_SUCCESS &&
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);
246 if (ret != LDB_SUCCESS) {
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,
259 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);
274 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
275 ldb_asprintf_errstring(module->ldb,
276 "Entry %s already exists",
277 ldb_dn_get_linearized(msg->dn));
281 if (ret == LDB_SUCCESS) {
282 ret = ltdb_index_one(module, msg, 1);
283 if (ret != LDB_SUCCESS) {
287 ret = ltdb_modified(module, msg->dn);
288 if (ret != LDB_SUCCESS) {
297 add a record to the database
299 static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
301 struct ltdb_private *ltdb;
302 struct ltdb_context *ltdb_ac;
303 int tret, ret = LDB_SUCCESS;
305 ltdb = talloc_get_type(module->private_data, struct ltdb_private);
307 if (check_critical_controls(req->controls)) {
308 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
311 req->handle = init_ltdb_handle(ltdb, module, req);
312 if (req->handle == NULL) {
313 return LDB_ERR_OPERATIONS_ERROR;
315 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
317 tret = ltdb_add_internal(module, req->op.add.message);
318 if (tret != LDB_SUCCESS) {
319 req->handle->status = tret;
323 if (ltdb_ac->callback) {
324 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
327 req->handle->state = LDB_ASYNC_DONE;
332 delete a record from the database, not updating indexes (used for deleting
335 int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn)
337 struct ltdb_private *ltdb =
338 talloc_get_type(module->private_data, struct ltdb_private);
342 tdb_key = ltdb_key(module, dn);
344 return LDB_ERR_OTHER;
347 ret = tdb_delete(ltdb->tdb, tdb_key);
348 talloc_free(tdb_key.dptr);
351 ret = ltdb_err_map(tdb_error(ltdb->tdb));
357 static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
359 struct ldb_message *msg;
362 msg = talloc(module, struct ldb_message);
364 return LDB_ERR_OPERATIONS_ERROR;
367 /* in case any attribute of the message was indexed, we need
368 to fetch the old record */
369 ret = ltdb_search_dn1(module, dn, msg);
370 if (ret != LDB_SUCCESS) {
371 /* not finding the old record is an error */
375 ret = ltdb_delete_noindex(module, dn);
376 if (ret != LDB_SUCCESS) {
380 /* remove one level attribute */
381 ret = ltdb_index_one(module, msg, 0);
382 if (ret != LDB_SUCCESS) {
386 /* remove any indexed attributes */
387 ret = ltdb_index_del(module, msg);
388 if (ret != LDB_SUCCESS) {
392 ret = ltdb_modified(module, dn);
393 if (ret != LDB_SUCCESS) {
403 delete a record from the database
405 static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
407 struct ltdb_private *ltdb;
408 struct ltdb_context *ltdb_ac;
409 int tret, ret = LDB_SUCCESS;
411 ltdb = talloc_get_type(module->private_data, struct ltdb_private);
413 if (check_critical_controls(req->controls)) {
414 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
419 if (ltdb_cache_load(module) != 0) {
420 return LDB_ERR_OPERATIONS_ERROR;
423 req->handle = init_ltdb_handle(ltdb, module, req);
424 if (req->handle == NULL) {
425 return LDB_ERR_OPERATIONS_ERROR;
427 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
429 tret = ltdb_delete_internal(module, req->op.del.dn);
430 if (tret != LDB_SUCCESS) {
431 req->handle->status = tret;
435 if (ltdb_ac->callback) {
436 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
439 req->handle->state = LDB_ASYNC_DONE;
444 find an element by attribute name. At the moment this does a linear search,
445 it should be re-coded to use a binary search once all places that modify
446 records guarantee sorted order
448 return the index of the first matching element if found, otherwise -1
450 static int find_element(const struct ldb_message *msg, const char *name)
453 for (i=0;i<msg->num_elements;i++) {
454 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
463 add an element to an existing record. Assumes a elements array that we
464 can call re-alloc on, and assumed that we can re-use the data pointers from
465 the passed in additional values. Use with care!
467 returns 0 on success, -1 on failure (and sets errno)
469 static int msg_add_element(struct ldb_context *ldb,
470 struct ldb_message *msg,
471 struct ldb_message_element *el)
473 struct ldb_message_element *e2;
476 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
477 msg->num_elements+1);
485 e2 = &msg->elements[msg->num_elements];
488 e2->flags = el->flags;
490 if (el->num_values != 0) {
491 e2->values = talloc_array(msg->elements,
492 struct ldb_val, el->num_values);
498 for (i=0;i<el->num_values;i++) {
499 e2->values[i] = el->values[i];
501 e2->num_values = el->num_values;
509 delete all elements having a specified attribute name
511 static int msg_delete_attribute(struct ldb_module *module,
512 struct ldb_context *ldb,
513 struct ldb_message *msg, const char *name)
518 dn = ldb_dn_get_linearized(msg->dn);
523 for (i=0;i<msg->num_elements;i++) {
524 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
525 for (j=0;j<msg->elements[i].num_values;j++) {
526 ltdb_index_del_value(module, dn,
527 &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_schema_attribute *a;
563 found = find_element(msg, name);
568 el = &msg->elements[found];
570 a = ldb_schema_attribute_by_name(ldb, el->name);
572 for (i=0;i<el->num_values;i++) {
573 if (a->syntax->comparison_fn(ldb, ldb,
574 &el->values[i], val) == 0) {
575 if (i<el->num_values-1) {
576 memmove(&el->values[i], &el->values[i+1],
577 sizeof(el->values[i])*
578 (el->num_values-(i+1)));
581 if (el->num_values == 0) {
582 return msg_delete_attribute(module, ldb,
594 modify a record - internal interface
596 yuck - this is O(n^2). Luckily n is usually small so we probably
597 get away with it, but if we ever have really large attribute lists
598 then we'll need to look at this again
600 int ltdb_modify_internal(struct ldb_module *module,
601 const struct ldb_message *msg)
603 struct ldb_context *ldb = module->ldb;
604 struct ltdb_private *ltdb =
605 talloc_get_type(module->private_data, struct ltdb_private);
606 TDB_DATA tdb_key, tdb_data;
607 struct ldb_message *msg2;
611 tdb_key = ltdb_key(module, msg->dn);
613 return LDB_ERR_OTHER;
616 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
617 if (!tdb_data.dptr) {
618 talloc_free(tdb_key.dptr);
619 return ltdb_err_map(tdb_error(ltdb->tdb));
622 msg2 = talloc(tdb_key.dptr, struct ldb_message);
624 talloc_free(tdb_key.dptr);
625 return LDB_ERR_OTHER;
628 ret = ltdb_unpack_data(module, &tdb_data, msg2);
638 for (i=0;i<msg->num_elements;i++) {
639 struct ldb_message_element *el = &msg->elements[i];
640 struct ldb_message_element *el2;
641 struct ldb_val *vals;
644 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
646 case LDB_FLAG_MOD_ADD:
647 /* add this element to the message. fail if it
649 idx = find_element(msg2, el->name);
652 if (msg_add_element(ldb, msg2, el) != 0) {
659 el2 = &msg2->elements[idx];
661 /* An attribute with this name already exists,
662 * add all values if they don't already exist
663 * (check both the other elements to be added,
664 * and those already in the db). */
666 for (j=0;j<el->num_values;j++) {
667 if (ldb_msg_find_val(el2, &el->values[j])) {
668 ldb_asprintf_errstring(module->ldb, "%s: value #%d already exists", el->name, j);
669 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
672 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
673 ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
674 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
679 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
680 el2->num_values + el->num_values);
687 for (j=0;j<el->num_values;j++) {
688 vals[el2->num_values + j] =
689 ldb_val_dup(vals, &el->values[j]);
693 el2->num_values += el->num_values;
697 case LDB_FLAG_MOD_REPLACE:
698 /* replace all elements of this attribute name with the elements
699 listed. The attribute not existing is not an error */
700 msg_delete_attribute(module, ldb, msg2, el->name);
702 for (j=0;j<el->num_values;j++) {
703 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
704 ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
705 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
710 /* add the replacement element, if not empty */
711 if (el->num_values != 0 &&
712 msg_add_element(ldb, msg2, el) != 0) {
718 case LDB_FLAG_MOD_DELETE:
720 dn = ldb_dn_get_linearized(msg->dn);
726 /* we could be being asked to delete all
727 values or just some values */
728 if (msg->elements[i].num_values == 0) {
729 if (msg_delete_attribute(module, ldb, msg2,
730 msg->elements[i].name) != 0) {
731 ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
732 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
737 for (j=0;j<msg->elements[i].num_values;j++) {
738 if (msg_delete_element(module,
740 msg->elements[i].name,
741 &msg->elements[i].values[j]) != 0) {
742 ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
743 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
746 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
747 if (ret != LDB_SUCCESS) {
753 ldb_asprintf_errstring(module->ldb,
754 "Invalid ldb_modify flags on %s: 0x%x",
755 msg->elements[i].name,
756 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
757 ret = LDB_ERR_PROTOCOL_ERROR;
762 /* we've made all the mods
763 * save the modified record back into the database */
764 ret = ltdb_store(module, msg2, TDB_MODIFY);
765 if (ret != LDB_SUCCESS) {
769 ret = ltdb_modified(module, msg->dn);
770 if (ret != LDB_SUCCESS) {
774 talloc_free(tdb_key.dptr);
779 talloc_free(tdb_key.dptr);
787 static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
789 struct ltdb_private *ltdb;
790 struct ltdb_context *ltdb_ac;
791 int tret, ret = LDB_SUCCESS;
793 ltdb = talloc_get_type(module->private_data, struct ltdb_private);
795 if (check_critical_controls(req->controls)) {
796 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
801 req->handle = init_ltdb_handle(ltdb, module, req);
802 if (req->handle == NULL) {
803 return LDB_ERR_OPERATIONS_ERROR;
805 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
807 tret = ltdb_check_special_dn(module, req->op.mod.message);
808 if (tret != LDB_SUCCESS) {
809 req->handle->status = tret;
813 if (ltdb_cache_load(module) != 0) {
814 ret = LDB_ERR_OPERATIONS_ERROR;
818 tret = ltdb_modify_internal(module, req->op.mod.message);
819 if (tret != LDB_SUCCESS) {
820 req->handle->status = tret;
824 if (ltdb_ac->callback) {
825 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
828 req->handle->state = LDB_ASYNC_DONE;
835 static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
837 struct ltdb_private *ltdb;
838 struct ltdb_context *ltdb_ac;
839 struct ldb_message *msg;
840 int tret, ret = LDB_SUCCESS;
842 ltdb = talloc_get_type(module->private_data, struct ltdb_private);
844 if (check_critical_controls(req->controls)) {
845 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
850 if (ltdb_cache_load(module) != 0) {
851 return LDB_ERR_OPERATIONS_ERROR;
854 req->handle = init_ltdb_handle(ltdb, module, req);
855 if (req->handle == NULL) {
856 return LDB_ERR_OPERATIONS_ERROR;
858 ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
860 msg = talloc(ltdb_ac, struct ldb_message);
862 ret = LDB_ERR_OPERATIONS_ERROR;
866 /* in case any attribute of the message was indexed, we need
867 to fetch the old record */
868 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
869 if (tret != LDB_SUCCESS) {
870 /* not finding the old record is an error */
871 req->handle->status = tret;
875 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
877 ret = LDB_ERR_OPERATIONS_ERROR;
881 if (ldb_dn_compare(req->op.rename.olddn, req->op.rename.newdn) == 0) {
882 /* The rename operation is apparently only changing case -
883 the DNs are the same. Delete the old DN before adding
884 the new one to avoid a TDB_ERR_EXISTS error.
886 The only drawback to this is that if the delete
887 succeeds but the add fails, we rely on the
888 transaction to roll this all back. */
889 ret = ltdb_delete_internal(module, req->op.rename.olddn);
890 if (ret != LDB_SUCCESS) {
894 ret = ltdb_add_internal(module, msg);
895 if (ret != LDB_SUCCESS) {
899 /* The rename operation is changing DNs. Try to add the new
900 DN first to avoid clobbering another DN not related to
901 this rename operation. */
902 ret = ltdb_add_internal(module, msg);
903 if (ret != LDB_SUCCESS) {
907 tret = ltdb_delete_internal(module, req->op.rename.olddn);
908 if (tret != LDB_SUCCESS) {
909 ltdb_delete_internal(module, req->op.rename.newdn);
910 ret = LDB_ERR_OPERATIONS_ERROR;
915 if (ltdb_ac->callback) {
916 ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
919 req->handle->state = LDB_ASYNC_DONE;
923 static int ltdb_start_trans(struct ldb_module *module)
925 struct ltdb_private *ltdb =
926 talloc_get_type(module->private_data, struct ltdb_private);
928 if (tdb_transaction_start(ltdb->tdb) != 0) {
929 return ltdb_err_map(tdb_error(ltdb->tdb));
932 ltdb->in_transaction++;
937 static int ltdb_end_trans(struct ldb_module *module)
939 struct ltdb_private *ltdb =
940 talloc_get_type(module->private_data, struct ltdb_private);
942 ltdb->in_transaction--;
944 if (tdb_transaction_commit(ltdb->tdb) != 0) {
945 return ltdb_err_map(tdb_error(ltdb->tdb));
951 static int ltdb_del_trans(struct ldb_module *module)
953 struct ltdb_private *ltdb =
954 talloc_get_type(module->private_data, struct ltdb_private);
956 ltdb->in_transaction--;
958 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
959 return ltdb_err_map(tdb_error(ltdb->tdb));
965 static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
967 return handle->status;
970 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
972 /* check for oustanding critical controls
973 * and return an error if found */
974 if (check_critical_controls(req->controls)) {
975 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
978 /* search, add, modify, delete, rename are handled by their own,
979 * no other op supported */
980 return LDB_ERR_OPERATIONS_ERROR;
984 return sequenceNumber from @BASEINFO
986 static int ltdb_sequence_number(struct ldb_module *module,
987 struct ldb_request *req)
990 struct ldb_message *msg = NULL;
995 tmp_ctx = talloc_new(req);
996 if (tmp_ctx == NULL) {
997 talloc_free(tmp_ctx);
998 return LDB_ERR_OPERATIONS_ERROR;
1001 dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
1003 msg = talloc(tmp_ctx, struct ldb_message);
1005 talloc_free(tmp_ctx);
1006 return LDB_ERR_OPERATIONS_ERROR;
1009 req->op.seq_num.flags = 0;
1011 tret = ltdb_search_dn1(module, dn, msg);
1012 if (tret != LDB_SUCCESS) {
1013 talloc_free(tmp_ctx);
1014 /* zero is as good as anything when we don't know */
1015 req->op.seq_num.seq_num = 0;
1019 switch (req->op.seq_num.type) {
1020 case LDB_SEQ_HIGHEST_SEQ:
1021 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
1024 req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
1025 req->op.seq_num.seq_num++;
1027 case LDB_SEQ_HIGHEST_TIMESTAMP:
1028 date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
1030 req->op.seq_num.seq_num = ldb_string_to_time(date);
1032 req->op.seq_num.seq_num = 0;
1033 /* zero is as good as anything when we don't know */
1037 talloc_free(tmp_ctx);
1041 static const struct ldb_module_ops ltdb_ops = {
1043 .search = ltdb_search,
1045 .modify = ltdb_modify,
1047 .rename = ltdb_rename,
1048 .request = ltdb_request,
1049 .start_transaction = ltdb_start_trans,
1050 .end_transaction = ltdb_end_trans,
1051 .del_transaction = ltdb_del_trans,
1053 .sequence_number = ltdb_sequence_number
1057 connect to the database
1059 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1060 unsigned int flags, const char *options[],
1061 struct ldb_module **module)
1064 int tdb_flags, open_flags;
1065 struct ltdb_private *ltdb;
1068 if (strchr(url, ':')) {
1069 if (strncmp(url, "tdb://", 6) != 0) {
1070 ldb_debug(ldb, LDB_DEBUG_ERROR,
1071 "Invalid tdb URL '%s'", url);
1079 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1081 /* check for the 'nosync' option */
1082 if (flags & LDB_FLG_NOSYNC) {
1083 tdb_flags |= TDB_NOSYNC;
1086 /* and nommap option */
1087 if (flags & LDB_FLG_NOMMAP) {
1088 tdb_flags |= TDB_NOMMAP;
1091 if (flags & LDB_FLG_RDONLY) {
1092 open_flags = O_RDONLY;
1094 open_flags = O_CREAT | O_RDWR;
1097 ltdb = talloc_zero(ldb, struct ltdb_private);
1103 /* note that we use quite a large default hash size */
1104 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1105 tdb_flags, open_flags,
1106 ldb->create_perms, ldb);
1108 ldb_debug(ldb, LDB_DEBUG_ERROR,
1109 "Unable to open tdb '%s'\n", path);
1114 ltdb->sequence_number = 0;
1116 *module = talloc(ldb, struct ldb_module);
1122 talloc_set_name_const(*module, "ldb_tdb backend");
1123 (*module)->ldb = ldb;
1124 (*module)->prev = (*module)->next = NULL;
1125 (*module)->private_data = ltdb;
1126 (*module)->ops = <db_ops;
1128 if (ltdb_cache_load(*module) != 0) {
1129 talloc_free(*module);
1137 const struct ldb_backend_ops ldb_tdb_backend_ops = {
1139 .connect_fn = ltdb_connect