r11567: Ldb API change patch.
[kai/samba-autobuild/.git] / source4 / lib / ldb / tools / ldbedit.c
index 7e417024222713a02e8fc51f8a2f76297f2a0568..570179c2e16a0eedbfd9921fac89d64a2a53afb2 100644 (file)
  */
 
 #include "includes.h"
+#include "ldb/include/ldb.h"
+#include "ldb/include/ldb_errors.h"
+#include "ldb/include/ldb_private.h"
+#include "ldb/tools/cmdline.h"
+
+#ifdef _SAMBA_BUILD_
+#include "system/filesys.h"
+#endif
+
+static struct ldb_cmdline *options;
+
+/*
+  debug routine 
+*/
+static void ldif_write_msg(struct ldb_context *ldb, 
+                          FILE *f, 
+                          enum ldb_changetype changetype,
+                          struct ldb_message *msg)
+{
+       struct ldb_ldif ldif;
+       ldif.changetype = changetype;
+       ldif.msg = msg;
+       ldb_ldif_write_file(ldb, f, &ldif);
+}
 
 /*
   modify a database record so msg1 becomes msg2
@@ -42,67 +66,42 @@ static int modify_record(struct ldb_context *ldb,
                         struct ldb_message *msg1,
                         struct ldb_message *msg2)
 {
-       struct ldb_message mod;
-       struct ldb_message_element *el;
-       int i;
-       int count = 0;
-
-       mod.dn = msg1->dn;
-       mod.num_elements = 0;
-       mod.elements = NULL;
+       struct ldb_message *mod;
 
-       /* look in msg2 to find elements that need to be added
-          or modified */
-       for (i=0;i<msg2->num_elements;i++) {
-               el = ldb_msg_find_element(msg1, msg2->elements[i].name);
-
-               if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
-                       continue;
-               }
-
-               if (ldb_msg_add(ldb, &mod, 
-                               &msg2->elements[i],
-                               el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
-                       return -1;
-               }
-               count++;
+       mod = ldb_msg_diff(ldb, msg1, msg2);
+       if (mod == NULL) {
+               fprintf(stderr, "Failed to calculate message differences\n");
+               return -1;
        }
 
-       /* look in msg1 to find elements that need to be deleted */
-       for (i=0;i<msg1->num_elements;i++) {
-               el = ldb_msg_find_element(msg2, msg1->elements[i].name);
-               if (!el) {
-                       if (ldb_msg_add_empty(ldb, &mod, 
-                                             msg1->elements[i].name,
-                                             LDB_FLAG_MOD_DELETE) != 0) {
-                               return -1;
-                       }
-                       count++;
-               }
+       if (mod->num_elements == 0) {
+               return 0;
        }
 
-       if (mod.num_elements == 0) {
-               return 0;
+       if (options->verbose > 0) {
+               ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod);
        }
 
-       if (ldb_modify(ldb, &mod) != 0) {
+       if (ldb_modify(ldb, mod) != 0) {
                fprintf(stderr, "failed to modify %s - %s\n", 
-                       msg1->dn, ldb_errstring(ldb));
+                       ldb_dn_linearize(ldb, msg1->dn), ldb_errstring(ldb));
                return -1;
        }
 
-       return count;
+       return mod->num_elements;
 }
 
 /*
   find dn in msgs[]
 */
-static struct ldb_message *msg_find(struct ldb_message **msgs, int count,
-                                   const char *dn)
+static struct ldb_message *msg_find(struct ldb_context *ldb,
+                                   struct ldb_message **msgs,
+                                   int count,
+                                   const struct ldb_dn *dn)
 {
        int i;
        for (i=0;i<count;i++) {
-               if (ldb_dn_cmp(dn, msgs[i]->dn) == 0) {
+               if (ldb_dn_compare(ldb, dn, msgs[i]->dn) == 0) {
                        return msgs[i];
                }
        }
@@ -123,11 +122,15 @@ static int merge_edits(struct ldb_context *ldb,
 
        /* do the adds and modifies */
        for (i=0;i<count2;i++) {
-               msg = msg_find(msgs1, count1, msgs2[i]->dn);
+               msg = msg_find(ldb, msgs1, count1, msgs2[i]->dn);
                if (!msg) {
+                       if (options->verbose > 0) {
+                               ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]);
+                       }
                        if (ldb_add(ldb, msgs2[i]) != 0) {
                                fprintf(stderr, "failed to add %s - %s\n",
-                                       msgs2[i]->dn, ldb_errstring(ldb));
+                                       ldb_dn_linearize(ldb, msgs2[i]->dn),
+                                       ldb_errstring(ldb));
                                return -1;
                        }
                        adds++;
@@ -140,11 +143,15 @@ static int merge_edits(struct ldb_context *ldb,
 
        /* do the deletes */
        for (i=0;i<count1;i++) {
-               msg = msg_find(msgs2, count2, msgs1[i]->dn);
+               msg = msg_find(ldb, msgs2, count2, msgs1[i]->dn);
                if (!msg) {
+                       if (options->verbose > 0) {
+                               ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]);
+                       }
                        if (ldb_delete(ldb, msgs1[i]->dn) != 0) {
                                fprintf(stderr, "failed to delete %s - %s\n",
-                                       msgs1[i]->dn, ldb_errstring(ldb));
+                                       ldb_dn_linearize(ldb, msgs1[i]->dn),
+                                       ldb_errstring(ldb));
                                return -1;
                        }
                        deletes++;
@@ -171,9 +178,9 @@ static int save_ldif(struct ldb_context *ldb,
                fprintf(f, "# record %d\n", i+1);
 
                ldif.changetype = LDB_CHANGETYPE_NONE;
-               ldif.msg = *msgs[i];
+               ldif.msg = msgs[i];
 
-               ldif_write_file(ldb, f, &ldif);
+               ldb_ldif_write_file(ldb, f, &ldif);
        }
 
        return 0;
@@ -243,13 +250,13 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun
                return -1;
        }
 
-       while ((ldif = ldif_read_file(ldb, f))) {
-               msgs2 = ldb_realloc_p(ldb, msgs2, struct ldb_message *, count2+1);
+       while ((ldif = ldb_ldif_read_file(ldb, f))) {
+               msgs2 = talloc_realloc(ldb, msgs2, struct ldb_message *, count2+1);
                if (!msgs2) {
                        fprintf(stderr, "out of memory");
                        return -1;
                }
-               msgs2[count2++] = &ldif->msg;
+               msgs2[count2++] = ldif->msg;
        }
 
        fclose(f);
@@ -267,121 +274,64 @@ static void usage(void)
        printf("  -b basedn        choose baseDN\n");
        printf("  -a               edit all records (expression 'objectclass=*')\n");
        printf("  -e editor        choose editor (or $VISUAL or $EDITOR)\n");
+       printf("  -v               verbose mode)\n");
        exit(1);
 }
 
- int main(int argc, char * const argv[])
+ int main(int argc, const char **argv)
 {
        struct ldb_context *ldb;
-       struct ldb_message **msgs;
+       struct ldb_result *result = NULL;
+       struct ldb_dn *basedn = NULL;
        int ret;
-       const char *expression = NULL;
-       const char *ldb_url;
-       const char *basedn = NULL;
-       int opt;
-       enum ldb_scope scope = LDB_SCOPE_SUBTREE;
-       const char *editor;
+       const char *expression = "(|(objectclass=*)(distinguishedName=*))";
        const char * const * attrs = NULL;
 
-       ldb_url = getenv("LDB_URL");
+       ldb = ldb_init(NULL);
 
-       /* build the editor command to run -
-          use the same editor priorities as vipw */
-       editor = getenv("VISUAL");
-       if (!editor) {
-               editor = getenv("EDITOR");
-       }
-       if (!editor) {
-               editor = "vi";
-       }
+       options = ldb_cmdline_process(ldb, argc, argv, usage);
 
-       while ((opt = getopt(argc, argv, "hab:e:H:s:")) != EOF) {
-               switch (opt) {
-               case 'b':
-                       basedn = optarg;
-                       break;
-
-               case 'H':
-                       ldb_url = optarg;
-                       break;
-
-               case 's':
-                       if (strcmp(optarg, "base") == 0) {
-                               scope = LDB_SCOPE_BASE;
-                       } else if (strcmp(optarg, "sub") == 0) {
-                               scope = LDB_SCOPE_SUBTREE;
-                       } else if (strcmp(optarg, "one") == 0) {
-                               scope = LDB_SCOPE_ONELEVEL;
-                       }
-                       break;
-
-               case 'e':
-                       editor = optarg;
-                       break;
-
-               case 'a':
-                       expression = "(|(objectclass=*)(dn=*))";
-                       break;
-                       
-               case 'h':
-               default:
-                       usage();
-                       break;
-               }
+       /* the check for '=' is for compatibility with ldapsearch */
+       if (options->argc > 0 && 
+           strchr(options->argv[0], '=')) {
+               expression = options->argv[0];
+               options->argv++;
+               options->argc--;
        }
 
-       if (!ldb_url) {
-               fprintf(stderr, "You must specify a ldb URL\n\n");
-               usage();
+       if (options->argc > 0) {
+               attrs = (const char * const *)(options->argv);
        }
 
-       argc -= optind;
-       argv += optind;
-
-       if (!expression) {
-               if (argc == 0) {
-                       usage();
+       if (options->basedn != NULL) {
+               basedn = ldb_dn_explode(ldb, options->basedn);
+               if (basedn == NULL) {
+                       printf("Invalid Base DN format\n");
+                       exit(1);
                }
-               expression = argv[0];
-               argc--;
-               argv++;
-       }
-
-       if (argc > 0) {
-               attrs = (const char * const *)argv;
        }
 
-       ldb = ldb_connect(ldb_url, 0, NULL);
-
-       if (!ldb) {
-               perror("ldb_connect");
-               exit(1);
-       }
-
-       ldb_set_debug_stderr(ldb);
-
-       ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs);
-
-       if (ret == -1) {
+       ret = ldb_search(ldb, basedn, options->scope, expression, attrs, &result);
+       if (ret != LDB_SUCCESS) {
                printf("search failed - %s\n", ldb_errstring(ldb));
                exit(1);
        }
 
-       if (ret == 0) {
+       if (result->count == 0) {
                printf("no matching records - cannot edit\n");
                return 0;
        }
 
-       do_edit(ldb, msgs, ret, editor);
+       do_edit(ldb, result->msgs, result->count, options->editor);
 
-       if (ret > 0) {
-               ret = ldb_search_free(ldb, msgs);
+       if (result) {
+               ret = talloc_free(result);
                if (ret == -1) {
-                       fprintf(stderr, "search_free failed - %s\n", ldb_errstring(ldb));
+                       fprintf(stderr, "talloc_free failed\n");
                        exit(1);
                }
        }
 
-       ldb_close(ldb);
+       talloc_free(ldb);
        return 0;
 }