Whitespace and C++-compatibility mainly.
Unix SMB/CIFS implementation.
trivial database library
Copyright (C) Rusty Russell 2009
Unix SMB/CIFS implementation.
trivial database library
Copyright (C) Rusty Russell 2009
** 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
const struct tdb_record *rec,
unsigned char **hashes,
int (*check)(TDB_DATA, TDB_DATA, void *),
const struct tdb_record *rec,
unsigned char **hashes,
int (*check)(TDB_DATA, TDB_DATA, void *),
if (!data.dptr)
goto fail_put_key;
if (!data.dptr)
goto fail_put_key;
- if (check(key, data, private) == -1)
+ if (check(key, data, private_data) == -1)
goto fail_put_data;
put_bytes(tdb, data);
}
goto fail_put_data;
put_bytes(tdb, data);
}
}
int tdb_check(struct tdb_context *tdb,
}
int tdb_check(struct tdb_context *tdb,
- int (*check)(TDB_DATA key, TDB_DATA data, void *private),
- void *private)
+ int (*check)(TDB_DATA key, TDB_DATA data, void *private_data),
+ void *private_data)
{
unsigned int h;
unsigned char **hashes;
{
unsigned int h;
unsigned char **hashes;
}
/* One big malloc: pointers then bit arrays. */
}
/* One big malloc: pointers then bit arrays. */
- hashes = calloc(1, sizeof(hashes[0]) * (1+tdb->header.hash_size)
+ hashes = (unsigned char **)calloc(
+ 1, sizeof(hashes[0]) * (1+tdb->header.hash_size)
+ BITMAP_BITS / CHAR_BIT * (1+tdb->header.hash_size));
if (!hashes) {
tdb->ecode = TDB_ERR_OOM;
+ BITMAP_BITS / CHAR_BIT * (1+tdb->header.hash_size));
if (!hashes) {
tdb->ecode = TDB_ERR_OOM;
case TDB_MAGIC:
case TDB_DEAD_MAGIC:
if (!tdb_check_used_record(tdb, off, &rec, hashes,
case TDB_MAGIC:
case TDB_DEAD_MAGIC:
if (!tdb_check_used_record(tdb, off, &rec, hashes,
goto free;
break;
case TDB_FREE_MAGIC:
goto free;
break;
case TDB_FREE_MAGIC:
#if HAVE_MMAP
if (tdb->map_ptr) {
#if HAVE_MMAP
if (tdb->map_ptr) {
- int ret = munmap(tdb->map_ptr, tdb->map_size);
+ int ret;
+
+ ret = munmap(tdb->map_ptr, tdb->map_size);
if (ret != 0)
return ret;
}
if (ret != 0)
return ret;
}
unsigned char *buf;
/* some systems don't like zero length malloc */
unsigned char *buf;
/* some systems don't like zero length malloc */
if (!(buf = (unsigned char *)malloc(len ? len : 1))) {
/* Ensure ecode is set for log fn. */
tdb->ecode = TDB_ERR_OOM;
if (!(buf = (unsigned char *)malloc(len ? len : 1))) {
/* Ensure ecode is set for log fn. */
tdb->ecode = TDB_ERR_OOM;
}
static int fcntl_lock(struct tdb_context *tdb,
}
static int fcntl_lock(struct tdb_context *tdb,
- int rw, off_t off, off_t len, bool wait)
+ int rw, off_t off, off_t len, bool waitflag)
fl.l_type = rw;
fl.l_whence = SEEK_SET;
fl.l_start = off;
fl.l_len = len;
fl.l_pid = 0;
fl.l_type = rw;
fl.l_whence = SEEK_SET;
fl.l_start = off;
fl.l_len = len;
fl.l_pid = 0;
return fcntl(tdb->fd, F_SETLKW, &fl);
else
return fcntl(tdb->fd, F_SETLK, &fl);
return fcntl(tdb->fd, F_SETLKW, &fl);
else
return fcntl(tdb->fd, F_SETLK, &fl);
* EAGAIN is an expected return from non-blocking
* locks. */
if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) {
* EAGAIN is an expected return from non-blocking
* locks. */
if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) {
- TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
+ TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
tdb->fd, offset, rw_type, flags, (int)len));
}
return -1;
tdb->fd, offset, rw_type, flags, (int)len));
}
return -1;
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
- TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
+ TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
tdb->fd, offset, rw_type, (int)len));
}
return ret;
tdb->fd, offset, rw_type, (int)len));
}
return ret;
return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
}
return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
}
/* record lock stops delete underneath */
int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
{
/* record lock stops delete underneath */
int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
{
errno = ENOMEM;
goto fail;
}
errno = ENOMEM;
goto fail;
}
tdb_io_init(tdb);
tdb->fd = -1;
#ifdef TDB_TRACE
tdb_io_init(tdb);
tdb->fd = -1;
#ifdef TDB_TRACE
{
char tracefile[strlen(name) + 32];
{
char tracefile[strlen(name) + 32];
- sprintf(tracefile, "%s.trace.%u", name, getpid());
+ snprintf(tracefile, sizeof(tracefile),
+ "%s.trace.%li", name, (long)getpid());
tdb->tracefd = open(tracefile, O_WRONLY|O_CREAT|O_EXCL, 0600);
if (tdb->tracefd >= 0) {
tdb_enable_seqnum(tdb);
tdb->tracefd = open(tracefile, O_WRONLY|O_CREAT|O_EXCL, 0600);
if (tdb->tracefd >= 0) {
tdb_enable_seqnum(tdb);
return tdb->log.log_private;
}
return tdb->log.log_private;
}
-/* reopen a tdb - this can be used after a fork to ensure that we have an independent
- seek pointer from our parent and to re-establish locks */
-int tdb_reopen(struct tdb_context *tdb)
+static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock)
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) &&
- (tdb->methods->brlock(tdb, F_RDLCK, ACTIVE_LOCK, 1, TDB_LOCK_WAIT) == -1)) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
- goto fail;
- }
if (fstat(tdb->fd, &st) != 0) {
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
goto fail;
if (fstat(tdb->fd, &st) != 0) {
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
goto fail;
+ if (active_lock &&
+ (tdb->methods->brlock(tdb, F_RDLCK, ACTIVE_LOCK, 1, TDB_LOCK_WAIT) == -1)) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
+ goto fail;
+ }
+
+/* reopen a tdb - this can be used after a fork to ensure that we have an independent
+ seek pointer from our parent and to re-establish locks */
+int tdb_reopen(struct tdb_context *tdb)
+{
+ return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST);
+}
+
/* reopen all tdb's */
int tdb_reopen_all(int parent_longlived)
{
struct tdb_context *tdb;
for (tdb=tdbs; tdb; tdb = tdb->next) {
/* reopen all tdb's */
int tdb_reopen_all(int parent_longlived)
{
struct tdb_context *tdb;
for (tdb=tdbs; tdb; tdb = tdb->next) {
+ bool active_lock = (tdb->flags & TDB_CLEAR_IF_FIRST);
+
/*
* If the parent is longlived (ie. a
* parent daemon architecture), we know
/*
* If the parent is longlived (ie. a
* parent daemon architecture), we know
*/
if (parent_longlived) {
/* Ensure no clear-if-first. */
*/
if (parent_longlived) {
/* Ensure no clear-if-first. */
- tdb->flags &= ~TDB_CLEAR_IF_FIRST;
- if (tdb_reopen(tdb) != 0)
+ if (tdb_reopen_internal(tdb, active_lock) != 0)
/* find which hash bucket it is in */
hash = tdb->hash_fn(&key);
/* find which hash bucket it is in */
hash = tdb->hash_fn(&key);
- if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
+ if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
rec.data_len);
ret.dsize = rec.data_len;
ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
rec.data_len);
ret.dsize = rec.data_len;
hash = tdb->hash_fn(&key);
if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
hash = tdb->hash_fn(&key);
if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
- tdb_trace_1rec_ret(tdb, "tdb_parse_record", key,
- -TDB_ERR_NOEXIST);
+ tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1);
tdb->ecode = TDB_ERR_NOEXIST;
return 0;
}
tdb->ecode = TDB_ERR_NOEXIST;
return 0;
}
}
static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
}
static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
- TDB_DATA dbuf, int flag, uint32_t hash)
+ TDB_DATA dbuf, int flag, uint32_t hash)
{
struct tdb_record rec;
tdb_off_t rec_ptr;
{
struct tdb_record rec;
tdb_off_t rec_ptr;
}
/* store an element in the database, replacing any existing element
}
/* store an element in the database, replacing any existing element
return 0 on success, -1 on failure
*/
return 0 on success, -1 on failure
*/
if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB_ERR_RDONLY;
if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB_ERR_RDONLY;
- tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag,
- -TDB_ERR_RDONLY);
+ tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag, -1);
/* Append to an entry. Create if not exist. */
int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
{
/* Append to an entry. Create if not exist. */
int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
{
tdb_off_t seqnum=0;
tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
tdb_off_t seqnum=0;
tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
- tdb_trace_ret(tdb, "tdb_get_seqnum", seqnum);
struct traverse_state {
bool error;
struct tdb_context *dest_db;
struct traverse_state {
bool error;
struct tdb_context *dest_db;
/*
traverse function for repacking
*/
/*
traverse function for repacking
*/
-static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
+static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data)
- struct traverse_state *state = (struct traverse_state *)private;
+ struct traverse_state *state = (struct traverse_state *)private_data;
if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) {
state->error = true;
return -1;
if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) {
state->error = true;
return -1;
tdb_trace(tdb, "tdb_repack");
if (tdb_transaction_start(tdb) != 0) {
tdb_trace(tdb, "tdb_repack");
if (tdb_transaction_start(tdb) != 0) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to start transaction\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to start transaction\n"));
return -1;
}
tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb), TDB_INTERNAL, O_RDWR|O_CREAT, 0);
if (tmp_db == NULL) {
return -1;
}
tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb), TDB_INTERNAL, O_RDWR|O_CREAT, 0);
if (tmp_db == NULL) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to create tmp_db\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to create tmp_db\n"));
tdb_transaction_cancel(tdb);
return -1;
}
tdb_transaction_cancel(tdb);
return -1;
}
state.dest_db = tmp_db;
if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) {
state.dest_db = tmp_db;
if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to traverse copying out\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying out\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (state.error) {
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (state.error) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Error during traversal\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during traversal\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (tdb_wipe_all(tdb) != 0) {
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (tdb_wipe_all(tdb) != 0) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to wipe database\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to wipe database\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
state.dest_db = tdb;
if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) {
state.dest_db = tdb;
if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to traverse copying back\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying back\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (state.error) {
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (state.error) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Error during second traversal\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during second traversal\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
tdb_close(tmp_db);
if (tdb_transaction_commit(tdb) != 0) {
tdb_close(tmp_db);
if (tdb_transaction_commit(tdb) != 0) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to commit\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to commit\n"));
static void tdb_trace_start(struct tdb_context *tdb)
{
tdb_off_t seqnum=0;
static void tdb_trace_start(struct tdb_context *tdb)
{
tdb_off_t seqnum=0;
- char msg[sizeof(tdb_off_t) * 4];
+ char msg[sizeof(tdb_off_t) * 4 + 1];
tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
- sprintf(msg, "%u ", seqnum);
+ snprintf(msg, sizeof(msg), "%u ", seqnum);
tdb_trace_write(tdb, msg);
}
tdb_trace_write(tdb, msg);
}
static void tdb_trace_end_ret(struct tdb_context *tdb, int ret)
{
static void tdb_trace_end_ret(struct tdb_context *tdb, int ret)
{
- char msg[sizeof(ret) * 4];
- sprintf(msg, " = %i\n", ret);
+ char msg[sizeof(ret) * 4 + 4];
+ snprintf(msg, sizeof(msg), " = %i\n", ret);
tdb_trace_write(tdb, msg);
}
tdb_trace_write(tdb, msg);
}
+ /* snprintf here is purely cargo-cult programming. */
- p += sprintf(p, " %zu:", rec.dsize);
+ p += snprintf(p, sizeof(msg), " %zu:", rec.dsize);
for (i = 0; i < rec.dsize; i++)
for (i = 0; i < rec.dsize; i++)
- p += sprintf(p, "%02x", rec.dptr[i]);
+ p += snprintf(p, 2, "%02x", rec.dptr[i]);
tdb_trace_write(tdb, msg);
}
tdb_trace_write(tdb, msg);
}
void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op)
{
void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op)
{
- char msg[sizeof(tdb_off_t) * 4];
+ char msg[sizeof(tdb_off_t) * 4 + 1];
- sprintf(msg, "%u ", seqnum);
+ snprintf(msg, sizeof(msg), "%u ", seqnum);
tdb_trace_write(tdb, msg);
tdb_trace_write(tdb, op);
tdb_trace_end(tdb);
tdb_trace_write(tdb, msg);
tdb_trace_write(tdb, op);
tdb_trace_end(tdb);
- sprintf(msg, "%s %u %#x %#x", op, hash_size, tdb_flags, open_flags);
+ snprintf(msg, sizeof(msg),
+ "%s %u 0x%x 0x%x", op, hash_size, tdb_flags, open_flags);
tdb_trace_start(tdb);
tdb_trace_write(tdb, msg);
tdb_trace_end(tdb);
tdb_trace_start(tdb);
tdb_trace_write(tdb, msg);
tdb_trace_end(tdb);
TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
int ret)
{
TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
int ret)
{
- char msg[sizeof(ret) * 4];
+ char msg[1 + sizeof(ret) * 4];
- sprintf(msg, " %#x", flag);
+ snprintf(msg, sizeof(msg), " %#x", flag);
tdb_trace_start(tdb);
tdb_trace_write(tdb, op);
tdb_trace_record(tdb, rec1);
tdb_trace_start(tdb);
tdb_trace_write(tdb, op);
tdb_trace_record(tdb, rec1);
/* #define TDB_TRACE 1 */
/* #define TDB_TRACE 1 */
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+#ifndef __STRINGSTRING
+#define __STRINGSTRING(x) __STRING(x)
+#endif
+
+#ifndef __location__
+#define __location__ __FILE__ ":" __STRINGSTRING(__LINE__)
+#endif
+
#if HAVE_GETPAGESIZE
#define getpagesize() 0x2000
#endif
#if HAVE_GETPAGESIZE
#define getpagesize() 0x2000
#endif
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(struct tdb_context *tdb,
- tdb_traverse_func fn, void *private_data,
- struct tdb_traverse_lock *tl)
+static int tdb_traverse_internal(struct tdb_context *tdb,
+ tdb_traverse_func fn, void *private_data,
+ struct tdb_traverse_lock *tl)
{
TDB_DATA key, dbuf;
struct tdb_record rec;
{
TDB_DATA key, dbuf;
struct tdb_record rec;
tdb->traverse_read++;
tdb_trace(tdb, "tdb_traverse_read_start");
tdb->traverse_read++;
tdb_trace(tdb, "tdb_traverse_read_start");
- ret = _tdb_traverse(tdb, fn, private_data, &tl);
+ ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
tdb->traverse_read--;
tdb_transaction_unlock(tdb, F_RDLCK);
tdb->traverse_read--;
tdb_transaction_unlock(tdb, F_RDLCK);
tdb->traverse_write++;
tdb_trace(tdb, "tdb_traverse_start");
tdb->traverse_write++;
tdb_trace(tdb, "tdb_traverse_start");
- ret = _tdb_traverse(tdb, fn, private_data, &tl);
+ ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
tdb->traverse_write--;
tdb_transaction_unlock(tdb, F_WRLCK);
tdb->traverse_write--;
tdb_transaction_unlock(tdb, F_WRLCK);