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 3 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, see <http://www.gnu.org/licenses/>.
27 * Component: ldbsearch
29 * Description: utility for ldb search - modelled on ldapsearch
31 * Author: Andrew Tridgell
35 #include "system/filesys.h"
36 #include "system/time.h"
38 #include "tools/cmdline.h"
40 static void usage(struct ldb_context
*ldb
)
42 printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
43 ldb_cmdline_help(ldb
, "ldbsearch", stdout
);
44 exit(LDB_ERR_OPERATIONS_ERROR
);
47 static int do_compare_msg(struct ldb_message
**el1
,
48 struct ldb_message
**el2
,
51 return ldb_dn_compare((*el1
)->dn
, (*el2
)->dn
);
54 struct search_context
{
55 struct ldb_context
*ldb
;
56 struct ldb_control
**req_ctrls
;
59 unsigned int num_stored
;
60 struct ldb_message
**store
;
61 unsigned int refs_stored
;
71 static int store_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
73 sctx
->store
= talloc_realloc(sctx
, sctx
->store
, struct ldb_message
*, sctx
->num_stored
+ 2);
75 fprintf(stderr
, "talloc_realloc failed while storing messages\n");
79 sctx
->store
[sctx
->num_stored
] = talloc_move(sctx
->store
, &msg
);
81 sctx
->store
[sctx
->num_stored
] = NULL
;
86 static int store_referral(char *referral
, struct search_context
*sctx
) {
88 sctx
->refs_store
= talloc_realloc(sctx
, sctx
->refs_store
, char *, sctx
->refs_stored
+ 2);
89 if (!sctx
->refs_store
) {
90 fprintf(stderr
, "talloc_realloc failed while storing referrals\n");
94 sctx
->refs_store
[sctx
->refs_stored
] = talloc_move(sctx
->refs_store
, &referral
);
96 sctx
->refs_store
[sctx
->refs_stored
] = NULL
;
101 static int display_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
102 struct ldb_ldif ldif
;
105 printf("# record %d\n", sctx
->entries
);
107 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
112 * Ensure attributes are always returned in the same
113 * order. For testing, this makes comparison of old
114 * vs. new much easier.
116 ldb_msg_sort_elements(ldif
.msg
);
119 ldb_ldif_write_file(sctx
->ldb
, stdout
, &ldif
);
124 static int display_referral(char *referral
, struct search_context
*sctx
)
128 printf("# Referral\nref: %s\n\n", referral
);
133 static int search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
135 struct search_context
*sctx
;
136 int ret
= LDB_SUCCESS
;
138 sctx
= talloc_get_type(req
->context
, struct search_context
);
141 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
143 if (ares
->error
!= LDB_SUCCESS
) {
144 return ldb_request_done(req
, ares
->error
);
147 switch (ares
->type
) {
148 case LDB_REPLY_ENTRY
:
150 ret
= store_message(ares
->message
, sctx
);
152 ret
= display_message(ares
->message
, sctx
);
156 case LDB_REPLY_REFERRAL
:
158 ret
= store_referral(ares
->referral
, sctx
);
160 ret
= display_referral(ares
->referral
, sctx
);
163 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
168 if (ares
->controls
) {
169 if (handle_controls_reply(ares
->controls
, sctx
->req_ctrls
) == 1)
173 return ldb_request_done(req
, LDB_SUCCESS
);
177 if (ret
!= LDB_SUCCESS
) {
178 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
184 static int do_search(struct ldb_context
*ldb
,
185 struct ldb_dn
*basedn
,
186 struct ldb_cmdline
*options
,
187 const char *expression
,
188 const char * const *attrs
)
190 struct ldb_request
*req
;
191 struct search_context
*sctx
;
196 sctx
= talloc_zero(ldb
, struct search_context
);
197 if (!sctx
) return LDB_ERR_OPERATIONS_ERROR
;
200 sctx
->sort
= options
->sorted
;
201 sctx
->req_ctrls
= ldb_parse_control_strings(ldb
, sctx
, (const char **)options
->controls
);
202 if (options
->controls
!= NULL
&& sctx
->req_ctrls
== NULL
) {
203 printf("parsing controls failed: %s\n", ldb_errstring(ldb
));
204 return LDB_ERR_OPERATIONS_ERROR
;
208 /* free any previous requests */
209 if (req
) talloc_free(req
);
211 ret
= ldb_build_search_req(&req
, ldb
, ldb
,
212 basedn
, options
->scope
,
215 sctx
, search_callback
,
217 if (ret
!= LDB_SUCCESS
) {
219 printf("allocating request failed: %s\n", ldb_errstring(ldb
));
223 if (basedn
== NULL
) {
225 we need to use a NULL base DN when doing a cross-ncs
226 search so we find results on all partitions in a
227 forest. When doing a domain-local search, default to
230 struct ldb_control
*ctrl
;
231 struct ldb_search_options_control
*search_options
= NULL
;
233 ctrl
= ldb_request_get_control(req
, LDB_CONTROL_SEARCH_OPTIONS_OID
);
235 search_options
= talloc_get_type(ctrl
->data
, struct ldb_search_options_control
);
238 if (ctrl
== NULL
|| search_options
== NULL
||
239 !(search_options
->search_options
& LDB_SEARCH_OPTION_PHANTOM_ROOT
)) {
240 struct ldb_dn
*base
= ldb_get_default_basedn(ldb
);
242 req
->op
.search
.base
= base
;
249 ret
= ldb_request(ldb
, req
);
250 if (ret
!= LDB_SUCCESS
) {
251 printf("search failed - %s\n", ldb_errstring(ldb
));
255 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
256 if (ret
!= LDB_SUCCESS
) {
257 printf("search error - %s\n", ldb_errstring(ldb
));
264 if (sctx
->sort
&& (sctx
->num_stored
!= 0 || sctx
->refs
!= 0)) {
267 if (sctx
->num_stored
) {
268 LDB_TYPESAFE_QSORT(sctx
->store
, sctx
->num_stored
, ldb
, do_compare_msg
);
270 for (i
= 0; i
< sctx
->num_stored
; i
++) {
271 display_message(sctx
->store
[i
], sctx
);
274 for (i
= 0; i
< sctx
->refs_stored
; i
++) {
275 display_referral(sctx
->refs_store
[i
], sctx
);
279 printf("# returned %u records\n# %u entries\n# %u referrals\n",
280 sctx
->entries
+ sctx
->refs
, sctx
->entries
, sctx
->refs
);
288 int main(int argc
, const char **argv
)
290 struct ldb_context
*ldb
;
291 struct ldb_dn
*basedn
= NULL
;
292 const char * const * attrs
= NULL
;
293 struct ldb_cmdline
*options
;
295 const char *expression
= "(|(objectClass=*)(distinguishedName=*))";
296 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
298 ldb
= ldb_init(mem_ctx
, NULL
);
300 return LDB_ERR_OPERATIONS_ERROR
;
303 options
= ldb_cmdline_process_search(ldb
, argc
, argv
, usage
);
305 /* the check for '=' is for compatibility with ldapsearch */
306 if (!options
->interactive
&&
308 strpbrk(options
->argv
[0], "=<>~:")) {
309 expression
= options
->argv
[0];
314 if (options
->argc
> 0) {
315 attrs
= (const char * const *)(options
->argv
);
318 if (options
->basedn
!= NULL
) {
319 basedn
= ldb_dn_new(ldb
, ldb
, options
->basedn
);
320 if (basedn
== NULL
) {
321 return LDB_ERR_OPERATIONS_ERROR
;
325 if (options
->interactive
) {
327 while (fgets(line
, sizeof(line
), stdin
)) {
328 ret
= do_search(ldb
, basedn
, options
, line
, attrs
);
331 ret
= do_search(ldb
, basedn
, options
, expression
, attrs
);
334 talloc_free(mem_ctx
);