diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 162 | ||||
-rwxr-xr-x | source4/script/tests/test_ejs.sh | 4 |
2 files changed, 140 insertions, 26 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 |