From 8b2aa9fb65b3f54700604738c5f869f4dc81b539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Tue, 14 Oct 2025 23:48:58 +0300 Subject: [PATCH] mdbx: add `getenv_bool()` and fetching debug-options from the process environment. --- src/global.c | 23 ++++++++++++++++++++++- src/osal.c | 44 ++++++++++++++++++++++++++++++++++++-------- src/osal.h | 13 +++++++++---- test/config.c++ | 22 ++++++++++------------ 4 files changed, 77 insertions(+), 25 deletions(-) diff --git a/src/global.c b/src/global.c index 36e9eaaf..894c7ef6 100644 --- a/src/global.c +++ b/src/global.c @@ -176,8 +176,29 @@ __cold static __attribute__((__destructor__)) void mdbx_global_destructor(void) struct libmdbx_globals globals; +static bool getenv_bool(const char *name, bool default_value) { + const char *value = osal_getenv(name, false); + if (value) { + if (*value == 0 /* implied ON */) + return true; + if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "on") == 0 || strcasecmp(value, "true") == 0 || + strcasecmp(value, "1") == 0) + return true; + if (strcasecmp(value, "no") == 0 || strcasecmp(value, "off") == 0 || strcasecmp(value, "false") == 0 || + strcasecmp(value, "0") == 0) + return false; + } + return default_value; +} + __cold static void mdbx_init(void) { - globals.runtime_flags = ((MDBX_DEBUG) > 0) * MDBX_DBG_ASSERT + ((MDBX_DEBUG) > 1) * MDBX_DBG_AUDIT; + globals.runtime_flags = (getenv_bool("MDBX_DBG_ASSERT", (MDBX_DEBUG) > 0) ? MDBX_DBG_ASSERT : 0) | + (getenv_bool("MDBX_DBG_AUDIT", (MDBX_DEBUG) > 1) ? MDBX_DBG_AUDIT : 0) | + (getenv_bool("MDBX_DBG_JITTER", false) ? MDBX_DBG_JITTER : 0) | + (getenv_bool("MDBX_DBG_DUMP", false) ? MDBX_DBG_DUMP : 0) | + (getenv_bool("MDBX_DBG_LEGACY_MULTIOPEN", false) ? MDBX_DBG_LEGACY_MULTIOPEN : 0) | + (getenv_bool("MDBX_DBG_LEGACY_OVERLAP", false) ? MDBX_DBG_LEGACY_OVERLAP : 0) | + (getenv_bool("MDBX_DBG_DONT_UPGRADE", false) ? MDBX_DBG_DONT_UPGRADE : 0); globals.loglevel = MDBX_LOG_FATAL; ENSURE(nullptr, osal_fastmutex_init(&globals.debug_lock) == 0); osal_ctor(); diff --git a/src/osal.c b/src/osal.c index aa2b3b74..199d2cc2 100644 --- a/src/osal.c +++ b/src/osal.c @@ -1777,8 +1777,8 @@ int osal_check_fs_incore(mdbx_filehandle_t handle) { const size_t name_len = 0; #endif if (name_len) { - if (osal_strncasecmp("tmpfs", name, 6) == 0 || osal_strncasecmp("mfs", name, 4) == 0 || - osal_strncasecmp("ramfs", name, 6) == 0 || osal_strncasecmp("romfs", name, 6) == 0) + if (strncasecmp("tmpfs", name, 6) == 0 || strncasecmp("mfs", name, 4) == 0 || strncasecmp("ramfs", name, 6) == 0 || + strncasecmp("romfs", name, 6) == 0) return MDBX_RESULT_TRUE; } #endif /* !Windows */ @@ -1990,14 +1990,13 @@ int osal_check_fs_local(mdbx_filehandle_t handle, int flags) { #endif if (name_len) { - if (((name_len > 2 && osal_strncasecmp("nfs", name, 3) == 0) || osal_strncasecmp("cifs", name, name_len) == 0 || - osal_strncasecmp("ncpfs", name, name_len) == 0 || osal_strncasecmp("smbfs", name, name_len) == 0 || - osal_strcasecmp("9P" /* WSL2 */, name) == 0 || - ((name_len > 3 && osal_strncasecmp("fuse", name, 4) == 0) && - osal_strncasecmp("fuseblk", name, name_len) != 0)) && + if (((name_len > 2 && strncasecmp("nfs", name, 3) == 0) || strncasecmp("cifs", name, name_len) == 0 || + strncasecmp("ncpfs", name, name_len) == 0 || strncasecmp("smbfs", name, name_len) == 0 || + strcasecmp("9P" /* WSL2 */, name) == 0 || + ((name_len > 3 && strncasecmp("fuse", name, 4) == 0) && strncasecmp("fuseblk", name, name_len) != 0)) && !(flags & MDBX_EXCLUSIVE)) return MDBX_EREMOTE; - if (osal_strcasecmp("ftp", name) == 0 || osal_strcasecmp("http", name) == 0 || osal_strcasecmp("sshfs", name) == 0) + if (strcasecmp("ftp", name) == 0 || strcasecmp("http", name) == 0 || strcasecmp("sshfs", name) == 0) return MDBX_EREMOTE; } @@ -3475,6 +3474,35 @@ bin128_t osal_guid(const MDBX_env *env) { return uuid; } +const char *osal_getenv(const char *name, bool secure) { + (void)secure; +#if defined(_WIN32) || defined(_WIN64) + static char buf[42]; + SetLastError(ERROR_OUT_OF_PAPER); + const size_t len = GetEnvironmentVariableA(name, buf, sizeof(buf)); + if (len >= sizeof(buf)) + /* no idea haw to handle */ + return nullptr; + if (len != 0) + return buf; + switch (GetLastError()) { + case ERROR_OUT_OF_PAPER: + return ""; + default: + /* no idea to do in case of other error */ + case ERROR_ENVVAR_NOT_FOUND: + return nullptr; + } + return (GetLastError() == ERROR_ENVVAR_NOT_FOUND) ? nullptr : ""; +#else +#if defined(_GNU_SOURCE) && __GLIBC_PREREQ(2, 17) + if (secure) + return secure_getenv(name); +#endif /* glibc >= 2.17 */ + return getenv(name); +#endif +} + /*--------------------------------------------------------------------------*/ void osal_ctor(void) { diff --git a/src/osal.h b/src/osal.h index d199a739..d943bfe0 100644 --- a/src/osal.h +++ b/src/osal.h @@ -122,8 +122,6 @@ static inline void osal_free(void *ptr) { HeapFree(GetProcessHeap(), 0, ptr); } #define osal_realloc realloc #define osal_free free #define osal_strdup _strdup -#define osal_strcasecmp _stricmp -#define osal_strncasecmp _strnicmp #endif /* MDBX_WITHOUT_MSVC_CRT */ @@ -135,6 +133,14 @@ static inline void osal_free(void *ptr) { HeapFree(GetProcessHeap(), 0, ptr); } #define vsnprintf _vsnprintf /* ntdll */ #endif +#ifndef strcasecmp +#define strcasecmp _stricmp /* ntdll */ +#endif + +#ifndef strncasecmp +#define strncasecmp _strnicmp /* ntdll */ +#endif + #else /*----------------------------------------------------------------------*/ typedef pthread_t osal_thread_t; @@ -152,8 +158,6 @@ typedef pthread_mutex_t osal_fastmutex_t; #define osal_realloc realloc #define osal_free free #define osal_strdup strdup -#define osal_strcasecmp strcasecmp -#define osal_strncasecmp strncasecmp #endif /* Platform */ #if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(malloc_usable_size) @@ -471,6 +475,7 @@ MDBX_MAYBE_UNUSED static inline bool osal_isdirsep(pathchar_t c) { c == '/'; } +MDBX_INTERNAL const char *osal_getenv(const char *name, bool secure); MDBX_INTERNAL bool osal_pathequal(const pathchar_t *l, const pathchar_t *r, size_t len); MDBX_INTERNAL pathchar_t *osal_fileext(const pathchar_t *pathname, size_t len); MDBX_INTERNAL int osal_fileexists(const pathchar_t *pathname); diff --git a/test/config.c++ b/test/config.c++ index 257d01c1..29b85b9c 100644 --- a/test/config.c++ +++ b/test/config.c++ @@ -152,21 +152,21 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option, u if (suffix && *suffix) { if (scale == no_scale || scale == intkey) failure("Option '--%s' doesn't accepts suffixes, so '%s' is unexpected\n", option, suffix); - if (strcmp(suffix, "K") == 0 || osal_strcasecmp(suffix, "Kilo") == 0) + if (strcmp(suffix, "K") == 0 || strcasecmp(suffix, "Kilo") == 0) multiplier = (scale == decimal) ? UINT64_C(1000) : UINT64_C(1024); - else if (strcmp(suffix, "M") == 0 || osal_strcasecmp(suffix, "Mega") == 0) + else if (strcmp(suffix, "M") == 0 || strcasecmp(suffix, "Mega") == 0) multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 : UINT64_C(1024) * 1024; - else if (strcmp(suffix, "G") == 0 || osal_strcasecmp(suffix, "Giga") == 0) + else if (strcmp(suffix, "G") == 0 || strcasecmp(suffix, "Giga") == 0) multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 : UINT64_C(1024) * 1024 * 1024; - else if (strcmp(suffix, "T") == 0 || osal_strcasecmp(suffix, "Tera") == 0) + else if (strcmp(suffix, "T") == 0 || strcasecmp(suffix, "Tera") == 0) multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 * 1000 : UINT64_C(1024) * 1024 * 1024 * 1024; - else if (scale == duration && (strcmp(suffix, "s") == 0 || osal_strcasecmp(suffix, "Seconds") == 0)) + else if (scale == duration && (strcmp(suffix, "s") == 0 || strcasecmp(suffix, "Seconds") == 0)) multiplier = 1; - else if (scale == duration && (strcmp(suffix, "m") == 0 || osal_strcasecmp(suffix, "Minutes") == 0)) + else if (scale == duration && (strcmp(suffix, "m") == 0 || strcasecmp(suffix, "Minutes") == 0)) multiplier = 60; - else if (scale == duration && (strcmp(suffix, "h") == 0 || osal_strcasecmp(suffix, "Hours") == 0)) + else if (scale == duration && (strcmp(suffix, "h") == 0 || strcasecmp(suffix, "Hours") == 0)) multiplier = 3600; - else if (scale == duration && (strcmp(suffix, "d") == 0 || osal_strcasecmp(suffix, "Days") == 0)) + else if (scale == duration && (strcmp(suffix, "d") == 0 || strcasecmp(suffix, "Days") == 0)) multiplier = 3600 * 24; else failure("Option '--%s' expects a numeric value with Kilo/Mega/Giga/Tera %s" @@ -309,14 +309,12 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option, b return true; } - if (osal_strcasecmp(value_cstr, "yes") == 0 || osal_strcasecmp(value_cstr, "1") == 0 || - osal_strcasecmp(value_cstr, "on") == 0) { + if (strcasecmp(value_cstr, "yes") == 0 || strcasecmp(value_cstr, "1") == 0 || strcasecmp(value_cstr, "on") == 0) { value = true; return true; } - if (osal_strcasecmp(value_cstr, "no") == 0 || osal_strcasecmp(value_cstr, "0") == 0 || - osal_strcasecmp(value_cstr, "off") == 0) { + if (strcasecmp(value_cstr, "no") == 0 || strcasecmp(value_cstr, "0") == 0 || strcasecmp(value_cstr, "off") == 0) { value = false; return true; }