]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/open.c
tdb2: disallow SEED attribute with TDB_VERSION1.
[ccan] / ccan / tdb2 / open.c
index e4551c8405e8ced1c3e72fa11ab1079b405a04d4..59b4667d1bb86320ef79f226e3de609888dc6939 100644 (file)
@@ -16,7 +16,6 @@
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 #include "private.h"
-#include <ccan/hash/hash.h>
 #include <assert.h>
 
 /* all tdbs, to detect double-opens (fcntl file don't nest!) */
@@ -210,6 +209,7 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb,
        case TDB_ATTRIBUTE_HASH:
        case TDB_ATTRIBUTE_SEED:
        case TDB_ATTRIBUTE_OPENHOOK:
+       case TDB_ATTRIBUTE_TDB1_HASHSIZE:
                return tdb->last_error
                        = tdb_logerr(tdb, TDB_ERR_EINVAL,
                                     TDB_LOG_USE_ERROR,
@@ -219,7 +219,9 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb,
                                     ? "TDB_ATTRIBUTE_HASH"
                                     : attr->base.attr == TDB_ATTRIBUTE_SEED
                                     ? "TDB_ATTRIBUTE_SEED"
-                                    : "TDB_ATTRIBUTE_OPENHOOK");
+                                    : attr->base.attr == TDB_ATTRIBUTE_OPENHOOK
+                                    ? "TDB_ATTRIBUTE_OPENHOOK"
+                                    : "TDB_ATTRIBUTE_TDB1_HASHSIZE");
        case TDB_ATTRIBUTE_STATS:
                return tdb->last_error
                        = tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -242,16 +244,6 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb,
        return TDB_SUCCESS;
 }
 
-static uint64_t jenkins_hash(const void *key, size_t length, uint64_t seed,
-                            void *unused)
-{
-       uint64_t ret;
-       /* hash64_stable assumes lower bits are more important; they are a
-        * slightly better hash.  We use the upper bits first, so swap them. */
-       ret = hash64_stable((const unsigned char *)key, length, seed);
-       return (ret >> 32) | (ret << 32);
-}
-
 enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb,
                                 union tdb_attribute *attr)
 {
@@ -267,6 +259,13 @@ enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb,
                attr->hash.data = tdb->hash_data;
                break;
        case TDB_ATTRIBUTE_SEED:
+               if (tdb->flags & TDB_VERSION1)
+                       return tdb->last_error
+                               = tdb_logerr(tdb, TDB_ERR_EINVAL,
+                                            TDB_LOG_USE_ERROR,
+                                    "tdb_get_attribute:"
+                                    " cannot get TDB_ATTRIBUTE_SEED"
+                                    " on TDB1 tdb.");
                attr->seed.seed = tdb->hash_seed;
                break;
        case TDB_ATTRIBUTE_OPENHOOK:
@@ -287,6 +286,16 @@ enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb,
                attr->flock.unlock = tdb->unlock_fn;
                attr->flock.data = tdb->lock_data;
                break;
+       case TDB_ATTRIBUTE_TDB1_HASHSIZE:
+               if (!(tdb->flags & TDB_VERSION1))
+                       return tdb->last_error
+                               = tdb_logerr(tdb, TDB_ERR_EINVAL,
+                                            TDB_LOG_USE_ERROR,
+                                    "tdb_get_attribute:"
+                                    " cannot get TDB_ATTRIBUTE_TDB1_HASHSIZE"
+                                    " on TDB2 tdb.");
+               attr->tdb1_hashsize.hsize = tdb->tdb1.header.hash_size;
+               break;
        default:
                return tdb->last_error
                        = tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -311,11 +320,14 @@ void tdb_unset_attribute(struct tdb_context *tdb,
                break;
        case TDB_ATTRIBUTE_HASH:
        case TDB_ATTRIBUTE_SEED:
+       case TDB_ATTRIBUTE_TDB1_HASHSIZE:
                tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
                           "tdb_unset_attribute: cannot unset %s after opening",
                           type == TDB_ATTRIBUTE_HASH
                           ? "TDB_ATTRIBUTE_HASH"
-                          : "TDB_ATTRIBUTE_SEED");
+                          : type == TDB_ATTRIBUTE_SEED
+                          ? "TDB_ATTRIBUTE_SEED"
+                          : "TDB_ATTRIBUTE_TDB1_HASHSIZE");
                break;
        case TDB_ATTRIBUTE_STATS:
                tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -347,6 +359,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        ssize_t rlen;
        struct tdb_header hdr;
        struct tdb_attribute_seed *seed = NULL;
+       struct tdb_attribute_tdb1_hashsize *hsize_attr = NULL;
        tdb_bool_err berr;
        enum TDB_ERROR ecode;
        int openlock;
@@ -371,7 +384,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        tdb->openhook = NULL;
        tdb->lock_fn = tdb_fcntl_lock;
        tdb->unlock_fn = tdb_fcntl_unlock;
-       tdb->hash_fn = jenkins_hash;
+       tdb->hash_fn = tdb_jenkins_hash;
        memset(&tdb->stats, 0, sizeof(tdb->stats));
        tdb->stats.base.attr = TDB_ATTRIBUTE_STATS;
        tdb->stats.size = sizeof(tdb->stats);
@@ -393,6 +406,9 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
                        tdb->openhook = attr->openhook.fn;
                        tdb->openhook_data = attr->openhook.data;
                        break;
+               case TDB_ATTRIBUTE_TDB1_HASHSIZE:
+                       hsize_attr = &attr->tdb1_hashsize;
+                       break;
                default:
                        /* These are set as normal. */
                        ecode = tdb_set_attribute(tdb, attr);
@@ -410,6 +426,37 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
                goto fail;
        }
 
+       if (hsize_attr) {
+               if (!(tdb_flags & TDB_VERSION1) ||
+                   (!(tdb_flags & TDB_INTERNAL) && !(open_flags & O_CREAT))) {
+                       ecode = tdb_logerr(tdb, TDB_ERR_EINVAL,
+                                          TDB_LOG_USE_ERROR,
+                                          "tdb_open: can only use"
+                                          " TDB_ATTRIBUTE_TDB1_HASHSIZE when"
+                                          " creating a TDB_VERSION1 tdb");
+                       goto fail;
+               }
+       }
+
+       if (seed) {
+               if (tdb_flags & TDB_VERSION1) {
+                       ecode = tdb_logerr(tdb, TDB_ERR_EINVAL,
+                                          TDB_LOG_USE_ERROR,
+                                          "tdb_open:"
+                                          " cannot set TDB_ATTRIBUTE_SEED"
+                                          " on TDB1 tdb.");
+                       goto fail;
+               } else if (!(tdb_flags & TDB_INTERNAL)
+                          && !(open_flags & O_CREAT)) {
+                       ecode = tdb_logerr(tdb, TDB_ERR_EINVAL,
+                                          TDB_LOG_USE_ERROR,
+                                          "tdb_open:"
+                                          " cannot set TDB_ATTRIBUTE_SEED"
+                                          " without O_CREAT.");
+                       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",