diff options
author | Andrew Bartlett <abartlet@samba.org> | 2012-04-04 15:17:32 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2012-04-10 11:14:43 +0200 |
commit | e17d12c23b2f56d8d29f7ee43148be85d28154c6 (patch) | |
tree | 40f233b97d294c70536f1e597de4b130ecd09807 | |
parent | 501d6d3dd4e3045e069bb2f7a52cf842dd1dfa67 (diff) | |
download | samba-e17d12c23b2f56d8d29f7ee43148be85d28154c6.tar.gz samba-e17d12c23b2f56d8d29f7ee43148be85d28154c6.tar.bz2 samba-e17d12c23b2f56d8d29f7ee43148be85d28154c6.zip |
ldb-tools: Place the whole of an ldif file in a transaction
This ensures that when operating ldbadd and ldbmodify against local
ldb files, either an ldif file succeeds or fails as a whole.
Also tests to verify that this is working correctly, and an ABI bump
due to the extra (private, but exported to ldb* tools) symbol and
behaviour change.
Andrew Bartlett
Autobuild-User: Andrew Bartlett <abartlet@samba.org>
Autobuild-Date: Tue Apr 10 11:14:43 CEST 2012 on sn-devel-104
-rw-r--r-- | lib/ldb/tests/test-dup-2.ldif | 6 | ||||
-rw-r--r-- | lib/ldb/tests/test-dup.ldif | 13 | ||||
-rwxr-xr-x | lib/ldb/tests/test-generic.sh | 21 | ||||
-rw-r--r-- | lib/ldb/tests/test-modify-unmet-2.ldif | 7 | ||||
-rw-r--r-- | lib/ldb/tests/test-modify-unmet.ldif | 15 | ||||
-rw-r--r-- | lib/ldb/tools/ldbadd.c | 45 | ||||
-rw-r--r-- | lib/ldb/tools/ldbmodify.c | 45 |
7 files changed, 136 insertions, 16 deletions
diff --git a/lib/ldb/tests/test-dup-2.ldif b/lib/ldb/tests/test-dup-2.ldif new file mode 100644 index 0000000000..a4261012ad --- /dev/null +++ b/lib/ldb/tests/test-dup-2.ldif @@ -0,0 +1,6 @@ +dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST +objectclass: OpenLDAPperson +cn: Sentinel +sn: USER +uid: USER, Sentinel + diff --git a/lib/ldb/tests/test-dup.ldif b/lib/ldb/tests/test-dup.ldif new file mode 100644 index 0000000000..b35420befb --- /dev/null +++ b/lib/ldb/tests/test-dup.ldif @@ -0,0 +1,13 @@ +dn: cn=Fred Bassett,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST +objectclass: OpenLDAPperson +cn: Fred Bassett +sn: Bassett +uid: Bassett, Fred + +dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST +objectclass: OpenLDAPperson +cn: Sentinel +sn: USER +uid: USER, Sentinel + + diff --git a/lib/ldb/tests/test-generic.sh b/lib/ldb/tests/test-generic.sh index 9c45ed9614..69f901bd7c 100755 --- a/lib/ldb/tests/test-generic.sh +++ b/lib/ldb/tests/test-generic.sh @@ -16,9 +16,30 @@ $VALGRIND ldbadd $LDBDIR/tests/test.ldif 2> /dev/null && { exit 1 } +echo "Adding LDIF with one already-existing user again - should fail" +$VALGRIND ldbadd $LDBDIR/tests/test-dup.ldif 2> /dev/null && { + echo "Should have failed to add again - gave $?" + exit 1 +} + +echo "Adding again - should succeed (as previous failed)" +$VALGRIND ldbadd $LDBDIR/tests/test-dup-2.ldif || exit 1 + echo "Modifying elements" $VALGRIND ldbmodify $LDBDIR/tests/test-modify.ldif || exit 1 +echo "Modify LDIF with one un-met constraint - should fail" +$VALGRIND ldbadd $LDBDIR/tests/test-modify-unmet.ldif 2> /dev/null && { + echo "Should have failed to modify - gave $?" + exit 1 +} + +echo "Modify LDIF with after failure of un-met constraint - should also fail" +$VALGRIND ldbadd $LDBDIR/tests/test-modify-unmet-2.ldif 2> /dev/null && { + echo "Should have failed to modify - gave $?" + exit 1 +} + echo "Showing modified record" $VALGRIND ldbsearch '(uid=uham)' || exit 1 diff --git a/lib/ldb/tests/test-modify-unmet-2.ldif b/lib/ldb/tests/test-modify-unmet-2.ldif new file mode 100644 index 0000000000..8760938282 --- /dev/null +++ b/lib/ldb/tests/test-modify-unmet-2.ldif @@ -0,0 +1,7 @@ +dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michiga + n,c=TEST +changetype: modify +delete: drink +drink: water + + diff --git a/lib/ldb/tests/test-modify-unmet.ldif b/lib/ldb/tests/test-modify-unmet.ldif new file mode 100644 index 0000000000..6a46cdf611 --- /dev/null +++ b/lib/ldb/tests/test-modify-unmet.ldif @@ -0,0 +1,15 @@ +dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michiga + n,c=TEST +changetype: modify +add: drink +drink: water + +dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michiga + n,c=TEST +changetype: modify +add: sn +sn: TEST +- +delete: sn +sn: USER2 + diff --git a/lib/ldb/tools/ldbadd.c b/lib/ldb/tools/ldbadd.c index 47fd261841..d0d5ec0ec4 100644 --- a/lib/ldb/tools/ldbadd.c +++ b/lib/ldb/tools/ldbadd.c @@ -34,8 +34,8 @@ #include "ldb.h" #include "tools/cmdline.h" #include "ldbutil.h" +#include "include/ldb_private.h" -static unsigned int failures; static struct ldb_cmdline *options; static void usage(struct ldb_context *ldb) @@ -55,13 +55,23 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) struct ldb_ldif *ldif; int fun_ret = LDB_SUCCESS, ret; struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); + struct ldif_read_file_state state = { + .f = f + }; + if (options->controls != NULL && req_ctrls== NULL) { printf("parsing controls failed: %s\n", ldb_errstring(ldb)); return LDB_ERR_OPERATIONS_ERROR; } + fun_ret = ldb_transaction_start(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction start\n", + ldb_errstring(ldb)); + return fun_ret; + } - while ((ldif = ldb_ldif_read_file(ldb, f))) { + while ((ldif = ldb_ldif_read_file_state(ldb, &state))) { if (ldif->changetype != LDB_CHANGETYPE_ADD && ldif->changetype != LDB_CHANGETYPE_NONE) { fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); @@ -73,7 +83,6 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) fprintf(stderr, "ERR: Message canonicalize failed - %s\n", ldb_strerror(ret)); - failures++; fun_ret = ret; ldb_ldif_read_free(ldb, ldif); continue; @@ -81,10 +90,10 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls); if (ret != LDB_SUCCESS) { - fprintf(stderr, "ERR: %s : \"%s\" on DN %s\n", + fprintf(stderr, "ERR: %s : \"%s\" on DN %s at block before line %llu\n", ldb_strerror(ret), ldb_errstring(ldb), - ldb_dn_get_linearized(ldif->msg->dn)); - failures++; + ldb_dn_get_linearized(ldif->msg->dn), + (unsigned long long)state.line_no); fun_ret = ret; } else { (*count)++; @@ -93,6 +102,24 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) } } ldb_ldif_read_free(ldb, ldif); + if (ret) { + break; + } + } + + if (fun_ret == LDB_SUCCESS && !feof(f)) { + fprintf(stderr, "Failed to parse ldif\n"); + fun_ret = LDB_ERR_OPERATIONS_ERROR; + } + + if (fun_ret == LDB_SUCCESS) { + fun_ret = ldb_transaction_commit(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction commit\n", + ldb_errstring(ldb)); + } + } else { + ldb_transaction_cancel(ldb); } return fun_ret; @@ -148,7 +175,11 @@ int main(int argc, const char **argv) talloc_free(mem_ctx); - printf("Added %u records with %u failures\n", count, failures); + if (ret) { + printf("Add failed after processing %u records\n", count); + } else { + printf("Added %u records successfully\n", count); + } return ret; } diff --git a/lib/ldb/tools/ldbmodify.c b/lib/ldb/tools/ldbmodify.c index 2ca7b62b2c..3a9a2657ce 100644 --- a/lib/ldb/tools/ldbmodify.c +++ b/lib/ldb/tools/ldbmodify.c @@ -34,8 +34,8 @@ #include "ldb.h" #include "tools/cmdline.h" #include "ldbutil.h" +#include "include/ldb_private.h" -static unsigned int failures; static struct ldb_cmdline *options; static void usage(struct ldb_context *ldb) @@ -54,13 +54,23 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) struct ldb_ldif *ldif; int fun_ret = LDB_SUCCESS, ret; struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); + struct ldif_read_file_state state = { + .f = f + }; if (options->controls != NULL && req_ctrls== NULL) { printf("parsing controls failed: %s\n", ldb_errstring(ldb)); exit(LDB_ERR_OPERATIONS_ERROR); } - while ((ldif = ldb_ldif_read_file(ldb, f))) { + fun_ret = ldb_transaction_start(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction start\n", + ldb_errstring(ldb)); + return fun_ret; + } + + while ((ldif = ldb_ldif_read_file_state(ldb, &state))) { struct ldb_dn *olddn; bool deleteoldrdn = false; struct ldb_dn *newdn; @@ -96,10 +106,10 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) if (errstr == NULL) { errstr = ldb_errstring(ldb); } - fprintf(stderr, "ERR: (%s) \"%s\" on DN %s\n", + fprintf(stderr, "ERR: (%s) \"%s\" on DN %s at block before line %llu\n", ldb_strerror(ret), - errstr, ldb_dn_get_linearized(ldif->msg->dn)); - failures++; + errstr, ldb_dn_get_linearized(ldif->msg->dn), + (unsigned long long)state.line_no); fun_ret = ret; } else { (*count)++; @@ -108,13 +118,26 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) } } ldb_ldif_read_free(ldb, ldif); + if (ret) { + break; + } } - - if (!feof(f)) { + + if (fun_ret == LDB_SUCCESS && !feof(f)) { fprintf(stderr, "Failed to parse ldif\n"); fun_ret = LDB_ERR_OPERATIONS_ERROR; } + if (fun_ret == LDB_SUCCESS) { + fun_ret = ldb_transaction_commit(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction commit\n", + ldb_errstring(ldb)); + } + } else { + ldb_transaction_cancel(ldb); + } + return fun_ret; } @@ -150,7 +173,11 @@ int main(int argc, const char **argv) talloc_free(mem_ctx); - printf("Modified %u records with %u failures\n", count, failures); - + if (ret) { + printf("Modify failed after processing %u records\n", count); + } else { + printf("Modified %u records successfully\n", count); + } + return ret; } |