diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c index 1f45558beb6..85f2213082f 100644 --- a/lib/dbwrap/dbwrap.c +++ b/lib/dbwrap/dbwrap.c @@ -86,7 +86,7 @@ NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags) { NTSTATUS status; - status = rec->store(rec, data, flags); + status = rec->storev(rec, &data, 1, flags); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/lib/dbwrap/dbwrap_private.h b/lib/dbwrap/dbwrap_private.h index 9b50ccc040e..2858afd8539 100644 --- a/lib/dbwrap/dbwrap_private.h +++ b/lib/dbwrap/dbwrap_private.h @@ -29,7 +29,8 @@ struct tevent_req; struct db_record { struct db_context *db; TDB_DATA key, value; - NTSTATUS (*store)(struct db_record *rec, TDB_DATA data, int flag); + NTSTATUS (*storev)(struct db_record *rec, const TDB_DATA *dbufs, + int num_dbufs, int flag); NTSTATUS (*delete_rec)(struct db_record *rec); void *private_data; }; diff --git a/lib/dbwrap/dbwrap_rbt.c b/lib/dbwrap/dbwrap_rbt.c index eb5ef10fddc..d9c743b80e8 100644 --- a/lib/dbwrap/dbwrap_rbt.c +++ b/lib/dbwrap/dbwrap_rbt.c @@ -118,7 +118,8 @@ overflow: return -1; } -static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag) +static NTSTATUS db_rbt_storev(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, int flag) { struct db_rbt_ctx *db_ctx = talloc_get_type_abort( rec->db->private_data, struct db_rbt_ctx); @@ -130,12 +131,23 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag) struct db_rbt_node *parent_node = NULL; ssize_t reclen; - TDB_DATA this_key, this_val; + TDB_DATA data, this_key, this_val; + void *to_free = NULL; if (db_ctx->traverse_read > 0) { return NT_STATUS_MEDIA_WRITE_PROTECTED; } + if (num_dbufs == 1) { + data = dbufs[0]; + } else { + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs); + if (data.dptr == NULL) { + return NT_STATUS_NO_MEMORY; + } + to_free = data.dptr; + } + if (rec_priv->node != NULL) { /* @@ -154,17 +166,20 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag) */ memcpy(this_val.dptr, data.dptr, data.dsize); rec_priv->node->valuesize = data.dsize; + TALLOC_FREE(to_free); return NT_STATUS_OK; } } reclen = db_rbt_reclen(rec->key.dsize, data.dsize); if (reclen == -1) { + TALLOC_FREE(to_free); return NT_STATUS_INSUFFICIENT_RESOURCES; } node = talloc_zero_size(db_ctx, reclen); if (node == NULL) { + TALLOC_FREE(to_free); return NT_STATUS_NO_MEMORY; } @@ -232,6 +247,8 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag) DLIST_ADD_AFTER(db_ctx->nodes, node, parent_node); rb_insert_color(&node->rb_node, &db_ctx->tree); + TALLOC_FREE(to_free); + return NT_STATUS_OK; } @@ -350,7 +367,7 @@ static struct db_record *db_rbt_fetch_locked(struct db_context *db_ctx, rec_priv = (struct db_rbt_rec *) ((char *)result + DBWRAP_RBT_ALIGN(sizeof(struct db_record))); - result->store = db_rbt_store; + result->storev = db_rbt_storev; result->delete_rec = db_rbt_delete; result->private_data = rec_priv; @@ -425,7 +442,7 @@ static int db_rbt_traverse_internal(struct db_context *db, ZERO_STRUCT(rec); rec.db = db; rec.private_data = &rec_priv; - rec.store = db_rbt_store; + rec.storev = db_rbt_storev; rec.delete_rec = db_rbt_delete; db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value); diff --git a/lib/dbwrap/dbwrap_tdb.c b/lib/dbwrap/dbwrap_tdb.c index e12ec4405d6..9f8a9a602d1 100644 --- a/lib/dbwrap/dbwrap_tdb.c +++ b/lib/dbwrap/dbwrap_tdb.c @@ -35,7 +35,8 @@ struct db_tdb_ctx { } id; }; -static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag); +static NTSTATUS db_tdb_storev(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, int flag); static NTSTATUS db_tdb_delete(struct db_record *rec); static void db_tdb_log_key(const char *prefix, TDB_DATA key) @@ -137,7 +138,7 @@ static struct db_record *db_tdb_fetch_locked_internal( talloc_set_destructor(state.result, db_tdb_record_destr); state.result->private_data = ctx; - state.result->store = db_tdb_store; + state.result->storev = db_tdb_storev; state.result->delete_rec = db_tdb_delete; DEBUG(10, ("Allocated locked data 0x%p\n", state.result)); @@ -173,7 +174,6 @@ static struct db_record *db_tdb_try_fetch_locked( return db_tdb_fetch_locked_internal(db, mem_ctx, key); } - static int db_tdb_exists(struct db_context *db, TDB_DATA key) { struct db_tdb_ctx *ctx = talloc_get_type_abort( @@ -236,10 +236,12 @@ static NTSTATUS db_tdb_parse(struct db_context *db, TDB_DATA key, return NT_STATUS_OK; } -static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag) +static NTSTATUS db_tdb_storev(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, int flag) { struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data, struct db_tdb_ctx); + int ret; /* * This has a bug: We need to replace rec->value for correct @@ -247,8 +249,8 @@ static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag) * anymore after it was stored. */ - return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; + ret = tdb_storev(ctx->wtdb->tdb, rec->key, dbufs, num_dbufs, flag); + return (ret == 0) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } static NTSTATUS db_tdb_delete(struct db_record *rec) @@ -282,7 +284,7 @@ static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, rec.key = kbuf; rec.value = dbuf; - rec.store = db_tdb_store; + rec.storev = db_tdb_storev; rec.delete_rec = db_tdb_delete; rec.private_data = ctx->db->private_data; rec.db = ctx->db; @@ -304,7 +306,9 @@ static int db_tdb_traverse(struct db_context *db, return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx); } -static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag) +static NTSTATUS db_tdb_storev_deny(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, + int flag) { return NT_STATUS_MEDIA_WRITE_PROTECTED; } @@ -323,7 +327,7 @@ static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA d rec.key = kbuf; rec.value = dbuf; - rec.store = db_tdb_store_deny; + rec.storev = db_tdb_storev_deny; rec.delete_rec = db_tdb_delete_deny; rec.private_data = ctx->db->private_data; rec.db = ctx->db; diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c index a5ac2b27074..05d51abf1d5 100644 --- a/source3/lib/dbwrap/dbwrap_ctdb.c +++ b/source3/lib/dbwrap/dbwrap_ctdb.c @@ -494,7 +494,9 @@ static bool pull_newest_from_marshall_buffer(struct ctdb_marshall_buffer *buf, return true; } -static NTSTATUS db_ctdb_store_transaction(struct db_record *rec, TDB_DATA data, int flag); +static NTSTATUS db_ctdb_storev_transaction(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, + int flag); static NTSTATUS db_ctdb_delete_transaction(struct db_record *rec); static struct db_record *db_ctdb_fetch_locked_transaction(struct db_ctdb_ctx *ctx, @@ -521,7 +523,7 @@ static struct db_record *db_ctdb_fetch_locked_transaction(struct db_ctdb_ctx *ct return NULL; } - result->store = db_ctdb_store_transaction; + result->storev = db_ctdb_storev_transaction; result->delete_rec = db_ctdb_delete_transaction; if (pull_newest_from_marshall_buffer(ctx->transaction->m_write, key, @@ -656,13 +658,23 @@ static NTSTATUS db_ctdb_transaction_store(struct db_ctdb_transaction_handle *h, /* a record store inside a transaction */ -static NTSTATUS db_ctdb_store_transaction(struct db_record *rec, TDB_DATA data, int flag) +static NTSTATUS db_ctdb_storev_transaction( + struct db_record *rec, const TDB_DATA *dbufs, int num_dbufs, int flag) { struct db_ctdb_transaction_handle *h = talloc_get_type_abort( rec->private_data, struct db_ctdb_transaction_handle); NTSTATUS status; + TDB_DATA data; + + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs); + if (data.dptr == NULL) { + return NT_STATUS_NO_MEMORY; + } status = db_ctdb_transaction_store(h, rec->key, data); + + TALLOC_FREE(data.dptr); + return status; } @@ -887,12 +899,23 @@ static int db_ctdb_transaction_cancel(struct db_context *db) } -static NTSTATUS db_ctdb_store(struct db_record *rec, TDB_DATA data, int flag) +static NTSTATUS db_ctdb_storev(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, int flag) { struct db_ctdb_rec *crec = talloc_get_type_abort( rec->private_data, struct db_ctdb_rec); + NTSTATUS status; + TDB_DATA data; - return db_ctdb_ltdb_store(crec->ctdb_ctx, rec->key, &(crec->header), data); + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs); + if (data.dptr == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = db_ctdb_ltdb_store(crec->ctdb_ctx, rec->key, &(crec->header), + data); + TALLOC_FREE(data.dptr); + return status; } @@ -954,7 +977,7 @@ static NTSTATUS db_ctdb_delete(struct db_record *rec) * tdb-level cleanup */ - status = db_ctdb_store(rec, tdb_null, 0); + status = db_ctdb_storev(rec, &tdb_null, 1, 0); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1125,7 +1148,7 @@ again: return NULL; } - result->store = db_ctdb_store; + result->storev = db_ctdb_storev; result->delete_rec = db_ctdb_delete; talloc_set_destructor(result, db_ctdb_record_destr); @@ -1658,7 +1681,8 @@ static int db_ctdb_traverse(struct db_context *db, return state.count; } -static NTSTATUS db_ctdb_store_deny(struct db_record *rec, TDB_DATA data, int flag) +static NTSTATUS db_ctdb_storev_deny(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, int flag) { return NT_STATUS_MEDIA_WRITE_PROTECTED; } @@ -1677,7 +1701,7 @@ static void traverse_read_callback(TDB_DATA key, TDB_DATA data, void *private_da rec.db = state->db; rec.key = key; rec.value = data; - rec.store = db_ctdb_store_deny; + rec.storev = db_ctdb_storev_deny; rec.delete_rec = db_ctdb_delete_deny; rec.private_data = NULL; state->fn(&rec, state->private_data); @@ -1704,7 +1728,7 @@ static int traverse_persistent_callback_read(TDB_CONTEXT *tdb, TDB_DATA kbuf, TD rec.db = state->db; rec.key = kbuf; rec.value = dbuf; - rec.store = db_ctdb_store_deny; + rec.storev = db_ctdb_storev_deny; rec.delete_rec = db_ctdb_delete_deny; rec.private_data = NULL; diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c index 585010f3dda..ab598036cab 100644 --- a/source3/lib/dbwrap/dbwrap_watch.c +++ b/source3/lib/dbwrap/dbwrap_watch.c @@ -238,8 +238,9 @@ struct db_watched_subrec { bool deleted; }; -static NTSTATUS dbwrap_watched_store(struct db_record *rec, TDB_DATA data, - int flag); +static NTSTATUS dbwrap_watched_storev(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, + int flag); static NTSTATUS dbwrap_watched_delete(struct db_record *rec); static struct db_record *dbwrap_watched_fetch_locked( @@ -271,7 +272,7 @@ static struct db_record *dbwrap_watched_fetch_locked( rec->db = db; rec->key = dbwrap_record_get_key(subrec->subrec); - rec->store = dbwrap_watched_store; + rec->storev = dbwrap_watched_storev; rec->delete_rec = dbwrap_watched_delete; subrec_value = dbwrap_record_get_value(subrec->subrec); @@ -383,18 +384,29 @@ static NTSTATUS dbwrap_watched_save(struct db_watched_subrec *subrec, return status; } -static NTSTATUS dbwrap_watched_store(struct db_record *rec, TDB_DATA data, - int flag) +static NTSTATUS dbwrap_watched_storev(struct db_record *rec, + const TDB_DATA *dbufs, int num_dbufs, + int flag) { struct db_watched_subrec *subrec = talloc_get_type_abort( rec->private_data, struct db_watched_subrec); + NTSTATUS status; + TDB_DATA data; + + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs); + if (data.dptr == NULL) { + return NT_STATUS_NO_MEMORY; + } dbwrap_watched_wakeup(rec, subrec); subrec->deleted = false; - return dbwrap_watched_save(subrec, data, flag); + status = dbwrap_watched_save(subrec, data, flag); + TALLOC_FREE(data.dptr); + + return status; } static NTSTATUS dbwrap_watched_delete(struct db_record *rec)