vfs_glusterfs: Use glfs_renameat() for SMB_VFS_RENAMEAT
[samba4-gss.git] / lib / dbwrap / dbwrap_tdb.c
blob6cd95fa25ad524559d219b1a765b887565d2b338
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 "replace.h"
21 #include "dbwrap/dbwrap.h"
22 #include "dbwrap/dbwrap_private.h"
23 #include "dbwrap/dbwrap_tdb.h"
24 #include "lib/tdb_wrap/tdb_wrap.h"
25 #include "lib/util/util_tdb.h"
26 #include "lib/util/debug.h"
27 #include "lib/util/samba_util.h"
28 #include "system/filesys.h"
29 #include "lib/param/param.h"
30 #include "libcli/util/error.h"
32 struct db_tdb_ctx {
33 struct tdb_wrap *wtdb;
35 struct {
36 dev_t dev;
37 ino_t ino;
38 } id;
41 static NTSTATUS db_tdb_storev(struct db_record *rec,
42 const TDB_DATA *dbufs, int num_dbufs, int flag);
43 static NTSTATUS db_tdb_delete(struct db_record *rec);
45 static void db_tdb_log_key(const char *prefix, TDB_DATA key)
47 if (DEBUGLEVEL < 10) {
48 return;
50 if (DEBUGLEVEL == 10) {
52 * Only fully spam at debuglevel > 10
54 key.dsize = MIN(10, key.dsize);
57 if (key.dsize < 1024) {
58 char keystr[key.dsize*2+1];
59 hex_encode_buf(keystr, key.dptr, key.dsize);
60 DBG_DEBUG("%s key %s\n", prefix, keystr);
61 return;
64 dump_data(DEBUGLEVEL, key.dptr, key.dsize);
67 static int db_tdb_record_destr(struct db_record* data)
69 struct db_tdb_ctx *ctx =
70 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
72 db_tdb_log_key("Unlocking", data->key);
73 tdb_chainunlock(ctx->wtdb->tdb, data->key);
74 return 0;
77 struct tdb_fetch_locked_state {
78 TALLOC_CTX *mem_ctx;
79 struct db_record *result;
82 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
83 void *private_data)
85 struct tdb_fetch_locked_state *state =
86 (struct tdb_fetch_locked_state *)private_data;
87 struct db_record *result;
89 result = (struct db_record *)talloc_size(
90 state->mem_ctx,
91 sizeof(struct db_record) + key.dsize + data.dsize);
93 if (result == NULL) {
94 return 0;
96 state->result = result;
98 result->key.dsize = key.dsize;
99 result->key.dptr = ((uint8_t *)result) + sizeof(struct db_record);
100 memcpy(result->key.dptr, key.dptr, key.dsize);
102 result->value.dsize = data.dsize;
104 if (data.dsize > 0) {
105 result->value.dptr = result->key.dptr+key.dsize;
106 memcpy(result->value.dptr, data.dptr, data.dsize);
108 else {
109 result->value.dptr = NULL;
111 result->value_valid = true;
113 return 0;
116 static struct db_record *db_tdb_fetch_locked_internal(
117 struct db_context *db,
118 struct db_tdb_ctx *ctx,
119 TALLOC_CTX *mem_ctx,
120 TDB_DATA key)
122 struct tdb_fetch_locked_state state;
123 int ret;
125 state = (struct tdb_fetch_locked_state) {
126 .mem_ctx = mem_ctx,
129 ret = tdb_parse_record(ctx->wtdb->tdb,
130 key,
131 db_tdb_fetchlock_parse,
132 &state);
133 if ((ret < 0) && (tdb_error(ctx->wtdb->tdb) != TDB_ERR_NOEXIST)) {
134 tdb_chainunlock(ctx->wtdb->tdb, key);
135 return NULL;
138 if (state.result == NULL) {
139 db_tdb_fetchlock_parse(key, tdb_null, &state);
142 if (state.result == NULL) {
143 tdb_chainunlock(ctx->wtdb->tdb, key);
144 return NULL;
147 talloc_set_destructor(state.result, db_tdb_record_destr);
149 state.result->private_data = ctx;
150 state.result->storev = db_tdb_storev;
151 state.result->delete_rec = db_tdb_delete;
153 DBG_DEBUG("Allocated locked data %p\n", state.result);
155 return state.result;
158 static struct db_record *db_tdb_fetch_locked(
159 struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
161 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
162 struct db_tdb_ctx);
164 db_tdb_log_key("Locking", key);
165 if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
166 DEBUG(3, ("tdb_chainlock failed\n"));
167 return NULL;
169 return db_tdb_fetch_locked_internal(db, ctx, mem_ctx, key);
172 static NTSTATUS db_tdb_do_locked(struct db_context *db, TDB_DATA key,
173 void (*fn)(struct db_record *rec,
174 TDB_DATA value,
175 void *private_data),
176 void *private_data)
178 struct db_tdb_ctx *ctx = talloc_get_type_abort(
179 db->private_data, struct db_tdb_ctx);
180 uint8_t *buf = NULL;
181 struct db_record rec;
182 int ret;
184 ret = tdb_chainlock(ctx->wtdb->tdb, key);
185 if (ret == -1) {
186 enum TDB_ERROR err = tdb_error(ctx->wtdb->tdb);
187 DBG_DEBUG("tdb_chainlock failed: %s\n",
188 tdb_errorstr(ctx->wtdb->tdb));
189 return map_nt_error_from_tdb(err);
192 ret = tdb_fetch_talloc(ctx->wtdb->tdb, key, ctx, &buf);
194 if ((ret != 0) && (ret != ENOENT)) {
195 DBG_DEBUG("tdb_fetch_talloc failed: %s\n",
196 strerror(errno));
197 tdb_chainunlock(ctx->wtdb->tdb, key);
198 return map_nt_error_from_unix_common(ret);
201 rec = (struct db_record) {
202 .db = db, .key = key,
203 .value_valid = false,
204 .storev = db_tdb_storev, .delete_rec = db_tdb_delete,
205 .private_data = ctx
208 fn(&rec,
209 (TDB_DATA) { .dptr = buf, .dsize = talloc_get_size(buf) },
210 private_data);
212 tdb_chainunlock(ctx->wtdb->tdb, key);
214 talloc_free(buf);
216 return NT_STATUS_OK;
219 static int db_tdb_exists(struct db_context *db, TDB_DATA key)
221 struct db_tdb_ctx *ctx = talloc_get_type_abort(
222 db->private_data, struct db_tdb_ctx);
223 return tdb_exists(ctx->wtdb->tdb, key);
226 static int db_tdb_wipe(struct db_context *db)
228 struct db_tdb_ctx *ctx = talloc_get_type_abort(
229 db->private_data, struct db_tdb_ctx);
230 return tdb_wipe_all(ctx->wtdb->tdb);
233 static int db_tdb_check(struct db_context *db)
235 struct db_tdb_ctx *ctx = talloc_get_type_abort(
236 db->private_data, struct db_tdb_ctx);
237 return tdb_check(ctx->wtdb->tdb, NULL, NULL);
240 struct db_tdb_parse_state {
241 void (*parser)(TDB_DATA key, TDB_DATA data,
242 void *private_data);
243 void *private_data;
247 * tdb_parse_record expects a parser returning int, mixing up tdb and
248 * parser errors. Wrap around that by always returning 0 and have
249 * dbwrap_parse_record expect a parser returning void.
252 static int db_tdb_parser(TDB_DATA key, TDB_DATA data, void *private_data)
254 struct db_tdb_parse_state *state =
255 (struct db_tdb_parse_state *)private_data;
256 state->parser(key, data, state->private_data);
257 return 0;
260 static NTSTATUS db_tdb_parse(struct db_context *db, TDB_DATA key,
261 void (*parser)(TDB_DATA key, TDB_DATA data,
262 void *private_data),
263 void *private_data)
265 struct db_tdb_ctx *ctx = talloc_get_type_abort(
266 db->private_data, struct db_tdb_ctx);
267 struct db_tdb_parse_state state;
268 int ret;
270 state.parser = parser;
271 state.private_data = private_data;
273 ret = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_parser, &state);
275 if (ret != 0) {
276 return map_nt_error_from_tdb(tdb_error(ctx->wtdb->tdb));
278 return NT_STATUS_OK;
281 static NTSTATUS db_tdb_storev(struct db_record *rec,
282 const TDB_DATA *dbufs, int num_dbufs, int flag)
284 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
285 struct db_tdb_ctx);
286 struct tdb_context *tdb = ctx->wtdb->tdb;
287 NTSTATUS status = NT_STATUS_OK;
288 int ret;
291 * This has a bug: We need to replace rec->value for correct
292 * operation, but right now brlock and locking don't use the value
293 * anymore after it was stored.
296 ret = tdb_storev(tdb, rec->key, dbufs, num_dbufs, flag);
297 if (ret == -1) {
298 enum TDB_ERROR err = tdb_error(tdb);
299 status = map_nt_error_from_tdb(err);
301 return status;
304 static NTSTATUS db_tdb_delete(struct db_record *rec)
306 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
307 struct db_tdb_ctx);
309 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
310 return NT_STATUS_OK;
313 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
314 return NT_STATUS_NOT_FOUND;
317 return NT_STATUS_UNSUCCESSFUL;
320 struct db_tdb_traverse_ctx {
321 struct db_context *db;
322 int (*f)(struct db_record *rec, void *private_data);
323 void *private_data;
326 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
327 void *private_data)
329 struct db_tdb_traverse_ctx *ctx =
330 (struct db_tdb_traverse_ctx *)private_data;
331 struct db_record rec;
333 rec.key = kbuf;
334 rec.value = dbuf;
335 rec.value_valid = true;
336 rec.storev = db_tdb_storev;
337 rec.delete_rec = db_tdb_delete;
338 rec.private_data = ctx->db->private_data;
339 rec.db = ctx->db;
341 return ctx->f(&rec, ctx->private_data);
344 static int db_tdb_traverse(struct db_context *db,
345 int (*f)(struct db_record *rec, void *private_data),
346 void *private_data)
348 struct db_tdb_ctx *db_ctx =
349 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
350 struct db_tdb_traverse_ctx ctx;
352 ctx.db = db;
353 ctx.f = f;
354 ctx.private_data = private_data;
355 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
358 static NTSTATUS db_tdb_storev_deny(struct db_record *rec,
359 const TDB_DATA *dbufs, int num_dbufs,
360 int flag)
362 return NT_STATUS_MEDIA_WRITE_PROTECTED;
365 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
367 return NT_STATUS_MEDIA_WRITE_PROTECTED;
370 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
371 void *private_data)
373 struct db_tdb_traverse_ctx *ctx =
374 (struct db_tdb_traverse_ctx *)private_data;
375 struct db_record rec;
377 rec.key = kbuf;
378 rec.value = dbuf;
379 rec.value_valid = true;
380 rec.storev = db_tdb_storev_deny;
381 rec.delete_rec = db_tdb_delete_deny;
382 rec.private_data = ctx->db->private_data;
383 rec.db = ctx->db;
385 return ctx->f(&rec, ctx->private_data);
388 static int db_tdb_traverse_read(struct db_context *db,
389 int (*f)(struct db_record *rec, void *private_data),
390 void *private_data)
392 struct db_tdb_ctx *db_ctx =
393 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
394 struct db_tdb_traverse_ctx ctx;
396 ctx.db = db;
397 ctx.f = f;
398 ctx.private_data = private_data;
399 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
402 static int db_tdb_get_seqnum(struct db_context *db)
405 struct db_tdb_ctx *db_ctx =
406 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
407 return tdb_get_seqnum(db_ctx->wtdb->tdb);
410 static int db_tdb_transaction_start(struct db_context *db)
412 struct db_tdb_ctx *db_ctx =
413 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
414 return tdb_transaction_start(db_ctx->wtdb->tdb) ? -1 : 0;
417 static NTSTATUS db_tdb_transaction_start_nonblock(struct db_context *db)
419 struct db_tdb_ctx *db_ctx =
420 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
421 int ret;
423 ret = tdb_transaction_start_nonblock(db_ctx->wtdb->tdb);
424 if (ret != 0) {
425 return map_nt_error_from_tdb(tdb_error(db_ctx->wtdb->tdb));
427 return NT_STATUS_OK;
430 static int db_tdb_transaction_commit(struct db_context *db)
432 struct db_tdb_ctx *db_ctx =
433 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
434 return tdb_transaction_commit(db_ctx->wtdb->tdb) ? -1 : 0;
437 static int db_tdb_transaction_cancel(struct db_context *db)
439 struct db_tdb_ctx *db_ctx =
440 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
441 tdb_transaction_cancel(db_ctx->wtdb->tdb);
442 return 0;
445 static size_t db_tdb_id(struct db_context *db, uint8_t *id, size_t idlen)
447 struct db_tdb_ctx *db_ctx =
448 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
450 if (idlen >= sizeof(db_ctx->id)) {
451 memcpy(id, &db_ctx->id, sizeof(db_ctx->id));
454 return sizeof(db_ctx->id);
457 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
458 const char *name,
459 int hash_size, int tdb_flags,
460 int open_flags, mode_t mode,
461 enum dbwrap_lock_order lock_order,
462 uint64_t dbwrap_flags)
464 struct db_context *result = NULL;
465 struct db_tdb_ctx *db_tdb;
466 struct stat st;
468 result = talloc_zero(mem_ctx, struct db_context);
469 if (result == NULL) {
470 DEBUG(0, ("talloc failed\n"));
471 goto fail;
474 result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
475 if (db_tdb == NULL) {
476 DEBUG(0, ("talloc failed\n"));
477 goto fail;
479 result->lock_order = lock_order;
481 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
482 open_flags, mode);
483 if (db_tdb->wtdb == NULL) {
484 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
485 goto fail;
488 ZERO_STRUCT(db_tdb->id);
490 if (fstat(tdb_fd(db_tdb->wtdb->tdb), &st) == -1) {
491 DEBUG(3, ("fstat failed: %s\n", strerror(errno)));
492 goto fail;
494 db_tdb->id.dev = st.st_dev;
495 db_tdb->id.ino = st.st_ino;
497 result->fetch_locked = db_tdb_fetch_locked;
498 result->do_locked = db_tdb_do_locked;
499 result->traverse = db_tdb_traverse;
500 result->traverse_read = db_tdb_traverse_read;
501 result->parse_record = db_tdb_parse;
502 result->get_seqnum = db_tdb_get_seqnum;
503 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
504 result->transaction_start = db_tdb_transaction_start;
505 result->transaction_start_nonblock = db_tdb_transaction_start_nonblock;
506 result->transaction_commit = db_tdb_transaction_commit;
507 result->transaction_cancel = db_tdb_transaction_cancel;
508 result->exists = db_tdb_exists;
509 result->wipe = db_tdb_wipe;
510 result->id = db_tdb_id;
511 result->check = db_tdb_check;
512 result->name = tdb_name(db_tdb->wtdb->tdb);
513 return result;
515 fail:
516 TALLOC_FREE(result);
517 return NULL;