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/>.
23 struct tdb_wrap *wtdb;
26 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
27 static NTSTATUS db_tdb_delete(struct db_record *rec);
29 static int db_tdb_record_destr(struct db_record* data)
31 struct db_tdb_ctx *ctx =
32 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
34 /* This hex_encode() call allocates memory on data context. By way how current
35 __talloc_free() code works, it is OK to allocate in the destructor as
36 the children of data will be freed after call to the destructor and this
37 new 'child' will be caught and freed correctly.
39 DEBUG(10, (DEBUGLEVEL > 10
40 ? "Unlocking key %s\n" : "Unlocking key %.20s\n",
41 hex_encode(data, (unsigned char *)data->key.dptr,
44 if (tdb_chainunlock(ctx->wtdb->tdb, data->key) != 0) {
45 DEBUG(0, ("tdb_chainunlock failed\n"));
51 struct tdb_fetch_locked_state {
53 struct db_record *result;
56 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
59 struct tdb_fetch_locked_state *state =
60 (struct tdb_fetch_locked_state *)private_data;
62 state->result = (struct db_record *)talloc_size(
64 sizeof(struct db_record) + key.dsize + data.dsize);
66 if (state->result == NULL) {
70 state->result->key.dsize = key.dsize;
71 state->result->key.dptr = ((uint8 *)state->result)
72 + sizeof(struct db_record);
73 memcpy(state->result->key.dptr, key.dptr, key.dsize);
75 state->result->value.dsize = data.dsize;
78 state->result->value.dptr = state->result->key.dptr+key.dsize;
79 memcpy(state->result->value.dptr, data.dptr, data.dsize);
82 state->result->value.dptr = NULL;
88 static struct db_record *db_tdb_fetch_locked(struct db_context *db,
89 TALLOC_CTX *mem_ctx, TDB_DATA key)
91 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
93 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(NULL, (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 res = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse,
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);
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));
136 struct tdb_fetch_state {
142 static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA 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,
150 if (state->data.dptr == NULL) {
155 state->data.dsize = data.dsize;
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;
169 state.data = tdb_null;
171 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
173 if (state.result == -1) {
181 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
183 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
187 * This has a bug: We need to replace rec->value for correct
188 * operation, but right now brlock and locking don't use the value
189 * anymore after it was stored.
192 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
193 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
196 static NTSTATUS db_tdb_delete(struct db_record *rec)
198 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
201 return (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) ?
202 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
205 struct db_tdb_traverse_ctx {
206 struct db_context *db;
207 int (*f)(struct db_record *rec, void *private_data);
211 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
214 struct db_tdb_traverse_ctx *ctx =
215 (struct db_tdb_traverse_ctx *)private_data;
216 struct db_record rec;
220 rec.store = db_tdb_store;
221 rec.delete_rec = db_tdb_delete;
222 rec.private_data = ctx->db->private_data;
224 return ctx->f(&rec, ctx->private_data);
227 static int db_tdb_traverse(struct db_context *db,
228 int (*f)(struct db_record *rec, void *private_data),
231 struct db_tdb_ctx *db_ctx =
232 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
233 struct db_tdb_traverse_ctx ctx;
237 ctx.private_data = private_data;
238 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
241 static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
243 return NT_STATUS_MEDIA_WRITE_PROTECTED;
246 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
248 return NT_STATUS_MEDIA_WRITE_PROTECTED;
251 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
254 struct db_tdb_traverse_ctx *ctx =
255 (struct db_tdb_traverse_ctx *)private_data;
256 struct db_record rec;
260 rec.store = db_tdb_store_deny;
261 rec.delete_rec = db_tdb_delete_deny;
262 rec.private_data = ctx->db->private_data;
264 return ctx->f(&rec, ctx->private_data);
267 static int db_tdb_traverse_read(struct db_context *db,
268 int (*f)(struct db_record *rec, void *private_data),
271 struct db_tdb_ctx *db_ctx =
272 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
273 struct db_tdb_traverse_ctx ctx;
277 ctx.private_data = private_data;
278 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
281 static int db_tdb_get_seqnum(struct db_context *db)
284 struct db_tdb_ctx *db_ctx =
285 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
286 return tdb_get_seqnum(db_ctx->wtdb->tdb);
289 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
291 int hash_size, int tdb_flags,
292 int open_flags, mode_t mode)
294 struct db_context *result = NULL;
295 struct db_tdb_ctx *db_tdb;
297 result = TALLOC_ZERO_P(mem_ctx, struct db_context);
298 if (result == NULL) {
299 DEBUG(0, ("talloc failed\n"));
303 result->private_data = db_tdb = TALLOC_P(result, struct db_tdb_ctx);
304 if (db_tdb == NULL) {
305 DEBUG(0, ("talloc failed\n"));
309 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
311 if (db_tdb->wtdb == NULL) {
312 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
316 result->fetch_locked = db_tdb_fetch_locked;
317 result->fetch = db_tdb_fetch;
318 result->traverse = db_tdb_traverse;
319 result->traverse_read = db_tdb_traverse_read;
320 result->get_seqnum = db_tdb_get_seqnum;
321 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
325 if (result != NULL) {