-/*
+/*
ldb database library
Copyright (C) Andrew Tridgell 2004
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
** under the LGPL
-
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
* Author: Andrew Tridgell
*/
-#include "ldb_includes.h"
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/time.h"
+#include "system/filesys.h"
+#include "ldb.h"
#include "tools/cmdline.h"
+#include "tools/ldbutil.h"
static struct ldb_cmdline *options;
/*
- debug routine
+ debug routine
*/
-static void ldif_write_msg(struct ldb_context *ldb,
- FILE *f,
+static void ldif_write_msg(struct ldb_context *ldb,
+ FILE *f,
enum ldb_changetype changetype,
struct ldb_message *msg)
{
modify a database record so msg1 becomes msg2
returns the number of modified elements
*/
-static int modify_record(struct ldb_context *ldb,
+static int modify_record(struct ldb_context *ldb,
struct ldb_message *msg1,
- struct ldb_message *msg2)
+ struct ldb_message *msg2,
+ struct ldb_control **req_ctrls)
{
+ int ret;
struct ldb_message *mod;
- mod = ldb_msg_diff(ldb, msg1, msg2);
- if (mod == NULL) {
+ if (ldb_msg_difference(ldb, ldb, msg1, msg2, &mod) != LDB_SUCCESS) {
fprintf(stderr, "Failed to calculate message differences\n");
return -1;
}
- if (mod->num_elements == 0) {
- return 0;
+ ret = mod->num_elements;
+ if (ret == 0) {
+ goto done;
}
if (options->verbose > 0) {
ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod);
}
- if (ldb_modify(ldb, mod) != 0) {
- fprintf(stderr, "failed to modify %s - %s\n",
+ if (ldb_modify_ctrl(ldb, mod, req_ctrls) != LDB_SUCCESS) {
+ fprintf(stderr, "failed to modify %s - %s\n",
ldb_dn_get_linearized(msg1->dn), ldb_errstring(ldb));
- return -1;
+ ret = -1;
+ goto done;
}
- return mod->num_elements;
+done:
+ talloc_free(mod);
+ return ret;
}
/*
*/
static struct ldb_message *msg_find(struct ldb_context *ldb,
struct ldb_message **msgs,
- int count,
+ unsigned int count,
struct ldb_dn *dn)
{
- int i;
+ unsigned int i;
for (i=0;i<count;i++) {
if (ldb_dn_compare(dn, msgs[i]->dn) == 0) {
return msgs[i];
merge the changes in msgs2 into the messages from msgs1
*/
static int merge_edits(struct ldb_context *ldb,
- struct ldb_message **msgs1, int count1,
- struct ldb_message **msgs2, int count2)
+ struct ldb_message **msgs1, unsigned int count1,
+ struct ldb_message **msgs2, unsigned int count2)
{
- int i;
+ unsigned int i;
struct ldb_message *msg;
- int ret = 0;
- int adds=0, modifies=0, deletes=0;
+ int ret;
+ unsigned int adds=0, modifies=0, deletes=0;
+ struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
+ if (options->controls != NULL && req_ctrls == NULL) {
+ fprintf(stderr, "parsing controls failed: %s\n", ldb_errstring(ldb));
+ return -1;
+ }
- if (ldb_transaction_start(ldb) != 0) {
+ if (ldb_transaction_start(ldb) != LDB_SUCCESS) {
fprintf(stderr, "Failed to start transaction: %s\n", ldb_errstring(ldb));
return -1;
}
if (options->verbose > 0) {
ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]);
}
- if (ldb_add(ldb, msgs2[i]) != 0) {
+ if (ldb_add_ctrl(ldb, msgs2[i], req_ctrls) != LDB_SUCCESS) {
fprintf(stderr, "failed to add %s - %s\n",
ldb_dn_get_linearized(msgs2[i]->dn),
ldb_errstring(ldb));
+ ldb_transaction_cancel(ldb);
return -1;
}
adds++;
} else {
- if (modify_record(ldb, msg, msgs2[i]) > 0) {
- modifies++;
+ ret = modify_record(ldb, msg, msgs2[i], req_ctrls);
+ if (ret != -1) {
+ modifies += (unsigned int) ret;
+ } else {
+ return -1;
}
}
}
if (options->verbose > 0) {
ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]);
}
- if (ldb_delete(ldb, msgs1[i]->dn) != 0) {
+ if (ldb_delete_ctrl(ldb, msgs1[i]->dn, req_ctrls) != LDB_SUCCESS) {
fprintf(stderr, "failed to delete %s - %s\n",
ldb_dn_get_linearized(msgs1[i]->dn),
ldb_errstring(ldb));
+ ldb_transaction_cancel(ldb);
return -1;
}
deletes++;
}
}
- if (ldb_transaction_commit(ldb) != 0) {
+ if (ldb_transaction_commit(ldb) != LDB_SUCCESS) {
fprintf(stderr, "Failed to commit transaction: %s\n", ldb_errstring(ldb));
return -1;
}
- printf("# %d adds %d modifies %d deletes\n", adds, modifies, deletes);
+ printf("# %u adds %u modifies %u deletes\n", adds, modifies, deletes);
- return ret;
+ return 0;
}
/*
save a set of messages as ldif to a file
*/
-static int save_ldif(struct ldb_context *ldb,
- FILE *f, struct ldb_message **msgs, int count)
+static int save_ldif(struct ldb_context *ldb,
+ FILE *f, struct ldb_message **msgs, unsigned int count)
{
- int i;
+ unsigned int i;
- fprintf(f, "# editing %d records\n", count);
+ fprintf(f, "# editing %u records\n", count);
for (i=0;i<count;i++) {
struct ldb_ldif ldif;
- fprintf(f, "# record %d\n", i+1);
+ fprintf(f, "# record %u\n", i+1);
ldif.changetype = LDB_CHANGETYPE_NONE;
ldif.msg = msgs[i];
/*
edit the ldb search results in msgs using the user selected editor
*/
-static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int count1,
- const char *editor)
+static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1,
+ unsigned int count1, const char *editor)
{
int fd, ret;
FILE *f;
char *cmd;
struct ldb_ldif *ldif;
struct ldb_message **msgs2 = NULL;
- int count2 = 0;
+ unsigned int count2 = 0;
/* write out the original set of messages to a temporary
file */
msgs2[count2++] = ldif->msg;
}
+ /* the feof() test works here, even for the last line of the
+ * file, as we parse ldif files character by character, and
+ * feof() is only true if we have failed to read a character
+ * from the file. So if the last line is bad, we don't get
+ * feof() set, so we know the record was bad. Only if we
+ * attempt to go to the next record will we get feof() and
+ * thus consider that the ldif has ended without errors
+ */
+ if (!feof(f)) {
+ fprintf(stderr, "Error parsing ldif - aborting\n");
+ fclose(f);
+ unlink(file_template);
+ return -1;
+ }
+
fclose(f);
unlink(file_template);
return merge_edits(ldb, msgs1, count1, msgs2, count2);
}
-static void usage(void)
+static void usage(struct ldb_context *ldb)
{
printf("Usage: ldbedit <options> <expression> <attributes ...>\n");
- printf("Options:\n");
- printf(" -H ldb_url choose the database (or $LDB_URL)\n");
- printf(" -s base|sub|one choose search scope\n");
- 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);
+ ldb_cmdline_help(ldb, "ldbedit", stdout);
+ exit(LDB_ERR_OPERATIONS_ERROR);
}
int main(int argc, const char **argv)
int ret;
const char *expression = "(|(objectClass=*)(distinguishedName=*))";
const char * const * attrs = NULL;
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
+ struct ldb_control **req_ctrls;
- ldb = ldb_init(NULL, NULL);
+ ldb = ldb_init(mem_ctx, NULL);
+ if (ldb == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
options = ldb_cmdline_process(ldb, argc, argv, usage);
/* the check for '=' is for compatibility with ldapsearch */
- if (options->argc > 0 &&
+ if (options->argc > 0 &&
strchr(options->argv[0], '=')) {
expression = options->argv[0];
options->argv++;
if (options->basedn != NULL) {
basedn = ldb_dn_new(ldb, ldb, options->basedn);
- if ( ! ldb_dn_validate(basedn)) {
- printf("Invalid Base DN format\n");
- exit(1);
+ if (basedn == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
}
- ret = ldb_search(ldb, ldb, &result, basedn, options->scope, attrs, "%s", expression);
+ req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
+ if (options->controls != NULL && req_ctrls== NULL) {
+ printf("parsing controls failed: %s\n", ldb_errstring(ldb));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_search_ctrl(ldb, ldb, &result, basedn, options->scope, attrs, req_ctrls, "%s", expression);
if (ret != LDB_SUCCESS) {
printf("search failed - %s\n", ldb_errstring(ldb));
- exit(1);
+ return ret;
}
if (result->count == 0) {
printf("no matching records - cannot edit\n");
- return 0;
+ talloc_free(mem_ctx);
+ return LDB_SUCCESS;
}
- do_edit(ldb, result->msgs, result->count, options->editor);
+ ret = do_edit(ldb, result->msgs, result->count, options->editor);
- if (result) {
- ret = talloc_free(result);
- if (ret == -1) {
- fprintf(stderr, "talloc_free failed\n");
- exit(1);
- }
- }
+ talloc_free(mem_ctx);
- talloc_free(ldb);
- return 0;
+ return ret == 0 ? LDB_SUCCESS : LDB_ERR_OPERATIONS_ERROR;
}