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_talloc() 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_talloc(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
;
95 /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
96 if(DEBUGLEVEL
>= 10) {
97 char *keystr
= hex_encode_talloc(talloc_tos(), (unsigned char*)key
.dptr
, key
.dsize
);
98 DEBUG(10, (DEBUGLEVEL
> 10
99 ? "Locking key %s\n" : "Locking key %.20s\n",
104 if (tdb_chainlock(ctx
->wtdb
->tdb
, key
) != 0) {
105 DEBUG(3, ("tdb_chainlock failed\n"));
109 state
.mem_ctx
= mem_ctx
;
112 tdb_parse_record(ctx
->wtdb
->tdb
, key
, db_tdb_fetchlock_parse
, &state
);
114 if (state
.result
== NULL
) {
115 db_tdb_fetchlock_parse(key
, tdb_null
, &state
);
118 if (state
.result
== NULL
) {
119 tdb_chainunlock(ctx
->wtdb
->tdb
, key
);
123 talloc_set_destructor(state
.result
, db_tdb_record_destr
);
125 state
.result
->private_data
= talloc_reference(state
.result
, ctx
);
126 state
.result
->store
= db_tdb_store
;
127 state
.result
->delete_rec
= db_tdb_delete
;
129 DEBUG(10, ("Allocated locked data 0x%p\n", state
.result
));
134 struct tdb_fetch_state
{
140 static int db_tdb_fetch_parse(TDB_DATA key
, TDB_DATA data
,
143 struct tdb_fetch_state
*state
=
144 (struct tdb_fetch_state
*)private_data
;
146 state
->data
.dptr
= (uint8
*)talloc_memdup(state
->mem_ctx
, data
.dptr
,
148 if (state
->data
.dptr
== NULL
) {
153 state
->data
.dsize
= data
.dsize
;
157 static int db_tdb_fetch(struct db_context
*db
, TALLOC_CTX
*mem_ctx
,
158 TDB_DATA key
, TDB_DATA
*pdata
)
160 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(
161 db
->private_data
, struct db_tdb_ctx
);
163 struct tdb_fetch_state state
;
165 state
.mem_ctx
= mem_ctx
;
167 state
.data
= tdb_null
;
169 tdb_parse_record(ctx
->wtdb
->tdb
, key
, db_tdb_fetch_parse
, &state
);
171 if (state
.result
== -1) {
179 static int db_tdb_parse(struct db_context
*db
, TDB_DATA key
,
180 int (*parser
)(TDB_DATA key
, TDB_DATA data
,
184 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(
185 db
->private_data
, struct db_tdb_ctx
);
187 return tdb_parse_record(ctx
->wtdb
->tdb
, key
, parser
, private_data
);
190 static NTSTATUS
db_tdb_store(struct db_record
*rec
, TDB_DATA data
, int flag
)
192 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(rec
->private_data
,
196 * This has a bug: We need to replace rec->value for correct
197 * operation, but right now brlock and locking don't use the value
198 * anymore after it was stored.
201 return (tdb_store(ctx
->wtdb
->tdb
, rec
->key
, data
, flag
) == 0) ?
202 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
205 static NTSTATUS
db_tdb_delete(struct db_record
*rec
)
207 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(rec
->private_data
,
210 if (tdb_delete(ctx
->wtdb
->tdb
, rec
->key
) == 0) {
214 if (tdb_error(ctx
->wtdb
->tdb
) == TDB_ERR_NOEXIST
) {
215 return NT_STATUS_NOT_FOUND
;
218 return NT_STATUS_UNSUCCESSFUL
;
221 struct db_tdb_traverse_ctx
{
222 struct db_context
*db
;
223 int (*f
)(struct db_record
*rec
, void *private_data
);
227 static int db_tdb_traverse_func(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
230 struct db_tdb_traverse_ctx
*ctx
=
231 (struct db_tdb_traverse_ctx
*)private_data
;
232 struct db_record rec
;
236 rec
.store
= db_tdb_store
;
237 rec
.delete_rec
= db_tdb_delete
;
238 rec
.private_data
= ctx
->db
->private_data
;
240 return ctx
->f(&rec
, ctx
->private_data
);
243 static int db_tdb_traverse(struct db_context
*db
,
244 int (*f
)(struct db_record
*rec
, void *private_data
),
247 struct db_tdb_ctx
*db_ctx
=
248 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
249 struct db_tdb_traverse_ctx ctx
;
253 ctx
.private_data
= private_data
;
254 return tdb_traverse(db_ctx
->wtdb
->tdb
, db_tdb_traverse_func
, &ctx
);
257 static NTSTATUS
db_tdb_store_deny(struct db_record
*rec
, TDB_DATA data
, int flag
)
259 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
262 static NTSTATUS
db_tdb_delete_deny(struct db_record
*rec
)
264 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
267 static int db_tdb_traverse_read_func(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
270 struct db_tdb_traverse_ctx
*ctx
=
271 (struct db_tdb_traverse_ctx
*)private_data
;
272 struct db_record rec
;
276 rec
.store
= db_tdb_store_deny
;
277 rec
.delete_rec
= db_tdb_delete_deny
;
278 rec
.private_data
= ctx
->db
->private_data
;
280 return ctx
->f(&rec
, ctx
->private_data
);
283 static int db_tdb_traverse_read(struct db_context
*db
,
284 int (*f
)(struct db_record
*rec
, void *private_data
),
287 struct db_tdb_ctx
*db_ctx
=
288 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
289 struct db_tdb_traverse_ctx ctx
;
293 ctx
.private_data
= private_data
;
294 return tdb_traverse_read(db_ctx
->wtdb
->tdb
, db_tdb_traverse_read_func
, &ctx
);
297 static int db_tdb_get_seqnum(struct db_context
*db
)
300 struct db_tdb_ctx
*db_ctx
=
301 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
302 return tdb_get_seqnum(db_ctx
->wtdb
->tdb
);
305 static int db_tdb_get_flags(struct db_context
*db
)
308 struct db_tdb_ctx
*db_ctx
=
309 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
310 return tdb_get_flags(db_ctx
->wtdb
->tdb
);
313 static int db_tdb_transaction_start(struct db_context
*db
)
315 struct db_tdb_ctx
*db_ctx
=
316 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
317 return tdb_transaction_start(db_ctx
->wtdb
->tdb
);
320 static int db_tdb_transaction_commit(struct db_context
*db
)
322 struct db_tdb_ctx
*db_ctx
=
323 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
324 return tdb_transaction_commit(db_ctx
->wtdb
->tdb
);
327 static int db_tdb_transaction_cancel(struct db_context
*db
)
329 struct db_tdb_ctx
*db_ctx
=
330 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
331 return tdb_transaction_cancel(db_ctx
->wtdb
->tdb
);
334 struct db_context
*db_open_tdb(TALLOC_CTX
*mem_ctx
,
336 int hash_size
, int tdb_flags
,
337 int open_flags
, mode_t mode
)
339 struct db_context
*result
= NULL
;
340 struct db_tdb_ctx
*db_tdb
;
342 result
= TALLOC_ZERO_P(mem_ctx
, struct db_context
);
343 if (result
== NULL
) {
344 DEBUG(0, ("talloc failed\n"));
348 result
->private_data
= db_tdb
= TALLOC_P(result
, struct db_tdb_ctx
);
349 if (db_tdb
== NULL
) {
350 DEBUG(0, ("talloc failed\n"));
354 db_tdb
->wtdb
= tdb_wrap_open(db_tdb
, name
, hash_size
, tdb_flags
,
356 if (db_tdb
->wtdb
== NULL
) {
357 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno
)));
361 result
->fetch_locked
= db_tdb_fetch_locked
;
362 result
->fetch
= db_tdb_fetch
;
363 result
->traverse
= db_tdb_traverse
;
364 result
->traverse_read
= db_tdb_traverse_read
;
365 result
->parse_record
= db_tdb_parse
;
366 result
->get_seqnum
= db_tdb_get_seqnum
;
367 result
->get_flags
= db_tdb_get_flags
;
368 result
->persistent
= ((tdb_flags
& TDB_CLEAR_IF_FIRST
) == 0);
369 result
->transaction_start
= db_tdb_transaction_start
;
370 result
->transaction_commit
= db_tdb_transaction_commit
;
371 result
->transaction_cancel
= db_tdb_transaction_cancel
;
375 if (result
!= NULL
) {