Whamcloud - gitweb
Fix dbg_print() format for unsigned long long.
[tools/e2fsprogs.git] / lib / ext2fs / tdb.c
index c868958..b36c485 100644 (file)
@@ -3,17 +3,17 @@ URL: svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb/common
 Rev: 23590
 Last Changed Date: 2007-06-22 13:36:10 -0400 (Fri, 22 Jun 2007)
 */
 Rev: 23590
 Last Changed Date: 2007-06-22 13:36:10 -0400 (Fri, 22 Jun 2007)
 */
- /* 
+ /*
    trivial database library - standalone version
 
    Copyright (C) Andrew Tridgell              1999-2005
    Copyright (C) Jeremy Allison               2000-2006
    Copyright (C) Paul `Rusty' Russell         2000
    trivial database library - standalone version
 
    Copyright (C) Andrew Tridgell              1999-2005
    Copyright (C) Jeremy Allison               2000-2006
    Copyright (C) Paul `Rusty' Russell         2000
-   
+
      ** NOTE! The following LGPL license applies to the tdb
      ** library. This does NOT imply that all of Samba is released
      ** under the LGPL
      ** NOTE! The following LGPL license applies to the tdb
      ** library. This does NOT imply that all of Samba is released
      ** under the LGPL
-   
+
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
@@ -36,8 +36,11 @@ Last Changed Date: 2007-06-22 13:36:10 -0400 (Fri, 22 Jun 2007)
 #define HAVE_UTIME_H
 #define HAVE_UTIME
 #endif
 #define HAVE_UTIME_H
 #define HAVE_UTIME
 #endif
-#define _XOPEN_SOURCE 500
+#ifndef __FreeBSD__
+#define _XOPEN_SOURCE 600
+#endif
 
 
+#include "config.h"
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -107,14 +110,12 @@ typedef int bool;
 
 #include "tdb.h"
 
 
 #include "tdb.h"
 
+static TDB_DATA tdb_null;
+
 #ifndef u32
 #define u32 unsigned
 #endif
 
 #ifndef u32
 #define u32 unsigned
 #endif
 
-#ifndef HAVE_GETPAGESIZE
-#define getpagesize() 0x2000
-#endif
-
 typedef u32 tdb_len_t;
 typedef u32 tdb_off_t;
 
 typedef u32 tdb_len_t;
 typedef u32 tdb_off_t;
 
@@ -247,6 +248,7 @@ struct tdb_context {
        int page_size;
        int max_dead_records;
        bool have_transaction_lock;
        int page_size;
        int max_dead_records;
        bool have_transaction_lock;
+       tdb_len_t real_map_size; /* how much space has been mapped */
 };
 
 
 };
 
 
@@ -327,11 +329,11 @@ const char *tdb_errorstr(struct tdb_context *tdb)
    this functions locks/unlocks 1 byte at the specified offset.
 
    On error, errno is also set so that errors are passed back properly
    this functions locks/unlocks 1 byte at the specified offset.
 
    On error, errno is also set so that errors are passed back properly
-   through tdb_open(). 
+   through tdb_open().
 
    note that a len of zero means lock to end of file
 */
 
    note that a len of zero means lock to end of file
 */
-int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, 
+int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
               int rw_type, int lck_type, int probe, size_t len)
 {
        struct flock fl;
               int rw_type, int lck_type, int probe, size_t len)
 {
        struct flock fl;
@@ -363,7 +365,7 @@ int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
                if (!probe && lck_type != F_SETLK) {
                        /* Ensure error code is set for log fun to examine. */
                        tdb->ecode = TDB_ERR_LOCK;
                if (!probe && lck_type != F_SETLK) {
                        /* Ensure error code is set for log fun to examine. */
                        tdb->ecode = TDB_ERR_LOCK;
-                       TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", 
+                       TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
                                 tdb->fd, offset, rw_type, lck_type, (int)len));
                }
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
                                 tdb->fd, offset, rw_type, lck_type, (int)len));
                }
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
@@ -376,7 +378,7 @@ int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
   upgrade a read lock to a write lock. This needs to be handled in a
   special way as some OSes (such as solaris) have too conservative
   deadlock detection and claim a deadlock when progress can be
   upgrade a read lock to a write lock. This needs to be handled in a
   special way as some OSes (such as solaris) have too conservative
   deadlock detection and claim a deadlock when progress can be
-  made. For those OSes we may loop for a while.  
+  made. For those OSes we may loop for a while.
 */
 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
 {
 */
 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
 {
@@ -409,7 +411,7 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
        ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
        ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
-       if (tdb->global_lock.count && 
+       if (tdb->global_lock.count &&
            (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
                return 0;
        }
            (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
                return 0;
        }
@@ -419,7 +421,7 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
        }
 
        if (list < -1 || list >= (int)tdb->header.hash_size) {
        }
 
        if (list < -1 || list >= (int)tdb->header.hash_size) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", 
+               TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n",
                           list, ltype));
                return -1;
        }
                           list, ltype));
                return -1;
        }
@@ -504,7 +506,7 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
        ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
        ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
-       if (tdb->global_lock.count && 
+       if (tdb->global_lock.count &&
            (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
                return 0;
        }
            (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
                return 0;
        }
@@ -574,7 +576,7 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
        }
 
        if (ret)
        }
 
        if (ret)
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n")); 
+               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n"));
        return ret;
 }
 
        return ret;
 }
 
@@ -586,7 +588,7 @@ int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
        if (tdb->have_transaction_lock || tdb->global_lock.count) {
                return 0;
        }
        if (tdb->have_transaction_lock || tdb->global_lock.count) {
                return 0;
        }
-       if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, 
+       if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype,
                                     F_SETLKW, 0, 1) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
                tdb->ecode = TDB_ERR_LOCK;
                                     F_SETLKW, 0, 1) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
                tdb->ecode = TDB_ERR_LOCK;
@@ -635,7 +637,7 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
                /* a global lock of a different type exists */
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
        }
                /* a global lock of a different type exists */
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
        }
-       
+
        if (tdb->num_locks != 0) {
                /* can't combine global and chain locks */
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
        if (tdb->num_locks != 0) {
                /* can't combine global and chain locks */
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
@@ -680,7 +682,7 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
        }
 
        if (!mark_lock &&
        }
 
        if (!mark_lock &&
-           tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 
+           tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW,
                                     0, 4*tdb->header.hash_size)) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
                return -1;
                                     0, 4*tdb->header.hash_size)) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
                return -1;
