]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#8192 LMDB: define new error codes to avoid errno abuse
authorHoward Chu <hyc@openldap.org>
Fri, 24 Apr 2026 15:05:40 +0000 (16:05 +0100)
committerHoward Chu <hyc@openldap.org>
Fri, 24 Apr 2026 15:05:40 +0000 (16:05 +0100)
And avoid confusion with Windows error codes

libraries/liblmdb/lmdb.h
libraries/liblmdb/mdb.c

index bb692e2c0b352007d5aec44232a2c7668d8df12f..454532b6189e26cc3479743133b6b59cfab657ce 100644 (file)
@@ -530,8 +530,16 @@ typedef enum MDB_cursor_op {
 #define MDB_CANT_ROLLBACK      (-30774)
        /** Can't drop main DBI while other DBIs are open */
 #define MDB_DBIS_BUSY  (-30773)
+       /** Write was incomplete */
+#define MDB_SHORT_WRITE        (-30772)
+       /** Env is busy, can't use previous snapshot */
+#define MDB_ENV_BUSY   (-30771)
+       /** Env or txn is read-only, can't write */
+#define MDB_IS_READONLY        (-30770)
+       /** Requested map address is unavailable */
+#define MDB_ADDR_BUSY
        /** The last defined error code */
-#define MDB_LAST_ERRCODE       MDB_CANT_ROLLBACK
+#define MDB_LAST_ERRCODE       MDB_ADDR_BUSY
 /** @} */
 
 /** @brief Statistics for a database in the environment */
index e5cc664796569942ca660d6e4bec4a6a7971fbfa..03f0a19ea1a561b7c4f25d9d2547f6864f48e1d5 100644 (file)
@@ -330,6 +330,7 @@ union semun {
 #endif
 
 /* Internal error codes, not exposed outside liblmdb */
+#define        MDB_NO_META             (MDB_LAST_ERRCODE + 9)
 #define        MDB_NO_ROOT             (MDB_LAST_ERRCODE + 10)
 #ifdef _WIN32
 #define MDB_OWNERDEAD  ((int) WAIT_ABANDONED)
@@ -1916,6 +1917,10 @@ static char *const mdb_errstr[] = {
        "MDB_TXN_PENDING: Transaction already prepared, must abort or commit",
        "MDB_CANT_ROLLBACK: Environment can't rollback last transaction",
        "MDB_DBIS_BUSY: Can't drop main DBI while other DBIs are open",
+       "MDB_SHORT_WRITE: Fewer bytes were written than requested",
+       "MDB_ENV_BUSY: Environment is busy, can't use previous snapshot",
+       "MDB_IS_READONLY: Can't write in readonly txn or environment",
+       "MDB_ADDR_BUSY: Requested map address is unavailable",
 };
 
 char *
@@ -1946,13 +1951,8 @@ mdb_strerror(int err)
         * have used LMDB-specific error codes for everything.
         */
        switch(err) {
-       case ENOENT:    /* 2, FILE_NOT_FOUND */
-       case EIO:               /* 5, ACCESS_DENIED */
        case ENOMEM:    /* 12, INVALID_ACCESS */
-       case EACCES:    /* 13, INVALID_DATA */
-       case EBUSY:             /* 16, CURRENT_DIRECTORY */
        case EINVAL:    /* 22, BAD_COMMAND */
-       case ENOSPC:    /* 28, OUT_OF_PAPER */
                return strerror(err);
        default:
                ;
@@ -3104,7 +3104,7 @@ mdb_env_sync0(MDB_env *env, int force, pgno_t numpgs)
 {
        int rc = 0;
        if (env->me_flags & MDB_RDONLY)
-               return EACCES;
+               return MDB_IS_READONLY;
        if (force || !(env->me_flags & MDB_NOSYNC)
 #ifdef _WIN32  /* Sync is normally achieved in Windows by doing WRITE_THROUGH writes */
                && (env->me_flags & MDB_WRITEMAP)
@@ -3485,7 +3485,7 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
        flags |= env->me_flags & MDB_WRITEMAP;
 
        if (env->me_flags & MDB_RDONLY & ~flags) /* write txn in RDONLY env */
-               return EACCES;
+               return MDB_IS_READONLY;
 
        if (parent) {
                /* Nested transactions:
@@ -4248,7 +4248,7 @@ bad_write:
                                                        goto retry_write;
                                                DPRINTF(("Write error: %s", strerror(rc)));
                                        } else {
-                                               rc = EIO; /* TODO: Use which error code? */
+                                               rc = MDB_SHORT_WRITE;
                                                DPUTS("short write, filesystem full?");
                                        }
                                }
@@ -4677,7 +4677,7 @@ mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta)
                p = (MDB_page *)env->me_map;
                for (i=0; i<NUM_METAS; i++) {
                        if (!F_ISSET(p->mp_flags, P_META))
-                               return ENOENT;
+                               return MDB_NO_META;
                        if (env->me_metas[i]->mm_magic != MDB_MAGIC)
                                return MDB_INVALID;
                        if (env->me_metas[i]->mm_version != MDB_DATA_VERSION)
@@ -4707,7 +4707,7 @@ mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta)
 #endif
                if (rc != Size) {
                        if (rc == 0 && off == 0)
-                               return ENOENT;
+                               return MDB_NO_META;
                        rc = rc < 0 ? (int) ErrCode() : MDB_INVALID;
                        DPRINTF(("read: %s", mdb_strerror(rc)));
                        return rc;
@@ -4717,7 +4717,7 @@ mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta)
 
                if (!F_ISSET(p->mp_flags, P_META)) {
                        if (env->me_flags & MDB_RAWPART)
-                               return ENOENT;
+                               return MDB_NO_META;
                        DPRINTF(("page %"Yu" not a meta page", p->mp_pgno));
                        return MDB_INVALID;
                }
@@ -4822,7 +4822,7 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
        else if ((unsigned) len == psize * NUM_METAS)
                rc = MDB_SUCCESS;
        else
-               rc = ENOSPC;
+               rc = MDB_SHORT_WRITE;
        free(p);
        return rc;
 }
@@ -4925,7 +4925,7 @@ retry_write:
        rc = pwrite(mfd, ptr, len, off);
 #endif
        if (rc != len) {
-               rc = rc < 0 ? ErrCode() : EIO;
+               rc = rc < 0 ? ErrCode() : MDB_SHORT_WRITE;
 #ifndef _WIN32
                if (rc == EINTR)
                        goto retry_write;
@@ -5128,7 +5128,7 @@ mdb_env_map(MDB_env *env, void *addr)
         * instead unmap existing pages to make room for the new map.
         */
        if (addr && env->me_map != addr)
-               return EBUSY;   /* TODO: Make a new MDB_* error code? */
+               return MDB_ADDR_BUSY;
 
        p = (MDB_page *)env->me_map;
        env->me_metas[0] = METADATA(p);
@@ -5501,7 +5501,7 @@ mdb_env_open2(MDB_env *env, int prev)
 #endif
 
        if ((i = mdb_env_read_header(env, prev, &meta)) != 0) {
-               if (i != ENOENT)
+               if (i != MDB_NO_META)
                        return i;
                DPUTS("new mdbenv");
                newenv = 1;
@@ -6077,10 +6077,6 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl)
                        rc = MDB_VERSION_MISMATCH;
                        goto fail;
                }
-               rc = ErrCode();
-               if (rc && rc != EACCES && rc != EAGAIN) {
-                       goto fail;
-               }
 #ifdef _WIN32
                mdb_env_mname_init(env);
                env->me_rmutex = OpenMutexA(SYNCHRONIZE, FALSE, MUTEXNAME(env, 'r'));
@@ -6297,7 +6293,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
                if (rc)
                        goto leave;
                if ((flags & MDB_PREVSNAPSHOT) && !excl) {
-                       rc = EAGAIN;
+                       rc = MDB_ENV_BUSY;
                        goto leave;
                }
        }
@@ -8507,7 +8503,7 @@ _mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
        flags &= ~MDB_NOSPILL;
 
        if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
-               return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+               return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? MDB_IS_READONLY : MDB_BAD_TXN;
 
        if (key->mv_size-1 >= ENV_MAXKEY(env))
                return MDB_BAD_VALSIZE;
@@ -9016,7 +9012,7 @@ _mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
        int rc;
 
        if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
-               return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+               return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? MDB_IS_READONLY : MDB_BAD_TXN;
 
        if (!(mc->mc_flags & C_INITIALIZED))
                return EINVAL;
@@ -10513,7 +10509,7 @@ mdb_del(MDB_txn *txn, MDB_dbi dbi,
                return EINVAL;
 
        if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
-               return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+               return (txn->mt_flags & MDB_TXN_RDONLY) ? MDB_IS_READONLY : MDB_BAD_TXN;
 
        if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) {
                /* must ignore any data */
@@ -11017,7 +11013,7 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
                return EINVAL;
 
        if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
-               return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+               return (txn->mt_flags & MDB_TXN_RDONLY) ? MDB_IS_READONLY : MDB_BAD_TXN;
 
        MDB_TRACE(("%p, %u, %"Z"u[%s], %"Z"u%s, %u",
                txn, dbi, key ? key->mv_size:0, DKEY(key), data->mv_size, mdb_dval(txn, dbi, data, dbuf), flags));
@@ -11111,7 +11107,7 @@ again:
                                wsize -= len;
                                continue;
                        } else {
-                               rc = EIO;
+                               rc = MDB_SHORT_WRITE;
                                break;
                        }
                }
