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 "tools/cmdline.h"
37 static void usage(void)
39 printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
41 printf(" -H ldb_url choose the database (or $LDB_URL)\n");
42 printf(" -s base|sub|one choose search scope\n");
43 printf(" -b basedn choose baseDN\n");
44 printf(" -i read search expressions from stdin\n");
45 printf(" -S sort returned attributes\n");
46 printf(" -o options pass options like modules to activate\n");
47 printf(" e.g: -o modules:timestamps\n");
51 static int do_compare_msg(struct ldb_message
**el1
,
52 struct ldb_message
**el2
,
55 return ldb_dn_compare((*el1
)->dn
, (*el2
)->dn
);
58 struct search_context
{
59 struct ldb_context
*ldb
;
60 struct ldb_control
**req_ctrls
;
64 struct ldb_message
**store
;
75 static int store_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
77 sctx
->store
= talloc_realloc(sctx
, sctx
->store
, struct ldb_message
*, sctx
->num_stored
+ 2);
79 fprintf(stderr
, "talloc_realloc failed while storing messages\n");
83 sctx
->store
[sctx
->num_stored
] = talloc_move(sctx
->store
, &msg
);
85 sctx
->store
[sctx
->num_stored
] = NULL
;
90 static int store_referral(char *referral
, struct search_context
*sctx
) {
92 sctx
->refs_store
= talloc_realloc(sctx
, sctx
->refs_store
, char *, sctx
->refs_stored
+ 2);
93 if (!sctx
->refs_store
) {
94 fprintf(stderr
, "talloc_realloc failed while storing referrals\n");
98 sctx
->refs_store
[sctx
->refs_stored
] = talloc_move(sctx
->refs_store
, &referral
);
100 sctx
->refs_store
[sctx
->refs_stored
] = NULL
;
105 static int display_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
106 struct ldb_ldif ldif
;
109 printf("# record %d\n", sctx
->entries
);
111 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
116 * Ensure attributes are always returned in the same
117 * order. For testing, this makes comparison of old
118 * vs. new much easier.
120 ldb_msg_sort_elements(ldif
.msg
);
123 ldb_ldif_write_file(sctx
->ldb
, stdout
, &ldif
);
128 static int display_referral(char *referral
, struct search_context
*sctx
)
132 printf("# Referral\nref: %s\n\n", referral
);
137 static int search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
139 struct search_context
*sctx
;
142 sctx
= talloc_get_type(req
->context
, struct search_context
);
145 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
147 if (ares
->error
!= LDB_SUCCESS
) {
148 return ldb_request_done(req
, ares
->error
);
151 switch (ares
->type
) {
152 case LDB_REPLY_ENTRY
:
154 ret
= store_message(ares
->message
, sctx
);
156 ret
= display_message(ares
->message
, sctx
);
160 case LDB_REPLY_REFERRAL
:
162 ret
= store_referral(ares
->referral
, sctx
);
164 ret
= display_referral(ares
->referral
, sctx
);
167 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
172 if (ares
->controls
) {
173 if (handle_controls_reply(ares
->controls
, sctx
->req_ctrls
) == 1)
177 return ldb_request_done(req
, LDB_SUCCESS
);
182 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
188 static int do_search(struct ldb_context
*ldb
,
189 struct ldb_dn
*basedn
,
190 struct ldb_cmdline
*options
,
191 const char *expression
,
192 const char * const *attrs
)
194 struct ldb_request
*req
;
195 struct search_context
*sctx
;
200 sctx
= talloc(ldb
, struct search_context
);
201 if (!sctx
) return -1;
204 sctx
->sort
= options
->sorted
;
205 sctx
->num_stored
= 0;
206 sctx
->refs_stored
= 0;
208 sctx
->req_ctrls
= ldb_parse_control_strings(ldb
, sctx
, (const char **)options
->controls
);
209 if (options
->controls
!= NULL
&& sctx
->req_ctrls
== NULL
) {
210 printf("parsing controls failed: %s\n", ldb_errstring(ldb
));
216 if (basedn
== NULL
) {
217 basedn
= ldb_get_default_basedn(ldb
);
221 /* free any previous requests */
222 if (req
) talloc_free(req
);
224 ret
= ldb_build_search_req(&req
, ldb
, ldb
,
225 basedn
, options
->scope
,
228 sctx
, search_callback
,
230 if (ret
!= LDB_SUCCESS
) {
232 printf("allocating request failed: %s\n", ldb_errstring(ldb
));
238 ret
= ldb_request(ldb
, req
);
239 if (ret
!= LDB_SUCCESS
) {
240 printf("search failed - %s\n", ldb_errstring(ldb
));
244 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
245 if (ret
!= LDB_SUCCESS
) {
246 printf("search error - %s\n", ldb_errstring(ldb
));
253 if (sctx
->sort
&& (sctx
->num_stored
!= 0 || sctx
->refs
!= 0)) {
256 if (sctx
->num_stored
) {
257 ldb_qsort(sctx
->store
, sctx
->num_stored
, sizeof(struct ldb_message
*),
258 ldb
, (ldb_qsort_cmp_fn_t
)do_compare_msg
);
260 for (i
= 0; i
< sctx
->num_stored
; i
++) {
261 display_message(sctx
->store
[i
], sctx
);
264 for (i
= 0; i
< sctx
->refs_stored
; i
++) {
265 display_referral(sctx
->refs_store
[i
], sctx
);
269 printf("# returned %d records\n# %d entries\n# %d referrals\n",
270 sctx
->entries
+ sctx
->refs
, sctx
->entries
, sctx
->refs
);
278 int main(int argc
, const char **argv
)
280 struct ldb_context
*ldb
;
281 struct ldb_dn
*basedn
= NULL
;
282 const char * const * attrs
= NULL
;
283 struct ldb_cmdline
*options
;
285 const char *expression
= "(|(objectClass=*)(distinguishedName=*))";
287 ldb
= ldb_init(NULL
, NULL
);
292 options
= ldb_cmdline_process(ldb
, argc
, argv
, usage
);
294 /* the check for '=' is for compatibility with ldapsearch */
295 if (!options
->interactive
&&
297 strchr(options
->argv
[0], '=')) {
298 expression
= options
->argv
[0];
303 if (options
->argc
> 0) {
304 attrs
= (const char * const *)(options
->argv
);
307 if (options
->basedn
!= NULL
) {
308 basedn
= ldb_dn_new(ldb
, ldb
, options
->basedn
);
309 if ( ! ldb_dn_validate(basedn
)) {
310 fprintf(stderr
, "Invalid Base DN format\n");
315 if (options
->interactive
) {
317 while (fgets(line
, sizeof(line
), stdin
)) {
318 if (do_search(ldb
, basedn
, options
, line
, attrs
) == -1) {
323 ret
= do_search(ldb
, basedn
, options
, expression
, attrs
);