@@ -831,7 +833,7 @@ int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off)
 
 /* check for an out of bounds access - if it is out of bounds then
    see if the database has been expanded by someone else and expand
 
 /* check for an out of bounds access - if it is out of bounds then
    see if the database has been expanded by someone else and expand
-   if necessary 
+   if necessary
    note that "len" is the minimum length needed for the db
 */
 static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
    note that "len" is the minimum length needed for the db
 */
 static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
@@ -872,7 +874,7 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
 }
 
 /* write a lump of data at a specified offset */
 }
 
 /* write a lump of data at a specified offset */
-static int tdb_write(struct tdb_context *tdb, tdb_off_t off, 
+static int tdb_write(struct tdb_context *tdb, tdb_off_t off,
                     const void *buf, tdb_len_t len)
 {
        if (len == 0) {
                     const void *buf, tdb_len_t len)
 {
        if (len == 0) {
@@ -910,7 +912,7 @@ void *tdb_convert(void *buf, u32 size)
 
 
 /* read a lump of data at a specified offset, maybe convert */
 
 
 /* read a lump of data at a specified offset, maybe convert */
-static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, 
+static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
                    tdb_len_t len, int cv)
 {
        if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) {
                    tdb_len_t len, int cv)
 {
        if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) {
@@ -942,7 +944,7 @@ static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
 /*
   do an unlocked scan of the hash table heads to find the next non-zero head. The value
   will then be confirmed with the lock held
 /*
   do an unlocked scan of the hash table heads to find the next non-zero head. The value
   will then be confirmed with the lock held
-*/             
+*/
 static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain)
 {
        u32 h = *chain;
 static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain)
 {
        u32 h = *chain;
@@ -971,9 +973,10 @@ int tdb_munmap(struct tdb_context *tdb)
 
 #ifdef HAVE_MMAP
        if (tdb->map_ptr) {
 
 #ifdef HAVE_MMAP
        if (tdb->map_ptr) {
-               int ret = munmap(tdb->map_ptr, tdb->map_size);
+               int ret = munmap(tdb->map_ptr, tdb->real_map_size);
                if (ret != 0)
                        return ret;
                if (ret != 0)
                        return ret;
+               tdb->real_map_size = 0;
        }
 #endif
        tdb->map_ptr = NULL;
        }
 #endif
        tdb->map_ptr = NULL;
@@ -987,8 +990,8 @@ void tdb_mmap(struct tdb_context *tdb)
 
 #ifdef HAVE_MMAP
        if (!(tdb->flags & TDB_NOMMAP)) {
 
 #ifdef HAVE_MMAP
        if (!(tdb->flags & TDB_NOMMAP)) {
-               tdb->map_ptr = mmap(NULL, tdb->map_size, 
-                                   PROT_READ|(tdb->read_only? 0:PROT_WRITE), 
+               tdb->map_ptr = mmap(NULL, tdb->map_size,
+                                   PROT_READ|(tdb->read_only? 0:PROT_WRITE),
                                    MAP_SHARED|MAP_FILE, tdb->fd, 0);
 
                /*
                                    MAP_SHARED|MAP_FILE, tdb->fd, 0);
 
                /*
@@ -996,10 +999,12 @@ void tdb_mmap(struct tdb_context *tdb)
                 */
 
                if (tdb->map_ptr == MAP_FAILED) {
                 */
 
                if (tdb->map_ptr == MAP_FAILED) {
+                       tdb->real_map_size = 0;
                        tdb->map_ptr = NULL;
                        tdb->map_ptr = NULL;
-                       TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n", 
+                       TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n",
                                 tdb->map_size, strerror(errno)));
                }
                                 tdb->map_size, strerror(errno)));
                }
+               tdb->real_map_size = tdb->map_size;
        } else {
                tdb->map_ptr = NULL;
        }
        } else {
                tdb->map_ptr = NULL;
        }
@@ -1022,7 +1027,7 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad
        if (ftruncate(tdb->fd, size+addition) == -1) {
                char b = 0;
                if (pwrite(tdb->fd,  &b, 1, (size+addition) - 1) != 1) {
        if (ftruncate(tdb->fd, size+addition) == -1) {
                char b = 0;
                if (pwrite(tdb->fd,  &b, 1, (size+addition) - 1) != 1) {
-                       TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", 
+                       TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n",
                                 size+addition, strerror(errno)));
                        return -1;
                }
                                 size+addition, strerror(errno)));
                        return -1;
                }
@@ -1036,7 +1041,7 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad
                int n = addition>sizeof(buf)?sizeof(buf):addition;
                int ret = pwrite(tdb->fd, buf, n, size);
                if (ret != n) {
                int n = addition>sizeof(buf)?sizeof(buf):addition;
                int ret = pwrite(tdb->fd, buf, n, size);
                if (ret != n) {
-                       TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n", 
+                       TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n",
                                   n, strerror(errno)));
                        return -1;
                }
                                   n, strerror(errno)));
                        return -1;
                }
@@ -1262,7 +1267,7 @@ void tdb_io_init(struct tdb_context *tdb)
   - allow for nested calls to tdb_transaction_start(), re-using the
     existing transaction record. If the inner transaction is cancelled
     then a subsequent commit will fail
   - allow for nested calls to tdb_transaction_start(), re-using the
     existing transaction record. If the inner transaction is cancelled
     then a subsequent commit will fail
+
   - keep a mirrored copy of the tdb hash chain heads to allow for the
     fast hash heads scan on traverse, updating the mirrored copy in
     the transaction version of tdb_write
   - keep a mirrored copy of the tdb hash chain heads to allow for the
     fast hash heads scan on traverse, updating the mirrored copy in
     the transaction version of tdb_write
@@ -1334,7 +1339,7 @@ struct tdb_transaction {
   read while in a transaction. We need to check first if the data is in our list
   of transaction elements, then if not do a real read
 */
   read while in a transaction. We need to check first if the data is in our list
   of transaction elements, then if not do a real read
 */
-static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, 
+static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
                            tdb_len_t len, int cv)
 {
        struct tdb_transaction_el *el;
                            tdb_len_t len, int cv)
 {
        struct tdb_transaction_el *el;
@@ -1373,7 +1378,7 @@ static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
                len -= partial;
                off += partial;
                buf = (void *)(partial + (char *)buf);
                len -= partial;
                off += partial;
                buf = (void *)(partial + (char *)buf);
-               
+
                if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) {
                        goto fail;
                }
                if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) {
                        goto fail;
                }
