From 14c9070322d089dd96b389e8087c4f4bf1a6c7cc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 22 Sep 2009 21:11:41 -0700 Subject: s4-ldb: merged with master --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 187 ++++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 78 deletions(-) (limited to 'source4/lib/ldb/ldb_tdb/ldb_tdb.c') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 55acb6132d..2348c0dcce 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -103,6 +103,53 @@ int ltdb_unlock_read(struct ldb_module *module) return 0; } +struct ldb_val ldb_dn_get_casefold_as_ldb_val(struct ldb_dn *dn) { + struct ldb_val val; + const char *casefold_dn = ldb_dn_get_casefold(dn); + val.data = (uint8_t *)((uintptr_t)casefold_dn); + val.length = strlen(casefold_dn); + return val; +} + +struct ldb_val ldb_dn_alloc_casefold_as_ldb_val(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { + struct ldb_val val; + const char *casefold_dn = ldb_dn_alloc_casefold(mem_ctx, dn); + val.data = (uint8_t *)((uintptr_t)casefold_dn); + val.length = strlen(casefold_dn); + return val; +} + +/* + form a TDB_DATA for a record key + caller frees + + This version takes the casefolded string form of the DN as an ldb_val +*/ +struct TDB_DATA ltdb_key_from_casefold_dn(TALLOC_CTX *mem_ctx, + struct ldb_val dn_folded) +{ + TDB_DATA key; + + key.dsize = dn_folded.length + 4; + key.dptr = talloc_size(mem_ctx, key.dsize); + if (!key.dptr) { + goto failed; + } + + memcpy(key.dptr, "DN=", 3); + memcpy(&key.dptr[3], dn_folded.data, key.dsize - 4); + + key.dptr[key.dsize - 1] = '\0'; + + return key; + +failed: + errno = ENOMEM; + key.dptr = NULL; + key.dsize = 0; + return key; +} + /* form a TDB_DATA for a record key @@ -111,12 +158,10 @@ int ltdb_unlock_read(struct ldb_module *module) note that the key for a record can depend on whether the dn refers to a case sensitive index record or not */ -struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn) +struct TDB_DATA ltdb_key(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { - struct ldb_context *ldb = ldb_module_get_ctx(module); TDB_DATA key; - char *key_str = NULL; - const char *dn_folded = NULL; + struct ldb_val dn_folded; /* most DNs are case insensitive. The exception is index DNs for @@ -130,31 +175,15 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn) the indexing code handles the rest */ - dn_folded = ldb_dn_get_casefold(dn); - if (!dn_folded) { - goto failed; - } - - key_str = talloc_strdup(ldb, "DN="); - if (!key_str) { - goto failed; - } - - key_str = talloc_strdup_append_buffer(key_str, dn_folded); - if (!key_str) { - goto failed; + dn_folded = ldb_dn_get_casefold_as_ldb_val(dn); + if (!dn_folded.data) { + errno = EINVAL; + key.dptr = NULL; + key.dsize = 0; + return key; } - key.dptr = (uint8_t *)key_str; - key.dsize = strlen(key_str) + 1; - - return key; - -failed: - errno = ENOMEM; - key.dptr = NULL; - key.dsize = 0; - return key; + return ltdb_key_from_casefold_dn(mem_ctx, dn_folded); } /* @@ -213,14 +242,15 @@ static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn) /* store a record into the db */ -int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs) +int ltdb_store(struct ldb_module *module, TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, int flgs) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); TDB_DATA tdb_key, tdb_data; int ret; - tdb_key = ltdb_key(module, msg->dn); + tdb_key = ltdb_key(mem_ctx, msg->dn); if (!tdb_key.dptr) { return LDB_ERR_OTHER; } @@ -237,7 +267,7 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg goto done; } - ret = ltdb_index_add(module, msg); + ret = ltdb_index_add(module, mem_ctx, msg); if (ret != LDB_SUCCESS) { tdb_delete(ltdb->tdb, tdb_key); } @@ -251,6 +281,7 @@ done: static int ltdb_add_internal(struct ldb_module *module, + TALLOC_CTX *mem_ctx, const struct ldb_message *msg) { struct ldb_context *ldb = ldb_module_get_ctx(module); @@ -283,7 +314,7 @@ static int ltdb_add_internal(struct ldb_module *module, } } - ret = ltdb_store(module, msg, TDB_INSERT); + ret = ltdb_store(module, mem_ctx, msg, TDB_INSERT); if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { ldb_asprintf_errstring(ldb, @@ -293,7 +324,7 @@ static int ltdb_add_internal(struct ldb_module *module, } if (ret == LDB_SUCCESS) { - ret = ltdb_index_one(module, msg, 1); + ret = ltdb_index_one(module, mem_ctx, msg, 1); if (ret != LDB_SUCCESS) { return ret; } @@ -318,7 +349,7 @@ static int ltdb_add(struct ltdb_context *ctx) ldb_request_set_state(req, LDB_ASYNC_PENDING); - tret = ltdb_add_internal(module, req->op.add.message); + tret = ltdb_add_internal(module, req, req->op.add.message); if (tret != LDB_SUCCESS) { return tret; } @@ -330,14 +361,14 @@ static int ltdb_add(struct ltdb_context *ctx) delete a record from the database, not updating indexes (used for deleting index records) */ -int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn) +int ltdb_delete_noindex(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); TDB_DATA tdb_key; int ret; - tdb_key = ltdb_key(module, dn); + tdb_key = ltdb_key(mem_ctx, dn); if (!tdb_key.dptr) { return LDB_ERR_OTHER; } @@ -352,12 +383,12 @@ int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn) return ret; } -static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn) +static int ltdb_delete_internal(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { struct ldb_message *msg; int ret; - msg = talloc(module, struct ldb_message); + msg = talloc(mem_ctx, struct ldb_message); if (msg == NULL) { return LDB_ERR_OPERATIONS_ERROR; } @@ -370,19 +401,19 @@ static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn) goto done; } - ret = ltdb_delete_noindex(module, dn); + ret = ltdb_delete_noindex(module, msg, dn); if (ret != LDB_SUCCESS) { goto done; } /* remove one level attribute */ - ret = ltdb_index_one(module, msg, 0); + ret = ltdb_index_one(module, msg, msg, 0); if (ret != LDB_SUCCESS) { goto done; } /* remove any indexed attributes */ - ret = ltdb_index_del(module, msg); + ret = ltdb_index_del(module, msg, msg); if (ret != LDB_SUCCESS) { goto done; } @@ -412,7 +443,7 @@ static int ltdb_delete(struct ltdb_context *ctx) return LDB_ERR_OPERATIONS_ERROR; } - tret = ltdb_delete_internal(module, req->op.del.dn); + tret = ltdb_delete_internal(module, req, req->op.del.dn); if (tret != LDB_SUCCESS) { return tret; } @@ -489,21 +520,14 @@ static int msg_add_element(struct ldb_context *ldb, delete all elements having a specified attribute name */ static int msg_delete_attribute(struct ldb_module *module, - struct ldb_context *ldb, struct ldb_message *msg, const char *name) { - const char *dn; unsigned int i, j; - dn = ldb_dn_get_linearized(msg->dn); - if (dn == NULL) { - return -1; - } - for (i=0;inum_elements;i++) { if (ldb_attr_cmp(msg->elements[i].name, name) == 0) { for (j=0;jelements[i].num_values;j++) { - ltdb_index_del_value(module, dn, + ltdb_index_del_value(module, msg, msg->dn, &msg->elements[i], j); } talloc_free(msg->elements[i].values); @@ -550,7 +574,7 @@ static int msg_delete_element(struct ldb_module *module, a = ldb_schema_attribute_by_name(ldb, el->name); for (i=0;inum_values;i++) { - if (a->syntax->comparison_fn(ldb, ldb, + if (a->syntax->comparison_fn(ldb, msg, &el->values[i], val) == 0) { if (inum_values-1) { memmove(&el->values[i], &el->values[i+1], @@ -559,7 +583,7 @@ static int msg_delete_element(struct ldb_module *module, } el->num_values--; if (el->num_values == 0) { - return msg_delete_attribute(module, ldb, + return msg_delete_attribute(module, msg, name); } return 0; @@ -578,6 +602,7 @@ static int msg_delete_element(struct ldb_module *module, then we'll need to look at this again */ int ltdb_modify_internal(struct ldb_module *module, + TALLOC_CTX *mem_ctx, const struct ldb_message *msg) { struct ldb_context *ldb = ldb_module_get_ctx(module); @@ -587,28 +612,32 @@ int ltdb_modify_internal(struct ldb_module *module, struct ldb_message *msg2; unsigned i, j; int ret, idx; - - tdb_key = ltdb_key(module, msg->dn); + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return LDB_ERR_OPERATIONS_ERROR; + } + tdb_key = ltdb_key(tmp_ctx, msg->dn); if (!tdb_key.dptr) { + talloc_free(tmp_ctx); return LDB_ERR_OTHER; } tdb_data = tdb_fetch(ltdb->tdb, tdb_key); + talloc_free(tdb_key.dptr); + if (!tdb_data.dptr) { - talloc_free(tdb_key.dptr); return ltdb_err_map(tdb_error(ltdb->tdb)); } - msg2 = talloc(tdb_key.dptr, struct ldb_message); + msg2 = talloc(tmp_ctx, struct ldb_message); if (msg2 == NULL) { - talloc_free(tdb_key.dptr); - return LDB_ERR_OTHER; + ldb_oom(ldb); + ret = LDB_ERR_OPERATIONS_ERROR; + goto failed; } ret = ltdb_unpack_data(module, &tdb_data, msg2); if (ret == -1) { - ret = LDB_ERR_OTHER; - goto failed; } if (!msg2->dn) { @@ -619,7 +648,6 @@ int ltdb_modify_internal(struct ldb_module *module, struct ldb_message_element *el = &msg->elements[i]; struct ldb_message_element *el2; struct ldb_val *vals; - const char *dn; const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name); switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { @@ -680,7 +708,8 @@ int ltdb_modify_internal(struct ldb_module *module, el2->num_values + el->num_values); if (vals == NULL) { - ret = LDB_ERR_OTHER; + ldb_oom(ldb); + ret = LDB_ERR_OPERATIONS_ERROR; goto failed; } @@ -704,7 +733,7 @@ int ltdb_modify_internal(struct ldb_module *module, } /* replace all elements of this attribute name with the elements listed. The attribute not existing is not an error */ - msg_delete_attribute(module, ldb, msg2, el->name); + msg_delete_attribute(module, msg2, el->name); for (j=0;jnum_values;j++) { if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) { @@ -724,17 +753,12 @@ int ltdb_modify_internal(struct ldb_module *module, case LDB_FLAG_MOD_DELETE: - dn = ldb_dn_get_linearized(msg->dn); - if (dn == NULL) { - ret = LDB_ERR_OTHER; - goto failed; - } - /* we could be being asked to delete all values or just some values */ if (msg->elements[i].num_values == 0) { - if (msg_delete_attribute(module, ldb, msg2, + if (msg_delete_attribute(module, msg2, msg->elements[i].name) != 0) { + const char *dn = ldb_dn_get_linearized(msg->dn); ldb_asprintf_errstring(ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn); ret = LDB_ERR_NO_SUCH_ATTRIBUTE; goto failed; @@ -746,11 +770,15 @@ int ltdb_modify_internal(struct ldb_module *module, msg2, msg->elements[i].name, &msg->elements[i].values[j]) != 0) { - ldb_asprintf_errstring(ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn); + const char *dn = ldb_dn_get_linearized(msg->dn); + ldb_asprintf_errstring(ldb, "No matching attribute value (%*.*s) when deleting attribute: %s on %s", + (int)msg->elements[i].values[j].length, (int)msg->elements[i].values[j].length, + (const char *)msg->elements[i].values[j].data, + msg->elements[i].name, dn); ret = LDB_ERR_NO_SUCH_ATTRIBUTE; goto failed; } - ret = ltdb_index_del_value(module, dn, &msg->elements[i], j); + ret = ltdb_index_del_value(module, tmp_ctx, msg->dn, &msg->elements[i], j); if (ret != LDB_SUCCESS) { goto failed; } @@ -768,7 +796,7 @@ int ltdb_modify_internal(struct ldb_module *module, /* we've made all the mods * save the modified record back into the database */ - ret = ltdb_store(module, msg2, TDB_MODIFY); + ret = ltdb_store(module, mem_ctx, msg2, TDB_MODIFY); if (ret != LDB_SUCCESS) { goto failed; } @@ -778,12 +806,11 @@ int ltdb_modify_internal(struct ldb_module *module, goto failed; } - talloc_free(tdb_key.dptr); free(tdb_data.dptr); return ret; failed: - talloc_free(tdb_key.dptr); + talloc_free(tmp_ctx); free(tdb_data.dptr); return ret; } @@ -808,7 +835,7 @@ static int ltdb_modify(struct ltdb_context *ctx) return LDB_ERR_OPERATIONS_ERROR; } - tret = ltdb_modify_internal(module, req->op.mod.message); + tret = ltdb_modify_internal(module, req, req->op.mod.message); if (tret != LDB_SUCCESS) { return tret; } @@ -841,12 +868,14 @@ static int ltdb_rename(struct ltdb_context *ctx) to fetch the old record */ tret = ltdb_search_dn1(module, req->op.rename.olddn, msg); if (tret != LDB_SUCCESS) { + talloc_free(msg); /* not finding the old record is an error */ return tret; } msg->dn = ldb_dn_copy(msg, req->op.rename.newdn); if (!msg->dn) { + talloc_free(msg); return LDB_ERR_OPERATIONS_ERROR; } @@ -854,12 +883,14 @@ static int ltdb_rename(struct ltdb_context *ctx) * unique indexes. We rely on the transaction to make this * atomic */ - tret = ltdb_delete_internal(module, req->op.rename.olddn); + tret = ltdb_delete_internal(module, msg, req->op.rename.olddn); if (tret != LDB_SUCCESS) { + talloc_free(msg); return tret; } - tret = ltdb_add_internal(module, msg); + tret = ltdb_add_internal(module, msg, msg); + talloc_free(msg); if (tret != LDB_SUCCESS) { return tret; } @@ -892,7 +923,7 @@ static int ltdb_prepare_commit(struct ldb_module *module) return LDB_SUCCESS; } - if (ltdb_index_transaction_commit(module) != 0) { + if (ltdb_index_transaction_prepare_commit(module) != 0) { tdb_transaction_cancel(ltdb->tdb); ltdb->in_transaction--; return ltdb_err_map(tdb_error(ltdb->tdb)); -- cgit