s3-utils/net_rpc_printer.c: print more info on write error
[Samba/gebeck_regimport.git] / source3 / lib / dbwrap_tdb.c
blob2efb3dfe39db2e102ccf60d85b4a014b18ae41c0
1 /*
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/>.
20 #include "includes.h"
21 #include "dbwrap.h"
22 #include "lib/util/tdb_wrap.h"
24 struct db_tdb_ctx {
25 struct tdb_wrap *wtdb;
28 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
29 static NTSTATUS db_tdb_delete(struct db_record *rec);
31 static int db_tdb_record_destr(struct db_record* data)
33 struct db_tdb_ctx *ctx =
34 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
36 /* This hex_encode_talloc() call allocates memory on data context. By way how current
37 __talloc_free() code works, it is OK to allocate in the destructor as
38 the children of data will be freed after call to the destructor and this
39 new 'child' will be caught and freed correctly.
41 DEBUG(10, (DEBUGLEVEL > 10
42 ? "Unlocking key %s\n" : "Unlocking key %.20s\n",
43 hex_encode_talloc(data, (unsigned char *)data->key.dptr,
44 data->key.dsize)));
46 tdb_chainunlock(ctx->wtdb->tdb, data->key);
47 return 0;
50 struct tdb_fetch_locked_state {
51 TALLOC_CTX *mem_ctx;
52 struct db_record *result;
55 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
56 void *private_data)
58 struct tdb_fetch_locked_state *state =
59 (struct tdb_fetch_locked_state *)private_data;
61 state->result = (struct db_record *)talloc_size(
62 state->mem_ctx,
63 sizeof(struct db_record) + key.dsize + data.dsize);
65 if (state->result == NULL) {
66 return 0;
69 state->result->key.dsize = key.dsize;
70 state->result->key.dptr = ((uint8 *)state->result)
71 + sizeof(struct db_record);
72 memcpy(state->result->key.dptr, key.dptr, key.dsize);
74 state->result->value.dsize = data.dsize;
76 if (data.dsize > 0) {
77 state->result->value.dptr = state->result->key.dptr+key.dsize;
78 memcpy(state->result->value.dptr, data.dptr, data.dsize);
80 else {
81 state->result->value.dptr = NULL;
84 return 0;
87 static struct db_record *db_tdb_fetch_locked(struct db_context *db,
88 TALLOC_CTX *mem_ctx, TDB_DATA key)
90 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
91 struct db_tdb_ctx);
92 struct tdb_fetch_locked_state state;
94 /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
95 if(DEBUGLEVEL >= 10) {
96 char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize);
97 DEBUG(10, (DEBUGLEVEL > 10
98 ? "Locking key %s\n" : "Locking key %.20s\n",
99 keystr));
100 TALLOC_FREE(keystr);
103 if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
104 DEBUG(3, ("tdb_chainlock failed\n"));
105 return NULL;
108 state.mem_ctx = mem_ctx;
109 state.result = NULL;
111 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
113 if (state.result == NULL) {
114 db_tdb_fetchlock_parse(key, tdb_null, &state);
117 if (state.result == NULL) {
118 tdb_chainunlock(ctx->wtdb->tdb, key);
119 return NULL;
122 talloc_set_destructor(state.result, db_tdb_record_destr);
124 state.result->private_data = talloc_reference(state.result, ctx);
125 state.result->store = db_tdb_store;
126 state.result->delete_rec = db_tdb_delete;
128 DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
130 return state.result;
133 struct tdb_fetch_state {
134 TALLOC_CTX *mem_ctx;
135 int result;
136 TDB_DATA data;
139 static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA data,
140 void *private_data)
142 struct tdb_fetch_state *state =
143 (struct tdb_fetch_state *)private_data;
145 state->data.dptr = (uint8 *)talloc_memdup(state->mem_ctx, data.dptr,
146 data.dsize);
147 if (state->data.dptr == NULL) {
148 state->result = -1;
149 return 0;
152 state->data.dsize = data.dsize;
153 return 0;
156 static int db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
157 TDB_DATA key, TDB_DATA *pdata)
159 struct db_tdb_ctx *ctx = talloc_get_type_abort(
160 db->private_data, struct db_tdb_ctx);
162 struct tdb_fetch_state state;
164 state.mem_ctx = mem_ctx;
165 state.result = 0;
166 state.data = tdb_null;
168 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
170 if (state.result == -1) {
171 return -1;
174 *pdata = state.data;
175 return 0;
178 static int db_tdb_parse(struct db_context *db, TDB_DATA key,
179 int (*parser)(TDB_DATA key, TDB_DATA data,
180 void *private_data),
181 void *private_data)
183 struct db_tdb_ctx *ctx = talloc_get_type_abort(
184 db->private_data, struct db_tdb_ctx);
186 return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data);
189 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
191 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
192 struct db_tdb_ctx);
195 * This has a bug: We need to replace rec->value for correct
196 * operation, but right now brlock and locking don't use the value
197 * anymore after it was stored.
200 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
201 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
204 static NTSTATUS db_tdb_delete(struct db_record *rec)
206 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
207 struct db_tdb_ctx);
209 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
210 return NT_STATUS_OK;
213 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
214 return NT_STATUS_NOT_FOUND;
217 return NT_STATUS_UNSUCCESSFUL;
220 struct db_tdb_traverse_ctx {
221 struct db_context *db;
222 int (*f)(struct db_record *rec, void *private_data);
223 void *private_data;
226 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
227 void *private_data)
229 struct db_tdb_traverse_ctx *ctx =
230 (struct db_tdb_traverse_ctx *)private_data;
231 struct db_record rec;
233 rec.key = kbuf;
234 rec.value = dbuf;
235 rec.store = db_tdb_store;
236 rec.delete_rec = db_tdb_delete;
237 rec.private_data = ctx->db->private_data;
239 return ctx->f(&rec, ctx->private_data);
242 static int db_tdb_traverse(struct db_context *db,
243 int (*f)(struct db_record *rec, void *private_data),
244 void *private_data)
246 struct db_tdb_ctx *db_ctx =
247 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
248 struct db_tdb_traverse_ctx ctx;
250 ctx.db = db;
251 ctx.f = f;
252 ctx.private_data = private_data;
253 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
256 static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
258 return NT_STATUS_MEDIA_WRITE_PROTECTED;
261 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
263 return NT_STATUS_MEDIA_WRITE_PROTECTED;
266 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
267 void *private_data)
269 struct db_tdb_traverse_ctx *ctx =
270 (struct db_tdb_traverse_ctx *)private_data;
271 struct db_record rec;
273 rec.key = kbuf;
274 rec.value = dbuf;
275 rec.store = db_tdb_store_deny;
276 rec.delete_rec = db_tdb_delete_deny;
277 rec.private_data = ctx->db->private_data;
279 return ctx->f(&rec, ctx->private_data);
282 static int db_tdb_traverse_read(struct db_context *db,
283 int (*f)(struct db_record *rec, void *private_data),
284 void *private_data)
286 struct db_tdb_ctx *db_ctx =
287 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
288 struct db_tdb_traverse_ctx ctx;
290 ctx.db = db;
291 ctx.f = f;
292 ctx.private_data = private_data;
293 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
296 static int db_tdb_get_seqnum(struct db_context *db)
299 struct db_tdb_ctx *db_ctx =
300 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
301 return tdb_get_seqnum(db_ctx->wtdb->tdb);
304 static int db_tdb_get_flags(struct db_context *db)
307 struct db_tdb_ctx *db_ctx =
308 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
309 return tdb_get_flags(db_ctx->wtdb->tdb);
312 static int db_tdb_transaction_start(struct db_context *db)
314 struct db_tdb_ctx *db_ctx =
315 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
316 return tdb_transaction_start(db_ctx->wtdb->tdb);
319 static int db_tdb_transaction_commit(struct db_context *db)
321 struct db_tdb_ctx *db_ctx =
322 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
323 return tdb_transaction_commit(db_ctx->wtdb->tdb);
326 static int db_tdb_transaction_cancel(struct db_context *db)
328 struct db_tdb_ctx *db_ctx =
329 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
330 tdb_transaction_cancel(db_ctx->wtdb->tdb);
331 return 0;
334 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
335 const char *name,
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(mem_ctx, struct db_context);
343 if (result == NULL) {
344 DEBUG(0, ("talloc failed\n"));
345 goto fail;
348 result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
349 if (db_tdb == NULL) {
350 DEBUG(0, ("talloc failed\n"));
351 goto fail;
354 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
355 open_flags, mode);
356 if (db_tdb->wtdb == NULL) {
357 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
358 goto fail;
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;
372 return result;
374 fail:
375 if (result != NULL) {
376 TALLOC_FREE(result);
378 return NULL;