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 DEBUG(10, (DEBUGLEVEL
> 10
35 ? "Unlocking key %s\n" : "Unlocking key %.20s\n",
36 hex_encode(data
, (unsigned char *)data
->key
.dptr
,
39 if (tdb_chainunlock(ctx
->wtdb
->tdb
, data
->key
) != 0) {
40 DEBUG(0, ("tdb_chainunlock failed\n"));
46 static struct db_record
*db_tdb_fetch_locked(struct db_context
*db
,
47 TALLOC_CTX
*mem_ctx
, TDB_DATA key
)
49 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(db
->private_data
,
51 struct db_record
*result
;
54 result
= TALLOC_P(mem_ctx
, struct db_record
);
56 DEBUG(0, ("talloc failed\n"));
60 result
->key
.dsize
= key
.dsize
;
61 result
->key
.dptr
= (uint8
*)talloc_memdup(result
, key
.dptr
, key
.dsize
);
62 if (result
->key
.dptr
== NULL
) {
63 DEBUG(0, ("talloc failed\n"));
68 result
->value
.dptr
= NULL
;
69 result
->value
.dsize
= 0;
70 result
->private_data
= talloc_reference(result
, ctx
);
71 result
->store
= db_tdb_store
;
72 result
->delete_rec
= db_tdb_delete
;
74 if (DEBUGLEVEL
>= 10) {
75 char *keystr
= hex_encode(NULL
, key
.dptr
, key
.dsize
);
76 DEBUG(10, (DEBUGLEVEL
> 10
77 ? "Locking key %s\n" : "Locking key %.20s\n",
82 if (tdb_chainlock(ctx
->wtdb
->tdb
, key
) != 0) {
83 DEBUG(3, ("tdb_chainlock failed\n"));
88 talloc_set_destructor(result
, db_tdb_record_destr
);
90 value
= tdb_fetch(ctx
->wtdb
->tdb
, key
);
92 if (value
.dptr
== NULL
) {
96 result
->value
.dsize
= value
.dsize
;
97 result
->value
.dptr
= (uint8
*)talloc_memdup(result
, value
.dptr
,
99 if (result
->value
.dptr
== NULL
) {
100 DEBUG(3, ("talloc failed\n"));
105 SAFE_FREE(value
.dptr
);
107 DEBUG(10, ("Allocated locked data 0x%p\n", result
));
112 static NTSTATUS
db_tdb_store(struct db_record
*rec
, TDB_DATA data
, int flag
)
114 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(rec
->private_data
,
118 * This has a bug: We need to replace rec->value for correct
119 * operation, but right now brlock and locking don't use the value
120 * anymore after it was stored.
123 return (tdb_store(ctx
->wtdb
->tdb
, rec
->key
, data
, flag
) == 0) ?
124 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
127 static NTSTATUS
db_tdb_delete(struct db_record
*rec
)
129 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(rec
->private_data
,
133 res
= tdb_delete(ctx
->wtdb
->tdb
, rec
->key
);
139 return map_nt_error_from_tdb(tdb_error(ctx
->wtdb
->tdb
));
142 struct db_tdb_traverse_ctx
{
143 struct db_context
*db
;
144 int (*f
)(struct db_record
*rec
, void *private_data
);
148 static int db_tdb_traverse_func(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
151 struct db_tdb_traverse_ctx
*ctx
=
152 (struct db_tdb_traverse_ctx
*)private_data
;
153 struct db_record rec
;
157 rec
.store
= db_tdb_store
;
158 rec
.delete_rec
= db_tdb_delete
;
159 rec
.private_data
= ctx
->db
->private_data
;
161 return ctx
->f(&rec
, ctx
->private_data
);
164 static int db_tdb_traverse(struct db_context
*db
,
165 int (*f
)(struct db_record
*rec
, void *private_data
),
168 struct db_tdb_ctx
*db_ctx
=
169 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
170 struct db_tdb_traverse_ctx ctx
;
174 ctx
.private_data
= private_data
;
175 return tdb_traverse(db_ctx
->wtdb
->tdb
, db_tdb_traverse_func
, &ctx
);
178 static NTSTATUS
db_tdb_store_deny(struct db_record
*rec
, TDB_DATA data
, int flag
)
180 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
183 static NTSTATUS
db_tdb_delete_deny(struct db_record
*rec
)
185 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
188 static int db_tdb_traverse_read_func(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
191 struct db_tdb_traverse_ctx
*ctx
=
192 (struct db_tdb_traverse_ctx
*)private_data
;
193 struct db_record rec
;
197 rec
.store
= db_tdb_store_deny
;
198 rec
.delete_rec
= db_tdb_delete_deny
;
199 rec
.private_data
= ctx
->db
->private_data
;
201 return ctx
->f(&rec
, ctx
->private_data
);
204 static int db_tdb_traverse_read(struct db_context
*db
,
205 int (*f
)(struct db_record
*rec
, void *private_data
),
208 struct db_tdb_ctx
*db_ctx
=
209 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
210 struct db_tdb_traverse_ctx ctx
;
214 ctx
.private_data
= private_data
;
215 return tdb_traverse_read(db_ctx
->wtdb
->tdb
, db_tdb_traverse_read_func
, &ctx
);
218 static int db_tdb_get_seqnum(struct db_context
*db
)
221 struct db_tdb_ctx
*db_ctx
=
222 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
223 return tdb_get_seqnum(db_ctx
->wtdb
->tdb
);
226 struct db_context
*db_open_tdb(TALLOC_CTX
*mem_ctx
,
228 int hash_size
, int tdb_flags
,
229 int open_flags
, mode_t mode
)
231 struct db_context
*result
= NULL
;
232 struct db_tdb_ctx
*db_tdb
;
234 result
= TALLOC_ZERO_P(mem_ctx
, struct db_context
);
235 if (result
== NULL
) {
236 DEBUG(0, ("talloc failed\n"));
240 result
->private_data
= db_tdb
= TALLOC_P(result
, struct db_tdb_ctx
);
241 if (db_tdb
== NULL
) {
242 DEBUG(0, ("talloc failed\n"));
246 db_tdb
->wtdb
= tdb_wrap_open(db_tdb
, name
, hash_size
, tdb_flags
,
248 if (db_tdb
->wtdb
== NULL
) {
249 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno
)));
253 result
->fetch_locked
= db_tdb_fetch_locked
;
254 result
->traverse
= db_tdb_traverse
;
255 result
->traverse_read
= db_tdb_traverse_read
;
256 result
->get_seqnum
= db_tdb_get_seqnum
;
260 if (result
!= NULL
) {