From 15a8af075a2d7b59f4d97d9804599b26325e5640 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 13 Aug 2019 14:18:05 +0200 Subject: [PATCH] lib: Enable watching and storing dbwrap_watch records. Samba so far on a dbwrap_watch record either watches or stores a record, but never both from the same db_record instance acquired from a dbwrap_fetch_locked(). In one of the next commits this will change, we will watch a record and at the same time store data into it. This patch enables a watch_send() followed by a storev() by properly keeping the watchers around. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/lib/dbwrap/dbwrap_watch.c | 69 ++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c index 6bbd68df859..b1a82d86006 100644 --- a/source3/lib/dbwrap/dbwrap_watch.c +++ b/source3/lib/dbwrap/dbwrap_watch.c @@ -223,6 +223,7 @@ static struct db_record *dbwrap_watched_fetch_locked( db->private_data, struct db_watched_ctx); struct db_record *rec; struct db_watched_subrec *subrec; + uint8_t *watchers = NULL; TDB_DATA subrec_value; bool ok; @@ -251,6 +252,26 @@ static struct db_record *dbwrap_watched_fetch_locked( subrec_value = dbwrap_record_get_value(subrec->subrec); ok = dbwrap_watch_rec_parse(subrec_value, &subrec->wrec); + if (!ok) { + return rec; /* fresh record */ + } + + /* + * subrec->wrec.watchers points *directly* into the + * returned data in the record. We need to talloc a + * copy of this so it belongs to subrec. + */ + + watchers = talloc_memdup( + subrec, + subrec->wrec.watchers, + subrec->wrec.num_watchers * SERVER_ID_BUF_LENGTH); + if (watchers == NULL) { + TALLOC_FREE(rec); + return NULL; + } + subrec->wrec.watchers = watchers; + if (ok) { rec->value = subrec->wrec.data; } @@ -314,6 +335,20 @@ static void dbwrap_watched_do_locked_fn(struct db_record *subrec, ok = dbwrap_watch_rec_parse(subrec_value, &state->subrec.wrec); if (ok) { + uint8_t *watchers = NULL; + + /* + * state->subrec.wrec.watchers points *directly* into the + * returned data in the record. We need to talloc a + * copy of this so it belongs to state->mem_ctx. + */ + watchers = talloc_memdup( + state->mem_ctx, + state->subrec.wrec.watchers, + state->subrec.wrec.num_watchers * SERVER_ID_BUF_LENGTH); + SMB_ASSERT(watchers != NULL); + state->subrec.wrec.watchers = watchers; + rec.value = state->subrec.wrec.data; } @@ -407,32 +442,38 @@ static NTSTATUS dbwrap_watched_save(struct db_record *rec, { uint32_t num_watchers_buf; uint8_t sizebuf[4]; - uint8_t addbuf[SERVER_ID_BUF_LENGTH]; NTSTATUS status; - struct TDB_DATA dbufs[num_databufs+3]; + struct TDB_DATA dbufs[num_databufs+2]; dbufs[0] = (TDB_DATA) { .dptr = sizebuf, .dsize = sizeof(sizebuf) }; - dbufs[1] = (TDB_DATA) { - .dptr = wrec->watchers, - .dsize = wrec->num_watchers * SERVER_ID_BUF_LENGTH - }; - if (addwatch != NULL) { - server_id_put(addbuf, *addwatch); + uint8_t *watchers, *new_watch; + + watchers = talloc_realloc( + NULL, + wrec->watchers, + uint8_t, + (wrec->num_watchers+1) * SERVER_ID_BUF_LENGTH); + if (watchers == NULL) { + return NT_STATUS_NO_MEMORY; + } + wrec->watchers = watchers; - dbufs[2] = (TDB_DATA) { - .dptr = addbuf, .dsize = SERVER_ID_BUF_LENGTH - }; + new_watch = &watchers[wrec->num_watchers*SERVER_ID_BUF_LENGTH]; + server_id_put(new_watch, *addwatch); wrec->num_watchers += 1; - } else { - dbufs[2] = (TDB_DATA) { 0 }; } + dbufs[1] = (TDB_DATA) { + .dptr = wrec->watchers, + .dsize = wrec->num_watchers * SERVER_ID_BUF_LENGTH + }; + if (num_databufs != 0) { - memcpy(&dbufs[3], databufs, sizeof(TDB_DATA) * num_databufs); + memcpy(&dbufs[2], databufs, sizeof(TDB_DATA) * num_databufs); } num_watchers_buf = wrec->num_watchers; -- 2.47.3