summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/Makefile.in5
-rw-r--r--source4/include/includes.h6
-rw-r--r--source4/include/rpc_lsa.h53
-rw-r--r--source4/lib/tdb/spinlock.c2
-rw-r--r--source4/lib/tdb/spinlock.h6
-rw-r--r--source4/lib/tdb/tdb.c91
-rw-r--r--source4/lib/tdb/tdbutil.c124
-rw-r--r--source4/passdb/privileges.c349
-rw-r--r--source4/smbd/process.c4
-rw-r--r--source4/tdb/spinlock.c2
-rw-r--r--source4/tdb/spinlock.h6
-rw-r--r--source4/tdb/tdb.c91
-rw-r--r--source4/tdb/tdbbackup.c190
-rw-r--r--source4/tdb/tdbtool.c107
-rw-r--r--source4/tdb/tdbtorture.c1
-rw-r--r--source4/tdb/tdbutil.c124
-rw-r--r--source4/torture/mangle_test.c4
-rw-r--r--source4/utils/tdb/tdbbackup.c190
-rw-r--r--source4/utils/tdb/tdbtool.c107
-rw-r--r--source4/utils/tdb/tdbtorture.c1
20 files changed, 552 insertions, 911 deletions
diff --git a/source4/Makefile.in b/source4/Makefile.in
index 73db956fae..85d51de58d 100644
--- a/source4/Makefile.in
+++ b/source4/Makefile.in
@@ -238,8 +238,7 @@ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
passdb/machine_sid.o passdb/pdb_smbpasswd.o \
passdb/pdb_tdb.o passdb/pdb_ldap.o \
passdb/pdb_unix.o passdb/pdb_guest.o passdb/util_sam_sid.o \
- passdb/pdb_compat.o passdb/pdb_nisplus.o \
- passdb/privileges.o
+ passdb/pdb_compat.o passdb/pdb_nisplus.o
XML_OBJ = modules/xml.o
MYSQL_OBJ = modules/mysql.o
@@ -648,7 +647,7 @@ pch: basics
$(CC) -I. -I$(srcdir) $(FLAGS) -c $(srcdir)/include/includes.h -o $(srcdir)/include/includes.h.gch
-idl:
+idl: build/pidl/idl.pm
script/build_idl.sh FULL
idl_test: build/pidl/idl.pm
diff --git a/source4/include/includes.h b/source4/include/includes.h
index d8784f618b..fe6fcf5bce 100644
--- a/source4/include/includes.h
+++ b/source4/include/includes.h
@@ -451,12 +451,10 @@
/*
* Define additional missing types
*/
-#if defined(HAVE_SIG_ATOMIC_T_TYPE) && defined(AIX)
+#if defined(HAVE_SIG_ATOMIC_T_TYPE)
typedef sig_atomic_t SIG_ATOMIC_T;
-#elif defined(HAVE_SIG_ATOMIC_T_TYPE) && !defined(AIX)
-typedef sig_atomic_t VOLATILE SIG_ATOMIC_T;
#else
-typedef int VOLATILE SIG_ATOMIC_T;
+typedef int SIG_ATOMIC_T;
#endif
#ifndef HAVE_SOCKLEN_T_TYPE
diff --git a/source4/include/rpc_lsa.h b/source4/include/rpc_lsa.h
index d4040af3aa..fb76546aa7 100644
--- a/source4/include/rpc_lsa.h
+++ b/source4/include/rpc_lsa.h
@@ -25,59 +25,6 @@
#include "rpc_misc.h"
-/* Opcodes available on PIPE_LSARPC */
-
-#define LSA_CLOSE 0x00
-#define LSA_DELETE 0x01
-#define LSA_ENUM_PRIVS 0x02
-#define LSA_QUERYSECOBJ 0x03
-#define LSA_SETSECOBJ 0x04
-#define LSA_CHANGEPASSWORD 0x05
-#define LSA_OPENPOLICY 0x06
-#define LSA_QUERYINFOPOLICY 0x07
-#define LSA_SETINFOPOLICY 0x08
-#define LSA_CLEARAUDITLOG 0x09
-#define LSA_CREATEACCOUNT 0x0a
-#define LSA_ENUM_ACCOUNTS 0x0b
-#define LSA_CREATETRUSTDOM 0x0c
-#define LSA_ENUMTRUSTDOM 0x0d
-#define LSA_LOOKUPNAMES 0x0e
-#define LSA_LOOKUPSIDS 0x0f
-#define LSA_CREATESECRET 0x10
-#define LSA_OPENACCOUNT 0x11
-#define LSA_ENUMPRIVSACCOUNT 0x12
-#define LSA_ADDPRIVS 0x13
-#define LSA_REMOVEPRIVS 0x14
-#define LSA_GETQUOTAS 0x15
-#define LSA_SETQUOTAS 0x16
-#define LSA_GETSYSTEMACCOUNT 0x17
-#define LSA_SETSYSTEMACCOUNT 0x18
-#define LSA_OPENTRUSTDOM 0x19
-#define LSA_QUERYTRUSTDOM 0x1a
-#define LSA_SETINFOTRUSTDOM 0x1b
-#define LSA_OPENSECRET 0x1c
-#define LSA_SETSECRET 0x1d
-#define LSA_QUERYSECRET 0x1e
-#define LSA_LOOKUPPRIVVALUE 0x1f
-#define LSA_LOOKUPPRIVNAME 0x20
-#define LSA_PRIV_GET_DISPNAME 0x21
-#define LSA_DELETEOBJECT 0x22
-#define LSA_ENUMACCTWITHRIGHT 0x23
-#define LSA_ENUMACCTRIGHTS 0x24
-#define LSA_ADDACCTRIGHTS 0x25
-#define LSA_REMOVEACCTRIGHTS 0x26
-#define LSA_QUERYTRUSTDOMINFO 0x27
-#define LSA_SETTRUSTDOMINFO 0x28
-#define LSA_DELETETRUSTDOM 0x29
-#define LSA_STOREPRIVDATA 0x2a
-#define LSA_RETRPRIVDATA 0x2b
-#define LSA_OPENPOLICY2 0x2c
-#define LSA_UNK_GET_CONNUSER 0x2d /* LsaGetConnectedCredentials ? */
-#define LSA_QUERYINFO2 0x2e
-
-/* XXXX these are here to get a compile! */
-#define LSA_LOOKUPRIDS 0xFD
-
typedef struct seq_qos_info
{
uint32 len; /* 12 */
diff --git a/source4/lib/tdb/spinlock.c b/source4/lib/tdb/spinlock.c
index 2370ce3bdd..3fddeafb2c 100644
--- a/source4/lib/tdb/spinlock.c
+++ b/source4/lib/tdb/spinlock.c
@@ -372,7 +372,7 @@ int tdb_create_rwlocks(int fd, unsigned int hash_size)
unsigned size, i;
tdb_rwlock_t *rwlocks;
- size = (hash_size + 1) * sizeof(tdb_rwlock_t);
+ size = TDB_SPINLOCK_SIZE(hash_size);
rwlocks = malloc(size);
if (!rwlocks)
return -1;
diff --git a/source4/lib/tdb/spinlock.h b/source4/lib/tdb/spinlock.h
index d6a2ac6eb8..967fe37457 100644
--- a/source4/lib/tdb/spinlock.h
+++ b/source4/lib/tdb/spinlock.h
@@ -1,7 +1,7 @@
#ifndef __SPINLOCK_H__
#define __SPINLOCK_H__
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -39,6 +39,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_create_rwlocks(int fd, unsigned int hash_size);
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
+#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t))
+
#else /* !USE_SPINLOCKS */
#if 0
#define tdb_create_rwlocks(fd, hash_size) 0
@@ -50,6 +52,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_create_rwlocks(int fd, unsigned int hash_size);
#endif
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
+#define TDB_SPINLOCK_SIZE(hash_size) 0
+
#endif
#endif
diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c
index 513fbce519..fc210f42d4 100644
--- a/source4/lib/tdb/tdb.c
+++ b/source4/lib/tdb/tdb.c
@@ -20,6 +20,27 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+
+/* NOTE: If you use tdbs under valgrind, and in particular if you run
+ * tdbtorture, you may get spurious "uninitialized value" warnings. I
+ * think this is because valgrind doesn't understand that the mmap'd
+ * area may be written to by other processes. Memory can, from the
+ * point of view of the grinded process, spontaneously become
+ * initialized.
+ *
+ * I can think of a few solutions. [mbp 20030311]
+ *
+ * 1 - Write suppressions for Valgrind so that it doesn't complain
+ * about this. Probably the most reasonable but people need to
+ * remember to use them.
+ *
+ * 2 - Use IO not mmap when running under valgrind. Not so nice.
+ *
+ * 3 - Use the special valgrind macros to mark memory as valid at the
+ * right time. Probably too hard -- the process just doesn't know.
+ */
+
#ifdef STANDALONE
#if HAVE_CONFIG_H
#include <config.h>
@@ -56,6 +77,8 @@
#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off))
+#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size))
+
/* NB assumes there is a local variable called "tdb" that is the
* current context, also takes doubly-parenthesized print-style
@@ -214,10 +237,15 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
tdb->fd, offset, rw_type, lck_type));
}
/* Was it an alarm timeout ? */
- if (errno == EINTR && palarm_fired && *palarm_fired)
+ if (errno == EINTR && palarm_fired && *palarm_fired) {
+ TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n",
+ tdb->fd, offset, rw_type, lck_type));
return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1);
+ }
/* Otherwise - generic lock error. */
/* errno set by fcntl */
+ TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n",
+ tdb->fd, offset, rw_type, lck_type, strerror(errno)));
return TDB_ERRCODE(TDB_ERR_LOCK, -1);
}
return 0;
@@ -642,10 +670,10 @@ static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
left:
/* Look left */
left = offset - sizeof(tdb_off);
- if (left > TDB_HASH_TOP(tdb->header.hash_size-1)) {
+ if (left > TDB_DATA_START(tdb->header.hash_size)) {
struct list_struct l;
tdb_off leftsize;
-
+
/* Read in tailer and jump back to header */
if (ofs_read(tdb, left, &leftsize) == -1) {
TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left));
@@ -994,12 +1022,11 @@ static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash)
}
/* As tdb_find, but if you succeed, keep the lock */
-static tdb_off tdb_find_lock(TDB_CONTEXT *tdb, TDB_DATA key, int locktype,
+static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype,
struct list_struct *rec)
{
- u32 hash, rec_ptr;
+ u32 rec_ptr;
- hash = tdb_hash(&key);
if (!tdb_keylocked(tdb, hash))
return 0;
if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
@@ -1040,13 +1067,13 @@ const char *tdb_errorstr(TDB_CONTEXT *tdb)
on failure return -1.
*/
-static int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf)
+static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
{
struct list_struct rec;
tdb_off rec_ptr;
/* find entry */
- if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec)))
+ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
return -1;
/* must be long enough key, data and tailer */
@@ -1080,9 +1107,11 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
tdb_off rec_ptr;
struct list_struct rec;
TDB_DATA ret;
+ u32 hash;
/* find which hash bucket it is in */
- if (!(rec_ptr = tdb_find_lock(tdb,key,F_RDLCK,&rec)))
+ hash = tdb_hash(&key);
+ if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
return tdb_null;
if (rec.data_len)
@@ -1101,16 +1130,22 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
this doesn't match the conventions in the rest of this module, but is
compatible with gdbm
*/
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
+static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
{
struct list_struct rec;
- if (tdb_find_lock(tdb, key, F_RDLCK, &rec) == 0)
+ if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
return 0;
tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
return 1;
}
+int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
+{
+ u32 hash = tdb_hash(&key);
+ return tdb_exists_hash(tdb, key, hash);
+}
+
/* record lock stops delete underneath */
static int lock_record(TDB_CONTEXT *tdb, tdb_off off)
{
@@ -1236,7 +1271,8 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
/* Try to clean dead ones from old traverses */
current = tlock->off;
tlock->off = rec->next;
- if (do_delete(tdb, current, rec) != 0)
+ if (!tdb->read_only &&
+ do_delete(tdb, current, rec) != 0)
goto fail;
}
tdb_unlock(tdb, tlock->hash, F_WRLCK);
@@ -1366,7 +1402,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
if (!tdb->travlocks.off) {
/* No previous element: do normal find, and lock record */
- tdb->travlocks.off = tdb_find_lock(tdb, oldkey, F_WRLCK, &rec);
+ tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec);
if (!tdb->travlocks.off)
return tdb_null;
tdb->travlocks.hash = BUCKET(rec.full_hash);
@@ -1394,13 +1430,13 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
}
/* delete an entry in the database given a key */
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
+static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
{
tdb_off rec_ptr;
struct list_struct rec;
int ret;
- if (!(rec_ptr = tdb_find_lock(tdb, key, F_WRLCK, &rec)))
+ if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
return -1;
ret = do_delete(tdb, rec_ptr, &rec);
if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
@@ -1408,6 +1444,12 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
return ret;
}
+int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
+{
+ u32 hash = tdb_hash(&key);
+ return tdb_delete_hash(tdb, key, hash);
+}
+
/* store an element in the database, replacing any existing element
with the same key
@@ -1430,13 +1472,13 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
/* check for it existing, on insert. */
if (flag == TDB_INSERT) {
- if (tdb_exists(tdb, key)) {
+ if (tdb_exists_hash(tdb, key, hash)) {
tdb->ecode = TDB_ERR_EXISTS;
goto fail;
}
} else {
/* first try in-place update, on modify or replace. */
- if (tdb_update(tdb, key, dbuf) == 0)
+ if (tdb_update_hash(tdb, key, hash, dbuf) == 0)
goto out;
if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST)
goto fail;
@@ -1448,7 +1490,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
care. Doing this first reduces fragmentation, and avoids
coalescing with `allocated' block before it's updated. */
if (flag != TDB_INSERT)
- tdb_delete(tdb, key);
+ tdb_delete_hash(tdb, key, hash);
/* Copy key+value *before* allocating free space in case malloc
fails and we are left with a dead spot in the tdb. */
@@ -1497,13 +1539,13 @@ fail:
is <= the old data size and the key exists.
on failure return -1. Record must be locked before calling.
*/
-static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
+static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf)
{
struct list_struct rec;
tdb_off rec_ptr;
/* find entry */
- if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec)))
+ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
return -1;
/* Append of 0 is always ok. */
@@ -1545,7 +1587,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
return -1;
/* first try in-place. */
- if (tdb_append_inplace(tdb, key, new_dbuf) == 0)
+ if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0)
goto out;
/* reset the error code potentially set by the tdb_append_inplace() */
@@ -1588,7 +1630,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
care. Doing this first reduces fragmentation, and avoids
coalescing with `allocated' block before it's updated. */
- tdb_delete(tdb, key);
+ tdb_delete_hash(tdb, key, hash);
if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec)))
goto fail;
@@ -1728,8 +1770,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
|| strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
- || tdb->header.version != TDB_VERSION
- || (tdb->header.hash_size != hash_size
+ || (tdb->header.version != TDB_VERSION
&& !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
/* its not a valid database - possibly initialise it */
if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
@@ -1934,6 +1975,8 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[])
void tdb_unlockkeys(TDB_CONTEXT *tdb)
{
u32 i;
+ if (!tdb->lockedkeys)
+ return;
for (i = 0; i < tdb->lockedkeys[0]; i++)
tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK);
SAFE_FREE(tdb->lockedkeys);
diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c
index 0d8f6128cc..ce5188300c 100644
--- a/source4/lib/tdb/tdbutil.c
+++ b/source4/lib/tdb/tdbutil.c
@@ -266,7 +266,7 @@ BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value)
on failure.
****************************************************************************/
-int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags)
+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);
@@ -278,7 +278,7 @@ int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int
free() on the result dptr.
****************************************************************************/
-TDB_DATA tdb_fetch_by_string(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);
@@ -289,7 +289,7 @@ TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, const char *keystr)
Delete an entry using a null terminated string key.
****************************************************************************/
-int tdb_delete_by_string(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);
@@ -311,7 +311,7 @@ int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldva
if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
/* The lookup failed */
if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
- /* but not becouse it didn't exist */
+ /* but not because it didn't exist */
goto err_out;
}
@@ -352,7 +352,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv
if (!tdb_fetch_uint32(tdb, keystr, &val)) {
/* It failed */
if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
- /* and not becouse it didn't exist */
+ /* and not because it didn't exist */
goto err_out;
}
@@ -387,6 +387,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv
size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
{
va_list ap;
+ uint8 bt;
uint16 w;
uint32 d;
int i;
@@ -402,44 +403,50 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
while (*fmt) {
switch ((c = *fmt++)) {
- case 'w':
+ 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 >= len)
+ if (bufsize && bufsize >= len)
SSVAL(buf, 0, w);
break;
- case 'd':
+ case 'd': /* signed 32-bit integer (standard int in most systems) */
len = 4;
d = va_arg(ap, uint32);
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
SIVAL(buf, 0, d);
break;
- case 'p':
+ case 'p': /* pointer */
len = 4;
p = va_arg(ap, void *);
d = p?1:0;
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
SIVAL(buf, 0, d);
break;
- case 'P':
+ case 'P': /* null-terminated string */
s = va_arg(ap,char *);
w = strlen(s);
len = w + 1;
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
memcpy(buf, s, len);
break;
- case 'f':
+ case 'f': /* null-terminated string */
s = va_arg(ap,char *);
w = strlen(s);
len = w + 1;
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
memcpy(buf, s, len);
break;
- case 'B':
+ case 'B': /* fixed-length string */
i = va_arg(ap, int);
s = va_arg(ap, char *);
len = 4+i;
- if (bufsize >= len) {
+ if (bufsize && bufsize >= len) {
SIVAL(buf, 0, i);
memcpy(buf+4, s, i);
}
@@ -452,7 +459,10 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
}
buf += len;
- bufsize -= len;
+ if (bufsize)
+ bufsize -= len;
+ if (bufsize < 0)
+ bufsize = 0;
}
va_end(ap);
@@ -471,6 +481,7 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
{
va_list ap;
+ uint8 *bt;
uint16 *w;
uint32 *d;
int len;
@@ -486,6 +497,13 @@ int tdb_unpack(char *buf, int bufsize, const char *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 *);
@@ -563,6 +581,67 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
return -1;
}
+
+/**
+ * Pack SID passed by pointer
+ *
+ * @param pack_buf pointer to buffer which is to be filled with packed data
+ * @param bufsize size of packing buffer
+ * @param sid pointer to sid to be packed
+ *
+ * @return length of the packed representation of the whole structure
+ **/
+size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+ int idx;
+ size_t len = 0;
+
+ if (!sid || !pack_buf) return -1;
+
+ len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num,
+ sid->num_auths);
+
+ for (idx = 0; idx < 6; idx++) {
+ len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]);
+ }
+
+ for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+ len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]);
+ }
+
+ return len;
+}
+
+
+/**
+ * Unpack SID into a pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param sid pointer to sid structure to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+ int idx, len = 0;
+
+ if (!sid || !pack_buf) return -1;
+
+ len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
+ &sid->sid_rev_num, &sid->num_auths);
+
+ for (idx = 0; idx < 6; idx++) {
+ len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
+ }
+
+ for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+ len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
+ }
+
+ return len;
+}
+
/****************************************************************************
Log tdb messages via DEBUG().
****************************************************************************/
@@ -665,7 +744,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
return list;
-};
+}
/**
@@ -679,9 +758,8 @@ void tdb_search_list_free(TDB_LIST_NODE* node)
while (node) {
next_node = node->next;
+ SAFE_FREE(node->node_key.dptr);
SAFE_FREE(node);
node = next_node;
- };
-};
-
-
+ }
+}
diff --git a/source4/passdb/privileges.c b/source4/passdb/privileges.c
deleted file mode 100644
index c90bc47d31..0000000000
--- a/source4/passdb/privileges.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * default privileges backend for passdb
- *
- * Copyright (C) Andrew Tridgell 2003
- *
- * 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"
-
-/*
- this is a local implementation of a privileges backend, with
- privileges stored in a tdb. Most passdb implementations will
- probably use this backend, although some (such as pdb_ldap) will
- store the privileges in another manner.
-
- The basic principle is that the backend should store a list of SIDs
- associated with each right, where a right is a string name such as
- 'SeTakeOwnershipPrivilege'. The SIDs can be of any type, and do not
- need to belong to the local domain.
-
- The way this is used is that certain places in the code which
- require access control will ask the privileges backend 'does this
- user have the following privilege'. The 'user' will be a NT_TOKEN,
- which is essentially just a list of SIDs. If any of those SIDs are
- listed in the list of SIDs for that privilege then the answer will
- be 'yes'. That will usually mean that the user gets unconditional
- access to that functionality, regradless of any ACLs. In this way
- privileges act in a similar fashion to unix setuid bits.
-*/
-
-/*
- The terms 'right' and 'privilege' are used interchangably in this
- file. This follows MSDN convention where the LSA calls are calls on
- 'rights', which really means privileges. My apologies for the
- confusion.
-*/
-
-
-/* 15 seconds seems like an ample time for timeouts on the privileges db */
-#define LOCK_TIMEOUT 15
-
-
-/* the tdb handle for the privileges database */
-static TDB_CONTEXT *tdb;
-
-
-/* initialise the privilege database */
-BOOL privilege_init(void)
-{
- TALLOC_CTX *mem_ctx;
-
- mem_ctx = talloc_init("privilege_init talloc");
- if (!mem_ctx) {
- DEBUG(0,("No memory to open privilege database\n"));
- return False;
- }
- tdb = tdb_open_log(lock_path(mem_ctx, "privilege.tdb"), 0, TDB_DEFAULT,
- O_RDWR|O_CREAT, 0600);
- talloc_destroy(mem_ctx);
- if (!tdb) {
- DEBUG(0,("Failed to open privilege database\n"));
- return False;
- }
-
- return True;
-}
-
-/*
- lock the record for a particular privilege (write lock)
-*/
-static NTSTATUS privilege_lock_right(const char *right)
-{
- if (tdb_lock_bystring(tdb, right, LOCK_TIMEOUT) != 0) {
- return NT_STATUS_INTERNAL_ERROR;
- }
- return NT_STATUS_OK;
-}
-
-/*
- unlock the record for a particular privilege (write lock)
-*/
-static void privilege_unlock_right(const char *right)
-{
- tdb_unlock_bystring(tdb, right);
-}
-
-
-/*
- return a list of SIDs that have a particular right
-*/
-NTSTATUS privilege_enum_account_with_right(const char *right,
- uint32 *count,
- DOM_SID **sids)
-{
- TDB_DATA data;
- char *p;
- int i;
-
- if (!tdb) {
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- data = tdb_fetch_by_string(tdb, right);
- if (!data.dptr) {
- *count = 0;
- *sids = NULL;
- return NT_STATUS_OK;
- }
-
- /* count them */
- for (i=0, p=data.dptr; p<data.dptr+data.dsize; i++) {
- p += strlen(p) + 1;
- }
- *count = i;
-
- /* allocate and parse */
- *sids = malloc(sizeof(DOM_SID) * *count);
- if (! *sids) {
- return NT_STATUS_NO_MEMORY;
- }
- for (i=0, p=data.dptr; p<data.dptr+data.dsize; i++) {
- if (!string_to_sid(&(*sids)[i], p)) {
- free(data.dptr);
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
- p += strlen(p) + 1;
- }
-
- free(data.dptr);
-
- return NT_STATUS_OK;
-}
-
-/*
- set what accounts have a given right - this is an internal interface
-*/
-static NTSTATUS privilege_set_accounts_with_right(const char *right,
- uint32 count,
- DOM_SID *sids)
-{
- TDB_DATA data;
- char *p;
- int i;
-
- if (!tdb) {
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- /* allocate the maximum size that we might use */
- data.dptr = malloc(count * ((MAXSUBAUTHS*11) + 30));
- if (!data.dptr) {
- return NT_STATUS_NO_MEMORY;
- }
-
- p = data.dptr;
-
- for (i=0;i<count;i++) {
- sid_to_string(p, &sids[i]);
- p += strlen(p) + 1;
- }
-
- data.dsize = PTR_DIFF(p, data.dptr);
-
- if (tdb_store_by_string(tdb, right, data, TDB_REPLACE) != 0) {
- free(data.dptr);
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- free(data.dptr);
- return NT_STATUS_OK;
-}
-
-
-/*
- add a SID to the list of SIDs for a right
-*/
-NTSTATUS privilege_add_account_right(const char *right,
- DOM_SID *sid)
-{
- NTSTATUS status;
- DOM_SID *current_sids;
- uint32 current_count;
- int i;
-
- status = privilege_lock_right(right);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = privilege_enum_account_with_right(right, &current_count, &current_sids);
- if (!NT_STATUS_IS_OK(status)) {
- privilege_unlock_right(right);
- return status;
- }
-
- /* maybe that SID is already listed? this is not an error */
- for (i=0;i<current_count;i++) {
- if (sid_equal(&current_sids[i], sid)) {
- privilege_unlock_right(right);
- free(current_sids);
- return NT_STATUS_OK;
- }
- }
-
- /* add it in */
- current_sids = Realloc(current_sids, sizeof(current_sids[0]) * (current_count+1));
- if (!current_sids) {
- privilege_unlock_right(right);
- return NT_STATUS_NO_MEMORY;
- }
-
- sid_copy(&current_sids[current_count], sid);
- current_count++;
-
- status = privilege_set_accounts_with_right(right, current_count, current_sids);
-
- free(current_sids);
- privilege_unlock_right(right);
-
- return status;
-}
-
-
-/*
- remove a SID from the list of SIDs for a right
-*/
-NTSTATUS privilege_remove_account_right(const char *right,
- DOM_SID *sid)
-{
- NTSTATUS status;
- DOM_SID *current_sids;
- uint32 current_count;
- int i;
-
- status = privilege_lock_right(right);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = privilege_enum_account_with_right(right, &current_count, &current_sids);
- if (!NT_STATUS_IS_OK(status)) {
- privilege_unlock_right(right);
- return status;
- }
-
- for (i=0;i<current_count;i++) {
- if (sid_equal(&current_sids[i], sid)) {
- /* found it - so remove it */
- if (current_count-i > 1) {
- memmove(&current_sids[i], &current_sids[i+1],
- sizeof(current_sids[0]) * ((current_count-i)-1));
- }
- current_count--;
- status = privilege_set_accounts_with_right(right,
- current_count,
- current_sids);
- free(current_sids);
- privilege_unlock_right(right);
- return status;
- }
- }
-
- /* removing a right that you don't have is not an error */
-
- safe_free(current_sids);
- privilege_unlock_right(right);
- return NT_STATUS_OK;
-}
-
-
-/*
- an internal function for checking if a SID has a right
-*/
-static BOOL privilege_sid_has_right(DOM_SID *sid, const char *right)
-{
- NTSTATUS status;
- uint32 count;
- DOM_SID *sids;
- int i;
-
- status = privilege_enum_account_with_right(right, &count, &sids);
- if (!NT_STATUS_IS_OK(status)) {
- return False;
- }
- for (i=0;i<count;i++) {
- if (sid_equal(sid, &sids[i])) {
- free(sids);
- return True;
- }
- }
-
- safe_free(sids);
- return False;
-}
-
-/*
- list the rights for an account. This involves traversing the database
-*/
-NTSTATUS privilege_enum_account_rights(DOM_SID *sid,
- uint32 *count,
- char ***rights)
-{
- TDB_DATA key, nextkey;
- char *right;
-
- if (!tdb) {
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- *rights = NULL;
- *count = 0;
-
- for (key = tdb_firstkey(tdb); key.dptr; key = nextkey) {
- nextkey = tdb_nextkey(tdb, key);
-
- right = key.dptr;
-
- if (privilege_sid_has_right(sid, right)) {
- (*rights) = (char **)Realloc(*rights,sizeof(char *) * ((*count)+1));
- if (! *rights) {
- safe_free(nextkey.dptr);
- free(key.dptr);
- return NT_STATUS_NO_MEMORY;
- }
-
- (*rights)[*count] = strdup(right);
- (*count)++;
- }
-
- free(key.dptr);
- }
-
- return NT_STATUS_OK;
-}
diff --git a/source4/smbd/process.c b/source4/smbd/process.c
index 81c658af06..3b2d1cf633 100644
--- a/source4/smbd/process.c
+++ b/source4/smbd/process.c
@@ -817,10 +817,6 @@ void smbd_process_init(void)
if (!init_change_notify())
exit(1);
- /* Setup privileges database */
- if (!privilege_init())
- exit(1);
-
/* Setup the NTVFS subsystem */
if (!ntvfs_init())
exit(1);
diff --git a/source4/tdb/spinlock.c b/source4/tdb/spinlock.c
index 2370ce3bdd..3fddeafb2c 100644
--- a/source4/tdb/spinlock.c
+++ b/source4/tdb/spinlock.c
@@ -372,7 +372,7 @@ int tdb_create_rwlocks(int fd, unsigned int hash_size)
unsigned size, i;
tdb_rwlock_t *rwlocks;
- size = (hash_size + 1) * sizeof(tdb_rwlock_t);
+ size = TDB_SPINLOCK_SIZE(hash_size);
rwlocks = malloc(size);
if (!rwlocks)
return -1;
diff --git a/source4/tdb/spinlock.h b/source4/tdb/spinlock.h
index d6a2ac6eb8..967fe37457 100644
--- a/source4/tdb/spinlock.h
+++ b/source4/tdb/spinlock.h
@@ -1,7 +1,7 @@
#ifndef __SPINLOCK_H__
#define __SPINLOCK_H__
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -39,6 +39,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_create_rwlocks(int fd, unsigned int hash_size);
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
+#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t))
+
#else /* !USE_SPINLOCKS */
#if 0
#define tdb_create_rwlocks(fd, hash_size) 0
@@ -50,6 +52,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_create_rwlocks(int fd, unsigned int hash_size);
#endif
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
+#define TDB_SPINLOCK_SIZE(hash_size) 0
+
#endif
#endif
diff --git a/source4/tdb/tdb.c b/source4/tdb/tdb.c
index 513fbce519..fc210f42d4 100644
--- a/source4/tdb/tdb.c
+++ b/source4/tdb/tdb.c
@@ -20,6 +20,27 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+
+/* NOTE: If you use tdbs under valgrind, and in particular if you run
+ * tdbtorture, you may get spurious "uninitialized value" warnings. I
+ * think this is because valgrind doesn't understand that the mmap'd
+ * area may be written to by other processes. Memory can, from the
+ * point of view of the grinded process, spontaneously become
+ * initialized.
+ *
+ * I can think of a few solutions. [mbp 20030311]
+ *
+ * 1 - Write suppressions for Valgrind so that it doesn't complain
+ * about this. Probably the most reasonable but people need to
+ * remember to use them.
+ *
+ * 2 - Use IO not mmap when running under valgrind. Not so nice.
+ *
+ * 3 - Use the special valgrind macros to mark memory as valid at the
+ * right time. Probably too hard -- the process just doesn't know.
+ */
+
#ifdef STANDALONE
#if HAVE_CONFIG_H
#include <config.h>
@@ -56,6 +77,8 @@
#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off))
+#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size))
+
/* NB assumes there is a local variable called "tdb" that is the
* current context, also takes doubly-parenthesized print-style
@@ -214,10 +237,15 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
tdb->fd, offset, rw_type, lck_type));
}
/* Was it an alarm timeout ? */
- if (errno == EINTR && palarm_fired && *palarm_fired)
+ if (errno == EINTR && palarm_fired && *palarm_fired) {
+ TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n",
+ tdb->fd, offset, rw_type, lck_type));
return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1);
+ }
/* Otherwise - generic lock error. */
/* errno set by fcntl */
+ TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n",
+ tdb->fd, offset, rw_type, lck_type, strerror(errno)));
return TDB_ERRCODE(TDB_ERR_LOCK, -1);
}
return 0;
@@ -642,10 +670,10 @@ static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
left:
/* Look left */
left = offset - sizeof(tdb_off);
- if (left > TDB_HASH_TOP(tdb->header.hash_size-1)) {
+ if (left > TDB_DATA_START(tdb->header.hash_size)) {
struct list_struct l;
tdb_off leftsize;
-
+
/* Read in tailer and jump back to header */
if (ofs_read(tdb, left, &leftsize) == -1) {
TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left));
@@ -994,12 +1022,11 @@ static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash)
}
/* As tdb_find, but if you succeed, keep the lock */
-static tdb_off tdb_find_lock(TDB_CONTEXT *tdb, TDB_DATA key, int locktype,
+static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype,
struct list_struct *rec)
{
- u32 hash, rec_ptr;
+ u32 rec_ptr;
- hash = tdb_hash(&key);
if (!tdb_keylocked(tdb, hash))
return 0;
if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
@@ -1040,13 +1067,13 @@ const char *tdb_errorstr(TDB_CONTEXT *tdb)
on failure return -1.
*/
-static int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf)
+static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
{
struct list_struct rec;
tdb_off rec_ptr;
/* find entry */
- if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec)))
+ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
return -1;
/* must be long enough key, data and tailer */
@@ -1080,9 +1107,11 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
tdb_off rec_ptr;
struct list_struct rec;
TDB_DATA ret;
+ u32 hash;
/* find which hash bucket it is in */
- if (!(rec_ptr = tdb_find_lock(tdb,key,F_RDLCK,&rec)))
+ hash = tdb_hash(&key);
+ if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
return tdb_null;
if (rec.data_len)
@@ -1101,16 +1130,22 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
this doesn't match the conventions in the rest of this module, but is
compatible with gdbm
*/
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
+static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
{
struct list_struct rec;
- if (tdb_find_lock(tdb, key, F_RDLCK, &rec) == 0)
+ if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
return 0;
tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
return 1;
}
+int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
+{
+ u32 hash = tdb_hash(&key);
+ return tdb_exists_hash(tdb, key, hash);
+}
+
/* record lock stops delete underneath */
static int lock_record(TDB_CONTEXT *tdb, tdb_off off)
{
@@ -1236,7 +1271,8 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
/* Try to clean dead ones from old traverses */
current = tlock->off;
tlock->off = rec->next;
- if (do_delete(tdb, current, rec) != 0)
+ if (!tdb->read_only &&
+ do_delete(tdb, current, rec) != 0)
goto fail;
}
tdb_unlock(tdb, tlock->hash, F_WRLCK);
@@ -1366,7 +1402,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
if (!tdb->travlocks.off) {
/* No previous element: do normal find, and lock record */
- tdb->travlocks.off = tdb_find_lock(tdb, oldkey, F_WRLCK, &rec);
+ tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec);
if (!tdb->travlocks.off)
return tdb_null;
tdb->travlocks.hash = BUCKET(rec.full_hash);
@@ -1394,13 +1430,13 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
}
/* delete an entry in the database given a key */
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
+static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
{
tdb_off rec_ptr;
struct list_struct rec;
int ret;
- if (!(rec_ptr = tdb_find_lock(tdb, key, F_WRLCK, &rec)))
+ if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
return -1;
ret = do_delete(tdb, rec_ptr, &rec);
if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
@@ -1408,6 +1444,12 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
return ret;
}
+int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
+{
+ u32 hash = tdb_hash(&key);
+ return tdb_delete_hash(tdb, key, hash);
+}
+
/* store an element in the database, replacing any existing element
with the same key
@@ -1430,13 +1472,13 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
/* check for it existing, on insert. */
if (flag == TDB_INSERT) {
- if (tdb_exists(tdb, key)) {
+ if (tdb_exists_hash(tdb, key, hash)) {
tdb->ecode = TDB_ERR_EXISTS;
goto fail;
}
} else {
/* first try in-place update, on modify or replace. */
- if (tdb_update(tdb, key, dbuf) == 0)
+ if (tdb_update_hash(tdb, key, hash, dbuf) == 0)
goto out;
if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST)
goto fail;
@@ -1448,7 +1490,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
care. Doing this first reduces fragmentation, and avoids
coalescing with `allocated' block before it's updated. */
if (flag != TDB_INSERT)
- tdb_delete(tdb, key);
+ tdb_delete_hash(tdb, key, hash);
/* Copy key+value *before* allocating free space in case malloc
fails and we are left with a dead spot in the tdb. */
@@ -1497,13 +1539,13 @@ fail:
is <= the old data size and the key exists.
on failure return -1. Record must be locked before calling.
*/
-static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
+static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf)
{
struct list_struct rec;
tdb_off rec_ptr;
/* find entry */
- if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec)))
+ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
return -1;
/* Append of 0 is always ok. */
@@ -1545,7 +1587,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
return -1;
/* first try in-place. */
- if (tdb_append_inplace(tdb, key, new_dbuf) == 0)
+ if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0)
goto out;
/* reset the error code potentially set by the tdb_append_inplace() */
@@ -1588,7 +1630,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
care. Doing this first reduces fragmentation, and avoids
coalescing with `allocated' block before it's updated. */
- tdb_delete(tdb, key);
+ tdb_delete_hash(tdb, key, hash);
if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec)))
goto fail;
@@ -1728,8 +1770,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
|| strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
- || tdb->header.version != TDB_VERSION
- || (tdb->header.hash_size != hash_size
+ || (tdb->header.version != TDB_VERSION
&& !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
/* its not a valid database - possibly initialise it */
if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
@@ -1934,6 +1975,8 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[])
void tdb_unlockkeys(TDB_CONTEXT *tdb)
{
u32 i;
+ if (!tdb->lockedkeys)
+ return;
for (i = 0; i < tdb->lockedkeys[0]; i++)
tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK);
SAFE_FREE(tdb->lockedkeys);
diff --git a/source4/tdb/tdbbackup.c b/source4/tdb/tdbbackup.c
index 7b344de6c4..1a0e1c1588 100644
--- a/source4/tdb/tdbbackup.c
+++ b/source4/tdb/tdbbackup.c
@@ -41,6 +41,11 @@
*/
+#ifdef STANDALONE
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -54,176 +59,15 @@
#include <sys/time.h>
#include <ctype.h>
#include <signal.h>
-#include "tdb.h"
-
-static int failed;
-
-static char *add_suffix(const char *name, const char *suffix)
-{
- char *ret;
- int len = strlen(name) + strlen(suffix) + 1;
- ret = malloc(len);
- if (!ret) {
- fprintf(stderr,"Out of memory!\n");
- exit(1);
- }
- strncpy(ret, name, len);
- strncat(ret, suffix, len);
- return ret;
-}
-
-static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
- TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state;
-
- if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) {
- fprintf(stderr,"Failed to insert into %s\n", tdb_new->name);
- failed = 1;
- return 1;
- }
- return 0;
-}
-
-
-static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
- return 0;
-}
-
-/*
- carefully backup a tdb, validating the contents and
- only doing the backup if its OK
- this function is also used for restore
-*/
-static int backup_tdb(const char *old_name, const char *new_name)
-{
- TDB_CONTEXT *tdb;
- TDB_CONTEXT *tdb_new;
- char *tmp_name;
- struct stat st;
- int count1, count2;
-
- tmp_name = add_suffix(new_name, ".tmp");
-
- /* stat the old tdb to find its permissions */
- if (stat(old_name, &st) != 0) {
- perror(old_name);
- return 1;
- }
- /* open the old tdb */
- tdb = tdb_open(old_name, 0, 0, O_RDWR, 0);
- if (!tdb) {
- printf("Failed to open %s\n", old_name);
- return 1;
- }
-
- /* create the new tdb */
- unlink(tmp_name);
- tdb_new = tdb_open(tmp_name, tdb->header.hash_size,
- TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL,
- st.st_mode & 0777);
- if (!tdb_new) {
- perror(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* lock the old tdb */
- if (tdb_lockall(tdb) != 0) {
- fprintf(stderr,"Failed to lock %s\n", old_name);
- tdb_close(tdb);
- tdb_close(tdb_new);
- unlink(tmp_name);
- free(tmp_name);
- return 1;
- }
+#else
- failed = 0;
+#include "includes.h"
- /* traverse and copy */
- count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new);
- if (count1 < 0 || failed) {
- fprintf(stderr,"failed to copy %s\n", old_name);
- tdb_close(tdb);
- tdb_close(tdb_new);
- unlink(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* close the old tdb */
- tdb_close(tdb);
-
- /* close the new tdb and re-open read-only */
- tdb_close(tdb_new);
- tdb_new = tdb_open(tmp_name, 0, TDB_DEFAULT, O_RDONLY, 0);
- if (!tdb_new) {
- fprintf(stderr,"failed to reopen %s\n", tmp_name);
- unlink(tmp_name);
- perror(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* traverse the new tdb to confirm */
- count2 = tdb_traverse(tdb_new, test_fn, 0);
- if (count2 != count1) {
- fprintf(stderr,"failed to copy %s\n", old_name);
- tdb_close(tdb_new);
- unlink(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* make sure the new tdb has reached stable storage */
- fsync(tdb_new->fd);
-
- /* close the new tdb and rename it to .bak */
- tdb_close(tdb_new);
- unlink(new_name);
- if (rename(tmp_name, new_name) != 0) {
- perror(new_name);
- free(tmp_name);
- return 1;
- }
-
- printf("%s : %d records\n", old_name, count1);
- free(tmp_name);
-
- return 0;
-}
-
-
-
-/*
- verify a tdb and if it is corrupt then restore from *.bak
-*/
-static int verify_tdb(const char *fname, const char *bak_name)
-{
- TDB_CONTEXT *tdb;
- int count = -1;
-
- /* open the tdb */
- tdb = tdb_open(fname, 0, 0, O_RDONLY, 0);
-
- /* traverse the tdb, then close it */
- if (tdb) {
- count = tdb_traverse(tdb, test_fn, NULL);
- tdb_close(tdb);
- }
-
- /* count is < 0 means an error */
- if (count < 0) {
- printf("restoring %s\n", fname);
- return backup_tdb(bak_name, fname);
- }
-
- printf("%s : %d records\n", fname, count);
-
- return 0;
-}
+#endif
+#include "tdb.h"
+#include "tdbback.h"
/*
see if one file is newer than another
@@ -245,7 +89,7 @@ static void usage(void)
printf("Usage: tdbbackup [options] <fname...>\n\n");
printf(" -h this help message\n");
printf(" -s suffix set the backup suffix\n");
- printf(" -v veryify mode (restore if corrupt)\n");
+ printf(" -v verify mode (restore if corrupt)\n");
}
@@ -255,7 +99,7 @@ static void usage(void)
int ret = 0;
int c;
int verify = 0;
- char *suffix = ".bak";
+ const char *suffix = ".bak";
extern int optind;
extern char *optarg;
@@ -303,13 +147,3 @@ static void usage(void)
return ret;
}
-
-#ifdef VALGRIND
-size_t valgrind_strlen(const char *s)
-{
- size_t count;
- for(count = 0; *s++; count++)
- ;
- return count;
-}
-#endif
diff --git a/source4/tdb/tdbtool.c b/source4/tdb/tdbtool.c
index f5e486be14..92009dcef4 100644
--- a/source4/tdb/tdbtool.c
+++ b/source4/tdb/tdbtool.c
@@ -111,23 +111,24 @@ static void print_data(unsigned char *buf,int len)
static void help(void)
{
- printf("
-tdbtool:
- create dbname : create a database
- open dbname : open an existing database
- erase : erase the database
- dump : dump the database as strings
- insert key data : insert a record
- store key data : store a record (replace)
- show key : show a record by key
- delete key : delete a record by key
- list : print the database hash table and freelist
- free : print the database freelist
- 1 | first : print the first record
- n | next : print the next record
- q | quit : terminate
- \\n : repeat 'next' command
-");
+ printf("\n"
+"tdbtool: \n"
+" create dbname : create a database\n"
+" open dbname : open an existing database\n"
+" erase : erase the database\n"
+" dump : dump the database as strings\n"
+" insert key data : insert a record\n"
+" move key file : move a record to a destination tdb\n"
+" store key data : store a record (replace)\n"
+" show key : show a record by key\n"
+" delete key : delete a record by key\n"
+" list : print the database hash table and freelist\n"
+" free : print the database freelist\n"
+" 1 | first : print the first record\n"
+" n | next : print the next record\n"
+" q | quit : terminate\n"
+" \\n : repeat 'next' command\n"
+"\n");
}
static void terror(char *why)
@@ -251,16 +252,26 @@ static void show_tdb(void)
}
key.dptr = k;
-/* key.dsize = strlen(k)+1;*/
- key.dsize = strlen(k);
+ key.dsize = strlen(k)+1;
dbuf = tdb_fetch(tdb, key);
if (!dbuf.dptr) {
- terror("fetch failed");
- return;
+ /* maybe it is non-NULL terminated key? */
+ key.dsize = strlen(k);
+ dbuf = tdb_fetch(tdb, key);
+
+ if ( !dbuf.dptr ) {
+ terror("fetch failed");
+ return;
+ }
}
+
/* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
print_rec(tdb, key, dbuf, NULL);
+
+ free( dbuf.dptr );
+
+ return;
}
static void delete_tdb(void)
@@ -281,6 +292,57 @@ static void delete_tdb(void)
}
}
+static void move_rec(void)
+{
+ char *k = get_token(1);
+ char *file = get_token(0);
+ TDB_DATA key, dbuf;
+ TDB_CONTEXT *dst_tdb;
+
+ if (!k) {
+ help();
+ return;
+ }
+
+ if ( !file ) {
+ terror("need destination tdb name");
+ return;
+ }
+
+ key.dptr = k;
+ key.dsize = strlen(k)+1;
+
+ dbuf = tdb_fetch(tdb, key);
+ if (!dbuf.dptr) {
+ /* maybe it is non-NULL terminated key? */
+ key.dsize = strlen(k);
+ dbuf = tdb_fetch(tdb, key);
+
+ if ( !dbuf.dptr ) {
+ terror("fetch failed");
+ return;
+ }
+ }
+
+ print_rec(tdb, key, dbuf, NULL);
+
+ dst_tdb = tdb_open(file, 0, 0, O_RDWR, 0600);
+ if ( !dst_tdb ) {
+ terror("unable to open destination tdb");
+ return;
+ }
+
+ if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
+ terror("failed to move record");
+ }
+ else
+ printf("record moved\n");
+
+ tdb_close( dst_tdb );
+
+ return;
+}
+
#if 0
static int print_conn_key(TDB_DATA key)
{
@@ -455,6 +517,9 @@ int main(int argc, char *argv[])
} else if (strcmp(tok,"dump") == 0) {
bIterate = 0;
tdb_traverse(tdb, print_rec, NULL);
+ } else if (strcmp(tok,"move") == 0) {
+ bIterate = 0;
+ move_rec();
} else if (strcmp(tok,"list") == 0) {
tdb_dump_all(tdb);
} else if (strcmp(tok, "free") == 0) {
diff --git a/source4/tdb/tdbtorture.c b/source4/tdb/tdbtorture.c
index e27bbff990..3f704e537e 100644
--- a/source4/tdb/tdbtorture.c
+++ b/source4/tdb/tdbtorture.c
@@ -5,6 +5,7 @@
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
+#include <signal.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <sys/stat.h>
diff --git a/source4/tdb/tdbutil.c b/source4/tdb/tdbutil.c
index 0d8f6128cc..ce5188300c 100644
--- a/source4/tdb/tdbutil.c
+++ b/source4/tdb/tdbutil.c
@@ -266,7 +266,7 @@ BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value)
on failure.
****************************************************************************/
-int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags)
+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);
@@ -278,7 +278,7 @@ int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int
free() on the result dptr.
****************************************************************************/
-TDB_DATA tdb_fetch_by_string(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);
@@ -289,7 +289,7 @@ TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, const char *keystr)
Delete an entry using a null terminated string key.
****************************************************************************/
-int tdb_delete_by_string(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);
@@ -311,7 +311,7 @@ int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldva
if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
/* The lookup failed */
if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
- /* but not becouse it didn't exist */
+ /* but not because it didn't exist */
goto err_out;
}
@@ -352,7 +352,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv
if (!tdb_fetch_uint32(tdb, keystr, &val)) {
/* It failed */
if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
- /* and not becouse it didn't exist */
+ /* and not because it didn't exist */
goto err_out;
}
@@ -387,6 +387,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv
size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
{
va_list ap;
+ uint8 bt;
uint16 w;
uint32 d;
int i;
@@ -402,44 +403,50 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
while (*fmt) {
switch ((c = *fmt++)) {
- case 'w':
+ 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 >= len)
+ if (bufsize && bufsize >= len)
SSVAL(buf, 0, w);
break;
- case 'd':
+ case 'd': /* signed 32-bit integer (standard int in most systems) */
len = 4;
d = va_arg(ap, uint32);
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
SIVAL(buf, 0, d);
break;
- case 'p':
+ case 'p': /* pointer */
len = 4;
p = va_arg(ap, void *);
d = p?1:0;
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
SIVAL(buf, 0, d);
break;
- case 'P':
+ case 'P': /* null-terminated string */
s = va_arg(ap,char *);
w = strlen(s);
len = w + 1;
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
memcpy(buf, s, len);
break;
- case 'f':
+ case 'f': /* null-terminated string */
s = va_arg(ap,char *);
w = strlen(s);
len = w + 1;
- if (bufsize >= len)
+ if (bufsize && bufsize >= len)
memcpy(buf, s, len);
break;
- case 'B':
+ case 'B': /* fixed-length string */
i = va_arg(ap, int);
s = va_arg(ap, char *);
len = 4+i;
- if (bufsize >= len) {
+ if (bufsize && bufsize >= len) {
SIVAL(buf, 0, i);
memcpy(buf+4, s, i);
}
@@ -452,7 +459,10 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
}
buf += len;
- bufsize -= len;
+ if (bufsize)
+ bufsize -= len;
+ if (bufsize < 0)
+ bufsize = 0;
}
va_end(ap);
@@ -471,6 +481,7 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
{
va_list ap;
+ uint8 *bt;
uint16 *w;
uint32 *d;
int len;
@@ -486,6 +497,13 @@ int tdb_unpack(char *buf, int bufsize, const char *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 *);
@@ -563,6 +581,67 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
return -1;
}
+
+/**
+ * Pack SID passed by pointer
+ *
+ * @param pack_buf pointer to buffer which is to be filled with packed data
+ * @param bufsize size of packing buffer
+ * @param sid pointer to sid to be packed
+ *
+ * @return length of the packed representation of the whole structure
+ **/
+size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+ int idx;
+ size_t len = 0;
+
+ if (!sid || !pack_buf) return -1;
+
+ len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num,
+ sid->num_auths);
+
+ for (idx = 0; idx < 6; idx++) {
+ len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]);
+ }
+
+ for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+ len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]);
+ }
+
+ return len;
+}
+
+
+/**
+ * Unpack SID into a pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param sid pointer to sid structure to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+ int idx, len = 0;
+
+ if (!sid || !pack_buf) return -1;
+
+ len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
+ &sid->sid_rev_num, &sid->num_auths);
+
+ for (idx = 0; idx < 6; idx++) {
+ len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
+ }
+
+ for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+ len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
+ }
+
+ return len;
+}
+
/****************************************************************************
Log tdb messages via DEBUG().
****************************************************************************/
@@ -665,7 +744,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
return list;
-};
+}
/**
@@ -679,9 +758,8 @@ void tdb_search_list_free(TDB_LIST_NODE* node)
while (node) {
next_node = node->next;
+ SAFE_FREE(node->node_key.dptr);
SAFE_FREE(node);
node = next_node;
- };
-};
-
-
+ }
+}
diff --git a/source4/torture/mangle_test.c b/source4/torture/mangle_test.c
index 758cef4861..de0a7f6a14 100644
--- a/source4/torture/mangle_test.c
+++ b/source4/torture/mangle_test.c
@@ -82,7 +82,7 @@ static BOOL test_one(struct cli_state *cli, const char *name)
}
/* see if the short name is already in the tdb */
- data = tdb_fetch_by_string(tdb, shortname);
+ data = tdb_fetch_bystring(tdb, shortname);
if (data.dptr) {
/* maybe its a duplicate long name? */
if (strcasecmp(name, data.dptr) != 0) {
@@ -98,7 +98,7 @@ static BOOL test_one(struct cli_state *cli, const char *name)
/* store it for later */
namedata.dptr = name;
namedata.dsize = strlen(name)+1;
- tdb_store_by_string(tdb, shortname, namedata, TDB_REPLACE);
+ tdb_store_bystring(tdb, shortname, namedata, TDB_REPLACE);
}
return True;
diff --git a/source4/utils/tdb/tdbbackup.c b/source4/utils/tdb/tdbbackup.c
index 7b344de6c4..1a0e1c1588 100644
--- a/source4/utils/tdb/tdbbackup.c
+++ b/source4/utils/tdb/tdbbackup.c
@@ -41,6 +41,11 @@
*/
+#ifdef STANDALONE
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -54,176 +59,15 @@
#include <sys/time.h>
#include <ctype.h>
#include <signal.h>
-#include "tdb.h"
-
-static int failed;
-
-static char *add_suffix(const char *name, const char *suffix)
-{
- char *ret;
- int len = strlen(name) + strlen(suffix) + 1;
- ret = malloc(len);
- if (!ret) {
- fprintf(stderr,"Out of memory!\n");
- exit(1);
- }
- strncpy(ret, name, len);
- strncat(ret, suffix, len);
- return ret;
-}
-
-static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
- TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state;
-
- if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) {
- fprintf(stderr,"Failed to insert into %s\n", tdb_new->name);
- failed = 1;
- return 1;
- }
- return 0;
-}
-
-
-static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
- return 0;
-}
-
-/*
- carefully backup a tdb, validating the contents and
- only doing the backup if its OK
- this function is also used for restore
-*/
-static int backup_tdb(const char *old_name, const char *new_name)
-{
- TDB_CONTEXT *tdb;
- TDB_CONTEXT *tdb_new;
- char *tmp_name;
- struct stat st;
- int count1, count2;
-
- tmp_name = add_suffix(new_name, ".tmp");
-
- /* stat the old tdb to find its permissions */
- if (stat(old_name, &st) != 0) {
- perror(old_name);
- return 1;
- }
- /* open the old tdb */
- tdb = tdb_open(old_name, 0, 0, O_RDWR, 0);
- if (!tdb) {
- printf("Failed to open %s\n", old_name);
- return 1;
- }
-
- /* create the new tdb */
- unlink(tmp_name);
- tdb_new = tdb_open(tmp_name, tdb->header.hash_size,
- TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL,
- st.st_mode & 0777);
- if (!tdb_new) {
- perror(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* lock the old tdb */
- if (tdb_lockall(tdb) != 0) {
- fprintf(stderr,"Failed to lock %s\n", old_name);
- tdb_close(tdb);
- tdb_close(tdb_new);
- unlink(tmp_name);
- free(tmp_name);
- return 1;
- }
+#else
- failed = 0;
+#include "includes.h"
- /* traverse and copy */
- count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new);
- if (count1 < 0 || failed) {
- fprintf(stderr,"failed to copy %s\n", old_name);
- tdb_close(tdb);
- tdb_close(tdb_new);
- unlink(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* close the old tdb */
- tdb_close(tdb);
-
- /* close the new tdb and re-open read-only */
- tdb_close(tdb_new);
- tdb_new = tdb_open(tmp_name, 0, TDB_DEFAULT, O_RDONLY, 0);
- if (!tdb_new) {
- fprintf(stderr,"failed to reopen %s\n", tmp_name);
- unlink(tmp_name);
- perror(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* traverse the new tdb to confirm */
- count2 = tdb_traverse(tdb_new, test_fn, 0);
- if (count2 != count1) {
- fprintf(stderr,"failed to copy %s\n", old_name);
- tdb_close(tdb_new);
- unlink(tmp_name);
- free(tmp_name);
- return 1;
- }
-
- /* make sure the new tdb has reached stable storage */
- fsync(tdb_new->fd);
-
- /* close the new tdb and rename it to .bak */
- tdb_close(tdb_new);
- unlink(new_name);
- if (rename(tmp_name, new_name) != 0) {
- perror(new_name);
- free(tmp_name);
- return 1;
- }
-
- printf("%s : %d records\n", old_name, count1);
- free(tmp_name);
-
- return 0;
-}
-
-
-
-/*
- verify a tdb and if it is corrupt then restore from *.bak
-*/
-static int verify_tdb(const char *fname, const char *bak_name)
-{
- TDB_CONTEXT *tdb;
- int count = -1;
-
- /* open the tdb */
- tdb = tdb_open(fname, 0, 0, O_RDONLY, 0);
-
- /* traverse the tdb, then close it */
- if (tdb) {
- count = tdb_traverse(tdb, test_fn, NULL);
- tdb_close(tdb);
- }
-
- /* count is < 0 means an error */
- if (count < 0) {
- printf("restoring %s\n", fname);
- return backup_tdb(bak_name, fname);
- }
-
- printf("%s : %d records\n", fname, count);
-
- return 0;
-}
+#endif
+#include "tdb.h"
+#include "tdbback.h"
/*
see if one file is newer than another
@@ -245,7 +89,7 @@ static void usage(void)
printf("Usage: tdbbackup [options] <fname...>\n\n");
printf(" -h this help message\n");
printf(" -s suffix set the backup suffix\n");
- printf(" -v veryify mode (restore if corrupt)\n");
+ printf(" -v verify mode (restore if corrupt)\n");
}
@@ -255,7 +99,7 @@ static void usage(void)
int ret = 0;
int c;
int verify = 0;
- char *suffix = ".bak";
+ const char *suffix = ".bak";
extern int optind;
extern char *optarg;
@@ -303,13 +147,3 @@ static void usage(void)
return ret;
}
-
-#ifdef VALGRIND
-size_t valgrind_strlen(const char *s)
-{
- size_t count;
- for(count = 0; *s++; count++)
- ;
- return count;
-}
-#endif
diff --git a/source4/utils/tdb/tdbtool.c b/source4/utils/tdb/tdbtool.c
index f5e486be14..92009dcef4 100644
--- a/source4/utils/tdb/tdbtool.c
+++ b/source4/utils/tdb/tdbtool.c
@@ -111,23 +111,24 @@ static void print_data(unsigned char *buf,int len)
static void help(void)
{
- printf("
-tdbtool:
- create dbname : create a database
- open dbname : open an existing database
- erase : erase the database
- dump : dump the database as strings
- insert key data : insert a record
- store key data : store a record (replace)
- show key : show a record by key
- delete key : delete a record by key
- list : print the database hash table and freelist
- free : print the database freelist
- 1 | first : print the first record
- n | next : print the next record
- q | quit : terminate
- \\n : repeat 'next' command
-");
+ printf("\n"
+"tdbtool: \n"
+" create dbname : create a database\n"
+" open dbname : open an existing database\n"
+" erase : erase the database\n"
+" dump : dump the database as strings\n"
+" insert key data : insert a record\n"
+" move key file : move a record to a destination tdb\n"
+" store key data : store a record (replace)\n"
+" show key : show a record by key\n"
+" delete key : delete a record by key\n"
+" list : print the database hash table and freelist\n"
+" free : print the database freelist\n"
+" 1 | first : print the first record\n"
+" n | next : print the next record\n"
+" q | quit : terminate\n"
+" \\n : repeat 'next' command\n"
+"\n");
}
static void terror(char *why)
@@ -251,16 +252,26 @@ static void show_tdb(void)
}
key.dptr = k;
-/* key.dsize = strlen(k)+1;*/
- key.dsize = strlen(k);
+ key.dsize = strlen(k)+1;
dbuf = tdb_fetch(tdb, key);
if (!dbuf.dptr) {
- terror("fetch failed");
- return;
+ /* maybe it is non-NULL terminated key? */
+ key.dsize = strlen(k);
+ dbuf = tdb_fetch(tdb, key);
+
+ if ( !dbuf.dptr ) {
+ terror("fetch failed");
+ return;
+ }
}
+
/* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
print_rec(tdb, key, dbuf, NULL);
+
+ free( dbuf.dptr );
+
+ return;
}
static void delete_tdb(void)
@@ -281,6 +292,57 @@ static void delete_tdb(void)
}
}
+static void move_rec(void)
+{
+ char *k = get_token(1);
+ char *file = get_token(0);
+ TDB_DATA key, dbuf;
+ TDB_CONTEXT *dst_tdb;
+
+ if (!k) {
+ help();
+ return;
+ }
+
+ if ( !file ) {
+ terror("need destination tdb name");
+ return;
+ }
+
+ key.dptr = k;
+ key.dsize = strlen(k)+1;
+
+ dbuf = tdb_fetch(tdb, key);
+ if (!dbuf.dptr) {
+ /* maybe it is non-NULL terminated key? */
+ key.dsize = strlen(k);
+ dbuf = tdb_fetch(tdb, key);
+
+ if ( !dbuf.dptr ) {
+ terror("fetch failed");
+ return;
+ }
+ }
+
+ print_rec(tdb, key, dbuf, NULL);
+
+ dst_tdb = tdb_open(file, 0, 0, O_RDWR, 0600);
+ if ( !dst_tdb ) {
+ terror("unable to open destination tdb");
+ return;
+ }
+
+ if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
+ terror("failed to move record");
+ }
+ else
+ printf("record moved\n");
+
+ tdb_close( dst_tdb );
+
+ return;
+}
+
#if 0
static int print_conn_key(TDB_DATA key)
{
@@ -455,6 +517,9 @@ int main(int argc, char *argv[])
} else if (strcmp(tok,"dump") == 0) {
bIterate = 0;
tdb_traverse(tdb, print_rec, NULL);
+ } else if (strcmp(tok,"move") == 0) {
+ bIterate = 0;
+ move_rec();
} else if (strcmp(tok,"list") == 0) {
tdb_dump_all(tdb);
} else if (strcmp(tok, "free") == 0) {
diff --git a/source4/utils/tdb/tdbtorture.c b/source4/utils/tdb/tdbtorture.c
index e27bbff990..3f704e537e 100644
--- a/source4/utils/tdb/tdbtorture.c
+++ b/source4/utils/tdb/tdbtorture.c
@@ -5,6 +5,7 @@
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
+#include <signal.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <sys/stat.h>