@@ -1395,7 +1400,7 @@ fail:
 /*
   write while in a transaction
 */
 /*
   write while in a transaction
 */
-static int transaction_write(struct tdb_context *tdb, tdb_off_t off, 
+static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
                             const void *buf, tdb_len_t len)
 {
        struct tdb_transaction_el *el, *best_el=NULL;
                             const void *buf, tdb_len_t len)
 {
        struct tdb_transaction_el *el, *best_el=NULL;
@@ -1403,7 +1408,7 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
        if (len == 0) {
                return 0;
        }
        if (len == 0) {
                return 0;
        }
-       
+
        /* if the write is to a hash head, then update the transaction
           hash heads */
        if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP &&
        /* if the write is to a hash head, then update the transaction
           hash heads */
        if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP &&
@@ -1447,7 +1452,7 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
                len -= partial;
                off += partial;
                buf = (const void *)(partial + (const char *)buf);
                len -= partial;
                off += partial;
                buf = (const void *)(partial + (const char *)buf);
-               
+
                if (len != 0 && transaction_write(tdb, off, buf, len) != 0) {
                        goto fail;
                }
                if (len != 0 && transaction_write(tdb, off, buf, len) != 0) {
                        goto fail;
                }
@@ -1456,7 +1461,7 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
        }
 
        /* see if we can append the new entry to an existing entry */
        }
 
        /* see if we can append the new entry to an existing entry */
-       if (best_el && best_el->offset + best_el->length == off && 
+       if (best_el && best_el->offset + best_el->length == off &&
            (off+len < tdb->transaction->old_map_size ||
             off > tdb->transaction->old_map_size)) {
                unsigned char *data = best_el->data;
            (off+len < tdb->transaction->old_map_size ||
             off > tdb->transaction->old_map_size)) {
                unsigned char *data = best_el->data;
@@ -1482,7 +1487,7 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
        el = (struct tdb_transaction_el *)malloc(sizeof(*el));
        if (el == NULL) {
                tdb->ecode = TDB_ERR_OOM;
        el = (struct tdb_transaction_el *)malloc(sizeof(*el));
        if (el == NULL) {
                tdb->ecode = TDB_ERR_OOM;
-               tdb->transaction->transaction_error = 1;                
+               tdb->transaction->transaction_error = 1;
                return -1;
        }
        el->next = NULL;
                return -1;
        }
        el->next = NULL;
@@ -1493,7 +1498,7 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
        if (el->data == NULL) {
                free(el);
                tdb->ecode = TDB_ERR_OOM;
        if (el->data == NULL) {
                free(el);
                tdb->ecode = TDB_ERR_OOM;
-               tdb->transaction->transaction_error = 1;                
+               tdb->transaction->transaction_error = 1;
                return -1;
        }
        if (buf) {
                return -1;
        }
        if (buf) {
@@ -1545,7 +1550,7 @@ static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
 /*
   transaction version of tdb_expand().
 */
 /*
   transaction version of tdb_expand().
 */
-static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, 
+static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size,
                                   tdb_off_t addition)
 {
        /* add a write to the transaction elements, so subsequent
                                   tdb_off_t addition)
 {
        /* add a write to the transaction elements, so subsequent
@@ -1560,7 +1565,7 @@ static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size,
 /*
   brlock during a transaction - ignore them
 */
 /*
   brlock during a transaction - ignore them
 */
-static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, 
+static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
                              int rw_type, int lck_type, int probe, size_t len)
 {
        return 0;
                              int rw_type, int lck_type, int probe, size_t len)
 {
        return 0;
@@ -1592,7 +1597,7 @@ int tdb_transaction_start(struct tdb_context *tdb)
        /* cope with nested tdb_transaction_start() calls */
        if (tdb->transaction != NULL) {
                tdb->transaction->nesting++;
        /* cope with nested tdb_transaction_start() calls */
        if (tdb->transaction != NULL) {
                tdb->transaction->nesting++;
-               TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", 
+               TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n",
                         tdb->transaction->nesting));
                return 0;
        }
                         tdb->transaction->nesting));
                return 0;
        }
@@ -1629,7 +1634,7 @@ int tdb_transaction_start(struct tdb_context *tdb)
                SAFE_FREE(tdb->transaction);
                return -1;
        }
                SAFE_FREE(tdb->transaction);
                return -1;
        }
-       
+
        /* get a read lock from the freelist to the end of file. This
           is upgraded to a write lock during the commit */
        if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
        /* get a read lock from the freelist to the end of file. This
           is upgraded to a write lock during the commit */
        if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
@@ -1665,7 +1670,7 @@ int tdb_transaction_start(struct tdb_context *tdb)
 
        /* by calling this transaction write here, we ensure that we don't grow the
           transaction linked list due to hash table updates */
 
        /* by calling this transaction write here, we ensure that we don't grow the
           transaction linked list due to hash table updates */
-       if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, 
+       if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
                              TDB_HASHTABLE_SIZE(tdb)) != 0) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n"));
                tdb->ecode = TDB_ERR_IO;
                              TDB_HASHTABLE_SIZE(tdb)) != 0) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n"));
                tdb->ecode = TDB_ERR_IO;
@@ -1674,7 +1679,7 @@ int tdb_transaction_start(struct tdb_context *tdb)
        }
 
        return 0;
        }
 
        return 0;
-       
+
 fail:
        tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
        tdb_transaction_unlock(tdb);
 fail:
        tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
        tdb_transaction_unlock(tdb);
@@ -1688,7 +1693,7 @@ fail:
   cancel the current transaction
 */
 int tdb_transaction_cancel(struct tdb_context *tdb)
   cancel the current transaction
 */
 int tdb_transaction_cancel(struct tdb_context *tdb)
