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/ldb.h"
37 #include "ldb/include/ldb_errors.h"
38 #include "ldb/include/ldb_private.h"
39 #include "ldb/ldb_tdb/ldb_tdb.h"
42 add one element to a message
44 static int msg_add_element(struct ldb_context *ldb,
45 struct ldb_message *ret, const struct ldb_message_element *el)
48 struct ldb_message_element *e2, *elnew;
50 e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1);
56 elnew = &e2[ret->num_elements];
58 elnew->name = talloc_strdup(ret->elements, el->name);
64 elnew->values = talloc_array(ret->elements, struct ldb_val, el->num_values);
72 for (i=0;i<el->num_values;i++) {
73 elnew->values[i] = ldb_val_dup(elnew->values, &el->values[i]);
74 if (elnew->values[i].length != el->values[i].length) {
79 elnew->num_values = el->num_values;
87 add all elements from one message into another
89 static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *ret,
90 const struct ldb_message *msg)
92 struct ldb_context *ldb = module->ldb;
95 for (i=0;i<msg->num_elements;i++) {
96 const struct ldb_attrib_handler *h;
97 h = ldb_attrib_handler(ldb, msg->elements[i].name);
98 if (h->flags & LDB_ATTR_FLAG_HIDDEN) {
101 if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) {
111 pull the specified list of attributes from a message
113 static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module,
114 const struct ldb_message *msg,
115 const char * const *attrs)
117 struct ldb_context *ldb = module->ldb;
118 struct ldb_message *ret;
121 ret = talloc(ldb, struct ldb_message);
126 ret->dn = ldb_dn_copy(ret, msg->dn);
132 ret->num_elements = 0;
133 ret->elements = NULL;
136 if (msg_add_all_elements(module, ret, msg) != 0) {
143 for (i=0;attrs[i];i++) {
144 struct ldb_message_element *el;
146 if (strcmp(attrs[i], "*") == 0) {
147 if (msg_add_all_elements(module, ret, msg) != 0) {
154 if (ldb_attr_cmp(attrs[i], "dn") == 0 ||
155 ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
156 struct ldb_message_element el2;
160 el2.name = talloc_strdup(ret, attrs[i]);
167 val.data = ldb_dn_linearize(ret, ret->dn);
168 val.length = strlen(val.data);
170 if (msg_add_element(ldb, ret, &el2) != 0) {
174 talloc_free(discard_const_p(char, el2.name));
178 el = ldb_msg_find_element(msg, attrs[i]);
182 if (msg_add_element(ldb, ret, el) != 0) {
193 search the database for a single simple dn, returning all attributes
196 return 1 on success, 0 on record-not-found and -1 on error
198 int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct ldb_message *msg)
200 struct ltdb_private *ltdb = module->private_data;
202 TDB_DATA tdb_key, tdb_data, tdb_data2;
204 memset(msg, 0, sizeof(*msg));
207 tdb_key = ltdb_key(module, dn);
212 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
213 talloc_free(tdb_key.dptr);
214 if (!tdb_data.dptr) {
218 tdb_data2.dptr = talloc_memdup(msg, tdb_data.dptr, tdb_data.dsize);
220 if (!tdb_data2.dptr) {
223 tdb_data2.dsize = tdb_data.dsize;
225 msg->num_elements = 0;
226 msg->elements = NULL;
228 ret = ltdb_unpack_data(module, &tdb_data2, msg);
230 talloc_free(tdb_data2.dptr);
235 msg->dn = ldb_dn_copy(tdb_data2.dptr, dn);
238 talloc_free(tdb_data2.dptr);
245 /* the lock key for search locking. Note that this is not a DN, its
246 just an arbitrary key to give to tdb. Also note that as we and
247 using transactions for all write operations and transactions take
248 care of their own locks, we don't need to do any locking anywhere
249 other than in ldb_search() */
250 #define LDBLOCK "INT_LDBLOCK"
253 lock the database for read - use by ltdb_search
255 static int ltdb_lock_read(struct ldb_module *module)
257 struct ltdb_private *ltdb = module->private_data;
260 key.dptr = discard_const(LDBLOCK);
261 key.dsize = strlen(LDBLOCK);
263 return tdb_chainlock_read(ltdb->tdb, key);
267 unlock the database after a ltdb_lock_read()
269 static int ltdb_unlock_read(struct ldb_module *module)
271 struct ltdb_private *ltdb = module->private_data;
274 key.dptr = discard_const(LDBLOCK);
275 key.dsize = strlen(LDBLOCK);
277 return tdb_chainunlock_read(ltdb->tdb, key);
283 search the database for a single simple dn
285 static int ltdb_search_dn(struct ldb_module *module, const struct ldb_dn *dn,
286 const char * const attrs[], struct ldb_message ***res)
288 struct ldb_context *ldb = module->ldb;
290 struct ldb_message *msg, *msg2;
294 if (ltdb_lock_read(module) != 0) {
298 if (ltdb_cache_load(module) != 0) {
299 ltdb_unlock_read(module);
303 *res = talloc_array(ldb, struct ldb_message *, 2);
308 msg = talloc(*res, struct ldb_message);
313 ret = ltdb_search_dn1(module, dn, msg);
317 ltdb_unlock_read(module);
321 msg2 = ltdb_pull_attrs(module, msg, attrs);
328 (*res)[0] = talloc_steal(*res, msg2);
331 ltdb_unlock_read(module);
337 ltdb_unlock_read(module);
343 add a set of attributes from a record to a set of results
344 return 0 on success, -1 on failure
346 int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg,
347 const char * const attrs[],
349 struct ldb_message ***res)
351 struct ldb_context *ldb = module->ldb;
352 struct ldb_message *msg2;
353 struct ldb_message **res2;
355 /* pull the attributes that the user wants */
356 msg2 = ltdb_pull_attrs(module, msg, attrs);
361 /* add to the results list */
362 res2 = talloc_realloc(ldb, *res, struct ldb_message *, (*count)+2);
370 (*res)[*count] = talloc_steal(*res, msg2);
371 (*res)[(*count)+1] = NULL;
379 internal search state during a full db search
381 struct ltdb_search_info {
382 struct ldb_module *module;
383 struct ldb_parse_tree *tree;
384 const struct ldb_dn *base;
385 enum ldb_scope scope;
386 const char * const *attrs;
387 struct ldb_message **msgs;
394 search function for a non-indexed search
396 static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
398 struct ltdb_search_info *sinfo = state;
399 struct ldb_message *msg;
403 strncmp(key.dptr, "DN=", 3) != 0) {
407 msg = talloc(sinfo, struct ldb_message);
412 /* unpack the record */
413 ret = ltdb_unpack_data(sinfo->module, &data, msg);
421 msg->dn = ldb_dn_explode(msg, key.dptr + 3);
422 if (msg->dn == NULL) {
428 /* see if it matches the given expression */
429 if (!ldb_match_msg(sinfo->module->ldb, msg, sinfo->tree,
430 sinfo->base, sinfo->scope)) {
435 ret = ltdb_add_attr_results(sinfo->module, msg, sinfo->attrs, &sinfo->count, &sinfo->msgs);
448 search the database with a LDAP-like expression.
449 this is the "full search" non-indexed variant
451 static int ltdb_search_full(struct ldb_module *module,
452 const struct ldb_dn *base,
453 enum ldb_scope scope,
454 struct ldb_parse_tree *tree,
455 const char * const attrs[], struct ldb_message ***res)
457 struct ltdb_private *ltdb = module->private_data;
459 struct ltdb_search_info *sinfo;
461 sinfo = talloc(ltdb, struct ltdb_search_info);
467 sinfo->module = module;
468 sinfo->scope = scope;
470 sinfo->attrs = attrs;
475 ret = tdb_traverse_read(ltdb->tdb, search_func, sinfo);
482 *res = talloc_steal(ltdb, sinfo->msgs);
483 count = sinfo->count;
492 search the database with a LDAP-like expression.
493 choses a search method
495 int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
496 enum ldb_scope scope, struct ldb_parse_tree *tree,
497 const char * const attrs[], struct ldb_message ***res)
501 if ((base == NULL || base->comp_num == 0) &&
502 (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1;
504 if (ltdb_lock_read(module) != 0) {
508 if (ltdb_cache_load(module) != 0) {
509 ltdb_unlock_read(module);
515 ret = ltdb_search_indexed(module, base, scope, tree, attrs, res);
517 ret = ltdb_search_full(module, base, scope, tree, attrs, res);
520 ltdb_unlock_read(module);