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");
41 ldb_cmdline_help("ldbsearch", stdout
);
45 static int do_compare_msg(struct ldb_message
**el1
,
46 struct ldb_message
**el2
,
49 return ldb_dn_compare((*el1
)->dn
, (*el2
)->dn
);
52 struct search_context
{
53 struct ldb_context
*ldb
;
54 struct ldb_control
**req_ctrls
;
57 unsigned int num_stored
;
58 struct ldb_message
**store
;
59 unsigned int refs_stored
;
69 static int store_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
71 sctx
->store
= talloc_realloc(sctx
, sctx
->store
, struct ldb_message
*, sctx
->num_stored
+ 2);
73 fprintf(stderr
, "talloc_realloc failed while storing messages\n");
77 sctx
->store
[sctx
->num_stored
] = talloc_move(sctx
->store
, &msg
);
79 sctx
->store
[sctx
->num_stored
] = NULL
;
84 static int store_referral(char *referral
, struct search_context
*sctx
) {
86 sctx
->refs_store
= talloc_realloc(sctx
, sctx
->refs_store
, char *, sctx
->refs_stored
+ 2);
87 if (!sctx
->refs_store
) {
88 fprintf(stderr
, "talloc_realloc failed while storing referrals\n");
92 sctx
->refs_store
[sctx
->refs_stored
] = talloc_move(sctx
->refs_store
, &referral
);
94 sctx
->refs_store
[sctx
->refs_stored
] = NULL
;
99 static int display_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
100 struct ldb_ldif ldif
;
103 printf("# record %d\n", sctx
->entries
);
105 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
110 * Ensure attributes are always returned in the same
111 * order. For testing, this makes comparison of old
112 * vs. new much easier.
114 ldb_msg_sort_elements(ldif
.msg
);
117 ldb_ldif_write_file(sctx
->ldb
, stdout
, &ldif
);
122 static int display_referral(char *referral
, struct search_context
*sctx
)
126 printf("# Referral\nref: %s\n\n", referral
);
131 static int search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
133 struct search_context
*sctx
;
136 sctx
= talloc_get_type(req
->context
, struct search_context
);
139 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
141 if (ares
->error
!= LDB_SUCCESS
) {
142 return ldb_request_done(req
, ares
->error
);
145 switch (ares
->type
) {
146 case LDB_REPLY_ENTRY
:
148 ret
= store_message(ares
->message
, sctx
);
150 ret
= display_message(ares
->message
, sctx
);
154 case LDB_REPLY_REFERRAL
:
156 ret
= store_referral(ares
->referral
, sctx
);
158 ret
= display_referral(ares
->referral
, sctx
);
161 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
166 if (ares
->controls
) {
167 if (handle_controls_reply(ares
->controls
, sctx
->req_ctrls
) == 1)
171 return ldb_request_done(req
, LDB_SUCCESS
);
176 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
182 static int do_search(struct ldb_context
*ldb
,
183 struct ldb_dn
*basedn
,
184 struct ldb_cmdline
*options
,
185 const char *expression
,
186 const char * const *attrs
)
188 struct ldb_request
*req
;
189 struct search_context
*sctx
;
194 sctx
= talloc_zero(ldb
, struct search_context
);
195 if (!sctx
) return -1;
198 sctx
->sort
= options
->sorted
;
199 sctx
->req_ctrls
= ldb_parse_control_strings(ldb
, sctx
, (const char **)options
->controls
);
200 if (options
->controls
!= NULL
&& sctx
->req_ctrls
== NULL
) {
201 printf("parsing controls failed: %s\n", ldb_errstring(ldb
));
205 if (basedn
== NULL
) {
206 basedn
= ldb_get_default_basedn(ldb
);
210 /* free any previous requests */
211 if (req
) talloc_free(req
);
213 ret
= ldb_build_search_req(&req
, ldb
, ldb
,
214 basedn
, options
->scope
,
217 sctx
, search_callback
,
219 if (ret
!= LDB_SUCCESS
) {
221 printf("allocating request failed: %s\n", ldb_errstring(ldb
));
227 ret
= ldb_request(ldb
, req
);
228 if (ret
!= LDB_SUCCESS
) {
229 printf("search failed - %s\n", ldb_errstring(ldb
));
233 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
234 if (ret
!= LDB_SUCCESS
) {
235 printf("search error - %s\n", ldb_errstring(ldb
));
242 if (sctx
->sort
&& (sctx
->num_stored
!= 0 || sctx
->refs
!= 0)) {
245 if (sctx
->num_stored
) {
246 LDB_TYPESAFE_QSORT(sctx
->store
, sctx
->num_stored
, ldb
, do_compare_msg
);
248 for (i
= 0; i
< sctx
->num_stored
; i
++) {
249 display_message(sctx
->store
[i
], sctx
);
252 for (i
= 0; i
< sctx
->refs_stored
; i
++) {
253 display_referral(sctx
->refs_store
[i
], sctx
);
257 printf("# returned %d records\n# %d entries\n# %d referrals\n",
258 sctx
->entries
+ sctx
->refs
, sctx
->entries
, sctx
->refs
);
266 int main(int argc
, const char **argv
)
268 struct ldb_context
*ldb
;
269 struct ldb_dn
*basedn
= NULL
;
270 const char * const * attrs
= NULL
;
271 struct ldb_cmdline
*options
;
273 const char *expression
= "(|(objectClass=*)(distinguishedName=*))";
275 ldb
= ldb_init(NULL
, NULL
);
280 options
= ldb_cmdline_process(ldb
, argc
, argv
, usage
);
282 /* the check for '=' is for compatibility with ldapsearch */
283 if (!options
->interactive
&&
285 strchr(options
->argv
[0], '=')) {
286 expression
= options
->argv
[0];
291 if (options
->argc
> 0) {
292 attrs
= (const char * const *)(options
->argv
);
295 if (options
->basedn
!= NULL
) {
296 basedn
= ldb_dn_new(ldb
, ldb
, options
->basedn
);
297 if ( ! ldb_dn_validate(basedn
)) {
298 fprintf(stderr
, "Invalid Base DN format\n");
303 if (options
->interactive
) {
305 while (fgets(line
, sizeof(line
), stdin
)) {
306 if (do_search(ldb
, basedn
, options
, line
, attrs
) == -1) {
311 ret
= do_search(ldb
, basedn
, options
, expression
, attrs
);