]> git.sur5r.net Git - openldap/blobdiff - libraries/liblmdb/mdb.c
ITS#7793 mdb_cursor_put(): Fix MDB_CURRENT.
[openldap] / libraries / liblmdb / mdb.c
index b6e2f842c772347c2a133cc74feb495b9969ab45..5a607a4c7e96d0324ec7086036f660191cca42fb 100644 (file)
@@ -2728,10 +2728,11 @@ mdb_freelist_save(MDB_txn *txn)
                        MDB_ID save;
 
                        mdb_tassert(txn, len >= 0 && id <= env->me_pglast);
-                       key.mv_data = &id;
                        if (len > mop_len) {
                                len = mop_len;
                                data.mv_size = (len + 1) * sizeof(MDB_ID);
+                               /* Drop MDB_CURRENT when changing the data size */
+                               key.mv_data = &id;
                                flags = 0;
                        }
                        data.mv_data = mop -= len;
@@ -3556,7 +3557,7 @@ mdb_env_open2(MDB_env *env)
                        env->me_mapsize = minsize;
        }
 
-       rc = mdb_env_map(env, meta.mm_address, newenv);
+       rc = mdb_env_map(env, meta.mm_address, newenv || env->me_mapsize != meta.mm_mapsize);
        if (rc)
                return rc;
 
@@ -5761,7 +5762,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
        unsigned int nflags;
        DKBUF;
 
-       if (mc == NULL || key == NULL)
+       if (mc == NULL)
                return EINVAL;
 
        env = mc->mc_txn->mt_env;
@@ -5782,8 +5783,16 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
        if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
                return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
 
-       if (flags != MDB_CURRENT && key->mv_size-1 >= ENV_MAXKEY(env))
-               return MDB_BAD_VALSIZE;
+       if (flags != MDB_CURRENT) {
+               if (key == NULL)
+                       return EINVAL;
+               if (key->mv_size-1 >= ENV_MAXKEY(env))
+                       return MDB_BAD_VALSIZE;
+       } else {
+               /* Ignore key except in sub-cursor, where key holds the data */
+               if (!(mc->mc_flags & C_SUB))
+                       key = NULL;
+       }
 
 #if SIZE_MAX > MAXDATASIZE
        if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE))
@@ -5912,7 +5921,7 @@ more:
                         * it.  mp: new (sub-)page.  offset: growth in page
                         * size.  xdata: node data with new page or DB.
                         */
-                       ssize_t         i, offset = 0;
+                       unsigned        i, offset = 0;
                        mp = fp = xdata.mv_data = env->me_pbuf;
                        mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
 
@@ -5968,17 +5977,17 @@ more:
                                fp = olddata.mv_data;
                                switch (flags) {
                                default:
-                                       i = -(ssize_t)SIZELEFT(fp);
                                        if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
-                                               offset = i += (ssize_t) EVEN(
-                                                       sizeof(indx_t) + NODESIZE + data->mv_size);
-                                       } else {
-                                               i += offset = fp->mp_pad;
-                                               offset *= 4; /* space for 4 more */
+                                               offset = EVEN(NODESIZE + sizeof(indx_t) +
+                                                       data->mv_size);
+                                               break;
                                        }
-                                       if (i > 0)
+                                       offset = fp->mp_pad;
+                                       if (SIZELEFT(fp) < offset) {
+                                               offset *= 4; /* space for 4 more */
                                                break;
-                                       /* FALLTHRU: Sub-page is big enough */
+                                       }
+                                       /* FALLTHRU: Big enough MDB_DUPFIXED sub-page */
                                case MDB_CURRENT:
                                        fp->mp_flags |= P_DIRTY;
                                        COPY_PGNO(fp->mp_pgno, mp->mp_pgno);
@@ -6027,7 +6036,7 @@ prep_subDB:
                                } else {
                                        memcpy((char *)mp + mp->mp_upper, (char *)fp + fp->mp_upper,
                                                olddata.mv_size - fp->mp_upper);
-                                       for (i = NUMKEYS(fp); --i >= 0; )
+                                       for (i=0; i<NUMKEYS(fp); i++)
                                                mp->mp_ptrs[i] = fp->mp_ptrs[i] + offset;
                                }
                        }
@@ -6107,7 +6116,7 @@ current:
                         */
                        if (F_ISSET(flags, MDB_RESERVE))
                                data->mv_data = olddata.mv_data;
-                       else if (data->mv_size)
+                       else if (!(mc->mc_flags & C_SUB))
                                memcpy(olddata.mv_data, data->mv_data, data->mv_size);
                        else
                                memcpy(NODEKEY(leaf), key->mv_data, key->mv_size);