From aa3ca346d82da2501406cc1f482643b20905e467 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 20 Oct 2006 23:46:59 +0000 Subject: r19429: moved tdb/common/tdbutil.c into lib/util_tdb.c see discussion on samba-technical (This used to be commit 1ad563286f00be0d72930b81b10cb74f13c5fbff) --- source3/lib/util_tdb.c | 811 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 811 insertions(+) create mode 100644 source3/lib/util_tdb.c (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c new file mode 100644 index 0000000000..3e18c09fbf --- /dev/null +++ b/source3/lib/util_tdb.c @@ -0,0 +1,811 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Rafal Szczesniak 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#undef malloc +#undef realloc +#undef calloc +#undef strdup + +/*************************************************************** + Allow a caller to set a "alarm" flag that tdb can check to abort + a blocking lock on SIGALRM. +***************************************************************/ + +static sig_atomic_t *palarm_fired; + +static void tdb_set_lock_alarm(sig_atomic_t *palarm) +{ + palarm_fired = palarm; +} + +/* these are little tdb utility functions that are meant to make + dealing with a tdb database a little less cumbersome in Samba */ + +static SIG_ATOMIC_T gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +/*************************************************************** + Make a TDB_DATA and keep the const warning in one place +****************************************************************/ + +TDB_DATA make_tdb_data(const char *dptr, size_t dsize) +{ + TDB_DATA ret; + ret.dptr = CONST_DISCARD(char *, dptr); + ret.dsize = dsize; + return ret; +} + +TDB_DATA string_tdb_data(const char *string) +{ + return make_tdb_data(string, strlen(string)); +} + +/**************************************************************************** + Lock a chain with timeout (in seconds). +****************************************************************************/ + +static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) +{ + /* Allow tdb_chainlock to be interrupted by an alarm. */ + int ret; + gotalarm = 0; + tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm)); + + if (timeout) { + CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(timeout); + } + + if (rw_type == F_RDLCK) + ret = tdb_chainlock_read(tdb, key); + else + ret = tdb_chainlock(tdb, key); + + if (timeout) { + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + if (gotalarm) { + DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", + timeout, key.dptr, tdb_name(tdb))); + /* TODO: If we time out waiting for a lock, it might + * be nice to use F_GETLK to get the pid of the + * process currently holding the lock and print that + * as part of the debugging message. -- mbp */ + return -1; + } + } + + return ret; +} + +/**************************************************************************** + Write lock a chain. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +{ + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); +} + +/**************************************************************************** + Lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock(tdb, key); +} + +int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, + int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout(tdb, key, timeout); +} + +/**************************************************************************** + Unlock a chain by string. +****************************************************************************/ + +void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock(tdb, key); +} + +/**************************************************************************** + Read lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK); +} + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ + +void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock_read(tdb, key); +} + + +/**************************************************************************** + Fetch a int32 value by a arbitrary blob key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + int32 ret; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(int32)) { + SAFE_FREE(data.dptr); + return -1; + } + + ret = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return ret; +} + +/**************************************************************************** + Fetch a int32 value by string key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) +{ + return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); +} + +/**************************************************************************** + Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + int32 v_store; + + SIVAL(&v_store,0,v); + data.dptr = (char *)&v_store; + data.dsize = sizeof(int32); + + return tdb_store(tdb, key, data, TDB_REPLACE); +} + +/**************************************************************************** + Store a int32 value by string key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) +{ + return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); +} + +/**************************************************************************** + Fetch a uint32 value by a arbitrary blob key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(uint32)) { + SAFE_FREE(data.dptr); + return False; + } + + *value = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return True; +} + +/**************************************************************************** + Fetch a uint32 value by string key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) +{ + return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} + +/**************************************************************************** + Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + uint32 v_store; + BOOL ret = True; + + SIVAL(&v_store, 0, value); + data.dptr = (char *)&v_store; + data.dsize = sizeof(uint32); + + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) + ret = False; + + return ret; +} + +/**************************************************************************** + Store a uint32 value by string key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) +{ + return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} +/**************************************************************************** + Store a buffer by a null terminated string key. Return 0 on success, -1 + on failure. +****************************************************************************/ + +int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_store(tdb, key, data, flags); +} + +/**************************************************************************** + Fetch a buffer using a null terminated string key. Don't forget to call + free() on the result dptr. +****************************************************************************/ + +TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_fetch(tdb, key); +} + +/**************************************************************************** + Delete an entry using a null terminated string key. +****************************************************************************/ + +int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_delete(tdb, key); +} + +/**************************************************************************** + Atomic integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val) +{ + int32 val; + int32 ret = -1; + + if (tdb_lock_bystring(tdb, keystr) == -1) + return -1; + + if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { + /* The lookup failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* but not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* It worked, set return value (oldval) to tdb data */ + *oldval = val; + } + + /* Increment value for storage and return next time */ + val += change_val; + + if (tdb_store_int32(tdb, keystr, val) == -1) + goto err_out; + + ret = 0; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) +{ + uint32 val; + BOOL ret = False; + + if (tdb_lock_bystring(tdb, keystr) == -1) + return False; + + if (!tdb_fetch_uint32(tdb, keystr, &val)) { + /* It failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* and not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* it worked, set return value (oldval) to tdb data */ + *oldval = val; + + } + + /* get a new value to store */ + val += change_val; + + if (!tdb_store_uint32(tdb, keystr, val)) + goto err_out; + + ret = True; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap) +{ + uint8 bt; + uint16 w; + uint32 d; + int i; + void *p; + int len; + char *s; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + while (*fmt) { + switch ((c = *fmt++)) { + case 'b': /* unsigned 8-bit integer */ + len = 1; + bt = (uint8)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, bt); + break; + case 'w': /* unsigned 16-bit integer */ + len = 2; + w = (uint16)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, w); + break; + case 'd': /* signed 32-bit integer (standard int in most systems) */ + len = 4; + d = va_arg(ap, uint32); + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'p': /* pointer */ + len = 4; + p = va_arg(ap, void *); + d = p?1:0; + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'P': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'f': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'B': /* fixed-length string */ + i = va_arg(ap, int); + s = va_arg(ap, char *); + len = 4+i; + if (bufsize && bufsize >= len) { + SIVAL(buf, 0, i); + memcpy(buf+4, s, i); + } + break; + default: + DEBUG(0,("Unknown tdb_pack format %c in %s\n", + c, fmt)); + len = 0; + break; + } + + buf += len; + if (bufsize) + bufsize -= len; + if (bufsize < 0) + bufsize = 0; + } + + DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + + return PTR_DIFF(buf, buf0); +} + +size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + size_t result; + + va_start(ap, fmt); + result = tdb_pack_va(buf, bufsize, fmt, ap); + va_end(ap); + return result; +} + +BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len, + const char *fmt, ...) +{ + va_list ap; + size_t len1, len2; + + va_start(ap, fmt); + len1 = tdb_pack_va(NULL, 0, fmt, ap); + va_end(ap); + + if (mem_ctx != NULL) { + *buf = TALLOC_REALLOC_ARRAY(mem_ctx, *buf, uint8, + (*len) + len1); + } else { + *buf = SMB_REALLOC_ARRAY(*buf, uint8, (*len) + len1); + } + + if (*buf == NULL) { + return False; + } + + va_start(ap, fmt); + len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap); + va_end(ap); + + if (len1 != len2) { + return False; + } + + *len += len2; + + return True; +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint8 *bt; + uint16 *w; + uint32 *d; + int len; + int *i; + void **p; + char *s, **b; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + va_start(ap, fmt); + + while (*fmt) { + switch ((c=*fmt++)) { + case 'b': + len = 1; + bt = va_arg(ap, uint8 *); + if (bufsize < len) + goto no_space; + *bt = SVAL(buf, 0); + break; + case 'w': + len = 2; + w = va_arg(ap, uint16 *); + if (bufsize < len) + goto no_space; + *w = SVAL(buf, 0); + break; + case 'd': + len = 4; + d = va_arg(ap, uint32 *); + if (bufsize < len) + goto no_space; + *d = IVAL(buf, 0); + break; + case 'p': + len = 4; + p = va_arg(ap, void **); + if (bufsize < len) + goto no_space; + /* + * This isn't a real pointer - only a token (1 or 0) + * to mark the fact a pointer is present. + */ + + *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL); + break; + case 'P': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(pstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'f': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(fstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'B': + i = va_arg(ap, int *); + b = va_arg(ap, char **); + len = 4; + if (bufsize < len) + goto no_space; + *i = IVAL(buf, 0); + if (! *i) { + *b = NULL; + break; + } + len += *i; + if (bufsize < len) + goto no_space; + *b = (char *)SMB_MALLOC(*i); + if (! *b) + goto no_space; + memcpy(*b, buf+4, *i); + break; + default: + DEBUG(0,("Unknown tdb_unpack format %c in %s\n", + c, fmt)); + + len = 0; + break; + } + + buf += len; + bufsize -= len; + } + + va_end(ap); + + DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + + return PTR_DIFF(buf, buf0); + + no_space: + return -1; +} + + +/**************************************************************************** + Log tdb messages via DEBUG(). +****************************************************************************/ + +static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (!ptr || !*ptr) + return; + + DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr)); + SAFE_FREE(ptr); +} + +/**************************************************************************** + Like tdb_open() but also setup a logging function that redirects to + the samba DEBUG() system. +****************************************************************************/ + +TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + TDB_CONTEXT *tdb; + struct tdb_logging_context log_ctx; + + if (!lp_use_mmap()) + tdb_flags |= TDB_NOMMAP; + + log_ctx.log_fn = tdb_log; + log_ctx.log_private = NULL; + + tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, &log_ctx, NULL); + if (!tdb) + return NULL; + + return tdb; +} + +/**************************************************************************** + Allow tdb_delete to be used as a tdb_traversal_fn. +****************************************************************************/ + +int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + + + +/** + * Search across the whole tdb for keys that match the given pattern + * return the result as a list of keys + * + * @param tdb pointer to opened tdb file context + * @param pattern searching pattern used by fnmatch(3) functions + * + * @return list of keys found by looking up with given pattern + **/ +TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) +{ + TDB_DATA key, next; + TDB_LIST_NODE *list = NULL; + TDB_LIST_NODE *rec = NULL; + + for (key = tdb_firstkey(tdb); key.dptr; key = next) { + /* duplicate key string to ensure null-termination */ + char *key_str = (char*) SMB_STRNDUP(key.dptr, key.dsize); + if (!key_str) { + DEBUG(0, ("tdb_search_keys: strndup() failed!\n")); + smb_panic("strndup failed!\n"); + } + + DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern)); + + next = tdb_nextkey(tdb, key); + + /* do the pattern checking */ + if (fnmatch(pattern, key_str, 0) == 0) { + rec = SMB_MALLOC_P(TDB_LIST_NODE); + ZERO_STRUCTP(rec); + + rec->node_key = key; + + DLIST_ADD_END(list, rec, TDB_LIST_NODE *); + + DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern)); + } else { + free(key.dptr); + } + + /* free duplicated key string */ + free(key_str); + } + + return list; + +} + + +/** + * Free the list returned by tdb_search_keys + * + * @param node list of results found by tdb_search_keys + **/ +void tdb_search_list_free(TDB_LIST_NODE* node) +{ + TDB_LIST_NODE *next_node; + + while (node) { + next_node = node->next; + SAFE_FREE(node->node_key.dptr); + SAFE_FREE(node); + node = next_node; + }; +} + +/**************************************************************************** + tdb_store, wrapped in a transaction. This way we make sure that a process + that dies within writing does not leave a corrupt tdb behind. +****************************************************************************/ + +int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, + int flag) +{ + int res; + + if ((res = tdb_transaction_start(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_start failed\n")); + return res; + } + + if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) { + DEBUG(10, ("tdb_store failed\n")); + if (tdb_transaction_cancel(tdb) != 0) { + smb_panic("Cancelling transaction failed\n"); + } + return res; + } + + if ((res = tdb_transaction_commit(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_commit failed\n")); + } + + return res; +} -- cgit From 2a10d7686553a2c2377165b7f80269d2dcae8847 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 21 Oct 2006 17:00:47 +0000 Subject: r19448: Convert delete_share_security to struct share_params plus some cleanups (This used to be commit c73d0815a3a1f58b951caa62fac601a8f4630894) --- source3/lib/util_tdb.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 3e18c09fbf..e847c79369 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -809,3 +809,32 @@ int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, return res; } + +/**************************************************************************** + tdb_delete, wrapped in a transaction. This way we make sure that a process + that dies within deleting does not leave a corrupt tdb behind. +****************************************************************************/ + +int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key) +{ + int res; + + if ((res = tdb_transaction_start(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_start failed\n")); + return res; + } + + if ((res = tdb_delete(tdb, key)) != 0) { + DEBUG(10, ("tdb_delete failed\n")); + if (tdb_transaction_cancel(tdb) != 0) { + smb_panic("Cancelling transaction failed\n"); + } + return res; + } + + if ((res = tdb_transaction_commit(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_commit failed\n")); + } + + return res; +} -- cgit From 7a192590514fe8adebf4cdf51dc96c48d5225329 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 22 Nov 2006 16:53:28 +0000 Subject: r19841: Wrap regdb_store_keys and regdb_store_values in tdb transactions (This used to be commit 5ec737922041b723b9e60c08049ace5fa2fa5dec) --- source3/lib/util_tdb.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index e847c79369..4db39095a6 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -302,6 +302,14 @@ int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int return tdb_store(tdb, key, data, flags); } +int tdb_trans_store_bystring(TDB_CONTEXT *tdb, const char *keystr, + TDB_DATA data, int flags) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_trans_store(tdb, key, data, flags); +} + /**************************************************************************** Fetch a buffer using a null terminated string key. Don't forget to call free() on the result dptr. -- cgit From 032bd8eea89ce24ab5fdd2eb6095b8416ebde558 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 12:01:52 +0000 Subject: r21076: Two pieces of infrastructure from Samba4: An API-compatible messaging wrapper and tdb_wrap_open. Volker (This used to be commit c01f164dcaf88fb7f3bed8f69b210ba8fab326d1) --- source3/lib/util_tdb.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 4db39095a6..b559f589dc 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -846,3 +846,101 @@ int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key) return res; } + +/* + Log tdb messages via DEBUG(). +*/ +static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, + const char *format, ...) PRINTF_ATTRIBUTE(3,4); + +static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, + const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + int debuglevel = 0; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + switch (level) { + case TDB_DEBUG_FATAL: + debug_level = 0; + break; + case TDB_DEBUG_ERROR: + debuglevel = 1; + break; + case TDB_DEBUG_WARNING: + debuglevel = 2; + break; + case TDB_DEBUG_TRACE: + debuglevel = 5; + break; + default: + debuglevel = 0; + } + + if (ptr != NULL) { + const char *name = tdb_name(tdb); + DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr)); + free(ptr); + } +} + +static struct tdb_wrap *tdb_list; + +/* destroy the last connection to a tdb */ +static int tdb_wrap_destructor(struct tdb_wrap *w) +{ + tdb_close(w->tdb); + DLIST_REMOVE(tdb_list, w); + return 0; +} + +/* + wrapped connection to a tdb database + to close just talloc_free() the tdb_wrap pointer + */ +struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, + const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + struct tdb_wrap *w; + struct tdb_logging_context log_ctx; + log_ctx.log_fn = tdb_wrap_log; + + for (w=tdb_list;w;w=w->next) { + if (strcmp(name, w->name) == 0) { + /* + * Yes, talloc_reference is exactly what we want + * here. Otherwise we would have to implement our own + * reference counting. + */ + return talloc_reference(mem_ctx, w); + } + } + + w = talloc(mem_ctx, struct tdb_wrap); + if (w == NULL) { + return NULL; + } + + if (!(w->name = talloc_strdup(w, name))) { + talloc_free(w); + return NULL; + } + + w->tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, &log_ctx, NULL); + if (w->tdb == NULL) { + talloc_free(w); + return NULL; + } + + talloc_set_destructor(w, tdb_wrap_destructor); + + DLIST_ADD(tdb_list, w); + + return w; +} -- cgit From eca13022ef78237f915c8fec1ecbe676b1c86ae3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Mar 2007 18:14:46 +0000 Subject: r21960: Fix bugs 4463,4464,4465,4466. Thanks Jason :-) (This used to be commit a2e27c443101a59ef3429a55e049af3ebd5ec1f2) --- source3/lib/util_tdb.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index b559f589dc..9e911a653c 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -25,18 +25,6 @@ #undef calloc #undef strdup -/*************************************************************** - Allow a caller to set a "alarm" flag that tdb can check to abort - a blocking lock on SIGALRM. -***************************************************************/ - -static sig_atomic_t *palarm_fired; - -static void tdb_set_lock_alarm(sig_atomic_t *palarm) -{ - palarm_fired = palarm; -} - /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ @@ -77,7 +65,6 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, /* Allow tdb_chainlock to be interrupted by an alarm. */ int ret; gotalarm = 0; - tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm)); if (timeout) { CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); -- cgit From 2aee3c26891e1fee94c26384231a54ec89789abd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Mar 2007 08:41:45 +0000 Subject: r21972: - add string_term_tdb_data() it creates a null-terminates tdb key from a string (the current string_tdb_data() creates a non-terminates tdb key from a string!) - pass TDB_DATA instead of const char *, size_t len to some functions metze (This used to be commit 815ef8acdc7f89d30f3fd1812b12bd0e2dc62473) --- source3/lib/util_tdb.c | 55 +++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 23 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 9e911a653c..66ea929e81 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -56,6 +56,11 @@ TDB_DATA string_tdb_data(const char *string) return make_tdb_data(string, strlen(string)); } +TDB_DATA string_term_tdb_data(const char *string) +{ + return make_tdb_data(string, strlen(string) + 1); +} + /**************************************************************************** Lock a chain with timeout (in seconds). ****************************************************************************/ @@ -108,7 +113,7 @@ int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int tim int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) { - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + TDB_DATA key = string_term_tdb_data(keyval); return tdb_chainlock(tdb, key); } @@ -116,7 +121,7 @@ int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, int timeout) { - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + TDB_DATA key = string_term_tdb_data(keyval); return tdb_chainlock_with_timeout(tdb, key, timeout); } @@ -127,7 +132,7 @@ int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) { - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + TDB_DATA key = string_term_tdb_data(keyval); tdb_chainunlock(tdb, key); } @@ -138,7 +143,7 @@ void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) { - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + TDB_DATA key = string_term_tdb_data(keyval); return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK); } @@ -149,7 +154,7 @@ int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, un void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) { - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + TDB_DATA key = string_term_tdb_data(keyval); tdb_chainunlock_read(tdb, key); } @@ -160,9 +165,8 @@ void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) Output is int32 in native byte order. ****************************************************************************/ -int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) +int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key) { - TDB_DATA key = make_tdb_data(keyval, len); TDB_DATA data; int32 ret; @@ -184,7 +188,9 @@ int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) { - return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); + TDB_DATA key = string_term_tdb_data(keystr); + + return tdb_fetch_int32_byblob(tdb, key); } /**************************************************************************** @@ -192,9 +198,8 @@ int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) Input is int32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v) +int tdb_store_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, int32 v) { - TDB_DATA key = make_tdb_data(keystr, len); TDB_DATA data; int32 v_store; @@ -212,7 +217,9 @@ int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) { - return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); + TDB_DATA key = string_term_tdb_data(keystr); + + return tdb_store_int32_byblob(tdb, key, v); } /**************************************************************************** @@ -220,9 +227,8 @@ int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) Output is uint32 in native byte order. ****************************************************************************/ -BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value) +BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) { - TDB_DATA key = make_tdb_data(keyval, len); TDB_DATA data; data = tdb_fetch(tdb, key); @@ -243,7 +249,9 @@ BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, u BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) { - return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); + TDB_DATA key = string_term_tdb_data(keystr); + + return tdb_fetch_uint32_byblob(tdb, key, value); } /**************************************************************************** @@ -251,9 +259,8 @@ BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) Input is uint32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value) +BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) { - TDB_DATA key = make_tdb_data(keystr, len); TDB_DATA data; uint32 v_store; BOOL ret = True; @@ -275,7 +282,9 @@ BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, u BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) { - return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); + TDB_DATA key = string_term_tdb_data(keystr); + + return tdb_store_uint32_byblob(tdb, key, value); } /**************************************************************************** Store a buffer by a null terminated string key. Return 0 on success, -1 @@ -284,15 +293,15 @@ BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) { - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); - + TDB_DATA key = string_term_tdb_data(keystr); + return tdb_store(tdb, key, data, flags); } int tdb_trans_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) { - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + TDB_DATA key = string_term_tdb_data(keystr); return tdb_trans_store(tdb, key, data, flags); } @@ -304,7 +313,7 @@ int tdb_trans_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) { - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + TDB_DATA key = string_term_tdb_data(keystr); return tdb_fetch(tdb, key); } @@ -315,7 +324,7 @@ TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) { - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + TDB_DATA key = string_term_tdb_data(keystr); return tdb_delete(tdb, key); } @@ -725,7 +734,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) for (key = tdb_firstkey(tdb); key.dptr; key = next) { /* duplicate key string to ensure null-termination */ - char *key_str = (char*) SMB_STRNDUP(key.dptr, key.dsize); + char *key_str = SMB_STRNDUP(key.dptr, key.dsize); if (!key_str) { DEBUG(0, ("tdb_search_keys: strndup() failed!\n")); smb_panic("strndup failed!\n"); -- cgit From 7bdd7ecafad307028b51fc0f8fe361f7acb53b7d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Mar 2007 08:08:52 +0000 Subject: r22007: make string_tdb_data(NULL) possible... metze (This used to be commit d03094708378bde088bf6e90efe54deb83d3952e) --- source3/lib/util_tdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 66ea929e81..5f96580120 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -53,12 +53,12 @@ TDB_DATA make_tdb_data(const char *dptr, size_t dsize) TDB_DATA string_tdb_data(const char *string) { - return make_tdb_data(string, strlen(string)); + return make_tdb_data(string, string ? strlen(string) : 0 ); } TDB_DATA string_term_tdb_data(const char *string) { - return make_tdb_data(string, strlen(string) + 1); + return make_tdb_data(string, string ? strlen(string) + 1 : 0); } /**************************************************************************** -- cgit From bc2b6436d0f5f3e9ffdfaeb7f1b32996a83d5478 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Mar 2007 09:35:51 +0000 Subject: r22009: change TDB_DATA from char * to unsigned char * and fix all compiler warnings in the users metze (This used to be commit 3a28443079c141a6ce8182c65b56ca210e34f37f) --- source3/lib/util_tdb.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 5f96580120..c6e3063d56 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -43,22 +43,22 @@ static void gotalarm_sig(void) Make a TDB_DATA and keep the const warning in one place ****************************************************************/ -TDB_DATA make_tdb_data(const char *dptr, size_t dsize) +TDB_DATA make_tdb_data(const uint8 *dptr, size_t dsize) { TDB_DATA ret; - ret.dptr = CONST_DISCARD(char *, dptr); + ret.dptr = CONST_DISCARD(uint8 *, dptr); ret.dsize = dsize; return ret; } TDB_DATA string_tdb_data(const char *string) { - return make_tdb_data(string, string ? strlen(string) : 0 ); + return make_tdb_data((const uint8 *)string, string ? strlen(string) : 0 ); } TDB_DATA string_term_tdb_data(const char *string) { - return make_tdb_data(string, string ? strlen(string) + 1 : 0); + return make_tdb_data((const uint8 *)string, string ? strlen(string) + 1 : 0); } /**************************************************************************** @@ -204,7 +204,7 @@ int tdb_store_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, int32 v) int32 v_store; SIVAL(&v_store,0,v); - data.dptr = (char *)&v_store; + data.dptr = (uint8 *)&v_store; data.dsize = sizeof(int32); return tdb_store(tdb, key, data, TDB_REPLACE); @@ -266,7 +266,7 @@ BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) BOOL ret = True; SIVAL(&v_store, 0, value); - data.dptr = (char *)&v_store; + data.dptr = (uint8 *)&v_store; data.dsize = sizeof(uint32); if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) @@ -417,7 +417,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv integers and strings. ****************************************************************************/ -size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap) +size_t tdb_pack_va(uint8 *buf, int bufsize, const char *fmt, va_list ap) { uint8 bt; uint16 w; @@ -427,7 +427,7 @@ size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap) int len; char *s; char c; - char *buf0 = buf; + uint8 *buf0 = buf; const char *fmt0 = fmt; int bufsize0 = bufsize; @@ -501,7 +501,7 @@ size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap) return PTR_DIFF(buf, buf0); } -size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) +size_t tdb_pack(uint8 *buf, int bufsize, const char *fmt, ...) { va_list ap; size_t result; @@ -534,7 +534,7 @@ BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len, } va_start(ap, fmt); - len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap); + len2 = tdb_pack_va((*buf)+(*len), len1, fmt, ap); va_end(ap); if (len1 != len2) { @@ -551,7 +551,7 @@ BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len, integers and strings. ****************************************************************************/ -int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) +int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) { va_list ap; uint8 *bt; @@ -562,7 +562,7 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) void **p; char *s, **b; char c; - char *buf0 = buf; + const uint8 *buf0 = buf; const char *fmt0 = fmt; int bufsize0 = bufsize; @@ -605,14 +605,14 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) break; case 'P': s = va_arg(ap,char *); - len = strlen(buf) + 1; + len = strlen((const char *)buf) + 1; if (bufsize < len || len > sizeof(pstring)) goto no_space; memcpy(s, buf, len); break; case 'f': s = va_arg(ap,char *); - len = strlen(buf) + 1; + len = strlen((const char *)buf) + 1; if (bufsize < len || len > sizeof(fstring)) goto no_space; memcpy(s, buf, len); @@ -734,7 +734,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) for (key = tdb_firstkey(tdb); key.dptr; key = next) { /* duplicate key string to ensure null-termination */ - char *key_str = SMB_STRNDUP(key.dptr, key.dsize); + char *key_str = SMB_STRNDUP((const char *)key.dptr, key.dsize); if (!key_str) { DEBUG(0, ("tdb_search_keys: strndup() failed!\n")); smb_panic("strndup failed!\n"); -- cgit From 7e27c984c4033d4f3cbeec9c18627ef9d8aa5f90 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 May 2007 11:08:58 +0000 Subject: r23170: Add map_nt_error_from_tdb() (This used to be commit 02beae81c8ecef7cfe300a29852d74813c9409bf) --- source3/lib/util_tdb.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index c6e3063d56..d6f110e458 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -940,3 +940,40 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, return w; } + +NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) +{ + struct { enum TDB_ERROR err; NTSTATUS status; } map[] = + { { TDB_SUCCESS, NT_STATUS_OK }, + { TDB_ERR_CORRUPT, NT_STATUS_INTERNAL_DB_CORRUPTION }, + { TDB_ERR_IO, NT_STATUS_UNEXPECTED_IO_ERROR }, + { TDB_ERR_OOM, NT_STATUS_NO_MEMORY }, + { TDB_ERR_EXISTS, NT_STATUS_OBJECT_NAME_COLLISION }, + + /* + * TDB_ERR_LOCK is very broad, we could for example + * distinguish between fcntl locks and invalid lock + * sequences. So NT_STATUS_FILE_LOCK_CONFLICT is a + * compromise. + */ + { TDB_ERR_LOCK, NT_STATUS_FILE_LOCK_CONFLICT }, + /* + * The next two ones in the enum are not actually used + */ + { TDB_ERR_NOLOCK, NT_STATUS_FILE_LOCK_CONFLICT }, + { TDB_ERR_LOCK_TIMEOUT, NT_STATUS_FILE_LOCK_CONFLICT }, + { TDB_ERR_NOEXIST, NT_STATUS_NOT_FOUND }, + { TDB_ERR_EINVAL, NT_STATUS_INVALID_PARAMETER }, + { TDB_ERR_RDONLY, NT_STATUS_ACCESS_DENIED } + }; + + int i; + + for (i=0; i < sizeof(map) / sizeof(map[0]); i++) { + if (err == map[i].err) { + return map[i].status; + } + } + + return NT_STATUS_INTERNAL_ERROR; +} -- cgit From cc2b76b644d41cca71b9d7b1845faf01cf86a96a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 6 Jun 2007 07:46:38 +0000 Subject: r23362: Respect "use mmap" in tdb_wrap_open(). Tridge, you might want to merge this in your tree. (This used to be commit c0f40eb5846f617d9c421136b0e1ea593c8d8458) --- source3/lib/util_tdb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index d6f110e458..4e0d16c354 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -906,6 +906,9 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, struct tdb_logging_context log_ctx; log_ctx.log_fn = tdb_wrap_log; + if (!lp_use_mmap()) + tdb_flags |= TDB_NOMMAP; + for (w=tdb_list;w;w=w->next) { if (strcmp(name, w->name) == 0) { /* -- cgit From b1ce226af8b61ad7e3c37860a59c6715012e738b Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 15 Jun 2007 21:58:49 +0000 Subject: r23510: Tidy calls to smb_panic by removing trailing newlines. Print the failed expression in SMB_ASSERT. (This used to be commit 171dc060e2a576d724eed1ca65636bdafffd7713) --- source3/lib/util_tdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 4e0d16c354..6d783198d6 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -802,7 +802,7 @@ int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) { DEBUG(10, ("tdb_store failed\n")); if (tdb_transaction_cancel(tdb) != 0) { - smb_panic("Cancelling transaction failed\n"); + smb_panic("Cancelling transaction failed"); } return res; } @@ -831,7 +831,7 @@ int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key) if ((res = tdb_delete(tdb, key)) != 0) { DEBUG(10, ("tdb_delete failed\n")); if (tdb_transaction_cancel(tdb) != 0) { - smb_panic("Cancelling transaction failed\n"); + smb_panic("Cancelling transaction failed"); } return res; } -- cgit From 133472ac668033c8d8153709c7b7ddaa235aa453 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 25 Jun 2007 20:17:04 +0000 Subject: r23600: First step in abstracting the winbindd cache validation code into a generic tdb validation code. In lib/util_tdb.c for a start. Michael (This used to be commit 527edfa0cbcb233218ebabc395666d1d7228ee37) --- source3/lib/util_tdb.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 6d783198d6..cb53b7f2e3 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -980,3 +980,206 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) return NT_STATUS_INTERNAL_ERROR; } + + +/********************************************************************* + * the following is a generic validation mechanism for tdbs. + *********************************************************************/ + +/* + * internal validation function, executed by the child. + */ +static int tdb_validate_child(const char *tdb_path, + tdb_validate_data_func validate_fn, + int pfd) +{ + int ret = -1; + int tfd = -1; + int num_entries = 0; + TDB_CONTEXT *tdb = NULL; + struct tdb_validation_status v_status; + + v_status.tdb_error = False; + v_status.bad_freelist = False; + v_status.bad_entry = False; + v_status.unknown_key = False; + v_status.success = True; + + tdb = tdb_open_log(tdb_path, + WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, + lp_winbind_offline_logon() + ? TDB_DEFAULT + : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), + O_RDWR|O_CREAT, 0600); + if (!tdb) { + v_status.tdb_error = True; + v_status.success = False; + goto out; + } + + tfd = tdb_fd(tdb); + + /* Check the cache freelist is good. */ + if (tdb_validate_freelist(tdb, &num_entries) == -1) { + DEBUG(0,("tdb_validate_child: bad freelist in cache %s\n", + tdb_path)); + v_status.bad_freelist = True; + v_status.success = False; + goto out; + } + + DEBUG(10,("tdb_validate_child: cache %s freelist has %d entries\n", + tdb_path, num_entries)); + + /* Now traverse the cache to validate it. */ + num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); + if (num_entries == -1 || !(v_status.success)) { + DEBUG(0,("tdb_validate_child: cache %s traverse failed\n", + tdb_path)); + if (!(v_status.success)) { + if (v_status.bad_entry) { + DEBUGADD(0, (" -> bad entry found\n")); + } + if (v_status.unknown_key) { + DEBUGADD(0, (" -> unknown key encountered\n")); + } + } + goto out; + } + + DEBUG(10,("tdb_validate_child: cache %s is good " + "with %d entries\n", tdb_path, num_entries)); + ret = 0; /* Cache is good. */ + +out: + if (tdb) { + if (ret == 0) { + tdb_close(tdb); + } + else if (tfd != -1) { + close(tfd); + } + } + + DEBUG(10, ("tdb_validate_child: writing status to pipe\n")); + write (pfd, (const char *)&v_status, sizeof(v_status)); + close(pfd); + + return ret; +} + +int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) +{ + pid_t child_pid = -1; + int child_status = 0; + int wait_pid = 0; + int ret = -1; + int pipe_fds[2]; + struct tdb_validation_status v_status; + int bytes_read = 0; + + /* fork and let the child do the validation. + * benefit: no need to twist signal handlers and panic functions. + * just let the child panic. we catch the signal. + * communicate the extended status struct over a pipe. */ + + if (pipe(pipe_fds) != 0) { + DEBUG(0, ("tdb_validate: unable to create pipe, " + "error %s", strerror(errno))); + smb_panic("winbind_validate_cache: unable to create pipe."); + } + + DEBUG(10, ("tdb_validate: forking to let child do validation.\n")); + child_pid = sys_fork(); + if (child_pid == 0) { + DEBUG(10, ("tdb_validate (validation child): created\n")); + close(pipe_fds[0]); /* close reading fd */ + DEBUG(10, ("tdb_validate (validation child): " + "calling tdb_validate_child\n")); + exit(tdb_validate_child(tdb_path, validate_fn, pipe_fds[1])); + } + else if (child_pid < 0) { + smb_panic("tdb_validate: fork for validation failed."); + } + + /* parent */ + + DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n", + child_pid)); + close(pipe_fds[1]); /* close writing fd */ + + v_status.success = True; + v_status.bad_entry = False; + v_status.unknown_key = False; + + DEBUG(10, ("tdb_validate: reading from pipe.\n")); + bytes_read = read(pipe_fds[0], (void *)&v_status, sizeof(v_status)); + close(pipe_fds[0]); + + if (bytes_read != sizeof(v_status)) { + DEBUG(10, ("tdb_validate: read %d bytes from pipe " + "but expected %d", bytes_read, (int)sizeof(v_status))); + DEBUGADD(10, (" -> assuming child crashed\n")); + v_status.success = False; + } + else { + DEBUG(10, ("tdb_validate: read status from child\n")); + DEBUGADD(10, (" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); + DEBUGADD(10, (" * bad freelist: %s\n", v_status.bad_freelist ? "yes" : "no")); + DEBUGADD(10, (" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); + DEBUGADD(10, (" * unknown key: %s\n", v_status.unknown_key ? "yes" : "no")); + DEBUGADD(10, (" => overall success: %s\n", v_status.success ? "yes" : "no")); + } + + if (!v_status.success) { + DEBUG(10, ("tdb_validate: validation not successful.\n")); + DEBUGADD(10, ("removing tdb %s.\n", tdb_path)); + unlink(tdb_path); + } + + DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); + while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { + if (errno == EINTR) { + DEBUG(10, ("tdb_validate: got signal during " + "waitpid, retrying\n")); + errno = 0; + continue; + } + DEBUG(0, ("tdb_validate: waitpid failed with " + "errno %s\n", strerror(errno))); + smb_panic("tdb_validate: waitpid failed."); + } + if (wait_pid != child_pid) { + DEBUG(0, ("tdb_validate: waitpid returned pid %d, " + "but %d was expexted\n", wait_pid, child_pid)); + smb_panic("tdb_validate: waitpid returned " + "unexpected PID."); + } + + + DEBUG(10, ("tdb_validate: validating child returned.\n")); + if (WIFEXITED(child_status)) { + DEBUG(10, ("tdb_validate: child exited, code %d.\n", + WEXITSTATUS(child_status))); + ret = WEXITSTATUS(child_status); + } + if (WIFSIGNALED(child_status)) { + DEBUG(10, ("tdb_validate: child terminated " + "by signal %d\n", WTERMSIG(child_status))); +#ifdef WCOREDUMP + if (WCOREDUMP(child_status)) { + DEBUGADD(10, ("core dumped\n")); + } +#endif + ret = WTERMSIG(child_status); + } + if (WIFSTOPPED(child_status)) { + DEBUG(10, ("tdb_validate: child was stopped " + "by signal %d\n", + WSTOPSIG(child_status))); + ret = WSTOPSIG(child_status); + } + + return ret; +} + -- cgit From 7c48598e86da3cbc116fd1992127f13132bc3f8f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 26 Jun 2007 13:45:07 +0000 Subject: r23610: Move some winbindd_cache specific flags and actions back to winbindd_cache.c. The generic mechanism should open the cache tdb readonly and with default flags. Michael (This used to be commit 062d8c61294a1e9f8588fa8af31954dd286c7bde) --- source3/lib/util_tdb.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index cb53b7f2e3..7a0cce6c25 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1005,12 +1005,7 @@ static int tdb_validate_child(const char *tdb_path, v_status.unknown_key = False; v_status.success = True; - tdb = tdb_open_log(tdb_path, - WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, - lp_winbind_offline_logon() - ? TDB_DEFAULT - : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), - O_RDWR|O_CREAT, 0600); + tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0); if (!tdb) { v_status.tdb_error = True; v_status.success = False; @@ -1182,4 +1177,3 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) return ret; } - -- cgit From 839d4647a91f3a240dd01136290c54c7ef79bb8a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 27 Jun 2007 22:10:25 +0000 Subject: r23639: Eliminate trailing whitespaces in the new tdb_validate functions... Michael (This used to be commit d4accdbb5285216d532f57f545a846734a2fe774) --- source3/lib/util_tdb.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 7a0cce6c25..38b9285719 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -990,7 +990,7 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) * internal validation function, executed by the child. */ static int tdb_validate_child(const char *tdb_path, - tdb_validate_data_func validate_fn, + tdb_validate_data_func validate_fn, int pfd) { int ret = -1; @@ -998,7 +998,7 @@ static int tdb_validate_child(const char *tdb_path, int num_entries = 0; TDB_CONTEXT *tdb = NULL; struct tdb_validation_status v_status; - + v_status.tdb_error = False; v_status.bad_freelist = False; v_status.bad_entry = False; @@ -1050,7 +1050,7 @@ out: if (tdb) { if (ret == 0) { tdb_close(tdb); - } + } else if (tfd != -1) { close(tfd); } @@ -1072,10 +1072,10 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) int pipe_fds[2]; struct tdb_validation_status v_status; int bytes_read = 0; - - /* fork and let the child do the validation. + + /* fork and let the child do the validation. * benefit: no need to twist signal handlers and panic functions. - * just let the child panic. we catch the signal. + * just let the child panic. we catch the signal. * communicate the extended status struct over a pipe. */ if (pipe(pipe_fds) != 0) { @@ -1099,7 +1099,7 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) /* parent */ - DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n", + DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n", child_pid)); close(pipe_fds[1]); /* close writing fd */ @@ -1151,7 +1151,6 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) "unexpected PID."); } - DEBUG(10, ("tdb_validate: validating child returned.\n")); if (WIFEXITED(child_status)) { DEBUG(10, ("tdb_validate: child exited, code %d.\n", -- cgit From 052ddc9cd0c1141104477ebd6c69320485b6315a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 8 Jul 2007 22:01:43 +0000 Subject: r23751: Call tdb_close even when validation was not successful. Michael (This used to be commit b68856d9902f41079224ba11c7d0ab811b082201) --- source3/lib/util_tdb.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 38b9285719..5f9a5115b6 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -994,7 +994,6 @@ static int tdb_validate_child(const char *tdb_path, int pfd) { int ret = -1; - int tfd = -1; int num_entries = 0; TDB_CONTEXT *tdb = NULL; struct tdb_validation_status v_status; @@ -1012,8 +1011,6 @@ static int tdb_validate_child(const char *tdb_path, goto out; } - tfd = tdb_fd(tdb); - /* Check the cache freelist is good. */ if (tdb_validate_freelist(tdb, &num_entries) == -1) { DEBUG(0,("tdb_validate_child: bad freelist in cache %s\n", @@ -1048,12 +1045,7 @@ static int tdb_validate_child(const char *tdb_path, out: if (tdb) { - if (ret == 0) { - tdb_close(tdb); - } - else if (tfd != -1) { - close(tfd); - } + tdb_close(tdb); } DEBUG(10, ("tdb_validate_child: writing status to pipe\n")); -- cgit From 5e4962d9e78caab4a4294dd0ae3e4a6caf179d77 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 9 Jul 2007 15:34:46 +0000 Subject: r23769: Move removal of the tdb from the generic tdb_validate function to the caller (winbindd_validate_cache in this case). Next, there will be a backup handling for the tdb files. Michael (This used to be commit 821bc84109625c9d85edee38fa26d16f9f0a0fe2) --- source3/lib/util_tdb.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 5f9a5115b6..564edffdac 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1118,12 +1118,6 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) DEBUGADD(10, (" => overall success: %s\n", v_status.success ? "yes" : "no")); } - if (!v_status.success) { - DEBUG(10, ("tdb_validate: validation not successful.\n")); - DEBUGADD(10, ("removing tdb %s.\n", tdb_path)); - unlink(tdb_path); - } - DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { if (errno == EINTR) { -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/lib/util_tdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 564edffdac..2a0053c0d1 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -6,7 +6,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/lib/util_tdb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 2a0053c0d1..3bd1a939b0 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -15,8 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" -- cgit From 344f7aa3814d214b76e8de12be92bd68c52b26a9 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 10 Jul 2007 12:34:12 +0000 Subject: r23814: Fix a couple of comments and debug messages. (This used to be commit ef40ef67649c8793921619c128e2923e20aa68da) --- source3/lib/util_tdb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 3bd1a939b0..338a0fabdb 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1010,22 +1010,22 @@ static int tdb_validate_child(const char *tdb_path, goto out; } - /* Check the cache freelist is good. */ + /* Check if the tdb's freelist is good. */ if (tdb_validate_freelist(tdb, &num_entries) == -1) { - DEBUG(0,("tdb_validate_child: bad freelist in cache %s\n", + DEBUG(0,("tdb_validate_child: bad freelist in tdb %s\n", tdb_path)); v_status.bad_freelist = True; v_status.success = False; goto out; } - DEBUG(10,("tdb_validate_child: cache %s freelist has %d entries\n", + DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n", tdb_path, num_entries)); - /* Now traverse the cache to validate it. */ + /* Now traverse the tdb to validate it. */ num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); if (num_entries == -1 || !(v_status.success)) { - DEBUG(0,("tdb_validate_child: cache %s traverse failed\n", + DEBUG(0,("tdb_validate_child: tdb %s traverse failed\n", tdb_path)); if (!(v_status.success)) { if (v_status.bad_entry) { @@ -1038,7 +1038,7 @@ static int tdb_validate_child(const char *tdb_path, goto out; } - DEBUG(10,("tdb_validate_child: cache %s is good " + DEBUG(10,("tdb_validate_child: tdb %s is good " "with %d entries\n", tdb_path, num_entries)); ret = 0; /* Cache is good. */ @@ -1072,7 +1072,7 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) if (pipe(pipe_fds) != 0) { DEBUG(0, ("tdb_validate: unable to create pipe, " "error %s", strerror(errno))); - smb_panic("winbind_validate_cache: unable to create pipe."); + smb_panic("tdb_validate: unable to create pipe."); } DEBUG(10, ("tdb_validate: forking to let child do validation.\n")); -- cgit From 054396379729f92083b15e9958d8d51ccaf7c6ea Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 10 Jul 2007 16:41:26 +0000 Subject: r23819: It is currently unnecessary to pass the extended validation status from the validating child process down to the parent though the pipe. All the parent evaluates is the overall success, so the exit status should do. Michael (This used to be commit 9415ea0fde2ff0c801d043ce77b778fceedb6592) --- source3/lib/util_tdb.c | 52 ++++++++++---------------------------------------- 1 file changed, 10 insertions(+), 42 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 338a0fabdb..65ecb1759d 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -989,8 +989,7 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) * internal validation function, executed by the child. */ static int tdb_validate_child(const char *tdb_path, - tdb_validate_data_func validate_fn, - int pfd) + tdb_validate_data_func validate_fn) { int ret = -1; int num_entries = 0; @@ -1047,9 +1046,12 @@ out: tdb_close(tdb); } - DEBUG(10, ("tdb_validate_child: writing status to pipe\n")); - write (pfd, (const char *)&v_status, sizeof(v_status)); - close(pfd); + DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); + DEBUGADD(10, (" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); + DEBUGADD(10, (" * bad freelist: %s\n", v_status.bad_freelist ? "yes" : "no")); + DEBUGADD(10, (" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); + DEBUGADD(10, (" * unknown key: %s\n", v_status.unknown_key ? "yes" : "no")); + DEBUGADD(10, (" => overall success: %s\n", v_status.success ? "yes" : "no")); return ret; } @@ -1060,29 +1062,19 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) int child_status = 0; int wait_pid = 0; int ret = -1; - int pipe_fds[2]; - struct tdb_validation_status v_status; - int bytes_read = 0; /* fork and let the child do the validation. * benefit: no need to twist signal handlers and panic functions. - * just let the child panic. we catch the signal. - * communicate the extended status struct over a pipe. */ - - if (pipe(pipe_fds) != 0) { - DEBUG(0, ("tdb_validate: unable to create pipe, " - "error %s", strerror(errno))); - smb_panic("tdb_validate: unable to create pipe."); - } + * just let the child panic. we catch the signal. */ DEBUG(10, ("tdb_validate: forking to let child do validation.\n")); child_pid = sys_fork(); if (child_pid == 0) { + /* child code */ DEBUG(10, ("tdb_validate (validation child): created\n")); - close(pipe_fds[0]); /* close reading fd */ DEBUG(10, ("tdb_validate (validation child): " "calling tdb_validate_child\n")); - exit(tdb_validate_child(tdb_path, validate_fn, pipe_fds[1])); + exit(tdb_validate_child(tdb_path, validate_fn)); } else if (child_pid < 0) { smb_panic("tdb_validate: fork for validation failed."); @@ -1092,30 +1084,6 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n", child_pid)); - close(pipe_fds[1]); /* close writing fd */ - - v_status.success = True; - v_status.bad_entry = False; - v_status.unknown_key = False; - - DEBUG(10, ("tdb_validate: reading from pipe.\n")); - bytes_read = read(pipe_fds[0], (void *)&v_status, sizeof(v_status)); - close(pipe_fds[0]); - - if (bytes_read != sizeof(v_status)) { - DEBUG(10, ("tdb_validate: read %d bytes from pipe " - "but expected %d", bytes_read, (int)sizeof(v_status))); - DEBUGADD(10, (" -> assuming child crashed\n")); - v_status.success = False; - } - else { - DEBUG(10, ("tdb_validate: read status from child\n")); - DEBUGADD(10, (" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); - DEBUGADD(10, (" * bad freelist: %s\n", v_status.bad_freelist ? "yes" : "no")); - DEBUGADD(10, (" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); - DEBUGADD(10, (" * unknown key: %s\n", v_status.unknown_key ? "yes" : "no")); - DEBUGADD(10, (" => overall success: %s\n", v_status.success ? "yes" : "no")); - } DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { -- cgit From d775ad4aba485e00066eef3d1c44929541c4ce61 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 10 Jul 2007 23:00:04 +0000 Subject: r23822: Clean some debugging output (as well in content and amount as in source code formatting...) Michael (This used to be commit 9794b94ebf79686da2e1b3ae343953581e3459a1) --- source3/lib/util_tdb.c | 53 ++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 65ecb1759d..c567250a9f 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1011,34 +1011,22 @@ static int tdb_validate_child(const char *tdb_path, /* Check if the tdb's freelist is good. */ if (tdb_validate_freelist(tdb, &num_entries) == -1) { - DEBUG(0,("tdb_validate_child: bad freelist in tdb %s\n", - tdb_path)); v_status.bad_freelist = True; v_status.success = False; goto out; } DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n", - tdb_path, num_entries)); + tdb_path, num_entries)); /* Now traverse the tdb to validate it. */ num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); if (num_entries == -1 || !(v_status.success)) { - DEBUG(0,("tdb_validate_child: tdb %s traverse failed\n", - tdb_path)); - if (!(v_status.success)) { - if (v_status.bad_entry) { - DEBUGADD(0, (" -> bad entry found\n")); - } - if (v_status.unknown_key) { - DEBUGADD(0, (" -> unknown key encountered\n")); - } - } goto out; } - DEBUG(10,("tdb_validate_child: tdb %s is good " - "with %d entries\n", tdb_path, num_entries)); + DEBUG(10,("tdb_validate_child: tdb %s is good with %d entries\n", + tdb_path, num_entries)); ret = 0; /* Cache is good. */ out: @@ -1046,12 +1034,12 @@ out: tdb_close(tdb); } - DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); - DEBUGADD(10, (" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); - DEBUGADD(10, (" * bad freelist: %s\n", v_status.bad_freelist ? "yes" : "no")); - DEBUGADD(10, (" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); - DEBUGADD(10, (" * unknown key: %s\n", v_status.unknown_key ? "yes" : "no")); - DEBUGADD(10, (" => overall success: %s\n", v_status.success ? "yes" : "no")); + DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); + DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); + DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no")); + DEBUGADD(10,(" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); + DEBUGADD(10,(" * unknown key: %s\n", v_status.unknown_key?"yes":"no")); + DEBUGADD(10,(" => overall success: %s\n", v_status.success?"yes":"no")); return ret; } @@ -1082,26 +1070,24 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) /* parent */ - DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n", - child_pid)); + DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n",child_pid)); DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { if (errno == EINTR) { - DEBUG(10, ("tdb_validate: got signal during " - "waitpid, retrying\n")); + DEBUG(10, ("tdb_validate: got signal during waitpid, " + "retrying\n")); errno = 0; continue; } - DEBUG(0, ("tdb_validate: waitpid failed with " - "errno %s\n", strerror(errno))); + DEBUG(0, ("tdb_validate: waitpid failed with errno %s\n", + strerror(errno))); smb_panic("tdb_validate: waitpid failed."); } if (wait_pid != child_pid) { DEBUG(0, ("tdb_validate: waitpid returned pid %d, " - "but %d was expexted\n", wait_pid, child_pid)); - smb_panic("tdb_validate: waitpid returned " - "unexpected PID."); + "but %d was expected\n", wait_pid, child_pid)); + smb_panic("tdb_validate: waitpid returned unexpected PID."); } DEBUG(10, ("tdb_validate: validating child returned.\n")); @@ -1111,8 +1097,8 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) ret = WEXITSTATUS(child_status); } if (WIFSIGNALED(child_status)) { - DEBUG(10, ("tdb_validate: child terminated " - "by signal %d\n", WTERMSIG(child_status))); + DEBUG(10, ("tdb_validate: child terminated by signal %d\n", + WTERMSIG(child_status))); #ifdef WCOREDUMP if (WCOREDUMP(child_status)) { DEBUGADD(10, ("core dumped\n")); @@ -1121,8 +1107,7 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) ret = WTERMSIG(child_status); } if (WIFSTOPPED(child_status)) { - DEBUG(10, ("tdb_validate: child was stopped " - "by signal %d\n", + DEBUG(10, ("tdb_validate: child was stopped by signal %d\n", WSTOPSIG(child_status))); ret = WSTOPSIG(child_status); } -- cgit From f0072e54767de3c964ee3c9ed732ab0b58d05004 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 11 Jul 2007 10:08:17 +0000 Subject: r23828: Add entry and exit debug statments to tdb_validate at a lower debug level. Michael (This used to be commit b636f8cdad72a9a9bc1d302d8d681dca2da6105a) --- source3/lib/util_tdb.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index c567250a9f..22831d97ac 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1051,6 +1051,8 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) int wait_pid = 0; int ret = -1; + DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_path)); + /* fork and let the child do the validation. * benefit: no need to twist signal handlers and panic functions. * just let the child panic. we catch the signal. */ @@ -1112,5 +1114,8 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) ret = WSTOPSIG(child_status); } + DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret, + tdb_path)); + return ret; } -- cgit From 7291251efb6669c8895440e05edbb4967f0a4632 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 17 Jul 2007 12:49:22 +0000 Subject: r23930: Introduce tdb_validate_and_backup: This is a wrapper around tdb_validate, that does backup handling: * if the given tdb is valid, a backup is created (name.bak) * if the tdb is invalid, if a valid bakup is found (validated with the same validation function) under the name "name.bak" the orignal tdb is moved to name.corrupt and the backup is restored. For the backup handling, a variant of the backup_tdb function from lib/tdb/tools/tdbbackup.c is included in lib/util_tdb.c. The copy function for the traverse action eliminates the need to maintain a global success state by using a struct wrapping the target tdb and a success flag as the private data. Michael (This used to be commit ca63a99b6188c0976603dc2852e478cc7a6b2f8b) --- source3/lib/util_tdb.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 239 insertions(+), 1 deletion(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 22831d97ac..7bba22f4bc 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1044,6 +1044,9 @@ out: return ret; } +/* + * tdb validation function returns 0 if tdb is ok, != 0 if it isn't. + */ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) { pid_t child_pid = -1; @@ -1099,7 +1102,7 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) ret = WEXITSTATUS(child_status); } if (WIFSIGNALED(child_status)) { - DEBUG(10, ("tdb_validate: child terminated by signal %d\n", + DEBUG(10, ("tdb_validate: child terminated by signal %d\n", WTERMSIG(child_status))); #ifdef WCOREDUMP if (WCOREDUMP(child_status)) { @@ -1119,3 +1122,238 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) return ret; } + +/* + * tdb backup function and helpers for tdb_validate wrapper with backup + * handling. + */ + +/* this structure eliminates the need for a global overall status for + * the traverse-copy */ +struct tdb_copy_data { + struct tdb_context *dst; + BOOL success; +}; + +static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key, + TDB_DATA dbuf, void *private_data) +{ + struct tdb_copy_data *data = (struct tdb_copy_data *)private_data; + + if (tdb_store(data->dst, key, dbuf, TDB_INSERT) != 0) { + DEBUG(4, ("Failed to insert into %s\n", tdb_name(data->dst))); + data->success = False; + return 1; + } + return 0; +} + +static int tdb_copy(struct tdb_context *src, struct tdb_context *dst) +{ + struct tdb_copy_data data; + int count; + + data.dst = dst; + data.success = True; + + count = tdb_traverse(src, traverse_copy_fn, (void *)(&data)); + if ((count < 0) || (data.success == False)) { + return -1; + } + return count; +} + +static int tdb_verify_basic(struct tdb_context *tdb) +{ + return tdb_traverse(tdb, NULL, NULL); +} + +/* this backup function is essentially taken from lib/tdb/tools/tdbbackup.tdb + */ +static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, + const char *dst_path, int hash_size) +{ + struct tdb_context *src_tdb = NULL; + struct tdb_context *dst_tdb = NULL; + char *tmp_path = NULL; + struct stat st; + int count1, count2; + int ret = -1; + + if (stat(src_path, &st) != 0) { + DEBUG(3, ("Could not stat '%s': %s\n", src_path, + strerror(errno))); + goto done; + } + + /* open old tdb RDWR - so we can lock it */ + src_tdb = tdb_open(src_path, 0, TDB_DEFAULT, O_RDWR, 0); + if (src_tdb == NULL) { + DEBUG(3, ("Failed to open tdb '%s'\n", src_path)); + goto done; + } + + if (tdb_lockall(src_tdb) != 0) { + DEBUG(3, ("Failed to lock tdb '%s'\n", src_path)); + goto done; + } + + tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp"); + unlink(tmp_path); + dst_tdb = tdb_open(tmp_path, + hash_size ? hash_size : tdb_hash_size(src_tdb), + TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, + st.st_mode & 0777); + if (dst_tdb == NULL) { + DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, + strerror(errno))); + unlink(tmp_path); + goto done; + } + + count1 = tdb_copy(src_tdb, dst_tdb); + if (count1 < 0) { + DEBUG(3, ("Failed to copy tdb '%s'\n", src_path)); + tdb_close(dst_tdb); + goto done; + } + + /* reopen ro and do basic verification */ + tdb_close(dst_tdb); + dst_tdb = tdb_open(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0); + if (!dst_tdb) { + DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path, + strerror(errno))); + goto done; + } + count2 = tdb_verify_basic(dst_tdb); + if (count2 != count1) { + DEBUG(3, ("Failed to verify result of copying tdb '%s'.\n", + src_path)); + tdb_close(dst_tdb); + goto done; + } + + /* make sure the new tdb has reached stable storage + * then rename it to its destination */ + fsync(tdb_fd(dst_tdb)); + tdb_close(dst_tdb); + unlink(dst_path); + if (rename(tmp_path, dst_path) != 0) { + DEBUG(3, ("Failed to rename '%s' to '%s': %s\n", + tmp_path, dst_path, strerror(errno))); + goto done; + } + + /* success */ + ret = 0; + +done: + if (src_tdb != NULL) { + tdb_close(src_tdb); + } + if (tmp_path != NULL) { + unlink(tmp_path); + TALLOC_FREE(tmp_path); + } + return ret; +} + +/* + * do a backup of a tdb, moving the destination out of the way first + */ +static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, + const char *dst_path, int hash_size, + const char *rotate_suffix) +{ + char *rotate_path; + int ret = -1; + + rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, rotate_suffix); + if ((rename(dst_path, rotate_path) != 0) && (errno != ENOENT)) { + DEBUG(0, ("tdb_backup_with_rotate: error renaming " + "%s to %s: %s\n", dst_path, rotate_path, + strerror(errno))); + goto done; + } + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + +done: + TALLOC_FREE(rotate_path); + return ret; +} + +/* + * validation function with backup handling: + * + * - calls tdb_validate + * - if the tdb is ok, create a backup "name.bak", possibly moving + * existing backup to name.bak.old + * - if the tdb is corrupt, check if there is a valid backup. + * if so, move corrupt tdb to "name.corrupt", + * and restore the backup + * (give up if there is no backup or if it is invalid) + */ +int tdb_validate_and_backup(const char *tdb_path, + tdb_validate_data_func validate_fn) +{ + int ret = -1; + const char *backup_suffix = ".bak"; + const char *corrupt_suffix = ".corrupt"; + const char *rotate_suffix = ".old"; + char *tdb_path_backup; + struct stat st; + TALLOC_CTX *ctx = NULL; + + ctx = talloc_new(NULL); + if (ctx == NULL) { + DEBUG(0, ("tdb_validate_and_backup: out of memory\n")); + goto done; + } + + tdb_path_backup = talloc_asprintf(ctx, "%s%s", tdb_path, backup_suffix); + + ret = tdb_validate(tdb_path, validate_fn); + + if (ret == 0) { + DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); + ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0, + rotate_suffix); + if (ret != 0) { + DEBUG(1, ("Error creating backup of tdb '%s'\n", + tdb_path)); + goto done; + } + DEBUG(1, ("Created backup '%s' of tdb '%s'\n", tdb_path_backup, + tdb_path)); + } else { + DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); + if (stat(tdb_path_backup, &st) != 0) { + DEBUG(3, ("Could not stat '%s': %s\n", tdb_path_backup, + strerror(errno))); + DEBUG(1, ("No backup found. Giving up.\n")); + goto done; + } + ret = tdb_validate(tdb_path_backup, validate_fn); + if (ret != 0) { + DEBUG(1, ("Backup '%s' found but it is invalid.\n", + tdb_path_backup)); + goto done; + } + DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); + ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, + corrupt_suffix); + if (ret != 0) { + DEBUG(1, ("Error restoring backup from '%s'\n", + tdb_path_backup)); + goto done; + } + DEBUG(1, ("Restored tdb backup from '%s'\n", tdb_path_backup)); + DEBUGADD(1, ("Corrupt tdb stored as '%s%s'\n", tdb_path, + corrupt_suffix)); + } + +done: + TALLOC_FREE(ctx); + return ret; +} -- cgit From dc278f2d8f1878b31acedb0271fcf964b4952114 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 17 Jul 2007 13:06:29 +0000 Subject: r23932: Fill extended status with information in case the validation traverse functions did not do so but returned an error. (This is the case when error occurred deeper than at the level of the content checking done by the per entry validate_fn.) Michael (This used to be commit e56be59947a29d0a5692f3f3bc6c089dd8b4b5d9) --- source3/lib/util_tdb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 7bba22f4bc..2fa915131b 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1021,7 +1021,11 @@ static int tdb_validate_child(const char *tdb_path, /* Now traverse the tdb to validate it. */ num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); - if (num_entries == -1 || !(v_status.success)) { + if (!v_status.success) { + goto out; + } else if (num_entries == -1) { + v_status.tdb_error = True; + v_status.success = False; goto out; } -- cgit From f932dccd5dc3df1c353a8db9f9eb633d9807222d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 17 Jul 2007 21:55:31 +0000 Subject: r23938: Add a debug message. (This used to be commit 6bd2c48921dd8dbf2885a8135ba01a1324e020c8) --- source3/lib/util_tdb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 2fa915131b..cd8eb4c8c1 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1238,6 +1238,8 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, goto done; } + DEBUG(10, ("tdb_backup: successfully copied %d entries\n", count1)); + /* make sure the new tdb has reached stable storage * then rename it to its destination */ fsync(tdb_fd(dst_tdb)); -- cgit From 21a847473da54b6e4b41a94f781a2935f482ebaa Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 18 Jul 2007 11:43:50 +0000 Subject: r23952: Streamline and improve the logic of tdb_validate_and backup: - call tdb_validate on the given tdb. - if validation is successful, create a backup return 0 (success) even if the backup fails. - if validation fails: - move tdb to name.corrupt (don't exit if this fails) - look for a valid backup - if a valid backup is found, restore it, else return -1 (failure) if restoring succeeds, return 0 (success), else -1 (failure) Summing up: If 0 is returned, there is a valid tdb at the given location: either the original one ore one restrored from a backup. If -1 is returned, there is no valid tdb at the given location: Either there is no file at all, or the original file is still in place (if moving it away failed). Michael (This used to be commit 1c36ccd86d85b02f27ec66d37bdf7f04ad760901) --- source3/lib/util_tdb.c | 92 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 29 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index cd8eb4c8c1..26239d1c78 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1265,6 +1265,30 @@ done: return ret; } +static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, + const char *suffix) +{ + int ret = -1; + char *dst_path; + + dst_path = talloc_asprintf(ctx, "%s%s", path, suffix); + + ret = (rename(path, dst_path) != 0); + + if (ret == 0) { + DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path)); + } else if (errno == ENOENT) { + DEBUG(3, ("file '%s' does not exist - so not moved\n", path)); + ret = 0; + } else { + DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path, + strerror(errno))); + } + + TALLOC_FREE(dst_path); + return ret; +} + /* * do a backup of a tdb, moving the destination out of the way first */ @@ -1272,20 +1296,14 @@ static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, const char *dst_path, int hash_size, const char *rotate_suffix) { - char *rotate_path; - int ret = -1; + int ret; - rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, rotate_suffix); - if ((rename(dst_path, rotate_path) != 0) && (errno != ENOENT)) { - DEBUG(0, ("tdb_backup_with_rotate: error renaming " - "%s to %s: %s\n", dst_path, rotate_path, - strerror(errno))); - goto done; - } + ret = rename_file_with_suffix(ctx, dst_path, rotate_suffix); + + /* ignore return value of rename here: + * the more important thing is to do the backup */ ret = tdb_backup(ctx, src_path, dst_path, hash_size); -done: - TALLOC_FREE(rotate_path); return ret; } @@ -1294,11 +1312,14 @@ done: * * - calls tdb_validate * - if the tdb is ok, create a backup "name.bak", possibly moving - * existing backup to name.bak.old - * - if the tdb is corrupt, check if there is a valid backup. - * if so, move corrupt tdb to "name.corrupt", - * and restore the backup - * (give up if there is no backup or if it is invalid) + * existing backup to name.bak.old, + * return 0 (success) even if the backup fails + * - if the tdb is corrupt: + * - move the tdb to "name.corrupt" + * - check if there is valid backup. + * if so, restore the backup. + * if restore is successful, return 0 (success), + * - otherwise return -1 (failure) */ int tdb_validate_and_backup(const char *tdb_path, tdb_validate_data_func validate_fn) @@ -1328,35 +1349,48 @@ int tdb_validate_and_backup(const char *tdb_path, if (ret != 0) { DEBUG(1, ("Error creating backup of tdb '%s'\n", tdb_path)); - goto done; + /* the actual validation was successful: */ + ret = 0; + } else { + DEBUG(1, ("Created backup '%s' of tdb '%s'\n", + tdb_path_backup, tdb_path)); } - DEBUG(1, ("Created backup '%s' of tdb '%s'\n", tdb_path_backup, - tdb_path)); } else { DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); + + /* move corrupt tdb away first, but don't return on error*/ + ret = rename_file_with_suffix(ctx, tdb_path, corrupt_suffix); + if (ret != 0) { + DEBUG(1, ("Error moving tdb to '%s%s'\n", tdb_path, + corrupt_suffix)); + } else { + DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", tdb_path, + corrupt_suffix)); + } + if (stat(tdb_path_backup, &st) != 0) { - DEBUG(3, ("Could not stat '%s': %s\n", tdb_path_backup, + DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup, strerror(errno))); - DEBUG(1, ("No backup found. Giving up.\n")); + DEBUG(1, ("No backup found.\n")); + ret = -1; goto done; } + DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); ret = tdb_validate(tdb_path_backup, validate_fn); if (ret != 0) { - DEBUG(1, ("Backup '%s' found but it is invalid.\n", - tdb_path_backup)); + DEBUG(1, ("Backup '%s' is invalid.\n",tdb_path_backup)); goto done; } + DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); - ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, - corrupt_suffix); + ret = tdb_backup(ctx, tdb_path_backup, tdb_path, 0); if (ret != 0) { DEBUG(1, ("Error restoring backup from '%s'\n", tdb_path_backup)); - goto done; + } else { + DEBUG(1, ("Restored tdb backup from '%s'\n", + tdb_path_backup)); } - DEBUG(1, ("Restored tdb backup from '%s'\n", tdb_path_backup)); - DEBUGADD(1, ("Corrupt tdb stored as '%s%s'\n", tdb_path, - corrupt_suffix)); } done: -- cgit From b8a4863ca4ac3e127ec681b8da462a8020a87395 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 18 Jul 2007 14:38:18 +0000 Subject: r23957: Use tdb_open_log instead of tdb_open. Michael (This used to be commit efabd7fe03733d1fcb02d0d270c18ede7836f3a9) --- source3/lib/util_tdb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 26239d1c78..c0933ba415 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1191,7 +1191,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, } /* open old tdb RDWR - so we can lock it */ - src_tdb = tdb_open(src_path, 0, TDB_DEFAULT, O_RDWR, 0); + src_tdb = tdb_open_log(src_path, 0, TDB_DEFAULT, O_RDWR, 0); if (src_tdb == NULL) { DEBUG(3, ("Failed to open tdb '%s'\n", src_path)); goto done; @@ -1204,10 +1204,10 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp"); unlink(tmp_path); - dst_tdb = tdb_open(tmp_path, - hash_size ? hash_size : tdb_hash_size(src_tdb), - TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, - st.st_mode & 0777); + dst_tdb = tdb_open_log(tmp_path, + hash_size ? hash_size : tdb_hash_size(src_tdb), + TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, + st.st_mode & 0777); if (dst_tdb == NULL) { DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, strerror(errno))); @@ -1224,7 +1224,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, /* reopen ro and do basic verification */ tdb_close(dst_tdb); - dst_tdb = tdb_open(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0); + dst_tdb = tdb_open_log(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0); if (!dst_tdb) { DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path, strerror(errno))); -- cgit From 6a16ad09cb499476954a17dd617c0793b7ea118a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 19 Jul 2007 14:22:24 +0000 Subject: r23975: Enhance some debug output. (This used to be commit 909172839a512b60db075fb1a7488345a2e48eb0) --- source3/lib/util_tdb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index c0933ba415..cc10e4c9ad 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1145,7 +1145,8 @@ static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key, struct tdb_copy_data *data = (struct tdb_copy_data *)private_data; if (tdb_store(data->dst, key, dbuf, TDB_INSERT) != 0) { - DEBUG(4, ("Failed to insert into %s\n", tdb_name(data->dst))); + DEBUG(4, ("Failed to insert into %s: %s\n", tdb_name(data->dst), + strerror(errno))); data->success = False; return 1; } @@ -1217,7 +1218,8 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, count1 = tdb_copy(src_tdb, dst_tdb); if (count1 < 0) { - DEBUG(3, ("Failed to copy tdb '%s'\n", src_path)); + DEBUG(3, ("Failed to copy tdb '%s': %s\n", src_path, + strerror(errno))); tdb_close(dst_tdb); goto done; } -- cgit From 7712e7eeb6358c05677ae718a6bd5bcb27d509a4 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 20 Jul 2007 16:39:42 +0000 Subject: r23981: Make tdb_validate_and_backup try harder to end up with a valid tdb: If restoring a backup fails due to lack of space, remove the corrupt tdb previously moved away to "name.corrupt", and retry. If restoring still fails, move the backup in place instead of copying it. Michael (This used to be commit f81f2bf480a955213be8461636ee6f81643f17b8) --- source3/lib/util_tdb.c | 83 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 23 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index cc10e4c9ad..471a8c7da9 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1183,6 +1183,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, char *tmp_path = NULL; struct stat st; int count1, count2; + int saved_errno = 0; int ret = -1; if (stat(src_path, &st) != 0) { @@ -1212,6 +1213,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, if (dst_tdb == NULL) { DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, strerror(errno))); + saved_errno = errno; unlink(tmp_path); goto done; } @@ -1264,6 +1266,9 @@ done: unlink(tmp_path); TALLOC_FREE(tmp_path); } + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1296,17 +1301,45 @@ static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, */ static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, const char *dst_path, int hash_size, - const char *rotate_suffix) + const char *rotate_suffix, + BOOL retry_norotate_if_nospc, + BOOL rename_as_last_resort_if_nospc) { int ret; - ret = rename_file_with_suffix(ctx, dst_path, rotate_suffix); + rename_file_with_suffix(ctx, dst_path, rotate_suffix); - /* ignore return value of rename here: - * the more important thing is to do the backup */ - ret = tdb_backup(ctx, src_path, dst_path, hash_size); + ret = tdb_backup(ctx, src_path, dst_path, hash_size); - return ret; + if (ret != 0) { + DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno))); + } + if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) + { + char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, + rotate_suffix); + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("trying to free some space by removing rotated " + "dst %s\n", rotate_path)); + if (unlink(rotate_path) == -1) { + DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, + strerror(errno))); + } else { + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + } + TALLOC_FREE(rotate_path); + } + + if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) + { + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("using 'rename' as a last resort\n")); + ret = rename(src_path, dst_path); + } + + return ret; } /* @@ -1347,7 +1380,7 @@ int tdb_validate_and_backup(const char *tdb_path, if (ret == 0) { DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0, - rotate_suffix); + rotate_suffix, True, False); if (ret != 0) { DEBUG(1, ("Error creating backup of tdb '%s'\n", tdb_path)); @@ -1360,32 +1393,36 @@ int tdb_validate_and_backup(const char *tdb_path, } else { DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); - /* move corrupt tdb away first, but don't return on error*/ - ret = rename_file_with_suffix(ctx, tdb_path, corrupt_suffix); + ret =stat(tdb_path_backup, &st); if (ret != 0) { - DEBUG(1, ("Error moving tdb to '%s%s'\n", tdb_path, - corrupt_suffix)); - } else { - DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", tdb_path, - corrupt_suffix)); - } - - if (stat(tdb_path_backup, &st) != 0) { DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup, strerror(errno))); DEBUG(1, ("No backup found.\n")); - ret = -1; - goto done; + } else { + DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); + ret = tdb_validate(tdb_path_backup, validate_fn); + if (ret != 0) { + DEBUG(1, ("Backup '%s' is invalid.\n", + tdb_path_backup)); + } } - DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); - ret = tdb_validate(tdb_path_backup, validate_fn); + if (ret != 0) { - DEBUG(1, ("Backup '%s' is invalid.\n",tdb_path_backup)); + int renamed = rename_file_with_suffix(ctx, tdb_path, + corrupt_suffix); + if (renamed != 0) { + DEBUG(1, ("Error moving tdb to '%s%s'\n", + tdb_path, corrupt_suffix)); + } else { + DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", + tdb_path, corrupt_suffix)); + } goto done; } DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); - ret = tdb_backup(ctx, tdb_path_backup, tdb_path, 0); + ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, + corrupt_suffix, True, True); if (ret != 0) { DEBUG(1, ("Error restoring backup from '%s'\n", tdb_path_backup)); -- cgit From 8c154674c69d61c433c9bbd30bf1099f50c56f59 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Aug 2007 11:21:48 +0000 Subject: r24265: Add the tdb_hashsize: parameter This makes it possible to set the default hashsize for any tdb. I would like to remove the "open files database hash size" in favor of this one. I'll check that removal in with the next commit, please complain/revert if it's not ok. Volker (This used to be commit e9bd7a63a8d462b1fc3bab99ff843e25bffd156b) --- source3/lib/util_tdb.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 471a8c7da9..28a31995c1 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -696,6 +696,17 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, log_ctx.log_fn = tdb_log; log_ctx.log_private = NULL; + if (hash_size == 0) { + const char *base = strrchr_m(name, '/'); + if (base != NULL) { + base += 1; + } + else { + base = name; + } + hash_size = lp_parm_int(-1, "tdb_hashsize", base, 0); + } + tdb = tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, &log_ctx, NULL); if (!tdb) @@ -929,6 +940,17 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, return NULL; } + if (hash_size == 0) { + const char *base = strrchr_m(name, '/'); + if (base != NULL) { + base += 1; + } + else { + base = name; + } + hash_size = lp_parm_int(-1, "tdb_hashsize", base, 0); + } + w->tdb = tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, &log_ctx, NULL); if (w->tdb == NULL) { -- cgit From 42c1eca26593246769739da58df7e9a76536f401 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Aug 2007 11:50:03 +0000 Subject: r24267: Fix the build farm I had only tested with "net getlocalsid". posix_locking_init() calls this with a NULL name... (This used to be commit 3eee1fe28057e2e3da2e9d1506f57f3e35fd37b7) --- source3/lib/util_tdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 28a31995c1..5aee74cbab 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -696,7 +696,7 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, log_ctx.log_fn = tdb_log; log_ctx.log_private = NULL; - if (hash_size == 0) { + if ((hash_size == 0) && (name != NULL)) { const char *base = strrchr_m(name, '/'); if (base != NULL) { base += 1; @@ -940,7 +940,7 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, return NULL; } - if (hash_size == 0) { + if ((hash_size == 0) && (name != NULL)) { const char *base = strrchr_m(name, '/'); if (base != NULL) { base += 1; -- cgit From f02f8563a20c8a676e81f61cf74fa3b20db000f0 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 31 Aug 2007 15:51:05 +0000 Subject: r24847: Change standard failure return code of tdb_validate from "-1" to "1". (This is more safely used with casts from int to uint8, e.g.) Michael (This used to be commit cb3583b39212688a627a29bbddb2e98497714d42) --- source3/lib/util_tdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 5aee74cbab..75eb3aab07 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1013,7 +1013,7 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) static int tdb_validate_child(const char *tdb_path, tdb_validate_data_func validate_fn) { - int ret = -1; + int ret = 1; int num_entries = 0; TDB_CONTEXT *tdb = NULL; struct tdb_validation_status v_status; @@ -1078,7 +1078,7 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) pid_t child_pid = -1; int child_status = 0; int wait_pid = 0; - int ret = -1; + int ret = 1; DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_path)); -- cgit From 57ac659fb6875be42c306f63984c5b9c8073c878 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 31 Aug 2007 16:30:40 +0000 Subject: r24848: Make tdb_validate() take an open tdb handle instead of a file name. A new wrapper tdb_validate_open() takes a filename an opens and closes the tdb before and after calling tdb_validate() respectively. winbindd_validata_cache_nobackup() now dynamically calls one of the above functions depending on whether the cache tdb has already been opened or not. Michael (This used to be commit dc0b08e6590caa4974fd4d9f34f39f261d1f1dee) --- source3/lib/util_tdb.c | 57 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 75eb3aab07..a6f3e2e21c 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1010,12 +1010,11 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) /* * internal validation function, executed by the child. */ -static int tdb_validate_child(const char *tdb_path, +static int tdb_validate_child(struct tdb_context *tdb, tdb_validate_data_func validate_fn) { int ret = 1; int num_entries = 0; - TDB_CONTEXT *tdb = NULL; struct tdb_validation_status v_status; v_status.tdb_error = False; @@ -1024,7 +1023,6 @@ static int tdb_validate_child(const char *tdb_path, v_status.unknown_key = False; v_status.success = True; - tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0); if (!tdb) { v_status.tdb_error = True; v_status.success = False; @@ -1039,7 +1037,7 @@ static int tdb_validate_child(const char *tdb_path, } DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n", - tdb_path, num_entries)); + tdb_name(tdb), num_entries)); /* Now traverse the tdb to validate it. */ num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); @@ -1052,14 +1050,10 @@ static int tdb_validate_child(const char *tdb_path, } DEBUG(10,("tdb_validate_child: tdb %s is good with %d entries\n", - tdb_path, num_entries)); + tdb_name(tdb), num_entries)); ret = 0; /* Cache is good. */ out: - if (tdb) { - tdb_close(tdb); - } - DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no")); @@ -1071,16 +1065,23 @@ out: } /* - * tdb validation function returns 0 if tdb is ok, != 0 if it isn't. + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this function expects an opened tdb. */ -int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) +int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) { pid_t child_pid = -1; int child_status = 0; int wait_pid = 0; int ret = 1; - DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_path)); + if (tdb == NULL) { + DEBUG(1, ("Error: tdb_validate called with tdb == NULL\n")); + return ret; + } + + DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_name(tdb))); /* fork and let the child do the validation. * benefit: no need to twist signal handlers and panic functions. @@ -1093,7 +1094,7 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) DEBUG(10, ("tdb_validate (validation child): created\n")); DEBUG(10, ("tdb_validate (validation child): " "calling tdb_validate_child\n")); - exit(tdb_validate_child(tdb_path, validate_fn)); + exit(tdb_validate_child(tdb, validate_fn)); } else if (child_pid < 0) { smb_panic("tdb_validate: fork for validation failed."); @@ -1144,8 +1145,32 @@ int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn) } DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret, - tdb_path)); + tdb_name(tdb))); + + return ret; +} + +/* + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this is a wrapper around the actual validation function that opens and closes + * the tdb. + */ +int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn) +{ + TDB_CONTEXT *tdb = NULL; + int ret = 1; + + DEBUG(5, ("tdb_validate_open called for tdb '%s'\n", tdb_path)); + + tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0); + if (!tdb) { + DEBUG(1, ("Error opening tdb %s\n", tdb_path)); + return ret; + } + ret = tdb_validate(tdb, validate_fn); + tdb_close(tdb); return ret; } @@ -1397,7 +1422,7 @@ int tdb_validate_and_backup(const char *tdb_path, tdb_path_backup = talloc_asprintf(ctx, "%s%s", tdb_path, backup_suffix); - ret = tdb_validate(tdb_path, validate_fn); + ret = tdb_validate_open(tdb_path, validate_fn); if (ret == 0) { DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); @@ -1422,7 +1447,7 @@ int tdb_validate_and_backup(const char *tdb_path, DEBUG(1, ("No backup found.\n")); } else { DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); - ret = tdb_validate(tdb_path_backup, validate_fn); + ret = tdb_validate_open(tdb_path_backup, validate_fn); if (ret != 0) { DEBUG(1, ("Backup '%s' is invalid.\n", tdb_path_backup)); -- cgit From 60abd094fa8af84a4f0db213143bc262e6b28ff9 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 2 Sep 2007 00:23:02 +0000 Subject: r24877: Don't panic in tdb validation code when the fork or waitpid fails. Return error instead. Michael (This used to be commit 9b25355dd66519afd548fecbf2da7608b024a35b) --- source3/lib/util_tdb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index a6f3e2e21c..c122b1ba45 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1097,7 +1097,8 @@ int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) exit(tdb_validate_child(tdb, validate_fn)); } else if (child_pid < 0) { - smb_panic("tdb_validate: fork for validation failed."); + DEBUG(1, ("tdb_validate: fork for validation failed.\n")); + goto done; } /* parent */ @@ -1112,14 +1113,14 @@ int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) errno = 0; continue; } - DEBUG(0, ("tdb_validate: waitpid failed with errno %s\n", + DEBUG(1, ("tdb_validate: waitpid failed with error '%s'.\n", strerror(errno))); - smb_panic("tdb_validate: waitpid failed."); + goto done; } if (wait_pid != child_pid) { - DEBUG(0, ("tdb_validate: waitpid returned pid %d, " + DEBUG(1, ("tdb_validate: waitpid returned pid %d, " "but %d was expected\n", wait_pid, child_pid)); - smb_panic("tdb_validate: waitpid returned unexpected PID."); + goto done; } DEBUG(10, ("tdb_validate: validating child returned.\n")); @@ -1144,6 +1145,7 @@ int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) ret = WSTOPSIG(child_status); } +done: DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret, tdb_name(tdb))); -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/lib/util_tdb.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index c122b1ba45..6aa7a5348f 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -226,7 +226,7 @@ int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) Output is uint32 in native byte order. ****************************************************************************/ -BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) +bool tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) { TDB_DATA data; @@ -246,7 +246,7 @@ BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) Output is uint32 in native byte order. ****************************************************************************/ -BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) +bool tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) { TDB_DATA key = string_term_tdb_data(keystr); @@ -258,11 +258,11 @@ BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) Input is uint32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) +bool tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) { TDB_DATA data; uint32 v_store; - BOOL ret = True; + bool ret = True; SIVAL(&v_store, 0, value); data.dptr = (uint8 *)&v_store; @@ -279,7 +279,7 @@ BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) Input is uint32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) +bool tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) { TDB_DATA key = string_term_tdb_data(keystr); @@ -373,10 +373,10 @@ int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldva Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. ****************************************************************************/ -BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) +bool tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) { uint32 val; - BOOL ret = False; + bool ret = False; if (tdb_lock_bystring(tdb, keystr) == -1) return False; @@ -511,7 +511,7 @@ size_t tdb_pack(uint8 *buf, int bufsize, const char *fmt, ...) return result; } -BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len, +bool tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len, const char *fmt, ...) { va_list ap; @@ -1185,7 +1185,7 @@ int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn) * the traverse-copy */ struct tdb_copy_data { struct tdb_context *dst; - BOOL success; + bool success; }; static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key, @@ -1351,8 +1351,8 @@ static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, const char *dst_path, int hash_size, const char *rotate_suffix, - BOOL retry_norotate_if_nospc, - BOOL rename_as_last_resort_if_nospc) + bool retry_norotate_if_nospc, + bool rename_as_last_resort_if_nospc) { int ret; -- cgit From d8f3c9d0786ff637241d2a9409e1c7c253715ba5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Nov 2007 21:47:57 -0800 Subject: Fix bug where tdb lock call interrupted with an alarm sig would not terminate and could lead to runaway smbd processes. Thanks to Dave Daugherty @ Centrify for pointing this out to us. Jeremy. (This used to be commit ef8da1698371c95495add53df81a978df709c88d) --- source3/lib/util_tdb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 6aa7a5348f..35c1a92ad5 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -72,6 +72,7 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, if (timeout) { CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + tdb_setalarm_sigptr(tdb, &gotalarm); alarm(timeout); } @@ -82,6 +83,7 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, if (timeout) { alarm(0); + tdb_setalarm_sigptr(tdb, NULL); CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); if (gotalarm) { DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", -- cgit From bcf033b38ee2f6c76cd56cae5cd84a6e321ffafa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Dec 2007 14:54:06 -0800 Subject: Change tdb_unpack "P" to return a malloc'ed string rather than expect a pstring space to put data into. Fix the (few) callers. Jeremy. (This used to be commit 7722a7d2c63f84b8105aa775b39f0ceedd4ed513) --- source3/lib/util_tdb.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 35c1a92ad5..ce2cb427d1 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -561,14 +561,14 @@ int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) int len; int *i; void **p; - char *s, **b; + char *s, **b, **ps; char c; const uint8 *buf0 = buf; const char *fmt0 = fmt; int bufsize0 = bufsize; va_start(ap, fmt); - + while (*fmt) { switch ((c=*fmt++)) { case 'b': @@ -597,7 +597,7 @@ int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) p = va_arg(ap, void **); if (bufsize < len) goto no_space; - /* + /* * This isn't a real pointer - only a token (1 or 0) * to mark the fact a pointer is present. */ @@ -605,11 +605,10 @@ int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL); break; case 'P': - s = va_arg(ap,char *); + /* Return malloc'ed string. */ + ps = va_arg(ap,char **); len = strlen((const char *)buf) + 1; - if (bufsize < len || len > sizeof(pstring)) - goto no_space; - memcpy(s, buf, len); + *ps = SMB_STRDUP((const char *)buf); break; case 'f': s = va_arg(ap,char *); @@ -638,7 +637,7 @@ int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) memcpy(*b, buf+4, *i); break; default: - DEBUG(0,("Unknown tdb_unpack format %c in %s\n", + DEBUG(0,("Unknown tdb_unpack format %c in %s\n", c, fmt)); len = 0; @@ -651,7 +650,7 @@ int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) va_end(ap); - DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", + DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); return PTR_DIFF(buf, buf0); @@ -673,7 +672,7 @@ static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *fo va_start(ap, format); vasprintf(&ptr, format, ap); va_end(ap); - + if (!ptr || !*ptr) return; -- cgit From 54db1839878641be1a9987ad3e0ddedbd6123b7c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 27 Jan 2008 17:31:56 +1100 Subject: Adding missing calls to va_end(). Just a small commit to get a handle on this git thingy. This patch fixes some missing calls to va_end() to match various calls to va_start() and VA_COPY(). Tim. (This used to be commit ec367f307dff7948722b9ac97beb960efd91991f) --- source3/lib/util_tdb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index ce2cb427d1..dd5ebcd7ab 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -656,6 +656,7 @@ int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) return PTR_DIFF(buf, buf0); no_space: + va_end(ap); return -1; } -- cgit From 317639287886181edf08ccecad1b324e4cc55d0b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Feb 2008 15:24:49 +0100 Subject: Fix some warnings warning: ignoring return value of 'asprintf', declared with attribute warn_unused_result (This used to be commit ad37b7b0aee265a3e4d8b7552610f4b9a105434d) --- source3/lib/util_tdb.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index dd5ebcd7ab..724832ea5b 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -669,12 +669,13 @@ static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *fo { va_list ap; char *ptr = NULL; + int ret; va_start(ap, format); - vasprintf(&ptr, format, ap); + ret = vasprintf(&ptr, format, ap); va_end(ap); - if (!ptr || !*ptr) + if ((ret == -1) || !*ptr) return; DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr)); @@ -867,11 +868,8 @@ static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, va_list ap; char *ptr = NULL; int debuglevel = 0; + int ret; - va_start(ap, format); - vasprintf(&ptr, format, ap); - va_end(ap); - switch (level) { case TDB_DEBUG_FATAL: debug_level = 0; @@ -889,7 +887,11 @@ static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, debuglevel = 0; } - if (ptr != NULL) { + va_start(ap, format); + ret = vasprintf(&ptr, format, ap); + va_end(ap); + + if (ret != -1) { const char *name = tdb_name(tdb); DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr)); free(ptr); -- cgit From 90ce5f189f1589bf237bb35e49b427c1da9c265b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 25 Mar 2008 13:52:32 +0100 Subject: util_tdb: make the _byblob functions static - not currently used elsewhere. Michael (This used to be commit b42cf3fc69414270be9d0f430f2e95a72894f00e) --- source3/lib/util_tdb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 724832ea5b..4ecb4d5b81 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -166,7 +166,7 @@ void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) Output is int32 in native byte order. ****************************************************************************/ -int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key) +static int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key) { TDB_DATA data; int32 ret; @@ -199,7 +199,7 @@ int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) Input is int32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -int tdb_store_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, int32 v) +static int tdb_store_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, int32 v) { TDB_DATA data; int32 v_store; @@ -228,7 +228,7 @@ int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) Output is uint32 in native byte order. ****************************************************************************/ -bool tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) +static bool tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) { TDB_DATA data; @@ -260,7 +260,7 @@ bool tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) Input is uint32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -bool tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) +static bool tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) { TDB_DATA data; uint32 v_store; @@ -418,7 +418,7 @@ bool tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv integers and strings. ****************************************************************************/ -size_t tdb_pack_va(uint8 *buf, int bufsize, const char *fmt, va_list ap) +static size_t tdb_pack_va(uint8 *buf, int bufsize, const char *fmt, va_list ap) { uint8 bt; uint16 w; -- cgit From aaa59713155b63b2597f955622be9019bb3cbe89 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 25 Mar 2008 14:18:08 +0100 Subject: util_tdb: add a wrapper tdb_wipe() for traverse with tdb_traverse_delete_fn(). Replace all callers of traverse with this tdb_traverse_delete_fn() and don't export tdb_traverse_delete_fn() anymore. Michael (This used to be commit d4be4e30cd8c3bdc303da30e42280f892a45a8c9) --- source3/lib/util_tdb.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 4ecb4d5b81..4332a7948f 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -722,12 +722,18 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, Allow tdb_delete to be used as a tdb_traversal_fn. ****************************************************************************/ -int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, - void *state) +static int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, + TDB_DATA dbuf, void *state) { return tdb_delete(the_tdb, key); } +int tdb_wipe(TDB_CONTEXT *tdb) +{ + return tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); +} + + /** -- cgit From 6fa39aa87d9c0c787fd3dd2ede69c6b891186f20 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 25 Mar 2008 15:55:03 +0100 Subject: util_tdb: add my (C) for the tdb validation code Michael (This used to be commit abf02a5a142c55d9e0053d319c867e4fcc3e6c30) --- source3/lib/util_tdb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 4332a7948f..0c56e10163 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -3,6 +3,7 @@ tdb utility functions Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Rafal Szczesniak 2002 + Copyright (C) Michael Adam 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- cgit From 6efe4873dcaa78520840a57264881d7b47036b91 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 26 Mar 2008 10:45:53 +0100 Subject: util_tdb: make the _byblob fetch/store functions public again. Users of these are currently being written... Michael (This used to be commit 1c51bec5318bad085c09931aa7e8f72f41d103fe) --- source3/lib/util_tdb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 0c56e10163..e9c2d31637 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -167,7 +167,7 @@ void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) Output is int32 in native byte order. ****************************************************************************/ -static int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key) +int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key) { TDB_DATA data; int32 ret; @@ -200,7 +200,7 @@ int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) Input is int32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -static int tdb_store_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, int32 v) +int tdb_store_int32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, int32 v) { TDB_DATA data; int32 v_store; @@ -229,7 +229,7 @@ int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) Output is uint32 in native byte order. ****************************************************************************/ -static bool tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) +bool tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 *value) { TDB_DATA data; @@ -261,7 +261,7 @@ bool tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) Input is uint32 in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -static bool tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) +bool tdb_store_uint32_byblob(TDB_CONTEXT *tdb, TDB_DATA key, uint32 value) { TDB_DATA data; uint32 v_store; -- cgit From f1c844c16806d41256fe442fb0fbd237dfef9e1f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 26 Mar 2008 11:13:47 +0100 Subject: util_tdb: remove trivial and unused tdb_wipe(). It has been replaced by tdb_wipe_all(). Michael (This used to be commit cdde2e4eaca51d51f036ad99d55df7bfd6535b03) --- source3/lib/util_tdb.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index e9c2d31637..ce5e77f8f4 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -719,23 +719,6 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, return tdb; } -/**************************************************************************** - Allow tdb_delete to be used as a tdb_traversal_fn. -****************************************************************************/ - -static int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, - TDB_DATA dbuf, void *state) -{ - return tdb_delete(the_tdb, key); -} - -int tdb_wipe(TDB_CONTEXT *tdb) -{ - return tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); -} - - - /** * Search across the whole tdb for keys that match the given pattern -- cgit From 8be49cdd3e84834bac7d9514c05b294e5403550a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 12 Apr 2008 01:36:10 +0200 Subject: util_tdb: fix a segfault caused by a fatal typo. In tdb_wrap_log(), in on occurrence of "debug_level = 0" instead of "debuglevel = 0" caused me segfaults when accessing DEBUGLEVEL (which is defined as "*debug_level"...) Michael (This used to be commit d9bd894c2ec4faf87e8ff96e27c7e2b8175f9387) --- source3/lib/util_tdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/util_tdb.c') diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index ce5e77f8f4..8257232667 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -862,7 +862,7 @@ static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, switch (level) { case TDB_DEBUG_FATAL: - debug_level = 0; + debuglevel = 0; break; case TDB_DEBUG_ERROR: debuglevel = 1; -- cgit