#include "private.h"
+#include <ccan/asprintf/asprintf.h>
#include <ccan/tdb2/tdb2.h>
#include <assert.h>
#include <stdarg.h>
newdb.hdr.hash_seed,
tdb->hash_priv);
newdb.hdr.recovery = 0;
+ newdb.hdr.features_used = newdb.hdr.features_offered = TDB_FEATURE_MASK;
memset(newdb.hdr.reserved, 0, sizeof(newdb.hdr.reserved));
/* Initial hashes are empty. */
memset(newdb.hdr.hashtable, 0, sizeof(newdb.hdr.hashtable));
attr = attr->base.next;
}
+ if (tdb_flags & ~(TDB_INTERNAL | TDB_NOLOCK | TDB_NOMMAP | TDB_CONVERT
+ | TDB_NOSYNC)) {
+ ecode = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+ "tdb_open: unknown flags %u", tdb_flags);
+ goto fail;
+ }
+
if ((open_flags & O_ACCMODE) == O_WRONLY) {
ecode = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
"tdb_open: can't open tdb %s write-only",
if ((open_flags & O_ACCMODE) == O_RDONLY) {
tdb->read_only = true;
- /* read only databases don't do locking */
- tdb->flags |= TDB_NOLOCK;
tdb->mmap_flags = PROT_READ;
} else {
tdb->read_only = false;
goto fail;
}
+ /* Clear any features we don't understand. */
+ if ((open_flags & O_ACCMODE) != O_RDONLY) {
+ hdr.features_used &= TDB_FEATURE_MASK;
+ if (tdb_write_convert(tdb, offsetof(struct tdb_header,
+ features_used),
+ &hdr.features_used,
+ sizeof(hdr.features_used)) == -1)
+ goto fail;
+ }
+
tdb->device = st.st_dev;
tdb->inode = st.st_ino;
tdb_unlock_open(tdb);
if (!tdb->logfn)
return ecode;
- /* FIXME: Doesn't assume asprintf. */
va_start(ap, fmt);
- len = vsnprintf(NULL, 0, fmt, ap);
+ len = vasprintf(&message, fmt, ap);
va_end(ap);
- message = malloc(len + 1);
- if (!message) {
+ if (len < 0) {
tdb->logfn(tdb, TDB_LOG_ERROR, tdb->log_private,
"out of memory formatting message:");
tdb->logfn(tdb, level, tdb->log_private, fmt);
- return ecode;
+ } else {
+ tdb->logfn(tdb, level, tdb->log_private, message);
+ free(message);
}
- va_start(ap, fmt);
- len = vsprintf(message, fmt, ap);
- va_end(ap);
- tdb->logfn(tdb, level, tdb->log_private, message);
- free(message);
errno = saved_errno;
return ecode;
}