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
,
83 int (*callback
)(struct ldb_context
*, void *, struct ldb_reply
*))
85 struct ltdb_context
*ac
;
88 h
= talloc_zero(ltdb
, struct ldb_handle
);
90 ldb_set_errstring(module
->ldb
, "Out of Memory");
96 ac
= talloc_zero(h
, struct ltdb_context
);
98 ldb_set_errstring(module
->ldb
, "Out of Memory");
103 h
->private_data
= (void *)ac
;
105 h
->state
= LDB_ASYNC_INIT
;
106 h
->status
= LDB_SUCCESS
;
109 ac
->context
= context
;
110 ac
->callback
= callback
;
116 form a TDB_DATA for a record key
119 note that the key for a record can depend on whether the
120 dn refers to a case sensitive index record or not
122 struct TDB_DATA
ltdb_key(struct ldb_module
*module
, const struct ldb_dn
*dn
)
124 struct ldb_context
*ldb
= module
->ldb
;
126 char *key_str
= NULL
;
127 char *dn_folded
= NULL
;
130 most DNs are case insensitive. The exception is index DNs for
131 case sensitive attributes
133 there are 3 cases dealt with in this code:
135 1) if the dn doesn't start with @ then uppercase the attribute
136 names and the attributes values of case insensitive attributes
137 2) if the dn starts with @ then leave it alone - the indexing code handles
141 dn_folded
= ldb_dn_linearize_casefold(ldb
, dn
);
146 key_str
= talloc_asprintf(ldb
, "DN=%s", dn_folded
);
148 talloc_free(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
, const struct ldb_message
*msg
)
174 if (! ldb_dn_is_special(msg
->dn
) ||
175 ! ldb_dn_check_special(msg
->dn
, LTDB_ATTRIBUTES
)) {
179 /* we have @ATTRIBUTES, let's check attributes are fine */
180 /* should we check that we deny multivalued attributes ? */
181 for (i
= 0; i
< msg
->num_elements
; i
++) {
182 for (j
= 0; j
< msg
->elements
[i
].num_values
; j
++) {
183 if (ltdb_check_at_attributes_values(&msg
->elements
[i
].values
[j
]) != 0) {
184 ldb_set_errstring(module
->ldb
, "Invalid attribute value in an @ATTRIBUTES entry");
185 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
195 we've made a modification to a dn - possibly reindex and
196 update sequence number
198 static int ltdb_modified(struct ldb_module
*module
, const struct ldb_dn
*dn
)
202 if (ldb_dn_is_special(dn
) &&
203 (ldb_dn_check_special(dn
, LTDB_INDEXLIST
) ||
204 ldb_dn_check_special(dn
, LTDB_ATTRIBUTES
)) ) {
205 ret
= ltdb_reindex(module
);
209 !(ldb_dn_is_special(dn
) &&
210 ldb_dn_check_special(dn
, LTDB_BASEINFO
)) ) {
211 ret
= ltdb_increase_sequence_number(module
);
218 store a record into the db
220 int ltdb_store(struct ldb_module
*module
, const struct ldb_message
*msg
, int flgs
)
222 struct ltdb_private
*ltdb
= module
->private_data
;
223 TDB_DATA tdb_key
, tdb_data
;
226 tdb_key
= ltdb_key(module
, msg
->dn
);
228 return LDB_ERR_OTHER
;
231 ret
= ltdb_pack_data(module
, msg
, &tdb_data
);
233 talloc_free(tdb_key
.dptr
);
234 return LDB_ERR_OTHER
;
237 ret
= tdb_store(ltdb
->tdb
, tdb_key
, tdb_data
, flgs
);
239 ret
= ltdb_err_map(tdb_error(ltdb
->tdb
));
243 ret
= ltdb_index_add(module
, msg
);
245 tdb_delete(ltdb
->tdb
, tdb_key
);
249 talloc_free(tdb_key
.dptr
);
250 talloc_free(tdb_data
.dptr
);
256 static int ltdb_add_internal(struct ldb_module
*module
, const struct ldb_message
*msg
)
260 ret
= ltdb_check_special_dn(module
, msg
);
261 if (ret
!= LDB_SUCCESS
) {
265 if (ltdb_cache_load(module
) != 0) {
266 return LDB_ERR_OPERATIONS_ERROR
;
269 ret
= ltdb_store(module
, msg
, TDB_INSERT
);
271 if (ret
== LDB_ERR_ENTRY_ALREADY_EXISTS
) {
274 dn
= ldb_dn_linearize(module
, msg
->dn
);
278 ldb_asprintf_errstring(module
->ldb
, "Entry %s already exists", dn
);
283 if (ret
== LDB_SUCCESS
) {
284 ret
= ltdb_modified(module
, msg
->dn
);
285 if (ret
!= LDB_SUCCESS
) {
286 return LDB_ERR_OPERATIONS_ERROR
;
294 add a record to the database
296 static int ltdb_add(struct ldb_module
*module
, struct ldb_request
*req
)
298 struct ltdb_private
*ltdb
= talloc_get_type(module
->private_data
, struct ltdb_private
);
299 struct ltdb_context
*ltdb_ac
;
300 int tret
, ret
= LDB_SUCCESS
;
302 if (req
->controls
!= NULL
) {
303 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Controls should not reach the ldb_tdb backend!\n");
304 if (check_critical_controls(req
->controls
)) {
305 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION
;
309 req
->handle
= init_ltdb_handle(ltdb
, module
, req
->context
, req
->callback
);
310 if (req
->handle
== NULL
) {
311 return LDB_ERR_OPERATIONS_ERROR
;
313 ltdb_ac
= talloc_get_type(req
->handle
->private_data
, struct ltdb_context
);
315 tret
= ltdb_add_internal(module
, req
->op
.add
.message
);
316 if (tret
!= LDB_SUCCESS
) {
317 req
->handle
->status
= tret
;
321 if (ltdb_ac
->callback
) {
322 ret
= ltdb_ac
->callback(module
->ldb
, ltdb_ac
->context
, NULL
);
325 req
->handle
->state
= LDB_ASYNC_DONE
;
330 delete a record from the database, not updating indexes (used for deleting
333 int ltdb_delete_noindex(struct ldb_module
*module
, const struct ldb_dn
*dn
)
335 struct ltdb_private
*ltdb
= module
->private_data
;
339 tdb_key
= ltdb_key(module
, dn
);
341 return LDB_ERR_OTHER
;
344 ret
= tdb_delete(ltdb
->tdb
, tdb_key
);
345 talloc_free(tdb_key
.dptr
);
348 ret
= ltdb_err_map(tdb_error(ltdb
->tdb
));
354 static int ltdb_delete_internal(struct ldb_module
*module
, const struct ldb_dn
*dn
)
356 struct ldb_message
*msg
;
359 msg
= talloc(module
, struct ldb_message
);
361 return LDB_ERR_OPERATIONS_ERROR
;
364 /* in case any attribute of the message was indexed, we need
365 to fetch the old record */
366 ret
= ltdb_search_dn1(module
, dn
, msg
);
368 /* not finding the old record is an error */
370 return LDB_ERR_NO_SUCH_OBJECT
;
373 ret
= ltdb_delete_noindex(module
, dn
);
374 if (ret
!= LDB_SUCCESS
) {
376 return LDB_ERR_NO_SUCH_OBJECT
;
379 /* remove any indexed attributes */
380 ret
= ltdb_index_del(module
, msg
);
381 if (ret
!= LDB_SUCCESS
) {
383 return LDB_ERR_OPERATIONS_ERROR
;
386 ret
= ltdb_modified(module
, dn
);
387 if (ret
!= LDB_SUCCESS
) {
388 return LDB_ERR_OPERATIONS_ERROR
;
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 (req
->controls
!= NULL
) {
405 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Controls should not reach the ldb_tdb backend!\n");
406 if (check_critical_controls(req
->controls
)) {
407 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION
;
413 if (ltdb_cache_load(module
) != 0) {
414 return LDB_ERR_OPERATIONS_ERROR
;
417 req
->handle
= init_ltdb_handle(ltdb
, module
, req
->context
, req
->callback
);
418 if (req
->handle
== NULL
) {
419 return LDB_ERR_OPERATIONS_ERROR
;
421 ltdb_ac
= talloc_get_type(req
->handle
->private_data
, struct ltdb_context
);
423 tret
= ltdb_delete_internal(module
, req
->op
.del
.dn
);
424 if (tret
!= LDB_SUCCESS
) {
425 req
->handle
->status
= tret
;
429 if (ltdb_ac
->callback
) {
430 ret
= ltdb_ac
->callback(module
->ldb
, ltdb_ac
->context
, NULL
);
433 req
->handle
->state
= LDB_ASYNC_DONE
;
438 find an element by attribute name. At the moment this does a linear search, it should
439 be re-coded to use a binary search once all places that modify records guarantee
442 return the index of the first matching element if found, otherwise -1
444 static int find_element(const struct ldb_message
*msg
, const char *name
)
447 for (i
=0;i
<msg
->num_elements
;i
++) {
448 if (ldb_attr_cmp(msg
->elements
[i
].name
, name
) == 0) {
457 add an element to an existing record. Assumes a elements array that we
458 can call re-alloc on, and assumed that we can re-use the data pointers from the
459 passed in additional values. Use with care!
461 returns 0 on success, -1 on failure (and sets errno)
463 static int msg_add_element(struct ldb_context
*ldb
,
464 struct ldb_message
*msg
, struct ldb_message_element
*el
)
466 struct ldb_message_element
*e2
;
469 e2
= talloc_realloc(msg
, msg
->elements
, struct ldb_message_element
,
470 msg
->num_elements
+1);
478 e2
= &msg
->elements
[msg
->num_elements
];
481 e2
->flags
= el
->flags
;
483 if (el
->num_values
!= 0) {
484 e2
->values
= talloc_array(msg
->elements
, struct ldb_val
, el
->num_values
);
490 for (i
=0;i
<el
->num_values
;i
++) {
491 e2
->values
[i
] = el
->values
[i
];
493 e2
->num_values
= el
->num_values
;
501 delete all elements having a specified attribute name
503 static int msg_delete_attribute(struct ldb_module
*module
,
504 struct ldb_context
*ldb
,
505 struct ldb_message
*msg
, const char *name
)
510 dn
= ldb_dn_linearize(ldb
, msg
->dn
);
515 for (i
=0;i
<msg
->num_elements
;i
++) {
516 if (ldb_attr_cmp(msg
->elements
[i
].name
, name
) == 0) {
517 for (j
=0;j
<msg
->elements
[i
].num_values
;j
++) {
518 ltdb_index_del_value(module
, dn
, &msg
->elements
[i
], j
);
520 talloc_free(msg
->elements
[i
].values
);
521 if (msg
->num_elements
> (i
+1)) {
522 memmove(&msg
->elements
[i
],
524 sizeof(struct ldb_message_element
)*
525 (msg
->num_elements
- (i
+1)));
529 msg
->elements
= talloc_realloc(msg
, msg
->elements
,
530 struct ldb_message_element
,
540 delete all elements matching an attribute name/value
542 return 0 on success, -1 on failure
544 static int msg_delete_element(struct ldb_module
*module
,
545 struct ldb_message
*msg
,
547 const struct ldb_val
*val
)
549 struct ldb_context
*ldb
= module
->ldb
;
552 struct ldb_message_element
*el
;
553 const struct ldb_attrib_handler
*h
;
555 found
= find_element(msg
, name
);
560 el
= &msg
->elements
[found
];
562 h
= ldb_attrib_handler(ldb
, el
->name
);
564 for (i
=0;i
<el
->num_values
;i
++) {
565 if (h
->comparison_fn(ldb
, ldb
, &el
->values
[i
], val
) == 0) {
566 if (i
<el
->num_values
-1) {
567 memmove(&el
->values
[i
], &el
->values
[i
+1],
568 sizeof(el
->values
[i
])*(el
->num_values
-(i
+1)));
571 if (el
->num_values
== 0) {
572 return msg_delete_attribute(module
, ldb
, msg
, name
);
583 modify a record - internal interface
585 yuck - this is O(n^2). Luckily n is usually small so we probably
586 get away with it, but if we ever have really large attribute lists
587 then we'll need to look at this again
589 int ltdb_modify_internal(struct ldb_module
*module
, const struct ldb_message
*msg
)
591 struct ldb_context
*ldb
= module
->ldb
;
592 struct ltdb_private
*ltdb
= module
->private_data
;
593 TDB_DATA tdb_key
, tdb_data
;
594 struct ldb_message
*msg2
;
598 tdb_key
= ltdb_key(module
, msg
->dn
);
600 return LDB_ERR_OTHER
;
603 tdb_data
= tdb_fetch(ltdb
->tdb
, tdb_key
);
604 if (!tdb_data
.dptr
) {
605 talloc_free(tdb_key
.dptr
);
606 return ltdb_err_map(tdb_error(ltdb
->tdb
));
609 msg2
= talloc(tdb_key
.dptr
, struct ldb_message
);
611 talloc_free(tdb_key
.dptr
);
612 return LDB_ERR_OTHER
;
615 ret
= ltdb_unpack_data(module
, &tdb_data
, msg2
);
625 for (i
=0;i
<msg
->num_elements
;i
++) {
626 struct ldb_message_element
*el
= &msg
->elements
[i
];
627 struct ldb_message_element
*el2
;
628 struct ldb_val
*vals
;
631 switch (msg
->elements
[i
].flags
& LDB_FLAG_MOD_MASK
) {
633 case LDB_FLAG_MOD_ADD
:
634 /* add this element to the message. fail if it
636 ret
= find_element(msg2
, el
->name
);
639 if (msg_add_element(ldb
, msg2
, el
) != 0) {
646 el2
= &msg2
->elements
[ret
];
648 /* An attribute with this name already exists, add all
649 * values if they don't already exist. */
651 for (j
=0;j
<el
->num_values
;j
++) {
652 if (ldb_msg_find_val(el2
, &el
->values
[j
])) {
653 ldb_set_errstring(module
->ldb
, "Type or value exists");
654 ret
= LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
;
659 vals
= talloc_realloc(msg2
->elements
, el2
->values
, struct ldb_val
,
660 el2
->num_values
+ el
->num_values
);
667 for (j
=0;j
<el
->num_values
;j
++) {
668 vals
[el2
->num_values
+ j
] =
669 ldb_val_dup(vals
, &el
->values
[j
]);
673 el2
->num_values
+= el
->num_values
;
677 case LDB_FLAG_MOD_REPLACE
:
678 /* replace all elements of this attribute name with the elements
679 listed. The attribute not existing is not an error */
680 msg_delete_attribute(module
, ldb
, msg2
, msg
->elements
[i
].name
);
682 /* add the replacement element, if not empty */
683 if (msg
->elements
[i
].num_values
!= 0 &&
684 msg_add_element(ldb
, msg2
, &msg
->elements
[i
]) != 0) {
690 case LDB_FLAG_MOD_DELETE
:
692 dn
= ldb_dn_linearize(msg2
, msg
->dn
);
698 /* we could be being asked to delete all
699 values or just some values */
700 if (msg
->elements
[i
].num_values
== 0) {
701 if (msg_delete_attribute(module
, ldb
, msg2
,
702 msg
->elements
[i
].name
) != 0) {
703 ldb_asprintf_errstring(module
->ldb
, "No such attribute: %s for delete on %s", msg
->elements
[i
].name
, dn
);
704 ret
= LDB_ERR_NO_SUCH_ATTRIBUTE
;
709 for (j
=0;j
<msg
->elements
[i
].num_values
;j
++) {
710 if (msg_delete_element(module
,
712 msg
->elements
[i
].name
,
713 &msg
->elements
[i
].values
[j
]) != 0) {
714 ldb_asprintf_errstring(module
->ldb
, "No matching attribute value when deleting attribute: %s on %s", msg
->elements
[i
].name
, dn
);
715 ret
= LDB_ERR_NO_SUCH_ATTRIBUTE
;
718 if (ltdb_index_del_value(module
, dn
, &msg
->elements
[i
], j
) != 0) {
725 ldb_asprintf_errstring(module
->ldb
, "Invalid ldb_modify flags on %s: 0x%x",
726 msg
->elements
[i
].name
,
727 msg
->elements
[i
].flags
& LDB_FLAG_MOD_MASK
);
728 ret
= LDB_ERR_PROTOCOL_ERROR
;
733 /* we've made all the mods - save the modified record back into the database */
734 ret
= ltdb_store(module
, msg2
, TDB_MODIFY
);
735 if (ret
!= LDB_SUCCESS
) {
739 if (ltdb_modified(module
, msg
->dn
) != LDB_SUCCESS
) {
740 ret
= LDB_ERR_OPERATIONS_ERROR
;
744 talloc_free(tdb_key
.dptr
);
749 talloc_free(tdb_key
.dptr
);
757 static int ltdb_modify(struct ldb_module
*module
, struct ldb_request
*req
)
759 struct ltdb_private
*ltdb
= talloc_get_type(module
->private_data
, struct ltdb_private
);
760 struct ltdb_context
*ltdb_ac
;
761 int tret
, ret
= LDB_SUCCESS
;
763 if (req
->controls
!= NULL
) {
764 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Controls should not reach the ldb_tdb backend!\n");
765 if (check_critical_controls(req
->controls
)) {
766 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION
;
772 req
->handle
= init_ltdb_handle(ltdb
, module
, req
->context
, req
->callback
);
773 if (req
->handle
== NULL
) {
774 return LDB_ERR_OPERATIONS_ERROR
;
776 ltdb_ac
= talloc_get_type(req
->handle
->private_data
, struct ltdb_context
);
778 tret
= ltdb_check_special_dn(module
, req
->op
.mod
.message
);
779 if (tret
!= LDB_SUCCESS
) {
780 req
->handle
->status
= tret
;
784 if (ltdb_cache_load(module
) != 0) {
785 ret
= LDB_ERR_OPERATIONS_ERROR
;
789 tret
= ltdb_modify_internal(module
, req
->op
.mod
.message
);
790 if (tret
!= LDB_SUCCESS
) {
791 req
->handle
->status
= tret
;
795 if (ltdb_ac
->callback
) {
796 ret
= ltdb_ac
->callback(module
->ldb
, ltdb_ac
->context
, NULL
);
799 req
->handle
->state
= LDB_ASYNC_DONE
;
806 static int ltdb_rename(struct ldb_module
*module
, struct ldb_request
*req
)
808 struct ltdb_private
*ltdb
= talloc_get_type(module
->private_data
, struct ltdb_private
);
809 struct ltdb_context
*ltdb_ac
;
810 struct ldb_message
*msg
;
811 int tret
, ret
= LDB_SUCCESS
;
813 if (req
->controls
!= NULL
) {
814 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Controls should not reach the ldb_tdb backend!\n");
815 if (check_critical_controls(req
->controls
)) {
816 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION
;
822 if (ltdb_cache_load(module
) != 0) {
823 return LDB_ERR_OPERATIONS_ERROR
;
826 req
->handle
= init_ltdb_handle(ltdb
, module
, req
->context
, req
->callback
);
827 if (req
->handle
== NULL
) {
828 return LDB_ERR_OPERATIONS_ERROR
;
830 ltdb_ac
= talloc_get_type(req
->handle
->private_data
, struct ltdb_context
);
832 msg
= talloc(ltdb_ac
, struct ldb_message
);
834 ret
= LDB_ERR_OPERATIONS_ERROR
;
838 /* in case any attribute of the message was indexed, we need
839 to fetch the old record */
840 tret
= ltdb_search_dn1(module
, req
->op
.rename
.olddn
, msg
);
842 /* not finding the old record is an error */
843 req
->handle
->status
= LDB_ERR_NO_SUCH_OBJECT
;
847 msg
->dn
= ldb_dn_copy(msg
, req
->op
.rename
.newdn
);
849 ret
= LDB_ERR_OPERATIONS_ERROR
;
853 tret
= ltdb_add_internal(module
, msg
);
854 if (tret
!= LDB_SUCCESS
) {
855 ret
= LDB_ERR_OPERATIONS_ERROR
;
859 tret
= ltdb_delete_internal(module
, req
->op
.rename
.olddn
);
860 if (tret
!= LDB_SUCCESS
) {
861 ltdb_delete_internal(module
, req
->op
.rename
.newdn
);
862 ret
= LDB_ERR_OPERATIONS_ERROR
;
866 if (ltdb_ac
->callback
) {
867 ret
= ltdb_ac
->callback(module
->ldb
, ltdb_ac
->context
, NULL
);
870 req
->handle
->state
= LDB_ASYNC_DONE
;
874 static int ltdb_start_trans(struct ldb_module
*module
)
876 struct ltdb_private
*ltdb
= module
->private_data
;
878 if (tdb_transaction_start(ltdb
->tdb
) != 0) {
879 return ltdb_err_map(tdb_error(ltdb
->tdb
));
885 static int ltdb_end_trans(struct ldb_module
*module
)
887 struct ltdb_private
*ltdb
= module
->private_data
;
889 if (tdb_transaction_commit(ltdb
->tdb
) != 0) {
890 return ltdb_err_map(tdb_error(ltdb
->tdb
));
896 static int ltdb_del_trans(struct ldb_module
*module
)
898 struct ltdb_private
*ltdb
= module
->private_data
;
900 if (tdb_transaction_cancel(ltdb
->tdb
) != 0) {
901 return ltdb_err_map(tdb_error(ltdb
->tdb
));
907 static int ltdb_wait(struct ldb_handle
*handle
, enum ldb_wait_type type
)
909 return handle
->status
;
912 static int ltdb_request(struct ldb_module
*module
, struct ldb_request
*req
)
914 /* check for oustanding critical controls and return an error if found */
915 if (req
->controls
!= NULL
) {
916 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Controls should not reach the ldb_tdb backend!\n");
917 if (check_critical_controls(req
->controls
)) {
918 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION
;
922 /* search, add, modify, delete, rename are handled by their own, no other op supported */
923 return LDB_ERR_OPERATIONS_ERROR
;
927 return sequenceNumber from @BASEINFO
929 static int ltdb_sequence_number(struct ldb_module
*module
, struct ldb_request
*req
)
931 TALLOC_CTX
*tmp_ctx
= talloc_new(req
);
932 struct ldb_message
*msg
= NULL
;
933 struct ldb_dn
*dn
= ldb_dn_explode(tmp_ctx
, LTDB_BASEINFO
);
936 if (tmp_ctx
== NULL
) {
937 talloc_free(tmp_ctx
);
938 return LDB_ERR_OPERATIONS_ERROR
;
941 msg
= talloc(tmp_ctx
, struct ldb_message
);
943 talloc_free(tmp_ctx
);
944 return LDB_ERR_OPERATIONS_ERROR
;
947 req
->op
.seq_num
.flags
= 0;
949 tret
= ltdb_search_dn1(module
, dn
, msg
);
951 talloc_free(tmp_ctx
);
952 req
->op
.seq_num
.seq_num
= 0;
953 /* zero is as good as anything when we don't know */
957 switch (req
->op
.seq_num
.type
) {
958 case LDB_SEQ_HIGHEST_SEQ
:
959 req
->op
.seq_num
.seq_num
= ldb_msg_find_attr_as_uint64(msg
, LTDB_SEQUENCE_NUMBER
, 0);
962 req
->op
.seq_num
.seq_num
= ldb_msg_find_attr_as_uint64(msg
, LTDB_SEQUENCE_NUMBER
, 0);
963 req
->op
.seq_num
.seq_num
++;
965 case LDB_SEQ_HIGHEST_TIMESTAMP
:
967 const char *date
= ldb_msg_find_attr_as_string(msg
, LTDB_MOD_TIMESTAMP
, NULL
);
969 req
->op
.seq_num
.seq_num
= ldb_string_to_time(date
);
971 req
->op
.seq_num
.seq_num
= 0;
972 /* zero is as good as anything when we don't know */
977 talloc_free(tmp_ctx
);
981 static const struct ldb_module_ops ltdb_ops
= {
983 .search
= ltdb_search
,
985 .modify
= ltdb_modify
,
987 .rename
= ltdb_rename
,
988 .request
= ltdb_request
,
989 .start_transaction
= ltdb_start_trans
,
990 .end_transaction
= ltdb_end_trans
,
991 .del_transaction
= ltdb_del_trans
,
993 .sequence_number
= ltdb_sequence_number
997 connect to the database
999 static int ltdb_connect(struct ldb_context
*ldb
, const char *url
,
1000 unsigned int flags
, const char *options
[],
1001 struct ldb_module
**module
)
1004 int tdb_flags
, open_flags
;
1005 struct ltdb_private
*ltdb
;
1008 if (strchr(url
, ':')) {
1009 if (strncmp(url
, "tdb://", 6) != 0) {
1010 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid tdb URL '%s'", url
);
1018 tdb_flags
= TDB_DEFAULT
;
1020 /* check for the 'nosync' option */
1021 if (flags
& LDB_FLG_NOSYNC
) {
1022 tdb_flags
|= TDB_NOSYNC
;
1025 if (flags
& LDB_FLG_RDONLY
) {
1026 open_flags
= O_RDONLY
;
1028 open_flags
= O_CREAT
| O_RDWR
;
1031 ltdb
= talloc_zero(ldb
, struct ltdb_private
);
1037 /* note that we use quite a large default hash size */
1038 ltdb
->tdb
= ltdb_wrap_open(ltdb
, path
, 10000,
1039 tdb_flags
, open_flags
, 0644, ldb
);
1041 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Unable to open tdb '%s'\n", path
);
1046 ltdb
->sequence_number
= 0;
1048 *module
= talloc(ldb
, struct ldb_module
);
1054 (*module
)->ldb
= ldb
;
1055 (*module
)->prev
= (*module
)->next
= NULL
;
1056 (*module
)->private_data
= ltdb
;
1057 (*module
)->ops
= <db_ops
;
1062 int ldb_tdb_init(void)
1064 return ldb_register_backend("tdb", ltdb_connect
);