s3-dbwrap: Use simpler code for logging keys
[Samba/vl.git] / source3 / lib / dbwrap / dbwrap_tdb.c
blob6a4636a9871518becf830784212f9c8ff90e4ead
1 /*
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/>.
20 #include "includes.h"
21 #include "dbwrap/dbwrap.h"
22 #include "dbwrap/dbwrap_private.h"
23 #include "dbwrap/dbwrap_tdb.h"
24 #include "lib/util/tdb_wrap.h"
25 #include "lib/param/param.h"
26 #include "util_tdb.h"
28 struct db_tdb_ctx {
29 struct tdb_wrap *wtdb;
32 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
33 static NTSTATUS db_tdb_delete(struct db_record *rec);
35 static void db_tdb_log_key(const char *prefix, TDB_DATA key)
37 size_t len;
38 char *keystr;
40 if (DEBUGLEVEL < 10) {
41 return;
43 len = key.dsize;
44 if (DEBUGLEVEL == 10) {
46 * Only fully spam at debuglevel > 10
48 len = MIN(10, key.dsize);
50 keystr = hex_encode_talloc(talloc_tos(), (unsigned char *)(key.dptr),
51 len);
52 DEBUG(10, ("%s key %s\n", prefix, keystr));
53 TALLOC_FREE(keystr);
56 static int db_tdb_record_destr(struct db_record* data)
58 struct db_tdb_ctx *ctx =
59 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
61 db_tdb_log_key("Unlocking", data->key);
62 tdb_chainunlock(ctx->wtdb->tdb, data->key);
63 return 0;
66 struct tdb_fetch_locked_state {
67 TALLOC_CTX *mem_ctx;
68 struct db_record *result;
71 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
72 void *private_data)
74 struct tdb_fetch_locked_state *state =
75 (struct tdb_fetch_locked_state *)private_data;
77 state->result = (struct db_record *)talloc_size(
78 state->mem_ctx,
79 sizeof(struct db_record) + key.dsize + data.dsize);
81 if (state->result == NULL) {
82 return 0;
85 state->result->key.dsize = key.dsize;
86 state->result->key.dptr = ((uint8 *)state->result)
87 + sizeof(struct db_record);
88 memcpy(state->result->key.dptr, key.dptr, key.dsize);
90 state->result->value.dsize = data.dsize;
92 if (data.dsize > 0) {
93 state->result->value.dptr = state->result->key.dptr+key.dsize;
94 memcpy(state->result->value.dptr, data.dptr, data.dsize);
96 else {
97 state->result->value.dptr = NULL;
100 return 0;
103 static struct db_record *db_tdb_fetch_locked(struct db_context *db,
104 TALLOC_CTX *mem_ctx, TDB_DATA key)
106 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
107 struct db_tdb_ctx);
108 struct tdb_fetch_locked_state state;
110 db_tdb_log_key("Locking", key);
112 if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
113 DEBUG(3, ("tdb_chainlock failed\n"));
114 return NULL;
117 state.mem_ctx = mem_ctx;
118 state.result = NULL;
120 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
122 if (state.result == NULL) {
123 db_tdb_fetchlock_parse(key, tdb_null, &state);
126 if (state.result == NULL) {
127 tdb_chainunlock(ctx->wtdb->tdb, key);
128 return NULL;
131 talloc_set_destructor(state.result, db_tdb_record_destr);
133 state.result->private_data = talloc_reference(state.result, ctx);
134 state.result->store = db_tdb_store;
135 state.result->delete_rec = db_tdb_delete;
137 DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
139 return state.result;
142 struct tdb_fetch_state {
143 TALLOC_CTX *mem_ctx;
144 NTSTATUS result;
145 TDB_DATA data;
148 static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA data,
149 void *private_data)
151 struct tdb_fetch_state *state =
152 (struct tdb_fetch_state *)private_data;
154 if (data.dptr == NULL) {
155 /* should not happen */
156 state->result = NT_STATUS_INTERNAL_DB_ERROR;
157 return -1;
160 state->data.dptr = (uint8 *)talloc_memdup(state->mem_ctx, data.dptr,
161 data.dsize);
162 if (state->data.dptr == NULL) {
163 state->result = NT_STATUS_NO_MEMORY;
164 return -1;
167 state->data.dsize = data.dsize;
168 return 0;
171 static NTSTATUS db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
172 TDB_DATA key, TDB_DATA *pdata)
174 struct db_tdb_ctx *ctx = talloc_get_type_abort(
175 db->private_data, struct db_tdb_ctx);
177 struct tdb_fetch_state state;
178 int ret;
180 state.mem_ctx = mem_ctx;
181 state.result = NT_STATUS_OK;
182 state.data = tdb_null;
184 ret = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
186 if (ret != 0) {
187 NTSTATUS status;
189 if (!NT_STATUS_IS_OK(state.result)) {
190 /* the parser has set an error code. return it */
191 return state.result;
194 status = map_nt_error_from_tdb(tdb_error(ctx->wtdb->tdb));
195 return status;
198 if (!NT_STATUS_IS_OK(state.result)) {
199 return state.result;
202 *pdata = state.data;
203 return NT_STATUS_OK;
206 static int db_tdb_exists(struct db_context *db, TDB_DATA key)
208 struct db_tdb_ctx *ctx = talloc_get_type_abort(
209 db->private_data, struct db_tdb_ctx);
210 return tdb_exists(ctx->wtdb->tdb, key);
213 static int db_tdb_wipe(struct db_context *db)
215 struct db_tdb_ctx *ctx = talloc_get_type_abort(
216 db->private_data, struct db_tdb_ctx);
217 return tdb_wipe_all(ctx->wtdb->tdb);
220 static int db_tdb_parse(struct db_context *db, TDB_DATA key,
221 int (*parser)(TDB_DATA key, TDB_DATA data,
222 void *private_data),
223 void *private_data)
225 struct db_tdb_ctx *ctx = talloc_get_type_abort(
226 db->private_data, struct db_tdb_ctx);
228 return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data) ? -1 : 0;
231 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
233 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
234 struct db_tdb_ctx);
237 * This has a bug: We need to replace rec->value for correct
238 * operation, but right now brlock and locking don't use the value
239 * anymore after it was stored.
242 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
243 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
246 static NTSTATUS db_tdb_delete(struct db_record *rec)
248 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
249 struct db_tdb_ctx);
251 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
252 return NT_STATUS_OK;
255 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
256 return NT_STATUS_NOT_FOUND;
259 return NT_STATUS_UNSUCCESSFUL;
262 struct db_tdb_traverse_ctx {
263 struct db_context *db;
264 int (*f)(struct db_record *rec, void *private_data);
265 void *private_data;
268 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
269 void *private_data)
271 struct db_tdb_traverse_ctx *ctx =
272 (struct db_tdb_traverse_ctx *)private_data;
273 struct db_record rec;
275 rec.key = kbuf;
276 rec.value = dbuf;
277 rec.store = db_tdb_store;
278 rec.delete_rec = db_tdb_delete;
279 rec.private_data = ctx->db->private_data;
281 return ctx->f(&rec, ctx->private_data);
284 static int db_tdb_traverse(struct db_context *db,
285 int (*f)(struct db_record *rec, void *private_data),
286 void *private_data)
288 struct db_tdb_ctx *db_ctx =
289 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
290 struct db_tdb_traverse_ctx ctx;
292 ctx.db = db;
293 ctx.f = f;
294 ctx.private_data = private_data;
295 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
298 static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
300 return NT_STATUS_MEDIA_WRITE_PROTECTED;
303 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
305 return NT_STATUS_MEDIA_WRITE_PROTECTED;
308 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
309 void *private_data)
311 struct db_tdb_traverse_ctx *ctx =
312 (struct db_tdb_traverse_ctx *)private_data;
313 struct db_record rec;
315 rec.key = kbuf;
316 rec.value = dbuf;
317 rec.store = db_tdb_store_deny;
318 rec.delete_rec = db_tdb_delete_deny;
319 rec.private_data = ctx->db->private_data;
321 return ctx->f(&rec, ctx->private_data);
324 static int db_tdb_traverse_read(struct db_context *db,
325 int (*f)(struct db_record *rec, void *private_data),
326 void *private_data)
328 struct db_tdb_ctx *db_ctx =
329 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
330 struct db_tdb_traverse_ctx ctx;
332 ctx.db = db;
333 ctx.f = f;
334 ctx.private_data = private_data;
335 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
338 static int db_tdb_get_seqnum(struct db_context *db)
341 struct db_tdb_ctx *db_ctx =
342 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
343 return tdb_get_seqnum(db_ctx->wtdb->tdb);
346 static int db_tdb_get_flags(struct db_context *db)
349 struct db_tdb_ctx *db_ctx =
350 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
351 return tdb_get_flags(db_ctx->wtdb->tdb);
354 static int db_tdb_transaction_start(struct db_context *db)
356 struct db_tdb_ctx *db_ctx =
357 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
358 return tdb_transaction_start(db_ctx->wtdb->tdb) ? -1 : 0;
361 static int db_tdb_transaction_commit(struct db_context *db)
363 struct db_tdb_ctx *db_ctx =
364 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
365 return tdb_transaction_commit(db_ctx->wtdb->tdb) ? -1 : 0;
368 static int db_tdb_transaction_cancel(struct db_context *db)
370 struct db_tdb_ctx *db_ctx =
371 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
372 tdb_transaction_cancel(db_ctx->wtdb->tdb);
373 return 0;
376 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
377 const char *name,
378 int hash_size, int tdb_flags,
379 int open_flags, mode_t mode)
381 struct db_context *result = NULL;
382 struct db_tdb_ctx *db_tdb;
383 struct loadparm_context *lp_ctx;
385 result = talloc_zero(mem_ctx, struct db_context);
386 if (result == NULL) {
387 DEBUG(0, ("talloc failed\n"));
388 goto fail;
390 lp_ctx = loadparm_init_s3(result, loadparm_s3_context());
392 result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
393 if (db_tdb == NULL) {
394 DEBUG(0, ("talloc failed\n"));
395 goto fail;
398 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
399 open_flags, mode, lp_ctx);
400 talloc_unlink(result, lp_ctx);
401 if (db_tdb->wtdb == NULL) {
402 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
403 goto fail;
406 result->fetch_locked = db_tdb_fetch_locked;
407 result->fetch = db_tdb_fetch;
408 result->traverse = db_tdb_traverse;
409 result->traverse_read = db_tdb_traverse_read;
410 result->parse_record = db_tdb_parse;
411 result->get_seqnum = db_tdb_get_seqnum;
412 result->get_flags = db_tdb_get_flags;
413 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
414 result->transaction_start = db_tdb_transaction_start;
415 result->transaction_commit = db_tdb_transaction_commit;
416 result->transaction_cancel = db_tdb_transaction_cancel;
417 result->exists = db_tdb_exists;
418 result->wipe = db_tdb_wipe;
419 return result;
421 fail:
422 if (result != NULL) {
423 TALLOC_FREE(result);
425 return NULL;