4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb search functions
30 * Description: functions to search ldb+tdb databases
32 * Author: Andrew Tridgell
36 #include "ldb/include/includes.h"
38 #include "ldb/ldb_tdb/ldb_tdb.h"
41 add one element to a message
43 static int msg_add_element(struct ldb_context *ldb,
44 struct ldb_message *ret,
45 const struct ldb_message_element *el,
49 struct ldb_message_element *e2, *elnew;
51 if (check_duplicates && ldb_msg_find_element(ret, el->name)) {
52 /* its already there */
56 e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1);
62 elnew = &e2[ret->num_elements];
64 elnew->name = talloc_strdup(ret->elements, el->name);
70 elnew->values = talloc_array(ret->elements, struct ldb_val, el->num_values);
78 for (i=0;i<el->num_values;i++) {
79 elnew->values[i] = ldb_val_dup(elnew->values, &el->values[i]);
80 if (elnew->values[i].length != el->values[i].length) {
85 elnew->num_values = el->num_values;
93 add the special distinguishedName element
95 static int msg_add_distinguished_name(struct ldb_module *module, struct ldb_message *msg)
97 struct ldb_message_element el;
102 el.name = "distinguishedName";
105 val.data = (uint8_t *)ldb_dn_linearize(msg, msg->dn);
106 val.length = strlen((char *)val.data);
108 ret = msg_add_element(module->ldb, msg, &el, 1);
113 add all elements from one message into another
115 static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *ret,
116 const struct ldb_message *msg)
118 struct ldb_context *ldb = module->ldb;
120 int check_duplicates = (ret->num_elements != 0);
122 if (msg_add_distinguished_name(module, ret) != 0) {
126 for (i=0;i<msg->num_elements;i++) {
127 const struct ldb_attrib_handler *h;
128 h = ldb_attrib_handler(ldb, msg->elements[i].name);
129 if (h->flags & LDB_ATTR_FLAG_HIDDEN) {
132 if (msg_add_element(ldb, ret, &msg->elements[i],
133 check_duplicates) != 0) {
143 pull the specified list of attributes from a message
145 static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module,
146 const struct ldb_message *msg,
147 const char * const *attrs)
149 struct ldb_context *ldb = module->ldb;
150 struct ldb_message *ret;
153 ret = talloc(ldb, struct ldb_message);
158 ret->dn = ldb_dn_copy(ret, msg->dn);
164 ret->num_elements = 0;
165 ret->elements = NULL;
168 if (msg_add_all_elements(module, ret, msg) != 0) {
175 for (i=0;attrs[i];i++) {
176 struct ldb_message_element *el;
178 if (strcmp(attrs[i], "*") == 0) {
179 if (msg_add_all_elements(module, ret, msg) != 0) {
186 if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
187 if (msg_add_distinguished_name(module, ret) != 0) {
193 el = ldb_msg_find_element(msg, attrs[i]);
197 if (msg_add_element(ldb, ret, el, 1) != 0) {
208 search the database for a single simple dn, returning all attributes
211 return 1 on success, 0 on record-not-found and -1 on error
213 int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct ldb_message *msg)
215 struct ltdb_private *ltdb = module->private_data;
217 TDB_DATA tdb_key, tdb_data, tdb_data2;
219 memset(msg, 0, sizeof(*msg));
222 tdb_key = ltdb_key(module, dn);
227 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
228 talloc_free(tdb_key.dptr);
229 if (!tdb_data.dptr) {
233 tdb_data2.dptr = talloc_memdup(msg, tdb_data.dptr, tdb_data.dsize);
235 if (!tdb_data2.dptr) {
238 tdb_data2.dsize = tdb_data.dsize;
240 msg->num_elements = 0;
241 msg->elements = NULL;
243 ret = ltdb_unpack_data(module, &tdb_data2, msg);
245 talloc_free(tdb_data2.dptr);
250 msg->dn = ldb_dn_copy(tdb_data2.dptr, dn);
253 talloc_free(tdb_data2.dptr);
260 /* the lock key for search locking. Note that this is not a DN, its
261 just an arbitrary key to give to tdb. Also note that as we and
262 using transactions for all write operations and transactions take
263 care of their own locks, we don't need to do any locking anywhere
264 other than in ldb_search() */
265 #define LDBLOCK "INT_LDBLOCK"
268 lock the database for read - use by ltdb_search
270 static int ltdb_lock_read(struct ldb_module *module)
272 struct ltdb_private *ltdb = module->private_data;
275 key.dptr = discard_const(LDBLOCK);
276 key.dsize = strlen(LDBLOCK);
278 return tdb_chainlock_read(ltdb->tdb, key);
282 unlock the database after a ltdb_lock_read()
284 static int ltdb_unlock_read(struct ldb_module *module)
286 struct ltdb_private *ltdb = module->private_data;
289 key.dptr = discard_const(LDBLOCK);
290 key.dsize = strlen(LDBLOCK);
292 return tdb_chainunlock_read(ltdb->tdb, key);
296 add a set of attributes from a record to a set of results
297 return 0 on success, -1 on failure
299 int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg,
300 const char * const attrs[],
302 struct ldb_message ***res)
304 struct ldb_context *ldb = module->ldb;
305 struct ldb_message *msg2;
306 struct ldb_message **res2;
308 /* pull the attributes that the user wants */
309 msg2 = ltdb_pull_attrs(module, msg, attrs);
314 /* add to the results list */
315 res2 = talloc_realloc(ldb, *res, struct ldb_message *, (*count)+2);
323 (*res)[*count] = talloc_steal(*res, msg2);
324 (*res)[(*count)+1] = NULL;
332 internal search state during a full db search
334 struct ltdb_search_info {
335 struct ldb_module *module;
336 struct ldb_parse_tree *tree;
337 const struct ldb_dn *base;
338 enum ldb_scope scope;
339 const char * const *attrs;
340 struct ldb_message **msgs;
341 unsigned int failures;
347 search function for a non-indexed search
349 static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
351 struct ltdb_search_info *sinfo = state;
352 struct ldb_message *msg;
356 strncmp((char *)key.dptr, "DN=", 3) != 0) {
360 msg = talloc(sinfo, struct ldb_message);
365 /* unpack the record */
366 ret = ltdb_unpack_data(sinfo->module, &data, msg);
374 msg->dn = ldb_dn_explode(msg, (char *)key.dptr + 3);
375 if (msg->dn == NULL) {
381 /* see if it matches the given expression */
382 if (!ldb_match_msg(sinfo->module->ldb, msg, sinfo->tree,
383 sinfo->base, sinfo->scope)) {
388 ret = ltdb_add_attr_results(sinfo->module, msg, sinfo->attrs, &sinfo->count, &sinfo->msgs);
401 search the database with a LDAP-like expression.
402 this is the "full search" non-indexed variant
404 static int ltdb_search_full(struct ldb_module *module,
405 const struct ldb_dn *base,
406 enum ldb_scope scope,
407 struct ldb_parse_tree *tree,
408 const char * const attrs[], struct ldb_result **res)
410 struct ltdb_private *ltdb = module->private_data;
411 struct ldb_result *result;
413 struct ltdb_search_info *sinfo;
415 result = talloc(ltdb, struct ldb_result);
416 if (result == NULL) {
417 return LDB_ERR_OTHER;
420 sinfo = talloc(ltdb, struct ltdb_search_info);
423 return LDB_ERR_OTHER;
427 sinfo->module = module;
428 sinfo->scope = scope;
430 sinfo->attrs = attrs;
435 ret = tdb_traverse_read(ltdb->tdb, search_func, sinfo);
443 result->controls = NULL;
444 result->msgs = talloc_steal(result, sinfo->msgs);
445 result->count = sinfo->count;
455 search the database with a LDAP-like expression.
456 choses a search method
458 int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
459 enum ldb_scope scope, struct ldb_parse_tree *tree,
460 const char * const attrs[], struct ldb_result **res)
464 if ((base == NULL || base->comp_num == 0) &&
465 (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1;
467 if (ltdb_lock_read(module) != 0) {
471 if (ltdb_cache_load(module) != 0) {
472 ltdb_unlock_read(module);
478 ret = ltdb_search_indexed(module, base, scope, tree, attrs, res);
480 ret = ltdb_search_full(module, base, scope, tree, attrs, res);
483 ltdb_unlock_read(module);