s3:net: registry: add new command enumerate_recursive
[Samba.git] / source3 / lib / dbwrap_tdb.c
blob98fd255ece41da28e7b102817d9bf768a5042e6e
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.h"
22 #include "lib/util/tdb_wrap.h"
24 struct db_tdb_ctx {
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,
44 data->key.dsize)));
46 if (tdb_chainunlock(ctx->wtdb->tdb, data->key) != 0) {
47 DEBUG(0, ("tdb_chainunlock failed\n"));
48 return -1;
50 return 0;
53 struct tdb_fetch_locked_state {
54 TALLOC_CTX *mem_ctx;
55 struct db_record *result;
58 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
59 void *private_data)
61 struct tdb_fetch_locked_state *state =
62 (struct tdb_fetch_locked_state *)private_data;
64 state->result = (struct db_record *)talloc_size(
65 state->mem_ctx,
66 sizeof(struct db_record) + key.dsize + data.dsize);
68 if (state->result == NULL) {
69 return 0;
72 state->result->key.dsize = key.dsize;
73 state->result->key.dptr = ((uint8 *)state->result)
74 + sizeof(struct db_record);
75 memcpy(state->result->key.dptr, key.dptr, key.dsize);
77 state->result->value.dsize = data.dsize;
79 if (data.dsize > 0) {
80 state->result->value.dptr = state->result->key.dptr+key.dsize;
81 memcpy(state->result->value.dptr, data.dptr, data.dsize);
83 else {
84 state->result->value.dptr = NULL;
87 return 0;
90 static struct db_record *db_tdb_fetch_locked(struct db_context *db,
91 TALLOC_CTX *mem_ctx, TDB_DATA key)
93 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
94 struct db_tdb_ctx);
95 struct tdb_fetch_locked_state state;
97 /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
98 if(DEBUGLEVEL >= 10) {
99 char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize);
100 DEBUG(10, (DEBUGLEVEL > 10
101 ? "Locking key %s\n" : "Locking key %.20s\n",
102 keystr));
103 TALLOC_FREE(keystr);
106 if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
107 DEBUG(3, ("tdb_chainlock failed\n"));
108 return NULL;
111 state.mem_ctx = mem_ctx;
112 state.result = NULL;
114 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
116 if (state.result == NULL) {
117 db_tdb_fetchlock_parse(key, tdb_null, &state);
120 if (state.result == NULL) {
121 tdb_chainunlock(ctx->wtdb->tdb, key);
122 return NULL;
125 talloc_set_destructor(state.result, db_tdb_record_destr);
127 state.result->private_data = talloc_reference(state.result, ctx);
128 state.result->store = db_tdb_store;
129 state.result->delete_rec = db_tdb_delete;
131 DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
133 return state.result;
136 struct tdb_fetch_state {
137 TALLOC_CTX *mem_ctx;
138 int result;
139 TDB_DATA data;
142 static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA data,
143 void *private_data)
145 struct tdb_fetch_state *state =
146 (struct tdb_fetch_state *)private_data;
148 state->data.dptr = (uint8 *)talloc_memdup(state->mem_ctx, data.dptr,
149 data.dsize);
150 if (state->data.dptr == NULL) {
151 state->result = -1;
152 return 0;
155 state->data.dsize = data.dsize;
156 return 0;
159 static int db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
160 TDB_DATA key, TDB_DATA *pdata)
162 struct db_tdb_ctx *ctx = talloc_get_type_abort(
163 db->private_data, struct db_tdb_ctx);
165 struct tdb_fetch_state state;
167 state.mem_ctx = mem_ctx;
168 state.result = 0;
169 state.data = tdb_null;
171 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
173 if (state.result == -1) {
174 return -1;
177 *pdata = state.data;
178 return 0;
181 static int db_tdb_parse(struct db_context *db, TDB_DATA key,
182 int (*parser)(TDB_DATA key, TDB_DATA data,
183 void *private_data),
184 void *private_data)
186 struct db_tdb_ctx *ctx = talloc_get_type_abort(
187 db->private_data, struct db_tdb_ctx);
189 return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data);
192 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
194 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
195 struct db_tdb_ctx);
198 * This has a bug: We need to replace rec->value for correct
199 * operation, but right now brlock and locking don't use the value
200 * anymore after it was stored.
203 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
204 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
207 static NTSTATUS db_tdb_delete(struct db_record *rec)
209 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
210 struct db_tdb_ctx);
212 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
213 return NT_STATUS_OK;
216 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
217 return NT_STATUS_NOT_FOUND;
220 return NT_STATUS_UNSUCCESSFUL;
223 struct db_tdb_traverse_ctx {
224 struct db_context *db;
225 int (*f)(struct db_record *rec, void *private_data);
226 void *private_data;
229 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
230 void *private_data)
232 struct db_tdb_traverse_ctx *ctx =
233 (struct db_tdb_traverse_ctx *)private_data;
234 struct db_record rec;
236 rec.key = kbuf;
237 rec.value = dbuf;
238 rec.store = db_tdb_store;
239 rec.delete_rec = db_tdb_delete;
240 rec.private_data = ctx->db->private_data;
242 return ctx->f(&rec, ctx->private_data);
245 static int db_tdb_traverse(struct db_context *db,
246 int (*f)(struct db_record *rec, void *private_data),
247 void *private_data)
249 struct db_tdb_ctx *db_ctx =
250 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
251 struct db_tdb_traverse_ctx ctx;
253 ctx.db = db;
254 ctx.f = f;
255 ctx.private_data = private_data;
256 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
259 static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
261 return NT_STATUS_MEDIA_WRITE_PROTECTED;
264 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
266 return NT_STATUS_MEDIA_WRITE_PROTECTED;
269 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
270 void *private_data)
272 struct db_tdb_traverse_ctx *ctx =
273 (struct db_tdb_traverse_ctx *)private_data;
274 struct db_record rec;
276 rec.key = kbuf;
277 rec.value = dbuf;
278 rec.store = db_tdb_store_deny;
279 rec.delete_rec = db_tdb_delete_deny;
280 rec.private_data = ctx->db->private_data;
282 return ctx->f(&rec, ctx->private_data);
285 static int db_tdb_traverse_read(struct db_context *db,
286 int (*f)(struct db_record *rec, void *private_data),
287 void *private_data)
289 struct db_tdb_ctx *db_ctx =
290 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
291 struct db_tdb_traverse_ctx ctx;
293 ctx.db = db;
294 ctx.f = f;
295 ctx.private_data = private_data;
296 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
299 static int db_tdb_get_seqnum(struct db_context *db)
302 struct db_tdb_ctx *db_ctx =
303 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
304 return tdb_get_seqnum(db_ctx->wtdb->tdb);
307 static int db_tdb_get_flags(struct db_context *db)
310 struct db_tdb_ctx *db_ctx =
311 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
312 return tdb_get_flags(db_ctx->wtdb->tdb);
315 static int db_tdb_transaction_start(struct db_context *db)
317 struct db_tdb_ctx *db_ctx =
318 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
319 return tdb_transaction_start(db_ctx->wtdb->tdb);
322 static int db_tdb_transaction_commit(struct db_context *db)
324 struct db_tdb_ctx *db_ctx =
325 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
326 return tdb_transaction_commit(db_ctx->wtdb->tdb);
329 static int db_tdb_transaction_cancel(struct db_context *db)
331 struct db_tdb_ctx *db_ctx =
332 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
333 return tdb_transaction_cancel(db_ctx->wtdb->tdb);
336 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
337 const char *name,
338 int hash_size, int tdb_flags,
339 int open_flags, mode_t mode)
341 struct db_context *result = NULL;
342 struct db_tdb_ctx *db_tdb;
344 result = TALLOC_ZERO_P(mem_ctx, struct db_context);
345 if (result == NULL) {
346 DEBUG(0, ("talloc failed\n"));
347 goto fail;
350 result->private_data = db_tdb = TALLOC_P(result, struct db_tdb_ctx);
351 if (db_tdb == NULL) {
352 DEBUG(0, ("talloc failed\n"));
353 goto fail;
356 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
357 open_flags, mode);
358 if (db_tdb->wtdb == NULL) {
359 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
360 goto fail;
363 result->fetch_locked = db_tdb_fetch_locked;
364 result->fetch = db_tdb_fetch;
365 result->traverse = db_tdb_traverse;
366 result->traverse_read = db_tdb_traverse_read;
367 result->parse_record = db_tdb_parse;
368 result->get_seqnum = db_tdb_get_seqnum;
369 result->get_flags = db_tdb_get_flags;
370 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
371 result->transaction_start = db_tdb_transaction_start;
372 result->transaction_commit = db_tdb_transaction_commit;
373 result->transaction_cancel = db_tdb_transaction_cancel;
374 return result;
376 fail:
377 if (result != NULL) {
378 TALLOC_FREE(result);
380 return NULL;