root/source3/lib/ldb/tools/ldbsearch.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usage
  2. do_compare_msg
  3. store_message
  4. store_referral
  5. display_message
  6. display_referral
  7. search_callback
  8. do_search
  9. main

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Andrew Tridgell  2004
   5 
   6      ** NOTE! The following LGPL license applies to the ldb
   7      ** library. This does NOT imply that all of Samba is released
   8      ** under the LGPL
   9    
  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.
  14 
  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.
  19 
  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/>.
  22 */
  23 
  24 /*
  25  *  Name: ldb
  26  *
  27  *  Component: ldbsearch
  28  *
  29  *  Description: utility for ldb search - modelled on ldapsearch
  30  *
  31  *  Author: Andrew Tridgell
  32  */
  33 
  34 #include "includes.h"
  35 #include "ldb/include/includes.h"
  36 #include "ldb/tools/cmdline.h"
  37 
  38 static void usage(void)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
  41         printf("Options:\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");
  49         exit(1);
  50 }
  51 
  52 static int do_compare_msg(struct ldb_message **el1,
     /* [<][>][^][v][top][bottom][index][help] */
  53                           struct ldb_message **el2,
  54                           void *opaque)
  55 {
  56         struct ldb_context *ldb = talloc_get_type(opaque, struct ldb_context);
  57         return ldb_dn_compare(ldb, (*el1)->dn, (*el2)->dn);
  58 }
  59 
  60 struct search_context {
  61         struct ldb_control **req_ctrls;
  62 
  63         int sort;
  64         int num_stored;
  65         struct ldb_message **store;
  66         char **refs_store;
  67 
  68         int entries;
  69         int refs;
  70 
  71         int pending;
  72         int status;
  73 };
  74 
  75 static int store_message(struct ldb_message *msg, struct search_context *sctx) {
     /* [<][>][^][v][top][bottom][index][help] */
  76 
  77         sctx->store = talloc_realloc(sctx, sctx->store, struct ldb_message *, sctx->num_stored + 2);
  78         if (!sctx->store) {
  79                 fprintf(stderr, "talloc_realloc failed while storing messages\n");
  80                 return -1;
  81         }
  82 
  83         sctx->store[sctx->num_stored] = talloc_move(sctx->store, &msg);
  84         sctx->num_stored++;
  85         sctx->store[sctx->num_stored] = NULL;
  86 
  87         return 0;
  88 }
  89 
  90 static int store_referral(char *referral, struct search_context *sctx) {
     /* [<][>][^][v][top][bottom][index][help] */
  91 
  92         sctx->refs_store = talloc_realloc(sctx, sctx->refs_store, char *, sctx->refs + 2);
  93         if (!sctx->refs_store) {
  94                 fprintf(stderr, "talloc_realloc failed while storing referrals\n");
  95                 return -1;
  96         }
  97 
  98         sctx->refs_store[sctx->refs] = talloc_move(sctx->refs_store, &referral);
  99         sctx->refs++;
 100         sctx->refs_store[sctx->refs] = NULL;
 101 
 102         return 0;
 103 }
 104 
 105 static int display_message(struct ldb_context *ldb, struct ldb_message *msg, struct search_context *sctx) {
     /* [<][>][^][v][top][bottom][index][help] */
 106         struct ldb_ldif ldif;
 107 
 108         sctx->entries++;
 109         printf("# record %d\n", sctx->entries);
 110 
 111         ldif.changetype = LDB_CHANGETYPE_NONE;
 112         ldif.msg = msg;
 113 
 114         if (sctx->sort) {
 115         /*
 116          * Ensure attributes are always returned in the same
 117          * order.  For testing, this makes comparison of old
 118          * vs. new much easier.
 119          */
 120                 ldb_msg_sort_elements(ldif.msg);
 121         }
 122 
 123         ldb_ldif_write_file(ldb, stdout, &ldif);
 124 
 125         return 0;
 126 }
 127 
 128 static int display_referral(char *referral, struct search_context *sctx)
     /* [<][>][^][v][top][bottom][index][help] */
 129 {
 130 
 131         sctx->refs++;
 132         printf("# Referral\nref: %s\n\n", referral);
 133 
 134         return 0;
 135 }
 136 
 137 static int search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
 138 {
 139         struct search_context *sctx = talloc_get_type(context, struct search_context);
 140         int ret;
 141         
 142         switch (ares->type) {
 143 
 144         case LDB_REPLY_ENTRY:
 145                 if (sctx->sort) {
 146                         ret = store_message(ares->message, sctx);
 147                 } else {
 148                         ret = display_message(ldb, ares->message, sctx);
 149                 }
 150                 break;
 151 
 152         case LDB_REPLY_REFERRAL:
 153                 if (sctx->sort) {
 154                         ret = store_referral(ares->referral, sctx);
 155                 } else {
 156                         ret = display_referral(ares->referral, sctx);
 157                 }
 158                 break;
 159 
 160         case LDB_REPLY_DONE:
 161                 if (ares->controls) {
 162                         if (handle_controls_reply(ares->controls, sctx->req_ctrls) == 1)
 163                                 sctx->pending = 1;
 164                 }
 165                 ret = 0;
 166                 break;
 167                 
 168         default:
 169                 fprintf(stderr, "unknown Reply Type\n");
 170                 return LDB_ERR_OTHER;
 171         }
 172 
 173         if (talloc_free(ares) == -1) {
 174                 fprintf(stderr, "talloc_free failed\n");
 175                 sctx->pending = 0;
 176                 return LDB_ERR_OPERATIONS_ERROR;
 177         }
 178 
 179         if (ret) {
 180                 return LDB_ERR_OPERATIONS_ERROR;
 181         }
 182 
 183         return LDB_SUCCESS;
 184 }
 185 
 186 static int do_search(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 187                      const struct ldb_dn *basedn,
 188                      struct ldb_cmdline *options,
 189                      const char *expression,
 190                      const char * const *attrs)
 191 {
 192         struct ldb_request *req;
 193         struct search_context *sctx;
 194         int ret;
 195 
 196         req = talloc(ldb, struct ldb_request);
 197         if (!req) return -1;
 198         
 199         sctx = talloc(req, struct search_context);
 200         if (!sctx) return -1;
 201 
 202         sctx->sort = options->sorted;
 203         sctx->num_stored = 0;
 204         sctx->store = NULL;
 205         sctx->req_ctrls = parse_controls(ldb, options->controls);
 206         if (options->controls != NULL &&  sctx->req_ctrls== NULL) return -1;
 207         sctx->entries = 0;
 208         sctx->refs = 0;
 209 
 210         if (basedn == NULL) {
 211                 basedn = ldb_get_default_basedn(ldb);
 212         }
 213 
 214         req->operation = LDB_SEARCH;
 215         req->op.search.base = basedn;
 216         req->op.search.scope = options->scope;
 217         req->op.search.tree = ldb_parse_tree(req, expression);
 218         if (req->op.search.tree == NULL) return -1;
 219         req->op.search.attrs = attrs;
 220         req->controls = sctx->req_ctrls;
 221         req->context = sctx;
 222         req->callback = &search_callback;
 223         ldb_set_timeout(ldb, req, 0); /* TODO: make this settable by command line */
 224 
 225 again:
 226         sctx->pending = 0;
 227 
 228         ret = ldb_request(ldb, req);
 229         if (ret != LDB_SUCCESS) {
 230                 printf("search failed - %s\n", ldb_errstring(ldb));
 231                 return -1;
 232         }
 233 
 234         ret = ldb_wait(req->handle, LDB_WAIT_ALL);
 235         if (ret != LDB_SUCCESS) {
 236                 printf("search error - %s\n", ldb_errstring(ldb));
 237                 return -1;
 238         }
 239 
 240         if (sctx->pending)
 241                 goto again;
 242 
 243         if (sctx->sort && sctx->num_stored != 0) {
 244                 int i;
 245 
 246                 ldb_qsort(sctx->store, ret, sizeof(struct ldb_message *),
 247                           ldb, (ldb_qsort_cmp_fn_t)do_compare_msg);
 248 
 249                 if (ret != 0) {
 250                         fprintf(stderr, "An error occurred while sorting messages\n");
 251                         exit(1);
 252                 }
 253 
 254                 for (i = 0; i < sctx->num_stored; i++) {
 255                         display_message(ldb, sctx->store[i], sctx);
 256                 }
 257 
 258                 for (i = 0; i < sctx->refs; i++) {
 259                         display_referral(sctx->refs_store[i], sctx);
 260                 }
 261         }
 262 
 263         printf("# returned %d records\n# %d entries\n# %d referrals\n",
 264                 sctx->entries + sctx->refs, sctx->entries, sctx->refs);
 265 
 266         talloc_free(req);
 267 
 268         return 0;
 269 }
 270 
 271 int main(int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 272 {
 273         struct ldb_context *ldb;
 274         struct ldb_dn *basedn = NULL;
 275         const char * const * attrs = NULL;
 276         struct ldb_cmdline *options;
 277         int ret = -1;
 278         const char *expression = "(|(objectClass=*)(distinguishedName=*))";
 279 
 280         ldb_global_init();
 281 
 282         ldb = ldb_init(NULL);
 283 
 284         options = ldb_cmdline_process(ldb, argc, argv, usage);
 285 
 286         /* the check for '=' is for compatibility with ldapsearch */
 287         if (!options->interactive &&
 288             options->argc > 0 && 
 289             strchr(options->argv[0], '=')) {
 290                 expression = options->argv[0];
 291                 options->argv++;
 292                 options->argc--;
 293         }
 294 
 295         if (options->argc > 0) {
 296                 attrs = (const char * const *)(options->argv);
 297         }
 298 
 299         if (options->basedn != NULL) {
 300                 basedn = ldb_dn_explode(ldb, options->basedn);
 301                 if (basedn == NULL) {
 302                         fprintf(stderr, "Invalid Base DN format\n");
 303                         exit(1);
 304                 }
 305         }
 306 
 307         if (options->interactive) {
 308                 char line[1024];
 309                 while (fgets(line, sizeof(line), stdin)) {
 310                         if (do_search(ldb, basedn, options, line, attrs) == -1) {
 311                                 ret = -1;
 312                         }
 313                 }
 314         } else {
 315                 ret = do_search(ldb, basedn, options, expression, attrs);
 316         }
 317 
 318         talloc_free(ldb);
 319         return ret;
 320 }

/* [<][>][^][v][top][bottom][index][help] */