diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 162 | ||||
-rwxr-xr-x | source4/script/tests/test_ejs.sh | 4 | ||||
-rwxr-xr-x | testprogs/ejs/ldb.js | 78 |
3 files changed, 209 insertions, 35 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 6d3d42c23a..c7c9aa7cfe 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -44,6 +44,24 @@ struct partition_private_data { struct partition **partitions; }; +struct ldb_module *make_module_for_next_request(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + struct ldb_module *module) +{ + struct ldb_module *current; + static const struct ldb_module_ops ops; /* zero */ + current = talloc_zero(mem_ctx, struct ldb_module); + if (current == NULL) { + return module; + } + + current->ldb = ldb; + current->ops = &ops; + current->prev = NULL; + current->next = module; + return current; +} + struct ldb_module *find_backend(struct ldb_module *module, struct ldb_request *req, const struct ldb_dn *dn) { int i; @@ -56,18 +74,7 @@ struct ldb_module *find_backend(struct ldb_module *module, struct ldb_request *r if (ldb_dn_compare_base(module->ldb, data->partitions[i]->dn, dn) == 0) { - struct ldb_module *current; - static const struct ldb_module_ops ops; /* zero */ - current = talloc_zero(req, struct ldb_module); - if (current == NULL) { - return module; - } - - current->ldb = module->ldb; - current->ops = &ops; - current->prev = module; - current->next = data->partitions[i]->module; - return current; + return make_module_for_next_request(req, module->ldb, data->partitions[i]->module); } } @@ -137,27 +144,128 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(backend, req); } -#if 0 -/* We should do this over the entire list of partitions */ - /* start a transaction */ static int partition_start_trans(struct ldb_module *module) { - return ldb_next_start_trans(module); + int i, ret; + struct partition_private_data *data = talloc_get_type(module->private_data, + struct partition_private_data); + /* Look at base DN */ + /* Figure out which partition it is under */ + /* Skip the lot if 'data' isn't here yet (initialistion) */ + ret = ldb_next_start_trans(module); + if (ret != LDB_SUCCESS) { + return ret; + } + + for (i=0; data && data->partitions && data->partitions[i]; i++) { + struct ldb_module *next = make_module_for_next_request(module, module->ldb, data->partitions[i]->module); + + ret = ldb_next_start_trans(next); + talloc_free(next); + if (ret != LDB_SUCCESS) { + /* Back it out, if it fails on one */ + for (i--; i >= 0; i--) { + next = make_module_for_next_request(module, module->ldb, data->partitions[i]->module); + ldb_next_del_trans(next); + talloc_free(next); + } + return ret; + } + } + return LDB_SUCCESS; } /* end a transaction */ static int partition_end_trans(struct ldb_module *module) { - return ldb_next_end_trans(module); + int i, ret, ret2 = LDB_SUCCESS; + struct partition_private_data *data = talloc_get_type(module->private_data, + struct partition_private_data); + ret = ldb_next_end_trans(module); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* Look at base DN */ + /* Figure out which partition it is under */ + /* Skip the lot if 'data' isn't here yet (initialistion) */ + for (i=0; data && data->partitions && data->partitions[i]; i++) { + struct ldb_module *next = make_module_for_next_request(module, module->ldb, data->partitions[i]->module); + + ret = ldb_next_end_trans(next); + talloc_free(next); + if (ret != LDB_SUCCESS) { + ret2 = ret; + } + } + + if (ret != LDB_SUCCESS) { + /* Back it out, if it fails on one */ + for (i=0; data && data->partitions && data->partitions[i]; i++) { + struct ldb_module *next = make_module_for_next_request(module, module->ldb, data->partitions[i]->module); + ldb_next_del_trans(next); + talloc_free(next); + } + } + return ret; } /* delete a transaction */ static int partition_del_trans(struct ldb_module *module) { - return ldb_next_del_trans(module); + int i, ret, ret2 = LDB_SUCCESS; + struct partition_private_data *data = talloc_get_type(module->private_data, + struct partition_private_data); + /* Look at base DN */ + /* Figure out which partition it is under */ + /* Skip the lot if 'data' isn't here yet (initialistion) */ + for (i=0; data && data->partitions && data->partitions[i]; i++) { + struct ldb_module *next = make_module_for_next_request(module, module->ldb, data->partitions[i]->module); + + ret = ldb_next_del_trans(next); + talloc_free(next); + if (ret != LDB_SUCCESS) { + ret2 = ret; + } + } + return ret2; +} + +static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req) +{ + int i, ret; + uint64_t seq_number = 0; + struct partition_private_data *data = talloc_get_type(module->private_data, + struct partition_private_data); + /* Look at base DN */ + /* Figure out which partition it is under */ + /* Skip the lot if 'data' isn't here yet (initialistion) */ + for (i=0; data && data->partitions && data->partitions[i]; i++) { + struct ldb_module *next = make_module_for_next_request(req, module->ldb, data->partitions[i]->module); + + ret = ldb_next_request(next, req); + talloc_free(next); + if (ret != LDB_SUCCESS) { + return ret; + } + seq_number = seq_number + req->op.seq_num.seq_num; + } + req->op.seq_num.seq_num = seq_number; + return LDB_SUCCESS; +} + +static int sort_compare(void *void1, + void *void2, void *opaque) +{ + struct ldb_context *ldb = talloc_get_type(opaque, struct ldb_context); + struct partition **pp1 = void1; + struct partition **pp2 = void2; + struct partition *partition1 = talloc_get_type(*pp1, struct partition); + struct partition *partition2 = talloc_get_type(*pp2, struct partition); + + return -ldb_dn_compare(ldb, partition1->dn, partition2->dn); } -#endif static int partition_init(struct ldb_module *module) { @@ -213,8 +321,6 @@ static int partition_init(struct ldb_module *module) return LDB_ERR_OPERATIONS_ERROR; } for (i=0; i < partition_attributes->num_values; i++) { - struct ldb_request *req; - char *base = talloc_strdup(data->partitions, (char *)partition_attributes->values[i].data); char *p = strchr(base, ':'); if (!p) { @@ -250,7 +356,15 @@ static int partition_init(struct ldb_module *module) if (ret != LDB_SUCCESS) { return ret; } - + } + data->partitions[i] = NULL; + + /* sort these into order */ + ldb_qsort(data->partitions, partition_attributes->num_values, sizeof(*data->partitions), + module->ldb, sort_compare); + + for (i=0; data->partitions[i]; i++) { + struct ldb_request *req; req = talloc_zero(mem_ctx, struct ldb_request); if (req == NULL) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "partition: Out of memory!\n"); @@ -267,7 +381,6 @@ static int partition_init(struct ldb_module *module) } talloc_free(req); } - data->partitions[i] = NULL; module->private_data = data; talloc_steal(module, data); @@ -284,11 +397,10 @@ static const struct ldb_module_ops partition_ops = { .modify = partition_modify, .del = partition_delete, .rename = partition_rename, -#if 0 .start_transaction = partition_start_trans, .end_transaction = partition_end_trans, .del_transaction = partition_del_trans, -#endif + .sequence_number = partition_sequence_number }; int ldb_partition_init(void) diff --git a/source4/script/tests/test_ejs.sh b/source4/script/tests/test_ejs.sh index 6df202122a..b4370b0384 100755 --- a/source4/script/tests/test_ejs.sh +++ b/source4/script/tests/test_ejs.sh @@ -20,12 +20,14 @@ SCRIPTDIR=../testprogs/ejs PATH=bin:$PATH export PATH -for f in samr.js echo.js ldb.js; do +for f in samr.js echo.js; do testit "$f" $SCRIPTDIR/$f $CONFIGURATION ncalrpc: -U$USERNAME%$PASSWORD || failed=`expr $failed + 1` done testit "ejsnet.js" $SCRIPTDIR/ejsnet.js $CONFIGURATION -U$USERNAME%$PASSWORD $DOMAIN ejstestuser || failed=`expr $failed + 1` +testit "ldb.js" $SCRIPTDIR/ldb.js `pwd` $CONFIGURATION || failed=`expr $failed + 1` + testit "winreg" scripting/bin/winreg $CONFIGURATION ncalrpc: 'HKLM' -U$USERNAME%$PASSWORD || failed=`expr $failed + 1` testok $0 $failed diff --git a/testprogs/ejs/ldb.js b/testprogs/ejs/ldb.js index c681ee9ebb..fe067f638a 100755 --- a/testprogs/ejs/ldb.js +++ b/testprogs/ejs/ldb.js @@ -7,6 +7,23 @@ exec smbscript "$0" ${1+"$@"} var ldb = ldb_init(); var sys; +var options = GetOptions(ARGV, + "POPT_AUTOHELP", + "POPT_COMMON_SAMBA"); +if (options == undefined) { + println("Failed to parse options"); + return -1; +} + +libinclude("base.js"); + +if (options.ARGV.length != 1) { + println("Usage: ldap.js <HOST>"); + return -1; +} + +prefix = options.ARGV[0]; + function basic_tests(ldb) { println("Running basic tests"); @@ -65,7 +82,16 @@ function setup_modules(ldb) { ok = ldb.add(" dn: @MODULES -@LIST: operational,objectguid,rdn_name +@LIST: rootdse,operational,objectguid,rdn_name,partition + +dn: cn=ROOTDSE +defaultNamingContext: cn=Test + +dn: @PARTITION +partition: cn=SideTest:" + prefix + "testside.ldb +partition: cn=Sub,cn=Test:" + prefix + "testsub.ldb +partition: cn=Test:" + prefix + "testpartition.ldb +partition: cn=Sub,cn=Sub,cn=Test:" + prefix + "testsubsub.ldb "); } @@ -80,7 +106,10 @@ dn: cn=x8,cn=test objectClass: foo x: 8 "); - assert(ok); + if (!ok) { + println("Failed to add: " + ldb.errstring()); + assert(ok); + } ok = ldb.add(" dn: cn=x9,cn=test @@ -88,9 +117,12 @@ objectClass: foo x: 9 cn: X9 "); - assert(ok); + if (!ok) { + println("Failed to add: " + ldb.errstring()); + assert(ok); + } - var res = ldb.search("x=8", NULL, ldb.SCOPE_DEFAULT); + var res = ldb.search("x=8", "cn=test", ldb.SCOPE_DEFAULT); assert(res[0].objectGUID != undefined); assert(res[0].createTimestamp == undefined); assert(res[0].whenCreated != undefined); @@ -98,7 +130,7 @@ cn: X9 assert(res[0].cn == "x8"); var attrs = new Array("*", "createTimestamp"); - var res2 = ldb.search("x=9", NULL, ldb.SCOPE_DEFAULT, attrs); + var res2 = ldb.search("x=9", "cn=test", ldb.SCOPE_DEFAULT, attrs); assert(res2[0].objectGUID != undefined); assert(res2[0].createTimestamp != undefined); assert(res2[0].whenCreated != undefined); @@ -107,22 +139,50 @@ cn: X9 assert(res[0].objectGUID != res2[0].objectGUID); + var attrs = new Array("*"); + var res3 = ldb.search("", "", ldb.SCOPE_BASE, attrs); + assert(res3[0].cn == undefined); + assert(res3[0].distinguishedName == undefined); + assert(res3[0].name == undefined); + assert(res3[0].currentTime != undefined); + assert(res3[0].highestCommittedUSN != undefined); + println(res3[0].namingContexts[0]); + println(res3[0].namingContexts[1]); + println(res3[0].namingContexts[2]); + println(res3[0].namingContexts[3]); + + assert(res3[0].namingContexts[0] == "cn=Test"); + assert(res3[0].namingContexts[1] == "cn=SideTest"); + assert(res3[0].namingContexts[2] == "cn=Sub,cn=Test"); + assert(res3[0].namingContexts[3] == "cn=Sub,cn=Sub,cn=Test"); + var usn = res3[0].highestCommittedUSN; + } sys = sys_init(); var dbfile = "test.ldb"; -sys.unlink(dbfile); -var ok = ldb.connect("tdb://" + dbfile); + +sys.unlink(prefix + dbfile); +sys.unlink(prefix + "testpartition.ldb"); +sys.unlink(prefix + "testsub.ldb"); +sys.unlink(prefix + "testsubsub.ldb"); +sys.unlink(prefix + "testside.ldb"); + +var ok = ldb.connect("tdb://" + prefix + dbfile); assert(ok); basic_tests(ldb); setup_modules(ldb); ldb = ldb_init(); -var ok = ldb.connect("tdb://" + dbfile); +var ok = ldb.connect("tdb://" + prefix + dbfile); assert(ok); modules_test(ldb); -sys.unlink(dbfile); +sys.unlink(prefix + dbfile); +sys.unlink(prefix + "testpartition.ldb"); +sys.unlink(prefix + "testsub.ldb"); +sys.unlink(prefix + "testsubsub.ldb"); +sys.unlink(prefix + "testside.ldb"); return 0; |