From: Volker Lendecke Date: Wed, 5 Nov 2014 13:02:38 +0000 (+0000) Subject: dbwrap: Add code to marshall a db_context's db X-Git-Tag: tdb-1.3.4~48 X-Git-Url: http://git.samba.org/samba.git/?p=kai%2Fsamba-autobuild%2F.git;a=commitdiff_plain;h=bbc5c64191d304aabf6ebebb2111396ee8bc2bc1 dbwrap: Add code to marshall a db_context's db Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h index e56e036c4c4..00c7672a905 100644 --- a/lib/dbwrap/dbwrap.h +++ b/lib/dbwrap/dbwrap.h @@ -155,6 +155,15 @@ NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key, NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx, const char *key, TDB_DATA *value); +size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize); +NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen, + bool (*fn)(TDB_DATA key, TDB_DATA value, + void *private_data), + void *private_data); +NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf, + size_t buflen); + + /** * This opens an ntdb or tdb file: you can hand it a .ntdb or .tdb extension * and it will decide (based on parameter settings, or else what exists) which diff --git a/lib/dbwrap/dbwrap_util.c b/lib/dbwrap/dbwrap_util.c index 4185fff9dd3..901ef564ab7 100644 --- a/lib/dbwrap/dbwrap_util.c +++ b/lib/dbwrap/dbwrap_util.c @@ -595,3 +595,169 @@ NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx, talloc_free(key_upper); return status; } + +struct dbwrap_marshall_state { + uint8_t *buf; + size_t bufsize; + size_t dbsize; +}; + +static int dbwrap_marshall_fn(struct db_record *rec, void *private_data) +{ + struct dbwrap_marshall_state *state = private_data; + TDB_DATA key, value; + size_t new_dbsize; + + key = dbwrap_record_get_key(rec); + value = dbwrap_record_get_value(rec); + + new_dbsize = state->dbsize; + new_dbsize += 8 + key.dsize; + new_dbsize += 8 + value.dsize; + + if (new_dbsize <= state->bufsize) { + uint8_t *p = state->buf + state->dbsize; + + SBVAL(p, 0, key.dsize); + p += 8; + memcpy(p, key.dptr, key.dsize); + p += key.dsize; + + SBVAL(p, 0, value.dsize); + p += 8; + memcpy(p, value.dptr, value.dsize); + } + state->dbsize = new_dbsize; + return 0; +} + +size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize) +{ + struct dbwrap_marshall_state state; + + state.bufsize = bufsize; + state.buf = buf; + state.dbsize = 0; + + dbwrap_traverse_read(db, dbwrap_marshall_fn, &state, NULL); + + return state.dbsize; +} + +static ssize_t dbwrap_unmarshall_get_data(const uint8_t *buf, size_t buflen, + size_t ofs, TDB_DATA *pdata) +{ + uint64_t space, len; + const uint8_t *p; + + if (ofs == buflen) { + return 0; + } + if (ofs > buflen) { + return -1; + } + + space = buflen - ofs; + if (space < 8) { + return -1; + } + + p = buf + ofs; + len = BVAL(p, 0); + + p += 8; + space -= 8; + + if (len > space) { + return -1; + } + + *pdata = (TDB_DATA) { .dptr = discard_const_p(uint8_t, p), + .dsize = len }; + return len + 8; +} + +NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen, + bool (*fn)(TDB_DATA key, TDB_DATA value, + void *private_data), + void *private_data) +{ + size_t ofs = 0; + + while (true) { + ssize_t len; + TDB_DATA key, value; + bool ok; + + len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &key); + if (len == 0) { + break; + } + if (len == -1) { + return NT_STATUS_INVALID_PARAMETER; + } + ofs += len; + + len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &value); + if (len == 0) { + break; + } + if (len == -1) { + return NT_STATUS_INVALID_PARAMETER; + } + ofs += len; + + ok = fn(key, value, private_data); + if (!ok) { + break; + } + } + + return NT_STATUS_OK; +} + +struct dbwrap_unmarshall_state { + struct db_context *db; + NTSTATUS ret; +}; + +static bool dbwrap_unmarshall_fn(TDB_DATA key, TDB_DATA value, + void *private_data) +{ + struct dbwrap_unmarshall_state *state = private_data; + struct db_record *rec; + NTSTATUS status; + + rec = dbwrap_fetch_locked(state->db, state->db, key); + if (rec == NULL) { + DEBUG(10, ("%s: dbwrap_fetch_locked failed\n", + __func__)); + state->ret = NT_STATUS_NO_MEMORY; + return false; + } + + status = dbwrap_record_store(rec, value, 0); + TALLOC_FREE(rec); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("%s: dbwrap_record_store failed: %s\n", + __func__, nt_errstr(status))); + state->ret = status; + return false; + } + + return true; +} + +NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf, + size_t buflen) +{ + struct dbwrap_unmarshall_state state = { .db = db }; + NTSTATUS status; + + status = dbwrap_parse_marshall_buf(buf, buflen, + dbwrap_unmarshall_fn, &state); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return state.ret; +}