-{      
+{
        if (tdb->transaction == NULL) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n"));
                return -1;
        if (tdb->transaction == NULL) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n"));
                return -1;
@@ -1698,7 +1703,7 @@ int tdb_transaction_cancel(struct tdb_context *tdb)
                tdb->transaction->transaction_error = 1;
                tdb->transaction->nesting--;
                return 0;
                tdb->transaction->transaction_error = 1;
                tdb->transaction->nesting--;
                return 0;
-       }               
+       }
 
        tdb->map_size = tdb->transaction->old_map_size;
 
 
        tdb->map_size = tdb->transaction->old_map_size;
 
@@ -1735,7 +1740,7 @@ int tdb_transaction_cancel(struct tdb_context *tdb)
        tdb_transaction_unlock(tdb);
        SAFE_FREE(tdb->transaction->hash_heads);
        SAFE_FREE(tdb->transaction);
        tdb_transaction_unlock(tdb);
        SAFE_FREE(tdb->transaction->hash_heads);
        SAFE_FREE(tdb->transaction);
-       
+
        return 0;
 }
 
        return 0;
 }
 
@@ -1743,16 +1748,16 @@ int tdb_transaction_cancel(struct tdb_context *tdb)
   sync to disk
 */
 static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length)
   sync to disk
 */
 static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length)
-{      
+{
        if (fsync(tdb->fd) != 0) {
                tdb->ecode = TDB_ERR_IO;
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
                return -1;
        }
        if (fsync(tdb->fd) != 0) {
                tdb->ecode = TDB_ERR_IO;
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
                return -1;
        }
-#ifdef MS_SYNC
+#if defined(HAVE_MSYNC) && defined(MS_SYNC)
        if (tdb->map_ptr) {
                tdb_off_t moffset = offset & ~(tdb->page_size-1);
        if (tdb->map_ptr) {
                tdb_off_t moffset = offset & ~(tdb->page_size-1);
-               if (msync(moffset + (char *)tdb->map_ptr, 
+               if (msync(moffset + (char *)tdb->map_ptr,
                          length + (offset - moffset), MS_SYNC) != 0) {
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n",
                          length + (offset - moffset), MS_SYNC) != 0) {
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n",
@@ -1788,7 +1793,7 @@ static tdb_len_t tdb_recovery_size(struct tdb_context *tdb)
   allocate the recovery area, or use an existing recovery area if it is
   large enough
 */
   allocate the recovery area, or use an existing recovery area if it is
   large enough
 */
-static int tdb_recovery_allocate(struct tdb_context *tdb, 
+static int tdb_recovery_allocate(struct tdb_context *tdb,
                                 tdb_len_t *recovery_size,
                                 tdb_off_t *recovery_offset,
                                 tdb_len_t *recovery_max_size)
                                 tdb_len_t *recovery_size,
                                 tdb_off_t *recovery_offset,
                                 tdb_len_t *recovery_max_size)
@@ -1804,7 +1809,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
 
        rec.rec_len = 0;
 
 
        rec.rec_len = 0;
 
-       if (recovery_head != 0 && 
+       if (recovery_head != 0 &&
            methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
                return -1;
            methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
                return -1;
@@ -1839,7 +1844,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
        *recovery_offset = tdb->map_size;
        recovery_head = *recovery_offset;
 
        *recovery_offset = tdb->map_size;
        recovery_head = *recovery_offset;
 
-       if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, 
+       if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
                                     (tdb->map_size - tdb->transaction->old_map_size) +
                                     sizeof(rec) + *recovery_max_size) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n"));
                                     (tdb->map_size - tdb->transaction->old_map_size) +
                                     sizeof(rec) + *recovery_max_size) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n"));
@@ -1856,7 +1861,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
        /* write the recovery header offset and sync - we can sync without a race here
           as the magic ptr in the recovery record has not been set */
        CONVERT(recovery_head);
        /* write the recovery header offset and sync - we can sync without a race here
           as the magic ptr in the recovery record has not been set */
        CONVERT(recovery_head);
-       if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, 
+       if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD,
                               &recovery_head, sizeof(tdb_off_t)) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n"));
                return -1;
                               &recovery_head, sizeof(tdb_off_t)) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n"));
                return -1;
@@ -1869,7 +1874,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
 /*
   setup the recovery data that will be used on a crash during commit
 */
 /*
   setup the recovery data that will be used on a crash during commit
 */
-static int transaction_setup_recovery(struct tdb_context *tdb, 
+static int transaction_setup_recovery(struct tdb_context *tdb,
                                      tdb_off_t *magic_offset)
 {
        struct tdb_transaction_el *el;
                                      tdb_off_t *magic_offset)
 {
        struct tdb_transaction_el *el;
@@ -1884,7 +1889,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
        /*
          check that the recovery area has enough space
        */
        /*
          check that the recovery area has enough space
        */
-       if (tdb_recovery_allocate(tdb, &recovery_size, 
+       if (tdb_recovery_allocate(tdb, &recovery_size,
                                  &recovery_offset, &recovery_max_size) == -1) {
                return -1;
        }
                                  &recovery_offset, &recovery_max_size) == -1) {
                return -1;
        }
@@ -1979,7 +1984,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
   commit the current transaction
 */
 int tdb_transaction_commit(struct tdb_context *tdb)
   commit the current transaction
 */
 int tdb_transaction_commit(struct tdb_context *tdb)
-{      
+{
        const struct tdb_methods *methods;
        tdb_off_t magic_offset = 0;
        u32 zero = 0;
        const struct tdb_methods *methods;
        tdb_off_t magic_offset = 0;
        u32 zero = 0;
@@ -1999,7 +2004,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
        if (tdb->transaction->nesting != 0) {
                tdb->transaction->nesting--;
                return 0;
        if (tdb->transaction->nesting != 0) {
                tdb->transaction->nesting--;
                return 0;
-       }               
+       }
 
        /* check for a null transaction */
        if (tdb->transaction->elements == NULL) {
 
        /* check for a null transaction */
        if (tdb->transaction->elements == NULL) {
@@ -2008,7 +2013,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
        }
 
        methods = tdb->transaction->io_methods;
        }
 
        methods = tdb->transaction->io_methods;
-       
+
        /* if there are any locks pending then the caller has not
           nested their locks properly, so fail the transaction */
        if (tdb->num_locks || tdb->global_lock.count) {
        /* if there are any locks pending then the caller has not
           nested their locks properly, so fail the transaction */
        if (tdb->num_locks || tdb->global_lock.count) {
@@ -2047,8 +2052,8 @@ int tdb_transaction_commit(struct tdb_context *tdb)
 
        /* expand the file to the new size if needed */
        if (tdb->map_size != tdb->transaction->old_map_size) {
 
        /* expand the file to the new size if needed */
        if (tdb->map_size != tdb->transaction->old_map_size) {
-               if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, 
-                                            tdb->map_size - 
+               if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
+                                            tdb->map_size -
                                             tdb->transaction->old_map_size) == -1) {
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n"));
                                             tdb->transaction->old_map_size) == -1) {
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n"));
@@ -2066,12 +2071,12 @@ int tdb_transaction_commit(struct tdb_context *tdb)
 
                if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
 
                if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
-                       
+
                        /* we've overwritten part of the data and
                           possibly expanded the file, so we need to
                           run the crash recovery code */
                        tdb->methods = methods;
                        /* we've overwritten part of the data and
                           possibly expanded the file, so we need to
                           run the crash recovery code */
                        tdb->methods = methods;
-                       tdb_transaction_recover(tdb); 
+                       tdb_transaction_recover(tdb);
 
                        tdb_transaction_cancel(tdb);
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
 
                        tdb_transaction_cancel(tdb);
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
@@ -2080,9 +2085,9 @@ int tdb_transaction_commit(struct tdb_context *tdb)
                        return -1;
                }
                tdb->transaction->elements = el->next;
                        return -1;
                }
                tdb->transaction->elements = el->next;
-               free(el->data); 
+               free(el->data);
                free(el);
                free(el);
-       } 
+       }
 
        if (!(tdb->flags & TDB_NOSYNC)) {
                /* ensure the new data is on disk */
 
        if (!(tdb->flags & TDB_NOSYNC)) {
                /* ensure the new data is on disk */
@@ -2151,9 +2156,9 @@ int tdb_transaction_recover(struct tdb_context *tdb)
        }
 
        /* read the recovery record */
        }
 
        /* read the recovery record */
-       if (tdb->methods->tdb_read(tdb, recovery_head, &rec, 
+       if (tdb->methods->tdb_read(tdb, recovery_head, &rec,
                                   sizeof(rec), DOCONV()) == -1) {
                                   sizeof(rec), DOCONV()) == -1) {
-               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n"));           
+               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n"));
                tdb->ecode = TDB_ERR_IO;
                return -1;
        }
                tdb->ecode = TDB_ERR_IO;
                return -1;
        }
@@ -2173,7 +2178,7 @@ int tdb_transaction_recover(struct tdb_context *tdb)
 
        data = (unsigned char *)malloc(rec.data_len);
        if (data == NULL) {
 
        data = (unsigned char *)malloc(rec.data_len);
        if (data == NULL) {
-               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n"));         
+               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n"));
                tdb->ecode = TDB_ERR_OOM;
                return -1;
        }
                tdb->ecode = TDB_ERR_OOM;
                return -1;
        }
@@ -2181,7 +2186,7 @@ int tdb_transaction_recover(struct tdb_context *tdb)
        /* read the full recovery data */
        if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data,
                                   rec.data_len, 0) == -1) {
        /* read the full recovery data */
        if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data,
                                   rec.data_len, 0) == -1) {
-               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n"));             
+               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n"));
                tdb->ecode = TDB_ERR_IO;
                return -1;
        }
                tdb->ecode = TDB_ERR_IO;
                return -1;
        }
@@ -2218,24 +2223,24 @@ int tdb_transaction_recover(struct tdb_context *tdb)
                if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n"));
                        tdb->ecode = TDB_ERR_IO;
                if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n"));
                        tdb->ecode = TDB_ERR_IO;
-                       return -1;                      
+                       return -1;
                }
        }
 
        /* remove the recovery magic */
                }
        }
 
        /* remove the recovery magic */
