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_message *ret,
44 const struct ldb_message_element *el,
48 struct ldb_message_element *e2, *elnew;
50 if (check_duplicates && ldb_msg_find_element(ret, el->name)) {
51 /* its already there */
55 e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1);
61 elnew = &e2[ret->num_elements];
63 elnew->name = talloc_strdup(ret->elements, el->name);
69 elnew->values = talloc_array(ret->elements, struct ldb_val, el->num_values);
77 for (i=0;i<el->num_values;i++) {
78 elnew->values[i] = ldb_val_dup(elnew->values, &el->values[i]);
79 if (elnew->values[i].length != el->values[i].length) {
84 elnew->num_values = el->num_values;
92 add the special distinguishedName element
94 static int msg_add_distinguished_name(struct ldb_message *msg)
96 struct ldb_message_element el;
101 el.name = "distinguishedName";
104 val.data = (uint8_t *)ldb_dn_linearize(msg, msg->dn);
105 val.length = strlen((char *)val.data);
107 ret = msg_add_element(msg, &el, 1);
112 add all elements from one message into another
114 static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *ret,
115 const struct ldb_message *msg)
117 struct ldb_context *ldb = module->ldb;
119 int check_duplicates = (ret->num_elements != 0);
121 if (msg_add_distinguished_name(ret) != 0) {
125 for (i=0;i<msg->num_elements;i++) {
126 const struct ldb_attrib_handler *h;
127 h = ldb_attrib_handler(ldb, msg->elements[i].name);
128 if (h->flags & LDB_ATTR_FLAG_HIDDEN) {
131 if (msg_add_element(ret, &msg->elements[i],
132 check_duplicates) != 0) {
142 pull the specified list of attributes from a message
144 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_message *ret;
152 ret = talloc(mem_ctx, struct ldb_message);
157 ret->dn = ldb_dn_copy(ret, msg->dn);
163 ret->num_elements = 0;
164 ret->elements = NULL;
167 if (msg_add_all_elements(module, ret, msg) != 0) {
174 for (i=0;attrs[i];i++) {
175 struct ldb_message_element *el;
177 if (strcmp(attrs[i], "*") == 0) {
178 if (msg_add_all_elements(module, ret, msg) != 0) {
185 if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
186 if (msg_add_distinguished_name(ret) != 0) {
192 el = ldb_msg_find_element(msg, attrs[i]);
196 if (msg_add_element(ret, el, 1) != 0) {
207 search the database for a single simple dn, returning all attributes
210 return 1 on success, 0 on record-not-found and -1 on error
212 int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct ldb_message *msg)
214 struct ltdb_private *ltdb = module->private_data;
216 TDB_DATA tdb_key, tdb_data, tdb_data2;
218 memset(msg, 0, sizeof(*msg));
221 tdb_key = ltdb_key(module, dn);
226 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
227 talloc_free(tdb_key.dptr);
228 if (!tdb_data.dptr) {
232 tdb_data2.dptr = talloc_memdup(msg, tdb_data.dptr, tdb_data.dsize);
234 if (!tdb_data2.dptr) {
237 tdb_data2.dsize = tdb_data.dsize;
239 msg->num_elements = 0;
240 msg->elements = NULL;
242 ret = ltdb_unpack_data(module, &tdb_data2, msg);
244 talloc_free(tdb_data2.dptr);
249 msg->dn = ldb_dn_copy(tdb_data2.dptr, dn);
252 talloc_free(tdb_data2.dptr);
259 /* the lock key for search locking. Note that this is not a DN, its
260 just an arbitrary key to give to tdb. Also note that as we and
261 using transactions for all write operations and transactions take
262 care of their own locks, we don't need to do any locking anywhere
263 other than in ldb_search() */
264 #define LDBLOCK "INT_LDBLOCK"
267 lock the database for read - use by ltdb_search
269 static int ltdb_lock_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_chainlock_read(ltdb->tdb, key);
281 unlock the database after a ltdb_lock_read()
283 static int ltdb_unlock_read(struct ldb_module *module)
285 struct ltdb_private *ltdb = module->private_data;
288 key.dptr = discard_const(LDBLOCK);
289 key.dsize = strlen(LDBLOCK);
291 return tdb_chainunlock_read(ltdb->tdb, key);
295 add a set of attributes from a record to a set of results
296 return 0 on success, -1 on failure
298 int ltdb_add_attr_results(struct ldb_module *module,
300 struct ldb_message *msg,
301 const char * const attrs[],
303 struct ldb_message ***res)
305 struct ldb_message *msg2;
306 struct ldb_message **res2;
308 /* pull the attributes that the user wants */
309 msg2 = ltdb_pull_attrs(module, mem_ctx, msg, attrs);
314 /* add to the results list */
315 res2 = talloc_realloc(mem_ctx, *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, sinfo, 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);