summaryrefslogtreecommitdiff
path: root/source3/tdb/tdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/tdb/tdb.c')
-rw-r--r--source3/tdb/tdb.c225
1 files changed, 69 insertions, 156 deletions
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c
index 3d4a6051d2..69e36ebd3e 100644
--- a/source3/tdb/tdb.c
+++ b/source3/tdb/tdb.c
@@ -35,7 +35,6 @@
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <stdarg.h>
#include "tdb.h"
#include "spinlock.h"
#else
@@ -150,12 +149,7 @@ struct list_struct {
};
/* a byte range locking function - return 0 on success
- 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().
-
- @param probe True to not emit errors if the lock fails. */
+ this functions locks/unlocks 1 byte at the specified offset */
static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
int rw_type, int lck_type, int probe)
{
@@ -163,10 +157,8 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
if (tdb->flags & TDB_NOLOCK)
return 0;
- if (tdb->read_only) {
- errno = EACCES;
+ if (tdb->read_only)
return -1;
- }
fl.l_type = rw_type;
fl.l_whence = SEEK_SET;
@@ -176,10 +168,9 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
if (fcntl(tdb->fd,lck_type,&fl)) {
if (!probe) {
- TDB_LOG((tdb, 5,"tdb_brlock failed at offset %d rw_type=%d lck_type=%d: %s\n",
- offset, rw_type, lck_type, strerror(errno)));
+ TDB_LOG((tdb, 5,"tdb_brlock failed at offset %d rw_type=%d lck_type=%d\n",
+ offset, rw_type, lck_type));
}
- /* errno set by fcntl */
return TDB_ERRCODE(TDB_ERR_LOCK, -1);
}
return 0;
@@ -1372,202 +1363,134 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
return ret;
}
-
-static int tdb_read_header(TDB_CONTEXT *tdb)
-{
- int readlen = read(tdb->fd, &tdb->header, sizeof(tdb->header));
-
- if (readlen == 0) {
- /* file is just empty, still needs to be created */
- } else if (readlen == -1) {
- TDB_LOG((tdb, 0, "tdb_read_header: failed to read tdb header of %s: %s\n",
- tdb->name, strerror(errno)));
- } else if (readlen != sizeof(tdb->header)) {
- TDB_LOG((tdb, 0, "tdb_read_header: tdb header in %s is truncated at byte %d\n",
- tdb->name, readlen));
- } else if (strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0) {
- TDB_LOG((tdb, 0, "tdb_read_header: rotten food in %s\n", tdb->name));
- errno = EIO;
- } else if (tdb->header.version != TDB_VERSION
- && tdb->header.version != TDB_BYTEREV(TDB_VERSION)) {
- TDB_LOG((tdb, 0, "tdb_read_header: bad version in header of %s: %#x\n",
- tdb->name, tdb->header.version));
- } else {
- return 1;
- }
- return 0;
-}
-
-
/* 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.
- 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). */
+ return is NULL on error */
TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode)
{
- return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL);
-}
-
-
-TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
- int open_flags, mode_t mode,
- tdb_log_func log_func)
-{
- TDB_CONTEXT tdb[1], *ret, *i;
+ TDB_CONTEXT tdb, *ret, *i;
struct stat st;
- int rev, locked;
+ int rev = 0, locked;
- memset(tdb, 0, sizeof(tdb));
- tdb->fd = -1;
- tdb->name = NULL;
- tdb->map_ptr = NULL;
- tdb->lockedkeys = NULL;
- tdb->flags = tdb_flags;
- tdb->open_flags = open_flags;
- tdb_logging_function(tdb, log_func);
+ memset(&tdb, 0, sizeof(tdb));
+ tdb.fd = -1;
+ tdb.name = NULL;
+ tdb.map_ptr = NULL;
+ tdb.lockedkeys = NULL;
+ tdb.flags = tdb_flags;
+ tdb.open_flags = open_flags;
- if ((open_flags & O_ACCMODE) == O_WRONLY) {
- TDB_LOG((tdb, 0, "tdb_open: tdb cannot be opened O_WRONLY\n"));
- errno = EINVAL;
+ if ((open_flags & O_ACCMODE) == O_WRONLY)
goto fail;
- }
-
if (hash_size == 0)
hash_size = DEFAULT_HASH_SIZE;
if ((open_flags & O_ACCMODE) == O_RDONLY) {
- tdb->read_only = 1;
+ tdb.read_only = 1;
/* read only databases don't do locking or clear if first */
- tdb->flags |= TDB_NOLOCK;
- tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+ tdb.flags |= TDB_NOLOCK;
+ tdb.flags &= ~TDB_CLEAR_IF_FIRST;
}
/* internal databases don't mmap or lock, and start off cleared */
- if (tdb->flags & TDB_INTERNAL) {
- tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
- tdb->flags &= ~TDB_CLEAR_IF_FIRST;
- tdb_new_database(tdb, hash_size);
+ if (tdb.flags & TDB_INTERNAL) {
+ tdb.flags |= (TDB_NOLOCK | TDB_NOMMAP);
+ tdb.flags &= ~TDB_CLEAR_IF_FIRST;
+ tdb_new_database(&tdb, hash_size);
goto internal;
}
- tdb->name = (char *)strdup(name);
- if (!tdb->name) {
- TDB_LOG((tdb, 0, "tdb_open: couldn't allocate memory for name\n"));
- errno = ENOMEM;
+ if ((tdb.fd = open(name, open_flags, mode)) == -1)
goto fail;
- }
-
- if ((tdb->fd = open(name, open_flags, mode)) == -1) {
- TDB_LOG((tdb, 0, "tdb_open: failed to open %s: %s\n",
- name, strerror(errno)));
- goto fail; /* errno set by open(2) */
- }
/* ensure there is only one process initialising at once */
- if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1)
- goto fail; /* errno set by tdb_brlock */
+ if (tdb_brlock(&tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1)
+ goto fail;
- /* We need to zero database if we are the only one with it
- * open. Be quiet if the lock fails. */
- if ((locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 1) == 0))
+ /* we need to zero database if we are the only one with it open */
+ if ((locked = (tdb_brlock(&tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))
&& (tdb_flags & TDB_CLEAR_IF_FIRST)) {
open_flags |= O_CREAT;
- if (ftruncate(tdb->fd, 0) == -1) {
- TDB_LOG((tdb, 0, "tdb_open: couldn't truncate %s: %s\n",
- name, strerror(errno)));
- goto fail; /* errno set by ftruncate */
- }
+ if (ftruncate(tdb.fd, 0) == -1)
+ goto fail;
}
-
- if (tdb_read_header(tdb)) {
- rev = tdb->header.version = TDB_BYTEREV(TDB_VERSION);
- } else {
+
+ 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
+ && !(rev = (tdb.header.version==TDB_BYTEREV(TDB_VERSION))))) {
/* its not a valid database - possibly initialise it */
- if (!(open_flags & O_CREAT)) {
- TDB_LOG((tdb, 0, "tdb_open: database header not OK and O_CREAT not specified\n"));
- errno = EIO; /* ie bad format or something */
- goto fail;
- } else if (tdb_new_database(tdb, hash_size) == -1) {
+ if (!(open_flags & O_CREAT) || tdb_new_database(&tdb, hash_size) == -1)
goto fail;
- }
-
- rev = (tdb->flags & TDB_CONVERT);
+ rev = (tdb.flags & TDB_CONVERT);
}
-
if (!rev)
- tdb->flags &= ~TDB_CONVERT;
+ tdb.flags &= ~TDB_CONVERT;
else {
- tdb->flags |= TDB_CONVERT;
- convert(&tdb->header, sizeof(tdb->header));
+ tdb.flags |= TDB_CONVERT;
+ convert(&tdb.header, sizeof(tdb.header));
}
- if (fstat(tdb->fd, &st) == -1) {
- TDB_LOG((tdb, 0, "tdb_open: fstat of %s failed: %s\n",
- name, strerror(errno)));
+ if (fstat(tdb.fd, &st) == -1)
goto fail;
- }
/* Is it already in the open list? If so, fail. */
for (i = tdbs; i; i = i->next) {
if (i->device == st.st_dev && i->inode == st.st_ino) {
errno = EBUSY;
- close(tdb->fd);
+ close(tdb.fd);
return NULL;
}
}
- tdb->map_size = st.st_size;
- tdb->device = st.st_dev;
- tdb->inode = st.st_ino;
- tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0]));
- if (!tdb->locked) {
- errno = ENOMEM;
+ /* map the database and fill in the return structure */
+ tdb.name = (char *)strdup(name);
+ if (!tdb.name)
goto fail;
- }
- tdb_mmap(tdb);
+ tdb.map_size = st.st_size;
+ tdb.device = st.st_dev;
+ tdb.inode = st.st_ino;
+ tdb.locked = calloc(tdb.header.hash_size+1, sizeof(tdb.locked[0]));
+ if (!tdb.locked)
+ goto fail;
+ tdb_mmap(&tdb);
if (locked) {
- if (!tdb->read_only)
- tdb_clear_spinlocks(tdb);
- if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1)
+ if (!tdb.read_only)
+ tdb_clear_spinlocks(&tdb);
+ if (tdb_brlock(&tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1)
goto fail;
}
/* leave this lock in place to indicate it's in use */
- if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
+ if (tdb_brlock(&tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
goto fail;
internal:
- if (!(ret = malloc(sizeof(tdb)))) {
- errno = ENOMEM;
+ if (!(ret = malloc(sizeof(tdb))))
goto fail;
- }
- *ret = *tdb;
- if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1)
+ *ret = tdb;
+ if (tdb_brlock(&tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1)
goto fail;
ret->next = tdbs;
tdbs = ret;
return ret;
fail:
- { int save_errno = errno;
-
- if (tdb->map_ptr) {
- if (tdb->flags & TDB_INTERNAL)
- free(tdb->map_ptr);
+ if (tdb.map_ptr) {
+ if (tdb.flags & TDB_INTERNAL)
+ free(tdb.map_ptr);
else
- tdb_munmap(tdb);
- }
- if (tdb->name)
- free(tdb->name);
- if (tdb->fd != -1)
- close(tdb->fd);
- if (tdb->locked)
- free(tdb->locked);
- errno = save_errno;
+ tdb_munmap(&tdb);
+ }
+ if (tdb.name)
+ free(tdb.name);
+ if (tdb.fd != -1)
+ close(tdb.fd);
+ if (tdb.locked)
+ free(tdb.locked);
return NULL;
- }
}
/* close a database */
@@ -1694,16 +1617,6 @@ void tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key)
}
-void tdb_log_to_stderr(TDB_CONTEXT *tdb, int level, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- vfprintf(stderr, format, ap);
- va_end(ap);
- fflush(stderr);
-}
-
/* register a loging function */
void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...))
{