-       if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), 
+       if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic),
                          &zero) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n"));
                tdb->ecode = TDB_ERR_IO;
                          &zero) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n"));
                tdb->ecode = TDB_ERR_IO;
-               return -1;                      
+               return -1;
        }
        }
-       
+
        /* reduce the file size to the old size */
        tdb_munmap(tdb);
        if (ftruncate(tdb->fd, recovery_eof) != 0) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));
                tdb->ecode = TDB_ERR_IO;
        /* reduce the file size to the old size */
        tdb_munmap(tdb);
        if (ftruncate(tdb->fd, recovery_eof) != 0) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));
                tdb->ecode = TDB_ERR_IO;
-               return -1;                      
+               return -1;
        }
        tdb->map_size = recovery_eof;
        tdb_mmap(tdb);
        }
        tdb->map_size = recovery_eof;
        tdb_mmap(tdb);
@@ -2246,7 +2251,7 @@ int tdb_transaction_recover(struct tdb_context *tdb)
                return -1;
        }
 
                return -1;
        }
 
-       TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n", 
+       TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n",
                 recovery_eof));
 
        /* all done */
                 recovery_eof));
 
        /* all done */
@@ -2264,7 +2269,7 @@ static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list
        if (rec->magic == TDB_MAGIC) {
                /* this happens when a app is showdown while deleting a record - we should
                   not completely fail when this happens */
        if (rec->magic == TDB_MAGIC) {
                /* this happens when a app is showdown while deleting a record - we should
                   not completely fail when this happens */
-               TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n", 
+               TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
                         rec->magic, off));
                rec->magic = TDB_FREE_MAGIC;
                if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
                         rec->magic, off));
                rec->magic = TDB_FREE_MAGIC;
                if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
@@ -2274,7 +2279,7 @@ static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list
        if (rec->magic != TDB_FREE_MAGIC) {
                /* Ensure ecode is set for log fn. */
                tdb->ecode = TDB_ERR_CORRUPT;
        if (rec->magic != TDB_FREE_MAGIC) {
                /* Ensure ecode is set for log fn. */
                tdb->ecode = TDB_ERR_CORRUPT;
-               TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", 
+               TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n",
                           rec->magic, off));
                return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
        }
                           rec->magic, off));
                return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
        }
@@ -2359,7 +2364,7 @@ left:
        if (left > TDB_DATA_START(tdb->header.hash_size)) {
                struct list_struct l;
                tdb_off_t leftsize;
        if (left > TDB_DATA_START(tdb->header.hash_size)) {
                struct list_struct l;
                tdb_off_t leftsize;
-               
+
                /* Read in tailer and jump back to header */
                if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left));
                /* Read in tailer and jump back to header */
                if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left));
