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
34 #include "ldb_includes.h"
36 #include "tools/cmdline.h"
38 static void usage(void)
40 printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
42 printf(" -H ldb_url choose the database (or $LDB_URL)\n");
43 printf(" -s base|sub|one choose search scope\n");
44 printf(" -b basedn choose baseDN\n");
45 printf(" -i read search expressions from stdin\n");
46 printf(" -S sort returned attributes\n");
47 printf(" -o options pass options like modules to activate\n");
48 printf(" e.g: -o modules:timestamps\n");
52 static int do_compare_msg(struct ldb_message
**el1
,
53 struct ldb_message
**el2
,
56 return ldb_dn_compare((*el1
)->dn
, (*el2
)->dn
);
59 struct search_context
{
60 struct ldb_context
*ldb
;
61 struct ldb_control
**req_ctrls
;
65 struct ldb_message
**store
;
76 static int store_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
78 sctx
->store
= talloc_realloc(sctx
, sctx
->store
, struct ldb_message
*, sctx
->num_stored
+ 2);
80 fprintf(stderr
, "talloc_realloc failed while storing messages\n");
84 sctx
->store
[sctx
->num_stored
] = talloc_move(sctx
->store
, &msg
);
86 sctx
->store
[sctx
->num_stored
] = NULL
;
91 static int store_referral(char *referral
, struct search_context
*sctx
) {
93 sctx
->refs_store
= talloc_realloc(sctx
, sctx
->refs_store
, char *, sctx
->refs_stored
+ 2);
94 if (!sctx
->refs_store
) {
95 fprintf(stderr
, "talloc_realloc failed while storing referrals\n");
99 sctx
->refs_store
[sctx
->refs_stored
] = talloc_move(sctx
->refs_store
, &referral
);
101 sctx
->refs_store
[sctx
->refs_stored
] = NULL
;
106 static int display_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
107 struct ldb_ldif ldif
;
110 printf("# record %d\n", sctx
->entries
);
112 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
117 * Ensure attributes are always returned in the same
118 * order. For testing, this makes comparison of old
119 * vs. new much easier.
121 ldb_msg_sort_elements(ldif
.msg
);
124 ldb_ldif_write_file(sctx
->ldb
, stdout
, &ldif
);
129 static int display_referral(char *referral
, struct search_context
*sctx
)
133 printf("# Referral\nref: %s\n\n", referral
);
138 static int search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
140 struct search_context
*sctx
;
143 sctx
= talloc_get_type(req
->context
, struct search_context
);
146 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
148 if (ares
->error
!= LDB_SUCCESS
) {
149 return ldb_request_done(req
, ares
->error
);
152 switch (ares
->type
) {
153 case LDB_REPLY_ENTRY
:
155 ret
= store_message(ares
->message
, sctx
);
157 ret
= display_message(ares
->message
, sctx
);
161 case LDB_REPLY_REFERRAL
:
163 ret
= store_referral(ares
->referral
, sctx
);
165 ret
= display_referral(ares
->referral
, sctx
);
168 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
173 if (ares
->controls
) {
174 if (handle_controls_reply(ares
->controls
, sctx
->req_ctrls
) == 1)
178 return ldb_request_done(req
, LDB_SUCCESS
);
183 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
189 static int do_search(struct ldb_context
*ldb
,
190 struct ldb_dn
*basedn
,
191 struct ldb_cmdline
*options
,
192 const char *expression
,
193 const char * const *attrs
)
195 struct ldb_request
*req
;
196 struct search_context
*sctx
;
201 sctx
= talloc(ldb
, struct search_context
);
202 if (!sctx
) return -1;
205 sctx
->sort
= options
->sorted
;
206 sctx
->num_stored
= 0;
207 sctx
->refs_stored
= 0;
209 sctx
->req_ctrls
= ldb_parse_control_strings(ldb
, sctx
, (const char **)options
->controls
);
210 if (options
->controls
!= NULL
&& sctx
->req_ctrls
== NULL
) {
211 printf("parsing controls failed: %s\n", ldb_errstring(ldb
));
217 if (basedn
== NULL
) {
218 basedn
= ldb_get_default_basedn(ldb
);
222 /* free any previous requests */
223 if (req
) talloc_free(req
);
225 ret
= ldb_build_search_req(&req
, ldb
, ldb
,
226 basedn
, options
->scope
,
229 sctx
, search_callback
,
231 if (ret
!= LDB_SUCCESS
) {
233 printf("allocating request failed: %s\n", ldb_errstring(ldb
));
239 ret
= ldb_request(ldb
, req
);
240 if (ret
!= LDB_SUCCESS
) {
241 printf("search failed - %s\n", ldb_errstring(ldb
));
245 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
246 if (ret
!= LDB_SUCCESS
) {
247 printf("search error - %s\n", ldb_errstring(ldb
));
254 if (sctx
->sort
&& (sctx
->num_stored
!= 0 || sctx
->refs
!= 0)) {
257 if (sctx
->num_stored
) {
258 ldb_qsort(sctx
->store
, sctx
->num_stored
, sizeof(struct ldb_message
*),
259 ldb
, (ldb_qsort_cmp_fn_t
)do_compare_msg
);
261 for (i
= 0; i
< sctx
->num_stored
; i
++) {
262 display_message(sctx
->store
[i
], sctx
);
265 for (i
= 0; i
< sctx
->refs_stored
; i
++) {
266 display_referral(sctx
->refs_store
[i
], sctx
);
270 printf("# returned %d records\n# %d entries\n# %d referrals\n",
271 sctx
->entries
+ sctx
->refs
, sctx
->entries
, sctx
->refs
);
279 int main(int argc
, const char **argv
)
281 struct ldb_context
*ldb
;
282 struct ldb_dn
*basedn
= NULL
;
283 const char * const * attrs
= NULL
;
284 struct ldb_cmdline
*options
;
286 const char *expression
= "(|(objectClass=*)(distinguishedName=*))";
288 ldb
= ldb_init(NULL
, NULL
);
293 options
= ldb_cmdline_process(ldb
, argc
, argv
, usage
);
295 /* the check for '=' is for compatibility with ldapsearch */
296 if (!options
->interactive
&&
298 strchr(options
->argv
[0], '=')) {
299 expression
= options
->argv
[0];
304 if (options
->argc
> 0) {
305 attrs
= (const char * const *)(options
->argv
);
308 if (options
->basedn
!= NULL
) {
309 basedn
= ldb_dn_new(ldb
, ldb
, options
->basedn
);
310 if ( ! ldb_dn_validate(basedn
)) {
311 fprintf(stderr
, "Invalid Base DN format\n");
316 if (options
->interactive
) {
318 while (fgets(line
, sizeof(line
), stdin
)) {
319 if (do_search(ldb
, basedn
, options
, line
, attrs
) == -1) {
324 ret
= do_search(ldb
, basedn
, options
, expression
, attrs
);