2 Unix SMB/CIFS implementation.
4 Database interface wrapper around tdb
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Andrew Tridgell 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "lib/tdb/include/tdb.h"
25 #include "lib/dbwrap/dbwrap.h"
26 #include "system/filesys.h"
28 #include "param/param.h"
31 struct tdb_wrap
*wtdb
;
34 static NTSTATUS
db_tdb_store(struct db_record
*rec
, TDB_DATA data
, int flag
);
35 static NTSTATUS
db_tdb_delete(struct db_record
*rec
);
37 static int db_tdb_record_destr(struct db_record
* data
)
39 struct db_tdb_ctx
*ctx
= talloc_get_type(data
->private_data
, struct db_tdb_ctx
);
41 if (tdb_chainunlock(ctx
->wtdb
->tdb
, data
->key
) != 0) {
42 DEBUG(0, ("tdb_chainunlock failed\n"));
48 static int db_tdb_fetch(struct db_context
*db
, TALLOC_CTX
*mem_ctx
, TDB_DATA key
, TDB_DATA
*data
)
50 struct db_tdb_ctx
*ctx
= talloc_get_type(db
->private_data
, struct db_tdb_ctx
);
53 value
= tdb_fetch(ctx
->wtdb
->tdb
, key
);
54 if (value
.dptr
== NULL
) {
58 data
->dsize
= value
.dsize
;
59 data
->dptr
= (uint8_t *)talloc_memdup(mem_ctx
, value
.dptr
, value
.dsize
);
61 if (data
->dptr
== NULL
) {
69 static struct db_record
*db_tdb_fetch_locked(struct db_context
*db
,
70 TALLOC_CTX
*mem_ctx
, TDB_DATA key
)
72 struct db_tdb_ctx
*ctx
= talloc_get_type(db
->private_data
, struct db_tdb_ctx
);
73 struct db_record
*result
;
76 result
= talloc(mem_ctx
, struct db_record
);
81 result
->key
.dsize
= key
.dsize
;
82 result
->key
.dptr
= (uint8_t *)talloc_memdup(result
, key
.dptr
, key
.dsize
);
83 if (result
->key
.dptr
== NULL
) {
88 result
->value
.dptr
= NULL
;
89 result
->value
.dsize
= 0;
90 result
->private_data
= talloc_reference(result
, ctx
);
91 result
->store
= db_tdb_store
;
92 result
->delete_rec
= db_tdb_delete
;
94 if (tdb_chainlock(ctx
->wtdb
->tdb
, key
) != 0) {
99 talloc_set_destructor(result
, db_tdb_record_destr
);
101 value
= tdb_fetch(ctx
->wtdb
->tdb
, key
);
103 if (value
.dptr
== NULL
) {
107 result
->value
.dsize
= value
.dsize
;
108 result
->value
.dptr
= (uint8_t *)talloc_memdup(result
, value
.dptr
,
111 if (result
->value
.dptr
== NULL
) {
119 static NTSTATUS
db_tdb_store(struct db_record
*rec
, TDB_DATA data
, int flag
)
121 struct db_tdb_ctx
*ctx
= talloc_get_type(rec
->private_data
, struct db_tdb_ctx
);
124 * This has a bug: We need to replace rec->value for correct
125 * operation, but right now brlock and locking don't use the value
126 * anymore after it was stored.
129 return (tdb_store(ctx
->wtdb
->tdb
, rec
->key
, data
, flag
) == 0) ?
130 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
133 static NTSTATUS
db_tdb_delete(struct db_record
*rec
)
135 struct db_tdb_ctx
*ctx
= talloc_get_type(rec
->private_data
, struct db_tdb_ctx
);
137 return (tdb_delete(ctx
->wtdb
->tdb
, rec
->key
) == 0) ?
138 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
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(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(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(db
->private_data
, struct db_tdb_ctx
);
222 return tdb_get_seqnum(db_ctx
->wtdb
->tdb
);
226 open a temporary database
228 struct db_context
*db_tmp_open_tdb(TALLOC_CTX
*mem_ctx
, struct loadparm_context
*lp_ctx
,
229 const char *name
, int tdb_flags
)
231 struct db_context
*result
;
232 struct db_tdb_ctx
*db_tdb
;
235 result
= talloc_zero(mem_ctx
, struct db_context
);
236 if (result
== NULL
) goto failed
;
238 db_tdb
= talloc(result
, struct db_tdb_ctx
);
239 if (db_tdb
== NULL
) goto failed
;
241 result
->private_data
= db_tdb
;
243 /* the name passed in should not be a full path, it should be
244 just be the db name */
245 path
= smbd_tmp_path(result
, lp_ctx
, name
);
247 db_tdb
->wtdb
= tdb_wrap_open(db_tdb
, path
, 0, tdb_flags
,
248 O_CREAT
|O_RDWR
, 0666);
249 if (db_tdb
->wtdb
== NULL
) {
250 DEBUG(3, ("Could not open tdb '%s': %s\n", path
, strerror(errno
)));
256 result
->fetch_locked
= db_tdb_fetch_locked
;
257 result
->fetch
= db_tdb_fetch
;
258 result
->traverse
= db_tdb_traverse
;
259 result
->traverse_read
= db_tdb_traverse_read
;
260 result
->get_seqnum
= db_tdb_get_seqnum
;