@@ -2417,7 +2422,7 @@ update:
 }
 
 
 }
 
 
-/* 
+/*
    the core of tdb_allocate - called when we have decided which
    free list entry to use
  */
    the core of tdb_allocate - called when we have decided which
    free list entry to use
  */
@@ -2433,22 +2438,22 @@ static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb
        if (rec->rec_len > length + MIN_REC_SIZE) {
                /* Length of left piece */
                length = TDB_ALIGN(length, TDB_ALIGNMENT);
        if (rec->rec_len > length + MIN_REC_SIZE) {
                /* Length of left piece */
                length = TDB_ALIGN(length, TDB_ALIGNMENT);
-               
+
                /* Right piece to go on free list */
                newrec.rec_len = rec->rec_len - (sizeof(*rec) + length);
                newrec_ptr = rec_ptr + sizeof(*rec) + length;
                /* Right piece to go on free list */
                newrec.rec_len = rec->rec_len - (sizeof(*rec) + length);
                newrec_ptr = rec_ptr + sizeof(*rec) + length;
-               
+
                /* And left record is shortened */
                rec->rec_len = length;
        } else {
                newrec_ptr = 0;
        }
                /* And left record is shortened */
                rec->rec_len = length;
        } else {
                newrec_ptr = 0;
        }
-       
+
        /* Remove allocated record from the free list */
        if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
                return 0;
        }
        /* Remove allocated record from the free list */
        if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
                return 0;
        }
-       
+
        /* Update header: do this before we drop alloc
           lock, otherwise tdb_free() might try to
           merge with us, thinking we're free.
        /* Update header: do this before we drop alloc
           lock, otherwise tdb_free() might try to
           merge with us, thinking we're free.
@@ -2457,7 +2462,7 @@ static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb
        if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
                return 0;
        }
        if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
                return 0;
        }
-       
+
        /* Did we create new block? */
        if (newrec_ptr) {
                /* Update allocated record tailer (we
        /* Did we create new block? */
        if (newrec_ptr) {
                /* Update allocated record tailer (we
@@ -2465,13 +2470,13 @@ static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb
                if (update_tailer(tdb, rec_ptr, rec) == -1) {
                        return 0;
                }
                if (update_tailer(tdb, rec_ptr, rec) == -1) {
                        return 0;
                }
-               
+
                /* Free new record */
                if (tdb_free(tdb, newrec_ptr, &newrec) == -1) {
                        return 0;
                }
        }
                /* Free new record */
                if (tdb_free(tdb, newrec_ptr, &newrec) == -1) {
                        return 0;
                }
        }
-       
+
        /* all done - return the new record offset */
        return rec_ptr;
 }
        /* all done - return the new record offset */
        return rec_ptr;
 }
@@ -2507,7 +2512,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
        bestfit.last_ptr = 0;
        bestfit.rec_len = 0;
 
        bestfit.last_ptr = 0;
        bestfit.rec_len = 0;
 
-       /* 
+       /*
           this is a best fit allocation strategy. Originally we used
           a first fit strategy, but it suffered from massive fragmentation
           issues when faced with a slowly increasing record size.
           this is a best fit allocation strategy. Originally we used
           a first fit strategy, but it suffered from massive fragmentation
           issues when faced with a slowly increasing record size.
@@ -2655,7 +2660,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc
                           common for the use of tdb with ldb, where large
                           hashes are used. In that case we spend most of our
                           time in tdb_brlock(), locking empty hash chains.
                           common for the use of tdb with ldb, where large
                           hashes are used. In that case we spend most of our
                           time in tdb_brlock(), locking empty hash chains.
-                          
+
                           To avoid this, we do an unlocked pre-check to see
                           if the hash chain is empty before starting to look
                           inside it. If it is empty then we can avoid that
                           To avoid this, we do an unlocked pre-check to see
                           if the hash chain is empty before starting to look
                           inside it. If it is empty then we can avoid that
@@ -2663,7 +2668,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc
                           the value we get back, as we read it without a
                           lock, so instead we get the lock and re-fetch the
                           value below.
                           the value we get back, as we read it without a
                           lock, so instead we get the lock and re-fetch the
                           value below.
-                          
+
                           Notice that not doing this optimisation on the
                           first hash chain is critical. We must guarantee
                           that we have done at least one fcntl lock at the
                           Notice that not doing this optimisation on the
                           first hash chain is critical. We must guarantee
                           that we have done at least one fcntl lock at the
@@ -2673,7 +2678,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc
                           could possibly miss those with this trick, but we
                           could miss them anyway without this trick, so the
                           semantics don't change.
                           could possibly miss those with this trick, but we
                           could miss them anyway without this trick, so the
                           semantics don't change.
-                          
+
                           With a non-indexed ldb search this trick gains us a
                           factor of around 80 in speed on a linux 2.6.x
                           system (testing using ldbtest).
                           With a non-indexed ldb search this trick gains us a
                           factor of around 80 in speed on a linux 2.6.x
                           system (testing using ldbtest).
@@ -2727,7 +2732,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc
                        /* Try to clean dead ones from old traverses */
                        current = tlock->off;
                        tlock->off = rec->next;
                        /* Try to clean dead ones from old traverses */
                        current = tlock->off;
                        tlock->off = rec->next;
-                       if (!(tdb->read_only || tdb->traverse_read) && 
+                       if (!(tdb->read_only || tdb->traverse_read) &&
                            tdb_do_delete(tdb, current, rec) != 0)
                                goto fail;
                }
                            tdb_do_delete(tdb, current, rec) != 0)
                                goto fail;
                }
@@ -2749,7 +2754,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc
    if fn is NULL then it is not called
    a non-zero return value from fn() indicates that the traversal should stop
   */
    if fn is NULL then it is not called
    a non-zero return value from fn() indicates that the traversal should stop
   */
