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 "dbwrap/dbwrap_private.h"
23 #include "dbwrap/dbwrap_tdb.h"
24 #include "lib/util/tdb_wrap.h"
27 struct tdb_wrap *wtdb;
30 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
31 static NTSTATUS db_tdb_delete(struct db_record *rec);
33 static int db_tdb_record_destr(struct db_record* data)
35 struct db_tdb_ctx *ctx =
36 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
38 /* This hex_encode_talloc() call allocates memory on data context. By way how current
39 __talloc_free() code works, it is OK to allocate in the destructor as
40 the children of data will be freed after call to the destructor and this
41 new 'child' will be caught and freed correctly.
43 DEBUG(10, (DEBUGLEVEL > 10
44 ? "Unlocking key %s\n" : "Unlocking key %.20s\n",
45 hex_encode_talloc(data, (unsigned char *)data->key.dptr,
48 tdb_chainunlock(ctx->wtdb->tdb, data->key);
52 struct tdb_fetch_locked_state {
54 struct db_record *result;
57 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
60 struct tdb_fetch_locked_state *state =
61 (struct tdb_fetch_locked_state *)private_data;
63 state->result = (struct db_record *)talloc_size(
65 sizeof(struct db_record) + key.dsize + data.dsize);
67 if (state->result == NULL) {
71 state->result->key.dsize = key.dsize;
72 state->result->key.dptr = ((uint8 *)state->result)
73 + sizeof(struct db_record);
74 memcpy(state->result->key.dptr, key.dptr, key.dsize);
76 state->result->value.dsize = data.dsize;
79 state->result->value.dptr = state->result->key.dptr+key.dsize;
80 memcpy(state->result->value.dptr, data.dptr, data.dsize);
83 state->result->value.dptr = NULL;
89 static struct db_record *db_tdb_fetch_locked(struct db_context *db,
90 TALLOC_CTX *mem_ctx, TDB_DATA key)
92 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
94 struct tdb_fetch_locked_state state;
96 /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
97 if(DEBUGLEVEL >= 10) {
98 char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize);
99 DEBUG(10, (DEBUGLEVEL > 10
100 ? "Locking key %s\n" : "Locking key %.20s\n",
105 if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
106 DEBUG(3, ("tdb_chainlock failed\n"));
110 state.mem_ctx = mem_ctx;
113 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
115 if (state.result == NULL) {
116 db_tdb_fetchlock_parse(key, tdb_null, &state);
119 if (state.result == NULL) {
120 tdb_chainunlock(ctx->wtdb->tdb, key);
124 talloc_set_destructor(state.result, db_tdb_record_destr);
126 state.result->private_data = talloc_reference(state.result, ctx);
127 state.result->store = db_tdb_store;
128 state.result->delete_rec = db_tdb_delete;
130 DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
135 struct tdb_fetch_state {
141 static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA data,
144 struct tdb_fetch_state *state =
145 (struct tdb_fetch_state *)private_data;
147 state->data.dptr = (uint8 *)talloc_memdup(state->mem_ctx, data.dptr,
149 if (state->data.dptr == NULL) {
154 state->data.dsize = data.dsize;
158 static int db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
159 TDB_DATA key, TDB_DATA *pdata)
161 struct db_tdb_ctx *ctx = talloc_get_type_abort(
162 db->private_data, struct db_tdb_ctx);
164 struct tdb_fetch_state state;
167 state.mem_ctx = mem_ctx;
169 state.data = tdb_null;
171 ret = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
177 if (state.result == -1) {
185 static int db_tdb_exists(struct db_context *db, TDB_DATA key)
187 struct db_tdb_ctx *ctx = talloc_get_type_abort(
188 db->private_data, struct db_tdb_ctx);
189 return tdb_exists(ctx->wtdb->tdb, key);
192 static int db_tdb_wipe(struct db_context *db)
194 struct db_tdb_ctx *ctx = talloc_get_type_abort(
195 db->private_data, struct db_tdb_ctx);
196 return tdb_wipe_all(ctx->wtdb->tdb);
199 static int db_tdb_parse(struct db_context *db, TDB_DATA key,
200 int (*parser)(TDB_DATA key, TDB_DATA data,
204 struct db_tdb_ctx *ctx = talloc_get_type_abort(
205 db->private_data, struct db_tdb_ctx);
207 return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data) ? -1 : 0;
210 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
212 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
216 * This has a bug: We need to replace rec->value for correct
217 * operation, but right now brlock and locking don't use the value
218 * anymore after it was stored.
221 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
222 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
225 static NTSTATUS db_tdb_delete(struct db_record *rec)
227 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
230 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
234 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
235 return NT_STATUS_NOT_FOUND;
238 return NT_STATUS_UNSUCCESSFUL;
241 struct db_tdb_traverse_ctx {
242 struct db_context *db;
243 int (*f)(struct db_record *rec, void *private_data);
247 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
250 struct db_tdb_traverse_ctx *ctx =
251 (struct db_tdb_traverse_ctx *)private_data;
252 struct db_record rec;
256 rec.store = db_tdb_store;
257 rec.delete_rec = db_tdb_delete;
258 rec.private_data = ctx->db->private_data;
260 return ctx->f(&rec, ctx->private_data);
263 static int db_tdb_traverse(struct db_context *db,
264 int (*f)(struct db_record *rec, void *private_data),
267 struct db_tdb_ctx *db_ctx =
268 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
269 struct db_tdb_traverse_ctx ctx;
273 ctx.private_data = private_data;
274 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
277 static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
279 return NT_STATUS_MEDIA_WRITE_PROTECTED;
282 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
284 return NT_STATUS_MEDIA_WRITE_PROTECTED;
287 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
290 struct db_tdb_traverse_ctx *ctx =
291 (struct db_tdb_traverse_ctx *)private_data;
292 struct db_record rec;
296 rec.store = db_tdb_store_deny;
297 rec.delete_rec = db_tdb_delete_deny;
298 rec.private_data = ctx->db->private_data;
300 return ctx->f(&rec, ctx->private_data);
303 static int db_tdb_traverse_read(struct db_context *db,
304 int (*f)(struct db_record *rec, void *private_data),
307 struct db_tdb_ctx *db_ctx =
308 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
309 struct db_tdb_traverse_ctx ctx;
313 ctx.private_data = private_data;
314 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
317 static int db_tdb_get_seqnum(struct db_context *db)
320 struct db_tdb_ctx *db_ctx =
321 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
322 return tdb_get_seqnum(db_ctx->wtdb->tdb);
325 static int db_tdb_get_flags(struct db_context *db)
328 struct db_tdb_ctx *db_ctx =
329 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
330 return tdb_get_flags(db_ctx->wtdb->tdb);
333 static int db_tdb_transaction_start(struct db_context *db)
335 struct db_tdb_ctx *db_ctx =
336 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
337 return tdb_transaction_start(db_ctx->wtdb->tdb) ? -1 : 0;
340 static int db_tdb_transaction_commit(struct db_context *db)
342 struct db_tdb_ctx *db_ctx =
343 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
344 return tdb_transaction_commit(db_ctx->wtdb->tdb) ? -1 : 0;
347 static int db_tdb_transaction_cancel(struct db_context *db)
349 struct db_tdb_ctx *db_ctx =
350 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
351 tdb_transaction_cancel(db_ctx->wtdb->tdb);
355 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
357 int hash_size, int tdb_flags,
358 int open_flags, mode_t mode)
360 struct db_context *result = NULL;
361 struct db_tdb_ctx *db_tdb;
363 result = talloc_zero(mem_ctx, struct db_context);
364 if (result == NULL) {
365 DEBUG(0, ("talloc failed\n"));
369 result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
370 if (db_tdb == NULL) {
371 DEBUG(0, ("talloc failed\n"));
375 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
377 if (db_tdb->wtdb == NULL) {
378 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
382 result->fetch_locked = db_tdb_fetch_locked;
383 result->fetch = db_tdb_fetch;
384 result->traverse = db_tdb_traverse;
385 result->traverse_read = db_tdb_traverse_read;
386 result->parse_record = db_tdb_parse;
387 result->get_seqnum = db_tdb_get_seqnum;
388 result->get_flags = db_tdb_get_flags;
389 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
390 result->transaction_start = db_tdb_transaction_start;
391 result->transaction_commit = db_tdb_transaction_commit;
392 result->transaction_cancel = db_tdb_transaction_cancel;
393 result->exists = db_tdb_exists;
394 result->wipe = db_tdb_wipe;
398 if (result != NULL) {