2 Unix SMB/CIFS implementation.
3 Database interface wrapper around tdb
4 Copyright (C) Volker Lendecke 2005-2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "dbwrap/dbwrap.h"
22 #include "lib/util/tdb_wrap.h"
25 struct tdb_wrap *wtdb;
28 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
29 static NTSTATUS db_tdb_delete(struct db_record *rec);
31 static int db_tdb_record_destr(struct db_record* data)
33 struct db_tdb_ctx *ctx =
34 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
36 /* This hex_encode_talloc() call allocates memory on data context. By way how current
37 __talloc_free() code works, it is OK to allocate in the destructor as
38 the children of data will be freed after call to the destructor and this
39 new 'child' will be caught and freed correctly.
41 DEBUG(10, (DEBUGLEVEL > 10
42 ? "Unlocking key %s\n" : "Unlocking key %.20s\n",
43 hex_encode_talloc(data, (unsigned char *)data->key.dptr,
46 tdb_chainunlock(ctx->wtdb->tdb, data->key);
50 struct tdb_fetch_locked_state {
52 struct db_record *result;
55 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
58 struct tdb_fetch_locked_state *state =
59 (struct tdb_fetch_locked_state *)private_data;
61 state->result = (struct db_record *)talloc_size(
63 sizeof(struct db_record) + key.dsize + data.dsize);
65 if (state->result == NULL) {
69 state->result->key.dsize = key.dsize;
70 state->result->key.dptr = ((uint8 *)state->result)
71 + sizeof(struct db_record);
72 memcpy(state->result->key.dptr, key.dptr, key.dsize);
74 state->result->value.dsize = data.dsize;
77 state->result->value.dptr = state->result->key.dptr+key.dsize;
78 memcpy(state->result->value.dptr, data.dptr, data.dsize);
81 state->result->value.dptr = NULL;
87 static struct db_record *db_tdb_fetch_locked(struct db_context *db,
88 TALLOC_CTX *mem_ctx, TDB_DATA key)
90 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
92 struct tdb_fetch_locked_state state;
94 /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
95 if(DEBUGLEVEL >= 10) {
96 char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize);
97 DEBUG(10, (DEBUGLEVEL > 10
98 ? "Locking key %s\n" : "Locking key %.20s\n",
103 if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
104 DEBUG(3, ("tdb_chainlock failed\n"));
108 state.mem_ctx = mem_ctx;
111 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
113 if (state.result == NULL) {
114 db_tdb_fetchlock_parse(key, tdb_null, &state);
117 if (state.result == NULL) {
118 tdb_chainunlock(ctx->wtdb->tdb, key);
122 talloc_set_destructor(state.result, db_tdb_record_destr);
124 state.result->private_data = talloc_reference(state.result, ctx);
125 state.result->store = db_tdb_store;
126 state.result->delete_rec = db_tdb_delete;
128 DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
133 struct tdb_fetch_state {
139 static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA data,
142 struct tdb_fetch_state *state =
143 (struct tdb_fetch_state *)private_data;
145 state->data.dptr = (uint8 *)talloc_memdup(state->mem_ctx, data.dptr,
147 if (state->data.dptr == NULL) {
152 state->data.dsize = data.dsize;
156 static int db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
157 TDB_DATA key, TDB_DATA *pdata)
159 struct db_tdb_ctx *ctx = talloc_get_type_abort(
160 db->private_data, struct db_tdb_ctx);
162 struct tdb_fetch_state state;
165 state.mem_ctx = mem_ctx;
167 state.data = tdb_null;
169 ret = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
175 if (state.result == -1) {
183 static int db_tdb_parse(struct db_context *db, TDB_DATA key,
184 int (*parser)(TDB_DATA key, TDB_DATA data,
188 struct db_tdb_ctx *ctx = talloc_get_type_abort(
189 db->private_data, struct db_tdb_ctx);
191 return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data);
194 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
196 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
200 * This has a bug: We need to replace rec->value for correct
201 * operation, but right now brlock and locking don't use the value
202 * anymore after it was stored.
205 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
206 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
209 static NTSTATUS db_tdb_delete(struct db_record *rec)
211 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
214 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
218 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
219 return NT_STATUS_NOT_FOUND;
222 return NT_STATUS_UNSUCCESSFUL;
225 struct db_tdb_traverse_ctx {
226 struct db_context *db;
227 int (*f)(struct db_record *rec, void *private_data);
231 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
234 struct db_tdb_traverse_ctx *ctx =
235 (struct db_tdb_traverse_ctx *)private_data;
236 struct db_record rec;
240 rec.store = db_tdb_store;
241 rec.delete_rec = db_tdb_delete;
242 rec.private_data = ctx->db->private_data;
244 return ctx->f(&rec, ctx->private_data);
247 static int db_tdb_traverse(struct db_context *db,
248 int (*f)(struct db_record *rec, void *private_data),
251 struct db_tdb_ctx *db_ctx =
252 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
253 struct db_tdb_traverse_ctx ctx;
257 ctx.private_data = private_data;
258 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
261 static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
263 return NT_STATUS_MEDIA_WRITE_PROTECTED;
266 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
268 return NT_STATUS_MEDIA_WRITE_PROTECTED;
271 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
274 struct db_tdb_traverse_ctx *ctx =
275 (struct db_tdb_traverse_ctx *)private_data;
276 struct db_record rec;
280 rec.store = db_tdb_store_deny;
281 rec.delete_rec = db_tdb_delete_deny;
282 rec.private_data = ctx->db->private_data;
284 return ctx->f(&rec, ctx->private_data);
287 static int db_tdb_traverse_read(struct db_context *db,
288 int (*f)(struct db_record *rec, void *private_data),
291 struct db_tdb_ctx *db_ctx =
292 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
293 struct db_tdb_traverse_ctx ctx;
297 ctx.private_data = private_data;
298 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
301 static int db_tdb_get_seqnum(struct db_context *db)
304 struct db_tdb_ctx *db_ctx =
305 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
306 return tdb_get_seqnum(db_ctx->wtdb->tdb);
309 static int db_tdb_get_flags(struct db_context *db)
312 struct db_tdb_ctx *db_ctx =
313 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
314 return tdb_get_flags(db_ctx->wtdb->tdb);
317 static int db_tdb_transaction_start(struct db_context *db)
319 struct db_tdb_ctx *db_ctx =
320 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
321 return tdb_transaction_start(db_ctx->wtdb->tdb);
324 static int db_tdb_transaction_commit(struct db_context *db)
326 struct db_tdb_ctx *db_ctx =
327 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
328 return tdb_transaction_commit(db_ctx->wtdb->tdb);
331 static int db_tdb_transaction_cancel(struct db_context *db)
333 struct db_tdb_ctx *db_ctx =
334 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
335 tdb_transaction_cancel(db_ctx->wtdb->tdb);
339 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
341 int hash_size, int tdb_flags,
342 int open_flags, mode_t mode)
344 struct db_context *result = NULL;
345 struct db_tdb_ctx *db_tdb;
347 result = talloc_zero(mem_ctx, struct db_context);
348 if (result == NULL) {
349 DEBUG(0, ("talloc failed\n"));
353 result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
354 if (db_tdb == NULL) {
355 DEBUG(0, ("talloc failed\n"));
359 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
361 if (db_tdb->wtdb == NULL) {
362 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
366 result->fetch_locked = db_tdb_fetch_locked;
367 result->fetch = db_tdb_fetch;
368 result->traverse = db_tdb_traverse;
369 result->traverse_read = db_tdb_traverse_read;
370 result->parse_record = db_tdb_parse;
371 result->get_seqnum = db_tdb_get_seqnum;
372 result->get_flags = db_tdb_get_flags;
373 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
374 result->transaction_start = db_tdb_transaction_start;
375 result->transaction_commit = db_tdb_transaction_commit;
376 result->transaction_cancel = db_tdb_transaction_cancel;
380 if (result != NULL) {