-static int tdb_traverse_internal(struct tdb_context *tdb, 
+static int tdb_traverse_internal(struct tdb_context *tdb,
                                 tdb_traverse_func fn, void *private_data,
                                 struct tdb_traverse_lock *tl)
 {
                                 tdb_traverse_func fn, void *private_data,
                                 struct tdb_traverse_lock *tl)
 {
@@ -2769,7 +2774,7 @@ static int tdb_traverse_internal(struct tdb_context *tdb,
        while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) {
                count++;
                /* now read the full record */
        while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) {
                count++;
                /* now read the full record */
-               key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), 
+               key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec),
                                          rec.key_len + rec.data_len);
                if (!key.dptr) {
                        ret = -1;
                                          rec.key_len + rec.data_len);
                if (!key.dptr) {
                        ret = -1;
@@ -2813,7 +2818,7 @@ out:
 /*
   a write style traverse - temporarily marks the db read only
 */
 /*
   a write style traverse - temporarily marks the db read only
 */
-int tdb_traverse_read(struct tdb_context *tdb, 
+int tdb_traverse_read(struct tdb_context *tdb,
                      tdb_traverse_func fn, void *private_data)
 {
        struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
                      tdb_traverse_func fn, void *private_data)
 {
        struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
@@ -2838,7 +2843,7 @@ int tdb_traverse_read(struct tdb_context *tdb,
   a write style traverse - needs to get the transaction lock to
   prevent deadlocks
 */
   a write style traverse - needs to get the transaction lock to
   prevent deadlocks
 */
-int tdb_traverse(struct tdb_context *tdb, 
+int tdb_traverse(struct tdb_context *tdb,
                 tdb_traverse_func fn, void *private_data)
 {
        struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK };
                 tdb_traverse_func fn, void *private_data)
 {
        struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK };
@@ -2847,7 +2852,7 @@ int tdb_traverse(struct tdb_context *tdb,
        if (tdb->read_only || tdb->traverse_read) {
                return tdb_traverse_read(tdb, fn, private_data);
        }
        if (tdb->read_only || tdb->traverse_read) {
                return tdb_traverse_read(tdb, fn, private_data);
        }
-       
+
        if (tdb_transaction_lock(tdb, F_WRLCK)) {
                return -1;
        }
        if (tdb_transaction_lock(tdb, F_WRLCK)) {
                return -1;
        }
@@ -2953,7 +2958,7 @@ static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash,
        struct list_struct rec;
        tdb_off_t tailer_ofs, tailer;
 
        struct list_struct rec;
        tdb_off_t tailer_ofs, tailer;
 
-       if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, 
+       if (tdb->methods->tdb_read(tdb, offset, (char *)&rec,
                                   sizeof(rec), DOCONV()) == -1) {
                printf("ERROR: failed to read record at %u\n", offset);
                return 0;
                                   sizeof(rec), DOCONV()) == -1) {
                printf("ERROR: failed to read record at %u\n", offset);
                return 0;
@@ -3030,7 +3035,7 @@ int tdb_printfreelist(struct tdb_context *tdb)
 
        printf("freelist top=[0x%08x]\n", rec_ptr );
        while (rec_ptr) {
 
        printf("freelist top=[0x%08x]\n", rec_ptr );
        while (rec_ptr) {
-               if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, 
+               if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec,
                                           sizeof(rec), DOCONV()) == -1) {
                        tdb_unlock(tdb, -1, F_WRLCK);
                        return -1;
                                           sizeof(rec), DOCONV()) == -1) {
                        tdb_unlock(tdb, -1, F_WRLCK);
                        return -1;
@@ -3042,14 +3047,14 @@ int tdb_printfreelist(struct tdb_context *tdb)
                        return -1;
                }
 
                        return -1;
                }
 
-               printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", 
+               printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n",
                       rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len);
                total_free += rec.rec_len;
 
                /* move to the next record */
                rec_ptr = rec.next;
        }
                       rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len);
                total_free += rec.rec_len;
 
                /* move to the next record */
                rec_ptr = rec.next;
        }
-       printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, 
+       printf("total rec_len = [0x%08x (%d)]\n", (int)total_free,
                (int)total_free);
 
        return tdb_unlock(tdb, -1, F_WRLCK);
                (int)total_free);
 
        return tdb_unlock(tdb, -1, F_WRLCK);
@@ -3057,8 +3062,6 @@ int tdb_printfreelist(struct tdb_context *tdb)
 
 /* file: tdb.c */
 
 
 /* file: tdb.c */
 
-TDB_DATA tdb_null;
-
 /*
   non-blocking increment of the tdb sequence number if the tdb has been opened using
   the TDB_SEQNUM flag
 /*
   non-blocking increment of the tdb sequence number if the tdb has been opened using
   the TDB_SEQNUM flag
@@ -3066,7 +3069,7 @@ TDB_DATA tdb_null;
 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
 {
        tdb_off_t seqnum=0;
 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
 {
        tdb_off_t seqnum=0;
-       
+
        if (!(tdb->flags & TDB_SEQNUM)) {
                return;
        }
        if (!(tdb->flags & TDB_SEQNUM)) {
                return;
        }
@@ -3109,7 +3112,7 @@ static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash,
                        struct list_struct *r)
 {
        tdb_off_t rec_ptr;
                        struct list_struct *r)
 {
        tdb_off_t rec_ptr;
-       
+
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                return 0;
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                return 0;
@@ -3173,7 +3176,7 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_
                rec.data_len = dbuf.dsize;
                return tdb_rec_write(tdb, rec_ptr, &rec);
        }
                rec.data_len = dbuf.dsize;
                return tdb_rec_write(tdb, rec_ptr, &rec);
        }
+
        return 0;
 }
 
        return 0;
 }
 
@@ -3243,7 +3246,7 @@ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
        return ret;
 }
 
        return ret;
 }
 
-/* check if an entry in the database exists 
+/* check if an entry in the database exists
 
    note that 1 is returned if the key is found and 0 is returned if not found
    this doesn't match the conventions in the rest of this module, but is
 
    note that 1 is returned if the key is found and 0 is returned if not found
    this doesn't match the conventions in the rest of this module, but is
@@ -3252,7 +3255,7 @@ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
 static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
 {
        struct list_struct rec;
 static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
 {
        struct list_struct rec;
-       
+
        if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
                return 0;
        tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
        if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
                return 0;
        tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
@@ -3305,7 +3308,7 @@ static int tdb_count_dead(struct tdb_context *tdb, u32 hash)
        int res = 0;
        tdb_off_t rec_ptr;
        struct list_struct rec;
        int res = 0;
        tdb_off_t rec_ptr;
        struct list_struct rec;
-       
+
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                return 0;
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                return 0;
@@ -3334,7 +3337,7 @@ static int tdb_purge_dead(struct tdb_context *tdb, u32 hash)
        if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
                return -1;
        }
        if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
                return -1;
        }
-       
+
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                goto fail;
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                goto fail;
@@ -3426,7 +3429,7 @@ static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash,
                               struct list_struct *r, tdb_len_t length)
 {
        tdb_off_t rec_ptr;
                               struct list_struct *r, tdb_len_t length)
 {
        tdb_off_t rec_ptr;
-       
+
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                return 0;
        /* read in the hash top */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                return 0;
