fixed spelling
[Samba.git] / source4 / lib / ldb / ldb_tdb / ldb_tdb.c
blob55acb6132d8f241de83bbb3bbc931b98e1d8f5fc
1 /*
2 ldb database library
4 Copyright (C) Andrew Tridgell 2004
5 Copyright (C) Stefan Metzmacher 2004
6 Copyright (C) Simo Sorce 2006-2008
9 ** NOTE! The following LGPL license applies to the ldb
10 ** library. This does NOT imply that all of Samba is released
11 ** under the LGPL
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/>.
28 * Name: ldb_tdb
30 * Component: ldb tdb backend
32 * Description: core functions for tdb backend
34 * Author: Andrew Tridgell
35 * Author: Stefan Metzmacher
37 * Modifications:
39 * - description: make the module use asyncronous calls
40 * date: Feb 2006
41 * Author: Simo Sorce
43 * - description: make it possible to use event contexts
44 * date: Jan 2008
45 * Author: Simo Sorce
48 #include "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)
56 switch (tdb_code) {
57 case TDB_SUCCESS:
58 return LDB_SUCCESS;
59 case TDB_ERR_CORRUPT:
60 case TDB_ERR_OOM:
61 case TDB_ERR_EINVAL:
62 return LDB_ERR_OPERATIONS_ERROR;
63 case TDB_ERR_IO:
64 return LDB_ERR_PROTOCOL_ERROR;
65 case TDB_ERR_LOCK:
66 case TDB_ERR_NOLOCK:
67 return LDB_ERR_BUSY;
68 case TDB_ERR_LOCK_TIMEOUT:
69 return LDB_ERR_TIME_LIMIT_EXCEEDED;
70 case TDB_ERR_EXISTS:
71 return LDB_ERR_ENTRY_ALREADY_EXISTS;
72 case TDB_ERR_NOEXIST:
73 return LDB_ERR_NO_SUCH_OBJECT;
74 case TDB_ERR_RDONLY:
75 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
77 return LDB_ERR_OTHER;
81 lock the database for read - use by ltdb_search and ltdb_sequence_number
83 int ltdb_lock_read(struct ldb_module *module)
85 void *data = ldb_module_get_private(module);
86 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
87 if (ltdb->in_transaction == 0) {
88 return tdb_lockall_read(ltdb->tdb);
90 return 0;
94 unlock the database after a ltdb_lock_read()
96 int ltdb_unlock_read(struct ldb_module *module)
98 void *data = ldb_module_get_private(module);
99 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
100 if (ltdb->in_transaction == 0) {
101 return tdb_unlockall_read(ltdb->tdb);
103 return 0;
108 form a TDB_DATA for a record key
109 caller frees
111 note that the key for a record can depend on whether the
112 dn refers to a case sensitive index record or not
114 struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn)
116 struct ldb_context *ldb = ldb_module_get_ctx(module);
117 TDB_DATA key;
118 char *key_str = NULL;
119 const char *dn_folded = NULL;
122 most DNs are case insensitive. The exception is index DNs for
123 case sensitive attributes
125 there are 3 cases dealt with in this code:
127 1) if the dn doesn't start with @ then uppercase the attribute
128 names and the attributes values of case insensitive attributes
129 2) if the dn starts with @ then leave it alone -
130 the indexing code handles the rest
133 dn_folded = ldb_dn_get_casefold(dn);
134 if (!dn_folded) {
135 goto failed;
138 key_str = talloc_strdup(ldb, "DN=");
139 if (!key_str) {
140 goto failed;
143 key_str = talloc_strdup_append_buffer(key_str, dn_folded);
144 if (!key_str) {
145 goto failed;
148 key.dptr = (uint8_t *)key_str;
149 key.dsize = strlen(key_str) + 1;
151 return key;
153 failed:
154 errno = ENOMEM;
155 key.dptr = NULL;
156 key.dsize = 0;
157 return key;
161 check special dn's have valid attributes
162 currently only @ATTRIBUTES is checked
164 static int ltdb_check_special_dn(struct ldb_module *module,
165 const struct ldb_message *msg)
167 struct ldb_context *ldb = ldb_module_get_ctx(module);
168 int i, j;
170 if (! ldb_dn_is_special(msg->dn) ||
171 ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
172 return 0;
175 /* we have @ATTRIBUTES, let's check attributes are fine */
176 /* should we check that we deny multivalued attributes ? */
177 for (i = 0; i < msg->num_elements; i++) {
178 for (j = 0; j < msg->elements[i].num_values; j++) {
179 if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
180 ldb_set_errstring(ldb, "Invalid attribute value in an @ATTRIBUTES entry");
181 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
186 return 0;
191 we've made a modification to a dn - possibly reindex and
192 update sequence number
194 static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn)
196 int ret = LDB_SUCCESS;
198 if (ldb_dn_is_special(dn) &&
199 (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
200 ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
201 ret = ltdb_reindex(module);
204 if (ret == LDB_SUCCESS &&
205 !(ldb_dn_is_special(dn) &&
206 ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
207 ret = ltdb_increase_sequence_number(module);
210 return ret;
214 store a record into the db
216 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
218 void *data = ldb_module_get_private(module);
219 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
220 TDB_DATA tdb_key, tdb_data;
221 int ret;
223 tdb_key = ltdb_key(module, msg->dn);
224 if (!tdb_key.dptr) {
225 return LDB_ERR_OTHER;
228 ret = ltdb_pack_data(module, msg, &tdb_data);
229 if (ret == -1) {
230 talloc_free(tdb_key.dptr);
231 return LDB_ERR_OTHER;
234 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
235 if (ret == -1) {
236 ret = ltdb_err_map(tdb_error(ltdb->tdb));
237 goto done;
240 ret = ltdb_index_add(module, msg);
241 if (ret != LDB_SUCCESS) {
242 tdb_delete(ltdb->tdb, tdb_key);
245 done:
246 talloc_free(tdb_key.dptr);
247 talloc_free(tdb_data.dptr);
249 return ret;
253 static int ltdb_add_internal(struct ldb_module *module,
254 const struct ldb_message *msg)
256 struct ldb_context *ldb = ldb_module_get_ctx(module);
257 int ret, i;
259 ret = ltdb_check_special_dn(module, msg);
260 if (ret != LDB_SUCCESS) {
261 return ret;
264 if (ltdb_cache_load(module) != 0) {
265 return LDB_ERR_OPERATIONS_ERROR;
268 for (i=0;i<msg->num_elements;i++) {
269 struct ldb_message_element *el = &msg->elements[i];
270 const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
272 if (el->num_values == 0) {
273 ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)",
274 el->name, ldb_dn_get_linearized(msg->dn));
275 return LDB_ERR_CONSTRAINT_VIOLATION;
277 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
278 if (el->num_values > 1) {
279 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
280 el->name, ldb_dn_get_linearized(msg->dn));
281 return LDB_ERR_CONSTRAINT_VIOLATION;
286 ret = ltdb_store(module, msg, TDB_INSERT);
288 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
289 ldb_asprintf_errstring(ldb,
290 "Entry %s already exists",
291 ldb_dn_get_linearized(msg->dn));
292 return ret;
295 if (ret == LDB_SUCCESS) {
296 ret = ltdb_index_one(module, msg, 1);
297 if (ret != LDB_SUCCESS) {
298 return ret;
301 ret = ltdb_modified(module, msg->dn);
302 if (ret != LDB_SUCCESS) {
303 return ret;
307 return ret;
311 add a record to the database
313 static int ltdb_add(struct ltdb_context *ctx)
315 struct ldb_module *module = ctx->module;
316 struct ldb_request *req = ctx->req;
317 int tret;
319 ldb_request_set_state(req, LDB_ASYNC_PENDING);
321 tret = ltdb_add_internal(module, req->op.add.message);
322 if (tret != LDB_SUCCESS) {
323 return tret;
326 return LDB_SUCCESS;
330 delete a record from the database, not updating indexes (used for deleting
331 index records)
333 int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn)
335 void *data = ldb_module_get_private(module);
336 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
337 TDB_DATA tdb_key;
338 int ret;
340 tdb_key = ltdb_key(module, dn);
341 if (!tdb_key.dptr) {
342 return LDB_ERR_OTHER;
345 ret = tdb_delete(ltdb->tdb, tdb_key);
346 talloc_free(tdb_key.dptr);
348 if (ret != 0) {
349 ret = ltdb_err_map(tdb_error(ltdb->tdb));
352 return ret;
355 static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
357 struct ldb_message *msg;
358 int ret;
360 msg = talloc(module, struct ldb_message);
361 if (msg == NULL) {
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);
368 if (ret != LDB_SUCCESS) {
369 /* not finding the old record is an error */
370 goto done;
373 ret = ltdb_delete_noindex(module, dn);
374 if (ret != LDB_SUCCESS) {
375 goto done;
378 /* remove one level attribute */
379 ret = ltdb_index_one(module, msg, 0);
380 if (ret != LDB_SUCCESS) {
381 goto done;
384 /* remove any indexed attributes */
385 ret = ltdb_index_del(module, msg);
386 if (ret != LDB_SUCCESS) {
387 goto done;
390 ret = ltdb_modified(module, dn);
391 if (ret != LDB_SUCCESS) {
392 goto done;
395 done:
396 talloc_free(msg);
397 return ret;
401 delete a record from the database
403 static int ltdb_delete(struct ltdb_context *ctx)
405 struct ldb_module *module = ctx->module;
406 struct ldb_request *req = ctx->req;
407 int tret;
409 ldb_request_set_state(req, LDB_ASYNC_PENDING);
411 if (ltdb_cache_load(module) != 0) {
412 return LDB_ERR_OPERATIONS_ERROR;
415 tret = ltdb_delete_internal(module, req->op.del.dn);
416 if (tret != LDB_SUCCESS) {
417 return tret;
420 return LDB_SUCCESS;
424 find an element by attribute name. At the moment this does a linear search,
425 it should be re-coded to use a binary search once all places that modify
426 records guarantee sorted order
428 return the index of the first matching element if found, otherwise -1
430 static int find_element(const struct ldb_message *msg, const char *name)
432 unsigned int i;
433 for (i=0;i<msg->num_elements;i++) {
434 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
435 return i;
438 return -1;
443 add an element to an existing record. Assumes a elements array that we
444 can call re-alloc on, and assumed that we can re-use the data pointers from
445 the passed in additional values. Use with care!
447 returns 0 on success, -1 on failure (and sets errno)
449 static int msg_add_element(struct ldb_context *ldb,
450 struct ldb_message *msg,
451 struct ldb_message_element *el)
453 struct ldb_message_element *e2;
454 unsigned int i;
456 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
457 msg->num_elements+1);
458 if (!e2) {
459 errno = ENOMEM;
460 return -1;
463 msg->elements = e2;
465 e2 = &msg->elements[msg->num_elements];
467 e2->name = el->name;
468 e2->flags = el->flags;
469 e2->values = NULL;
470 if (el->num_values != 0) {
471 e2->values = talloc_array(msg->elements,
472 struct ldb_val, el->num_values);
473 if (!e2->values) {
474 errno = ENOMEM;
475 return -1;
478 for (i=0;i<el->num_values;i++) {
479 e2->values[i] = el->values[i];
481 e2->num_values = el->num_values;
483 msg->num_elements++;
485 return 0;
489 delete all elements having a specified attribute name
491 static int msg_delete_attribute(struct ldb_module *module,
492 struct ldb_context *ldb,
493 struct ldb_message *msg, const char *name)
495 const char *dn;
496 unsigned int i, j;
498 dn = ldb_dn_get_linearized(msg->dn);
499 if (dn == NULL) {
500 return -1;
503 for (i=0;i<msg->num_elements;i++) {
504 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
505 for (j=0;j<msg->elements[i].num_values;j++) {
506 ltdb_index_del_value(module, dn,
507 &msg->elements[i], j);
509 talloc_free(msg->elements[i].values);
510 if (msg->num_elements > (i+1)) {
511 memmove(&msg->elements[i],
512 &msg->elements[i+1],
513 sizeof(struct ldb_message_element)*
514 (msg->num_elements - (i+1)));
516 msg->num_elements--;
517 i--;
518 msg->elements = talloc_realloc(msg, msg->elements,
519 struct ldb_message_element,
520 msg->num_elements);
524 return 0;
528 delete all elements matching an attribute name/value
530 return 0 on success, -1 on failure
532 static int msg_delete_element(struct ldb_module *module,
533 struct ldb_message *msg,
534 const char *name,
535 const struct ldb_val *val)
537 struct ldb_context *ldb = ldb_module_get_ctx(module);
538 unsigned int i;
539 int found;
540 struct ldb_message_element *el;
541 const struct ldb_schema_attribute *a;
543 found = find_element(msg, name);
544 if (found == -1) {
545 return -1;
548 el = &msg->elements[found];
550 a = ldb_schema_attribute_by_name(ldb, el->name);
552 for (i=0;i<el->num_values;i++) {
553 if (a->syntax->comparison_fn(ldb, ldb,
554 &el->values[i], val) == 0) {
555 if (i<el->num_values-1) {
556 memmove(&el->values[i], &el->values[i+1],
557 sizeof(el->values[i])*
558 (el->num_values-(i+1)));
560 el->num_values--;
561 if (el->num_values == 0) {
562 return msg_delete_attribute(module, ldb,
563 msg, name);
565 return 0;
569 return -1;
574 modify a record - internal interface
576 yuck - this is O(n^2). Luckily n is usually small so we probably
577 get away with it, but if we ever have really large attribute lists
578 then we'll need to look at this again
580 int ltdb_modify_internal(struct ldb_module *module,
581 const struct ldb_message *msg)
583 struct ldb_context *ldb = ldb_module_get_ctx(module);
584 void *data = ldb_module_get_private(module);
585 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
586 TDB_DATA tdb_key, tdb_data;
587 struct ldb_message *msg2;
588 unsigned i, j;
589 int ret, idx;
591 tdb_key = ltdb_key(module, msg->dn);
592 if (!tdb_key.dptr) {
593 return LDB_ERR_OTHER;
596 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
597 if (!tdb_data.dptr) {
598 talloc_free(tdb_key.dptr);
599 return ltdb_err_map(tdb_error(ltdb->tdb));
602 msg2 = talloc(tdb_key.dptr, struct ldb_message);
603 if (msg2 == NULL) {
604 talloc_free(tdb_key.dptr);
605 return LDB_ERR_OTHER;
608 ret = ltdb_unpack_data(module, &tdb_data, msg2);
609 if (ret == -1) {
610 ret = LDB_ERR_OTHER;
611 goto failed;
614 if (!msg2->dn) {
615 msg2->dn = msg->dn;
618 for (i=0;i<msg->num_elements;i++) {
619 struct ldb_message_element *el = &msg->elements[i];
620 struct ldb_message_element *el2;
621 struct ldb_val *vals;
622 const char *dn;
623 const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
624 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
626 case LDB_FLAG_MOD_ADD:
628 /* add this element to the message. fail if it
629 already exists */
630 idx = find_element(msg2, el->name);
632 if (el->num_values == 0) {
633 ldb_asprintf_errstring(ldb, "attribute %s on %s speicified, but with 0 values (illigal)",
634 el->name, ldb_dn_get_linearized(msg->dn));
635 return LDB_ERR_CONSTRAINT_VIOLATION;
637 if (idx == -1) {
638 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
639 if (el->num_values > 1) {
640 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
641 el->name, ldb_dn_get_linearized(msg->dn));
642 return LDB_ERR_CONSTRAINT_VIOLATION;
645 if (msg_add_element(ldb, msg2, el) != 0) {
646 ret = LDB_ERR_OTHER;
647 goto failed;
649 continue;
652 /* If this is an add, then if it already
653 * exists in the object, then we violoate the
654 * single-value rule */
655 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
656 return LDB_ERR_CONSTRAINT_VIOLATION;
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(ldb, "%s: value #%d already exists", el->name, j);
669 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
670 goto failed;
672 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
673 ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j);
674 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
675 goto failed;
679 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
680 el2->num_values + el->num_values);
682 if (vals == NULL) {
683 ret = LDB_ERR_OTHER;
684 goto failed;
687 for (j=0;j<el->num_values;j++) {
688 vals[el2->num_values + j] =
689 ldb_val_dup(vals, &el->values[j]);
692 el2->values = vals;
693 el2->num_values += el->num_values;
695 break;
697 case LDB_FLAG_MOD_REPLACE:
698 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
699 if (el->num_values > 1) {
700 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
701 el->name, ldb_dn_get_linearized(msg->dn));
702 return LDB_ERR_CONSTRAINT_VIOLATION;
705 /* replace all elements of this attribute name with the elements
706 listed. The attribute not existing is not an error */
707 msg_delete_attribute(module, ldb, msg2, el->name);
709 for (j=0;j<el->num_values;j++) {
710 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
711 ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j);
712 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
713 goto failed;
717 /* add the replacement element, if not empty */
718 if (el->num_values != 0 &&
719 msg_add_element(ldb, msg2, el) != 0) {
720 ret = LDB_ERR_OTHER;
721 goto failed;
723 break;
725 case LDB_FLAG_MOD_DELETE:
727 dn = ldb_dn_get_linearized(msg->dn);
728 if (dn == NULL) {
729 ret = LDB_ERR_OTHER;
730 goto failed;
733 /* we could be being asked to delete all
734 values or just some values */
735 if (msg->elements[i].num_values == 0) {
736 if (msg_delete_attribute(module, ldb, msg2,
737 msg->elements[i].name) != 0) {
738 ldb_asprintf_errstring(ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
739 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
740 goto failed;
742 break;
744 for (j=0;j<msg->elements[i].num_values;j++) {
745 if (msg_delete_element(module,
746 msg2,
747 msg->elements[i].name,
748 &msg->elements[i].values[j]) != 0) {
749 ldb_asprintf_errstring(ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
750 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
751 goto failed;
753 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
754 if (ret != LDB_SUCCESS) {
755 goto failed;
758 break;
759 default:
760 ldb_asprintf_errstring(ldb,
761 "Invalid ldb_modify flags on %s: 0x%x",
762 msg->elements[i].name,
763 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
764 ret = LDB_ERR_PROTOCOL_ERROR;
765 goto failed;
769 /* we've made all the mods
770 * save the modified record back into the database */
771 ret = ltdb_store(module, msg2, TDB_MODIFY);
772 if (ret != LDB_SUCCESS) {
773 goto failed;
776 ret = ltdb_modified(module, msg->dn);
777 if (ret != LDB_SUCCESS) {
778 goto failed;
781 talloc_free(tdb_key.dptr);
782 free(tdb_data.dptr);
783 return ret;
785 failed:
786 talloc_free(tdb_key.dptr);
787 free(tdb_data.dptr);
788 return ret;
792 modify a record
794 static int ltdb_modify(struct ltdb_context *ctx)
796 struct ldb_module *module = ctx->module;
797 struct ldb_request *req = ctx->req;
798 int tret;
800 ldb_request_set_state(req, LDB_ASYNC_PENDING);
802 tret = ltdb_check_special_dn(module, req->op.mod.message);
803 if (tret != LDB_SUCCESS) {
804 return tret;
807 if (ltdb_cache_load(module) != 0) {
808 return LDB_ERR_OPERATIONS_ERROR;
811 tret = ltdb_modify_internal(module, req->op.mod.message);
812 if (tret != LDB_SUCCESS) {
813 return tret;
816 return LDB_SUCCESS;
820 rename a record
822 static int ltdb_rename(struct ltdb_context *ctx)
824 struct ldb_module *module = ctx->module;
825 struct ldb_request *req = ctx->req;
826 struct ldb_message *msg;
827 int tret;
829 ldb_request_set_state(req, LDB_ASYNC_PENDING);
831 if (ltdb_cache_load(ctx->module) != 0) {
832 return LDB_ERR_OPERATIONS_ERROR;
835 msg = talloc(ctx, struct ldb_message);
836 if (msg == NULL) {
837 return 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);
843 if (tret != LDB_SUCCESS) {
844 /* not finding the old record is an error */
845 return tret;
848 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
849 if (!msg->dn) {
850 return LDB_ERR_OPERATIONS_ERROR;
853 /* Always delete first then add, to avoid conflicts with
854 * unique indexes. We rely on the transaction to make this
855 * atomic
857 tret = ltdb_delete_internal(module, req->op.rename.olddn);
858 if (tret != LDB_SUCCESS) {
859 return tret;
862 tret = ltdb_add_internal(module, msg);
863 if (tret != LDB_SUCCESS) {
864 return tret;
867 return LDB_SUCCESS;
870 static int ltdb_start_trans(struct ldb_module *module)
872 void *data = ldb_module_get_private(module);
873 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
875 if (tdb_transaction_start(ltdb->tdb) != 0) {
876 return ltdb_err_map(tdb_error(ltdb->tdb));
879 ltdb->in_transaction++;
881 ltdb_index_transaction_start(module);
883 return LDB_SUCCESS;
886 static int ltdb_prepare_commit(struct ldb_module *module)
888 void *data = ldb_module_get_private(module);
889 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
891 if (ltdb->in_transaction != 1) {
892 return LDB_SUCCESS;
895 if (ltdb_index_transaction_commit(module) != 0) {
896 tdb_transaction_cancel(ltdb->tdb);
897 ltdb->in_transaction--;
898 return ltdb_err_map(tdb_error(ltdb->tdb));
901 if (tdb_transaction_prepare_commit(ltdb->tdb) != 0) {
902 ltdb->in_transaction--;
903 return ltdb_err_map(tdb_error(ltdb->tdb));
906 ltdb->prepared_commit = true;
908 return LDB_SUCCESS;
911 static int ltdb_end_trans(struct ldb_module *module)
913 void *data = ldb_module_get_private(module);
914 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
916 if (!ltdb->prepared_commit) {
917 int ret = ltdb_prepare_commit(module);
918 if (ret != LDB_SUCCESS) {
919 return ret;
923 ltdb->in_transaction--;
924 ltdb->prepared_commit = false;
926 if (tdb_transaction_commit(ltdb->tdb) != 0) {
927 return ltdb_err_map(tdb_error(ltdb->tdb));
930 return LDB_SUCCESS;
933 static int ltdb_del_trans(struct ldb_module *module)
935 void *data = ldb_module_get_private(module);
936 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
938 ltdb->in_transaction--;
940 if (ltdb_index_transaction_cancel(module) != 0) {
941 tdb_transaction_cancel(ltdb->tdb);
942 return ltdb_err_map(tdb_error(ltdb->tdb));
945 if (tdb_transaction_cancel(ltdb->tdb) != 0) {
946 return ltdb_err_map(tdb_error(ltdb->tdb));
949 return LDB_SUCCESS;
953 return sequenceNumber from @BASEINFO
955 static int ltdb_sequence_number(struct ltdb_context *ctx,
956 struct ldb_extended **ext)
958 struct ldb_context *ldb;
959 struct ldb_module *module = ctx->module;
960 struct ldb_request *req = ctx->req;
961 TALLOC_CTX *tmp_ctx;
962 struct ldb_seqnum_request *seq;
963 struct ldb_seqnum_result *res;
964 struct ldb_message *msg = NULL;
965 struct ldb_dn *dn;
966 const char *date;
967 int ret;
969 ldb = ldb_module_get_ctx(module);
971 seq = talloc_get_type(req->op.extended.data,
972 struct ldb_seqnum_request);
973 if (seq == NULL) {
974 return LDB_ERR_OPERATIONS_ERROR;
977 ldb_request_set_state(req, LDB_ASYNC_PENDING);
979 if (ltdb_lock_read(module) != 0) {
980 return LDB_ERR_OPERATIONS_ERROR;
983 res = talloc_zero(req, struct ldb_seqnum_result);
984 if (res == NULL) {
985 ret = LDB_ERR_OPERATIONS_ERROR;
986 goto done;
988 tmp_ctx = talloc_new(req);
989 if (tmp_ctx == NULL) {
990 ret = LDB_ERR_OPERATIONS_ERROR;
991 goto done;
994 dn = ldb_dn_new(tmp_ctx, ldb, LTDB_BASEINFO);
996 msg = talloc(tmp_ctx, struct ldb_message);
997 if (msg == NULL) {
998 ret = LDB_ERR_OPERATIONS_ERROR;
999 goto done;
1002 ret = ltdb_search_dn1(module, dn, msg);
1003 if (ret != LDB_SUCCESS) {
1004 goto done;
1007 switch (seq->type) {
1008 case LDB_SEQ_HIGHEST_SEQ:
1009 res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
1010 break;
1011 case LDB_SEQ_NEXT:
1012 res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
1013 res->seq_num++;
1014 break;
1015 case LDB_SEQ_HIGHEST_TIMESTAMP:
1016 date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
1017 if (date) {
1018 res->seq_num = ldb_string_to_time(date);
1019 } else {
1020 res->seq_num = 0;
1021 /* zero is as good as anything when we don't know */
1023 break;
1026 *ext = talloc_zero(req, struct ldb_extended);
1027 if (*ext == NULL) {
1028 ret = LDB_ERR_OPERATIONS_ERROR;
1029 goto done;
1031 (*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
1032 (*ext)->data = talloc_steal(*ext, res);
1034 ret = LDB_SUCCESS;
1036 done:
1037 talloc_free(tmp_ctx);
1038 ltdb_unlock_read(module);
1039 return ret;
1042 static void ltdb_request_done(struct ltdb_context *ctx, int error)
1044 struct ldb_context *ldb;
1045 struct ldb_request *req;
1046 struct ldb_reply *ares;
1048 ldb = ldb_module_get_ctx(ctx->module);
1049 req = ctx->req;
1051 /* if we already returned an error just return */
1052 if (ldb_request_get_status(req) != LDB_SUCCESS) {
1053 return;
1056 ares = talloc_zero(req, struct ldb_reply);
1057 if (!ares) {
1058 ldb_oom(ldb);
1059 req->callback(req, NULL);
1060 return;
1062 ares->type = LDB_REPLY_DONE;
1063 ares->error = error;
1065 req->callback(req, ares);
1068 static void ltdb_timeout(struct tevent_context *ev,
1069 struct tevent_timer *te,
1070 struct timeval t,
1071 void *private_data)
1073 struct ltdb_context *ctx;
1074 ctx = talloc_get_type(private_data, struct ltdb_context);
1076 if (!ctx->request_terminated) {
1077 /* request is done now */
1078 ltdb_request_done(ctx, LDB_ERR_TIME_LIMIT_EXCEEDED);
1081 if (!ctx->request_terminated) {
1082 /* neutralize the spy */
1083 ctx->spy->ctx = NULL;
1085 talloc_free(ctx);
1088 static void ltdb_request_extended_done(struct ltdb_context *ctx,
1089 struct ldb_extended *ext,
1090 int error)
1092 struct ldb_context *ldb;
1093 struct ldb_request *req;
1094 struct ldb_reply *ares;
1096 ldb = ldb_module_get_ctx(ctx->module);
1097 req = ctx->req;
1099 /* if we already returned an error just return */
1100 if (ldb_request_get_status(req) != LDB_SUCCESS) {
1101 return;
1104 ares = talloc_zero(req, struct ldb_reply);
1105 if (!ares) {
1106 ldb_oom(ldb);
1107 req->callback(req, NULL);
1108 return;
1110 ares->type = LDB_REPLY_DONE;
1111 ares->response = ext;
1112 ares->error = error;
1114 req->callback(req, ares);
1117 static void ltdb_handle_extended(struct ltdb_context *ctx)
1119 struct ldb_extended *ext = NULL;
1120 int ret;
1122 if (strcmp(ctx->req->op.extended.oid,
1123 LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
1124 /* get sequence number */
1125 ret = ltdb_sequence_number(ctx, &ext);
1126 } else {
1127 /* not recognized */
1128 ret = LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
1131 ltdb_request_extended_done(ctx, ext, ret);
1134 static void ltdb_callback(struct tevent_context *ev,
1135 struct tevent_timer *te,
1136 struct timeval t,
1137 void *private_data)
1139 struct ltdb_context *ctx;
1140 int ret;
1142 ctx = talloc_get_type(private_data, struct ltdb_context);
1144 if (ctx->request_terminated) {
1145 goto done;
1148 switch (ctx->req->operation) {
1149 case LDB_SEARCH:
1150 ret = ltdb_search(ctx);
1151 break;
1152 case LDB_ADD:
1153 ret = ltdb_add(ctx);
1154 break;
1155 case LDB_MODIFY:
1156 ret = ltdb_modify(ctx);
1157 break;
1158 case LDB_DELETE:
1159 ret = ltdb_delete(ctx);
1160 break;
1161 case LDB_RENAME:
1162 ret = ltdb_rename(ctx);
1163 break;
1164 case LDB_EXTENDED:
1165 ltdb_handle_extended(ctx);
1166 goto done;
1167 default:
1168 /* no other op supported */
1169 ret = LDB_ERR_UNWILLING_TO_PERFORM;
1172 if (!ctx->request_terminated) {
1173 /* request is done now */
1174 ltdb_request_done(ctx, ret);
1177 done:
1178 if (!ctx->request_terminated) {
1179 /* neutralize the spy */
1180 ctx->spy->ctx = NULL;
1182 talloc_free(ctx);
1185 static int ltdb_request_destructor(void *ptr)
1187 struct ltdb_req_spy *spy = talloc_get_type(ptr, struct ltdb_req_spy);
1189 if (spy->ctx != NULL) {
1190 spy->ctx->request_terminated = true;
1193 return 0;
1196 static int ltdb_handle_request(struct ldb_module *module,
1197 struct ldb_request *req)
1199 struct ldb_context *ldb;
1200 struct tevent_context *ev;
1201 struct ltdb_context *ac;
1202 struct tevent_timer *te;
1203 struct timeval tv;
1205 if (check_critical_controls(req->controls)) {
1206 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
1209 ldb = ldb_module_get_ctx(module);
1211 if (req->starttime == 0 || req->timeout == 0) {
1212 ldb_set_errstring(ldb, "Invalid timeout settings");
1213 return LDB_ERR_TIME_LIMIT_EXCEEDED;
1216 ev = ldb_get_event_context(ldb);
1218 ac = talloc_zero(ldb, struct ltdb_context);
1219 if (ac == NULL) {
1220 ldb_set_errstring(ldb, "Out of Memory");
1221 return LDB_ERR_OPERATIONS_ERROR;
1224 ac->module = module;
1225 ac->req = req;
1227 tv.tv_sec = 0;
1228 tv.tv_usec = 0;
1229 te = tevent_add_timer(ev, ac, tv, ltdb_callback, ac);
1230 if (NULL == te) {
1231 talloc_free(ac);
1232 return LDB_ERR_OPERATIONS_ERROR;
1235 tv.tv_sec = req->starttime + req->timeout;
1236 ac->timeout_event = tevent_add_timer(ev, ac, tv, ltdb_timeout, ac);
1237 if (NULL == ac->timeout_event) {
1238 talloc_free(ac);
1239 return LDB_ERR_OPERATIONS_ERROR;
1242 /* set a spy so that we do not try to use the request context
1243 * if it is freed before ltdb_callback fires */
1244 ac->spy = talloc(req, struct ltdb_req_spy);
1245 if (NULL == ac->spy) {
1246 talloc_free(ac);
1247 return LDB_ERR_OPERATIONS_ERROR;
1249 ac->spy->ctx = ac;
1251 talloc_set_destructor((TALLOC_CTX *)ac->spy, ltdb_request_destructor);
1253 return LDB_SUCCESS;
1256 static const struct ldb_module_ops ltdb_ops = {
1257 .name = "tdb",
1258 .search = ltdb_handle_request,
1259 .add = ltdb_handle_request,
1260 .modify = ltdb_handle_request,
1261 .del = ltdb_handle_request,
1262 .rename = ltdb_handle_request,
1263 .extended = ltdb_handle_request,
1264 .start_transaction = ltdb_start_trans,
1265 .end_transaction = ltdb_end_trans,
1266 .prepare_commit = ltdb_prepare_commit,
1267 .del_transaction = ltdb_del_trans,
1271 connect to the database
1273 static int ltdb_connect(struct ldb_context *ldb, const char *url,
1274 unsigned int flags, const char *options[],
1275 struct ldb_module **_module)
1277 struct ldb_module *module;
1278 const char *path;
1279 int tdb_flags, open_flags;
1280 struct ltdb_private *ltdb;
1282 /* parse the url */
1283 if (strchr(url, ':')) {
1284 if (strncmp(url, "tdb://", 6) != 0) {
1285 ldb_debug(ldb, LDB_DEBUG_ERROR,
1286 "Invalid tdb URL '%s'", url);
1287 return -1;
1289 path = url+6;
1290 } else {
1291 path = url;
1294 tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1296 /* check for the 'nosync' option */
1297 if (flags & LDB_FLG_NOSYNC) {
1298 tdb_flags |= TDB_NOSYNC;
1301 /* and nommap option */
1302 if (flags & LDB_FLG_NOMMAP) {
1303 tdb_flags |= TDB_NOMMAP;
1306 if (flags & LDB_FLG_RDONLY) {
1307 open_flags = O_RDONLY;
1308 } else {
1309 open_flags = O_CREAT | O_RDWR;
1312 ltdb = talloc_zero(ldb, struct ltdb_private);
1313 if (!ltdb) {
1314 ldb_oom(ldb);
1315 return -1;
1318 /* note that we use quite a large default hash size */
1319 ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1320 tdb_flags, open_flags,
1321 ldb_get_create_perms(ldb), ldb);
1322 if (!ltdb->tdb) {
1323 ldb_debug(ldb, LDB_DEBUG_ERROR,
1324 "Unable to open tdb '%s'", path);
1325 talloc_free(ltdb);
1326 return -1;
1329 ltdb->sequence_number = 0;
1331 module = ldb_module_new(ldb, ldb, "ldb_tdb backend", &ltdb_ops);
1332 if (!module) {
1333 talloc_free(ltdb);
1334 return -1;
1336 ldb_module_set_private(module, ltdb);
1338 if (ltdb_cache_load(module) != 0) {
1339 talloc_free(module);
1340 talloc_free(ltdb);
1341 return -1;
1344 *_module = module;
1345 return 0;
1348 const struct ldb_backend_ops ldb_tdb_backend_ops = {
1349 .name = "tdb",
1350 .connect_fn = ltdb_connect