485
Log tdb messages via DEBUG().
487
static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
488
const char *format, ...) PRINTF_ATTRIBUTE(3,4);
490
static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
491
const char *format, ...)
499
case TDB_DEBUG_FATAL:
502
case TDB_DEBUG_ERROR:
505
case TDB_DEBUG_WARNING:
508
case TDB_DEBUG_TRACE:
515
va_start(ap, format);
516
ret = vasprintf(&ptr, format, ap);
520
const char *name = tdb_name(tdb);
521
DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr));
526
static struct tdb_wrap *tdb_list;
528
/* destroy the last connection to a tdb */
529
static int tdb_wrap_destructor(struct tdb_wrap *w)
532
DLIST_REMOVE(tdb_list, w);
537
wrapped connection to a tdb database
538
to close just talloc_free() the tdb_wrap pointer
540
struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx,
541
const char *name, int hash_size, int tdb_flags,
542
int open_flags, mode_t mode)
545
struct tdb_logging_context log_ctx;
546
log_ctx.log_fn = tdb_wrap_log;
549
tdb_flags |= TDB_NOMMAP;
551
for (w=tdb_list;w;w=w->next) {
552
if (strcmp(name, w->name) == 0) {
554
* Yes, talloc_reference is exactly what we want
555
* here. Otherwise we would have to implement our own
556
* reference counting.
558
return talloc_reference(mem_ctx, w);
562
w = talloc(mem_ctx, struct tdb_wrap);
567
if (!(w->name = talloc_strdup(w, name))) {
572
if ((hash_size == 0) && (name != NULL)) {
573
const char *base = strrchr_m(name, '/');
580
hash_size = lp_parm_int(-1, "tdb_hashsize", base, 0);
583
w->tdb = tdb_open_ex(name, hash_size, tdb_flags,
584
open_flags, mode, &log_ctx, NULL);
585
if (w->tdb == NULL) {
590
talloc_set_destructor(w, tdb_wrap_destructor);
592
DLIST_ADD(tdb_list, w);
597
487
NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err)
599
struct { enum TDB_ERROR err; NTSTATUS status; } map[] =
600
{ { TDB_SUCCESS, NT_STATUS_OK },
601
{ TDB_ERR_CORRUPT, NT_STATUS_INTERNAL_DB_CORRUPTION },
602
{ TDB_ERR_IO, NT_STATUS_UNEXPECTED_IO_ERROR },
603
{ TDB_ERR_OOM, NT_STATUS_NO_MEMORY },
604
{ TDB_ERR_EXISTS, NT_STATUS_OBJECT_NAME_COLLISION },
607
* TDB_ERR_LOCK is very broad, we could for example
608
* distinguish between fcntl locks and invalid lock
609
* sequences. So NT_STATUS_FILE_LOCK_CONFLICT is a
612
{ TDB_ERR_LOCK, NT_STATUS_FILE_LOCK_CONFLICT },
614
* The next two ones in the enum are not actually used
616
{ TDB_ERR_NOLOCK, NT_STATUS_FILE_LOCK_CONFLICT },
617
{ TDB_ERR_LOCK_TIMEOUT, NT_STATUS_FILE_LOCK_CONFLICT },
618
{ TDB_ERR_NOEXIST, NT_STATUS_NOT_FOUND },
619
{ TDB_ERR_EINVAL, NT_STATUS_INVALID_PARAMETER },
620
{ TDB_ERR_RDONLY, NT_STATUS_ACCESS_DENIED }
625
for (i=0; i < sizeof(map) / sizeof(map[0]); i++) {
626
if (err == map[i].err) {
627
return map[i].status;
631
return NT_STATUS_INTERNAL_ERROR;
489
NTSTATUS result = NT_STATUS_INTERNAL_ERROR;
493
result = NT_STATUS_OK;
495
case TDB_ERR_CORRUPT:
496
result = NT_STATUS_INTERNAL_DB_CORRUPTION;
499
result = NT_STATUS_UNEXPECTED_IO_ERROR;
502
result = NT_STATUS_NO_MEMORY;
505
result = NT_STATUS_OBJECT_NAME_COLLISION;
510
* TDB_ERR_LOCK is very broad, we could for example
511
* distinguish between fcntl locks and invalid lock
512
* sequences. So NT_STATUS_FILE_LOCK_CONFLICT is a
515
result = NT_STATUS_FILE_LOCK_CONFLICT;
519
case TDB_ERR_LOCK_TIMEOUT:
521
* These two ones in the enum are not actually used
523
result = NT_STATUS_FILE_LOCK_CONFLICT;
525
case TDB_ERR_NOEXIST:
526
result = NT_STATUS_NOT_FOUND;
529
result = NT_STATUS_INVALID_PARAMETER;
532
result = NT_STATUS_ACCESS_DENIED;
534
case TDB_ERR_NESTING:
535
result = NT_STATUS_INTERNAL_ERROR;
634
541
int tdb_data_cmp(TDB_DATA t1, TDB_DATA t2)