@@ -3449,7 +3452,7 @@ static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash,
 }
 
 /* store an element in the database, replacing any existing element
 }
 
 /* store an element in the database, replacing any existing element
-   with the same key 
+   with the same key
 
    return 0 on success, -1 on failure
 */
 
    return 0 on success, -1 on failure
 */
@@ -3585,7 +3588,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
                tdb_increment_seqnum(tdb);
        }
 
                tdb_increment_seqnum(tdb);
        }
 
-       SAFE_FREE(p); 
+       SAFE_FREE(p);
        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
        return ret;
 }
        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
        return ret;
 }
@@ -3625,7 +3628,7 @@ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
        dbuf.dsize += new_dbuf.dsize;
 
        ret = tdb_store(tdb, key, dbuf, 0);
        dbuf.dsize += new_dbuf.dsize;
 
        ret = tdb_store(tdb, key, dbuf, 0);
-       
+
 failed:
        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
        SAFE_FREE(dbuf.dptr);
 failed:
        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
        SAFE_FREE(dbuf.dptr);
@@ -3710,17 +3713,17 @@ void tdb_enable_seqnum(struct tdb_context *tdb)
 static struct tdb_context *tdbs = NULL;
 
 
 static struct tdb_context *tdbs = NULL;
 
 
-/* This is based on the hash algorithm from gdbm */
+/* This is from a hash algorithm suggested by Rogier Wolff */
 static unsigned int default_tdb_hash(TDB_DATA *key)
 {
        u32 value;      /* Used to compute the hash value.  */
        u32   i;        /* Used to cycle through random values. */
 
        /* Set the initial value from the key size. */
 static unsigned int default_tdb_hash(TDB_DATA *key)
 {
        u32 value;      /* Used to compute the hash value.  */
        u32   i;        /* Used to cycle through random values. */
 
        /* Set the initial value from the key size. */
-       for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
-               value = (value + (key->dptr[i] << (i*5 % 24)));
+       for (value = 0, i=0; i < key->dsize; i++)
+               value = value * 256 + key->dptr[i] + (value >> 24) * 241;
 
 
-       return (1103515243 * value + 12345);  
+       return value;
 }
 
 
 }
 
 
@@ -3774,7 +3777,7 @@ static int tdb_already_open(dev_t device,
                            ino_t ino)
 {
        struct tdb_context *i;
                            ino_t ino)
 {
        struct tdb_context *i;
-       
+
        for (i = tdbs; i; i = i->next) {
                if (i->device == device && i->inode == ino) {
                        return 1;
        for (i = tdbs; i; i = i->next) {
                if (i->device == device && i->inode == ino) {
                        return 1;
@@ -3784,13 +3787,13 @@ static int tdb_already_open(dev_t device,
        return 0;
 }
 
        return 0;
 }
 
-/* open the database, creating it if necessary 
+/* open the database, creating it if necessary
 
    The open_flags and mode are passed straight to the open call on the
    database file. A flags value of O_WRONLY is invalid. The hash size
    is advisory, use zero for a default value.
 
 
    The open_flags and mode are passed straight to the open call on the
    database file. A flags value of O_WRONLY is invalid. The hash size
    is advisory, use zero for a default value.
 
-   Return is NULL on error, in which case errno is also set.  Don't 
+   Return is NULL on error, in which case errno is also set.  Don't
    try to call tdb_error or tdb_errname, just do strerror(errno).
 
    @param name may be NULL for internal databases. */
    try to call tdb_error or tdb_errname, just do strerror(errno).
 
    @param name may be NULL for internal databases. */
@@ -3838,7 +3841,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
        tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
 
        /* cache the page size */
        tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
 
        /* cache the page size */
-       tdb->page_size = getpagesize();
+       tdb->page_size = sysconf(_SC_PAGESIZE);
        if (tdb->page_size <= 0) {
                tdb->page_size = 0x2000;
        }
        if (tdb->page_size <= 0) {
                tdb->page_size = 0x2000;
        }
@@ -3849,7 +3852,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
                errno = EINVAL;
                goto fail;
        }
                errno = EINVAL;
                goto fail;
        }
-       
+
        if (hash_size == 0)
                hash_size = DEFAULT_HASH_SIZE;
        if ((open_flags & O_ACCMODE) == O_RDONLY) {
        if (hash_size == 0)
                hash_size = DEFAULT_HASH_SIZE;
        if ((open_flags & O_ACCMODE) == O_RDONLY) {
@@ -3983,7 +3986,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
 
        if (!tdb)
                return NULL;
 
        if (!tdb)
                return NULL;
-       
+
        if (tdb->map_ptr) {
                if (tdb->flags & TDB_INTERNAL)
                        SAFE_FREE(tdb->map_ptr);
        if (tdb->map_ptr) {
                if (tdb->flags & TDB_INTERNAL)
                        SAFE_FREE(tdb->map_ptr);
@@ -4091,7 +4094,7 @@ int tdb_reopen(struct tdb_context *tdb)
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
                goto fail;
        }
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
                goto fail;
        }
-       if ((tdb->flags & TDB_CLEAR_IF_FIRST) && 
+       if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
            (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
                goto fail;
            (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
                goto fail;
@@ -4141,3 +4144,13 @@ int tdb_reopen_all(int parent_longlived)
 
        return 0;
 }
 
        return 0;
 }
+
+/**
+ * Flush a database file from the page cache.
+ **/
+int tdb_flush(struct tdb_context *tdb)
+{
+       if (tdb->fd != -1)
+               return fsync(tdb->fd);
+       return 0;
+}