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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 struct tdb_wrap
*wtdb
;
27 static NTSTATUS
db_tdb_store(struct db_record
*rec
, TDB_DATA data
, int flag
);
28 static NTSTATUS
db_tdb_delete(struct db_record
*rec
);
30 static int db_tdb_record_destr(struct db_record
* data
)
32 struct db_tdb_ctx
*ctx
=
33 talloc_get_type_abort(data
->private_data
, struct db_tdb_ctx
);
35 DEBUG(10, ("Unlocking key %s\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
;
75 char *keystr
= hex_encode(NULL
, (unsigned char *)key
.dptr
,
77 DEBUG(10, ("Locking key %s\n", keystr
));
81 if (tdb_chainlock(ctx
->wtdb
->tdb
, key
) != 0) {
82 DEBUG(3, ("tdb_chainlock failed\n"));
87 talloc_set_destructor(result
, db_tdb_record_destr
);
89 value
= tdb_fetch(ctx
->wtdb
->tdb
, key
);
91 if (value
.dptr
== NULL
) {
95 result
->value
.dsize
= value
.dsize
;
96 result
->value
.dptr
= (uint8
*)talloc_memdup(result
, value
.dptr
,
98 if (result
->value
.dptr
== NULL
) {
99 DEBUG(3, ("talloc failed\n"));
104 SAFE_FREE(value
.dptr
);
106 DEBUG(10, ("Allocated locked data 0x%p\n", result
));
111 static NTSTATUS
db_tdb_store(struct db_record
*rec
, TDB_DATA data
, int flag
)
113 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(rec
->private_data
,
117 * This has a bug: We need to replace rec->value for correct
118 * operation, but right now brlock and locking don't use the value
119 * anymore after it was stored.
122 return (tdb_store(ctx
->wtdb
->tdb
, rec
->key
, data
, flag
) == 0) ?
123 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
126 static NTSTATUS
db_tdb_delete(struct db_record
*rec
)
128 struct db_tdb_ctx
*ctx
= talloc_get_type_abort(rec
->private_data
,
132 res
= tdb_delete(ctx
->wtdb
->tdb
, rec
->key
);
138 return map_nt_error_from_tdb(tdb_error(ctx
->wtdb
->tdb
));
141 struct db_tdb_traverse_ctx
{
142 struct db_context
*db
;
143 int (*f
)(struct db_record
*rec
, void *private_data
);
147 static int db_tdb_traverse_func(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
150 struct db_tdb_traverse_ctx
*ctx
=
151 (struct db_tdb_traverse_ctx
*)private_data
;
152 struct db_record rec
;
156 rec
.store
= db_tdb_store
;
157 rec
.delete_rec
= db_tdb_delete
;
158 rec
.private_data
= ctx
->db
->private_data
;
160 return ctx
->f(&rec
, ctx
->private_data
);
163 static int db_tdb_traverse(struct db_context
*db
,
164 int (*f
)(struct db_record
*rec
, void *private_data
),
167 struct db_tdb_ctx
*db_ctx
=
168 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
169 struct db_tdb_traverse_ctx ctx
;
173 ctx
.private_data
= private_data
;
174 return tdb_traverse(db_ctx
->wtdb
->tdb
, db_tdb_traverse_func
, &ctx
);
177 static NTSTATUS
db_tdb_store_deny(struct db_record
*rec
, TDB_DATA data
, int flag
)
179 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
182 static NTSTATUS
db_tdb_delete_deny(struct db_record
*rec
)
184 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
187 static int db_tdb_traverse_read_func(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
190 struct db_tdb_traverse_ctx
*ctx
=
191 (struct db_tdb_traverse_ctx
*)private_data
;
192 struct db_record rec
;
196 rec
.store
= db_tdb_store_deny
;
197 rec
.delete_rec
= db_tdb_delete_deny
;
198 rec
.private_data
= ctx
->db
->private_data
;
200 return ctx
->f(&rec
, ctx
->private_data
);
203 static int db_tdb_traverse_read(struct db_context
*db
,
204 int (*f
)(struct db_record
*rec
, void *private_data
),
207 struct db_tdb_ctx
*db_ctx
=
208 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
209 struct db_tdb_traverse_ctx ctx
;
213 ctx
.private_data
= private_data
;
214 return tdb_traverse_read(db_ctx
->wtdb
->tdb
, db_tdb_traverse_read_func
, &ctx
);
217 static int db_tdb_get_seqnum(struct db_context
*db
)
220 struct db_tdb_ctx
*db_ctx
=
221 talloc_get_type_abort(db
->private_data
, struct db_tdb_ctx
);
222 return tdb_get_seqnum(db_ctx
->wtdb
->tdb
);
225 struct db_context
*db_open_tdb(TALLOC_CTX
*mem_ctx
,
227 int hash_size
, int tdb_flags
,
228 int open_flags
, mode_t mode
)
230 struct db_context
*result
= NULL
;
231 struct db_tdb_ctx
*db_tdb
;
233 result
= TALLOC_ZERO_P(mem_ctx
, struct db_context
);
234 if (result
== NULL
) {
235 DEBUG(0, ("talloc failed\n"));
239 result
->private_data
= db_tdb
= TALLOC_P(result
, struct db_tdb_ctx
);
240 if (db_tdb
== NULL
) {
241 DEBUG(0, ("talloc failed\n"));
245 db_tdb
->wtdb
= tdb_wrap_open(db_tdb
, name
, hash_size
, tdb_flags
,
247 if (db_tdb
->wtdb
== NULL
) {
248 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno
)));
252 result
->fetch_locked
= db_tdb_fetch_locked
;
253 result
->traverse
= db_tdb_traverse
;
254 result
->traverse_read
= db_tdb_traverse_read
;
255 result
->get_seqnum
= db_tdb_get_seqnum
;
259 if (result
!= NULL
) {