#define MAP_FAILED ((void *)-1)
#endif
+/* free memory if the pointer is valid and zero the pointer */
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
+#endif
+
#define BUCKET(hash) ((hash) % tdb->header.hash_size)
TDB_DATA tdb_null;
fl.l_len = 1;
fl.l_pid = 0;
- if (fcntl(tdb->fd,lck_type,&fl)) {
+ if (fcntl(tdb->fd,lck_type,&fl) == -1) {
if (!probe) {
- TDB_LOG((tdb, 5,"tdb_brlock failed at offset %d rw_type=%d lck_type=%d\n",
- offset, rw_type, lck_type));
+ TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n",
+ tdb->fd, offset, rw_type, lck_type));
}
/* errno set by fcntl */
return TDB_ERRCODE(TDB_ERR_LOCK, -1);
if (tdb->locked[list+1].count == 0) {
if (!tdb->read_only && tdb->header.rwlocks) {
if (tdb_spinlock(tdb, list, ltype)) {
- TDB_LOG((tdb, 0, "tdb_lock spinlock on list ltype=%d\n",
+ TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n",
list, ltype));
return -1;
}
return TDB_ERRCODE(TDB_ERR_OOM, buf);
}
if (tdb_read(tdb, offset, buf, len, 0) == -1) {
- free(buf);
+ SAFE_FREE(buf);
return NULL;
}
return buf;
}
if (tailer != rec.rec_len + sizeof(rec)) {
- printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", tailer, rec.rec_len + sizeof(rec));
+ printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n",
+ (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec)));
}
return rec.next;
}
void tdb_printfreelist(TDB_CONTEXT *tdb)
{
long total_free = 0;
- tdb_off offset, rec_ptr, last_ptr;
+ tdb_off offset, rec_ptr;
struct list_struct rec;
tdb_lock(tdb, -1, F_WRLCK);
- last_ptr = 0;
offset = FREELIST_TOP;
/* read in the freelist top */
ret = tdb_create_rwlocks(tdb->fd, hash_size);
fail:
- free(newdb);
+ SAFE_FREE(newdb);
return ret;
}
return 0;
if (memcmp(key.dptr, k, key.dsize) == 0) {
- free(k);
+ SAFE_FREE(k);
return rec_ptr;
}
- free(k);
+ SAFE_FREE(k);
}
rec_ptr = r->next;
}
/* They want us to terminate traversal */
unlock_record(tdb, tl.off);
tdb->travlocks.next = tl.next;
- free(key.dptr);
+ SAFE_FREE(key.dptr);
return count;
}
- free(key.dptr);
+ SAFE_FREE(key.dptr);
}
tdb->travlocks.next = tl.next;
if (ret < 0)
tdb->travlocks.off = 0;
}
- if (k)
- free(k);
+ SAFE_FREE(k);
}
if (!tdb->travlocks.off) {
ret = -1;
}
out:
- if (p)
- free(p);
+ SAFE_FREE(p);
tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
return ret;
}
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). */
-TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
+ try to call tdb_error or tdb_errname, just do strerror(errno).
+
+ @param name may be NULL for internal databases. */
+TDB_CONTEXT *tdb_open(const 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,
+TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
tdb_log_func log_fn)
{
tdb->flags = tdb_flags;
tdb->open_flags = open_flags;
tdb->log_fn = log_fn;
-
+
if ((open_flags & O_ACCMODE) == O_WRONLY) {
TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
name));
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)
+ if (ftruncate(tdb->fd, 0) == -1) {
+ TDB_LOG((tdb, 0, "tdb_open_ex: "
+ "failed to truncate %s: %s\n",
+ name, strerror(errno)));
goto fail; /* errno set by ftruncate */
+ }
}
if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
goto fail;
}
- /* map the database and fill in the return structure */
- tdb->name = (char *)strdup(name);
- if (!tdb->name) {
+ if (!(tdb->name = (char *)strdup(name))) {
errno = ENOMEM;
goto fail;
}
+
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) {
+ TDB_LOG((tdb, 2, "tdb_open_ex: "
+ "failed to allocate lock structure for %s\n",
+ name));
errno = ENOMEM;
goto fail;
}
if (locked) {
if (!tdb->read_only)
tdb_clear_spinlocks(tdb);
- if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1)
+ if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) {
+ TDB_LOG((tdb, 0, "tdb_open_ex: "
+ "failed to take ACTIVE_LOCK on %s: %s\n",
+ name, strerror(errno)));
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->map_ptr) {
if (tdb->flags & TDB_INTERNAL)
- free(tdb->map_ptr);
+ SAFE_FREE(tdb->map_ptr);
else
tdb_munmap(tdb);
}
- if (tdb->name)
- free(tdb->name);
+ SAFE_FREE(tdb->name);
if (tdb->fd != -1)
close(tdb->fd);
- if (tdb->locked)
- free(tdb->locked);
+ SAFE_FREE(tdb->locked);
errno = save_errno;
return NULL;
}
if (tdb->map_ptr) {
if (tdb->flags & TDB_INTERNAL)
- free(tdb->map_ptr);
+ SAFE_FREE(tdb->map_ptr);
else
tdb_munmap(tdb);
}
- if (tdb->name)
- free(tdb->name);
+ SAFE_FREE(tdb->name);
if (tdb->fd != -1)
ret = close(tdb->fd);
- if (tdb->locked)
- free(tdb->locked);
- if (tdb->lockedkeys)
- free(tdb->lockedkeys);
+ SAFE_FREE(tdb->locked);
+ SAFE_FREE(tdb->lockedkeys);
/* Remove from contexts list */
for (i = &tdbs; *i; i = &(*i)->next) {
}
memset(tdb, 0, sizeof(*tdb));
- free(tdb);
+ SAFE_FREE(tdb);
return ret;
}
if (i < number) {
for ( j = 0; j < i; j++)
tdb_unlock(tdb, j, F_WRLCK);
- free(tdb->lockedkeys);
- tdb->lockedkeys = NULL;
+ SAFE_FREE(tdb->lockedkeys);
return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
}
return 0;
u32 i;
for (i = 0; i < tdb->lockedkeys[0]; i++)
tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK);
- free(tdb->lockedkeys);
- tdb->lockedkeys = NULL;
+ SAFE_FREE(tdb->lockedkeys);
}
/* lock/unlock one hash chain. This is meant to be used to reduce