@@ -11488,7 +11484,7 @@ mdb_env_copyfd0(MDB_env *env, HANDLE fd)
                        continue;
                } else {
                        /* Non-blocking or async handles are not supported */
-                       rc = EIO;
+                       rc = MDB_SHORT_WRITE;
                        break;
                }
        }
@@ -11519,7 +11515,7 @@ mdb_env_copyfd0(MDB_env *env, HANDLE fd)
                        wsize -= len;
                        continue;
                } else {
-                       rc = EIO;
+                       rc = MDB_SHORT_WRITE;
                        break;
                }
        }
@@ -11675,7 +11671,7 @@ mdb_env_incr_dumpfd(MDB_env *env, HANDLE fd, size_t txnid)
                                        w3 -= len;
                                        continue;
                                } else {
-                                       rc = EIO;
+                                       rc = MDB_SHORT_WRITE;
                                        goto leave;
                                }
                        }
@@ -12022,7 +12018,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
                if (rc != MDB_NOTFOUND || !(flags & MDB_CREATE))
                        return rc;
                if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
-                       return EACCES;
+                       return MDB_IS_READONLY;
        }
 
        /* Done here so we cannot fail after creating a new DB */
@@ -12223,7 +12219,7 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
                return EINVAL;
 
        if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
-               return EACCES;
+               return MDB_IS_READONLY;
 
        if (TXN_DBI_CHANGED(txn, dbi))
                return MDB_BAD_DBI;