Move SAFE_FREE into tdb.c to stop exporting it into tdb.h namespace.
[ira/wip.git] / source3 / tdb / tdb.c
index de376d29b20c1e6e2837cf5b19d409e2400b0c9f..6398a2a166c23237a16268830aa9cb9693aba580 100644 (file)
 #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;
 
@@ -175,10 +180,10 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
        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);
@@ -202,7 +207,7 @@ static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype)
        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;
                        }
@@ -343,7 +348,7 @@ static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len)
                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;
@@ -424,7 +429,8 @@ static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset)
        }
 
        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;
 }
@@ -464,12 +470,11 @@ void tdb_dump_all(TDB_CONTEXT *tdb)
 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 */
@@ -855,7 +860,7 @@ static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
                ret = tdb_create_rwlocks(tdb->fd, hash_size);
 
   fail:
-       free(newdb);
+       SAFE_FREE(newdb);
        return ret;
 }
 
@@ -884,10 +889,10 @@ static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash,
                                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;
        }
@@ -1195,10 +1200,10 @@ int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state)
                        /* 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)
@@ -1248,8 +1253,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
                        tdb->travlocks.off = 0;
                }
 
-               if (k)
-                       free(k);
+               SAFE_FREE(k);
        }
 
        if (!tdb->travlocks.off) {
@@ -1367,8 +1371,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
                ret = -1;
        }
  out:
-       if (p)
-               free(p); 
+       SAFE_FREE(p); 
        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
        return ret;
 }
@@ -1394,15 +1397,17 @@ static int tdb_already_open(dev_t device,
    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)
 {
@@ -1422,7 +1427,7 @@ TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
        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));
@@ -1464,8 +1469,12 @@ TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
        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)
@@ -1497,17 +1506,19 @@ TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
                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;
        }
@@ -1515,8 +1526,12 @@ TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
        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)
@@ -1540,16 +1555,14 @@ TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
        
        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;
        }
@@ -1563,18 +1576,15 @@ int tdb_close(TDB_CONTEXT *tdb)
 
        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) {
@@ -1585,7 +1595,7 @@ int tdb_close(TDB_CONTEXT *tdb)
        }
 
        memset(tdb, 0, sizeof(*tdb));
-       free(tdb);
+       SAFE_FREE(tdb);
 
        return ret;
 }
@@ -1650,8 +1660,7 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[])
        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;
@@ -1663,8 +1672,7 @@ void tdb_unlockkeys(TDB_CONTEXT *tdb)
        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