mdbx: native wchar_t pathname for Windows.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2022-08-09 18:27:43 +03:00
parent 98c53555ab
commit 2ff8d3c4f2
7 changed files with 264 additions and 198 deletions

35
mdbx.h
View File

@ -827,18 +827,30 @@ enum MDBX_constants {
#ifndef MDBX_LOCKNAME
/** \brief The name of the lock file in the environment
* without using \ref MDBX_NOSUBDIR */
#if !(defined(_WIN32) || defined(_WIN64))
#define MDBX_LOCKNAME "/mdbx.lck"
#else
#define MDBX_LOCKNAME L"\\mdbx.lck"
#endif
#endif /* MDBX_LOCKNAME */
#ifndef MDBX_DATANAME
/** \brief The name of the data file in the environment
* without using \ref MDBX_NOSUBDIR */
#if !(defined(_WIN32) || defined(_WIN64))
#define MDBX_DATANAME "/mdbx.dat"
#else
#define MDBX_DATANAME L"\\mdbx.dat"
#endif
#endif /* MDBX_DATANAME */
#ifndef MDBX_LOCK_SUFFIX
/** \brief The suffix of the lock file when \ref MDBX_NOSUBDIR is used */
#if !(defined(_WIN32) || defined(_WIN64))
#define MDBX_LOCK_SUFFIX "-lck"
#else
#define MDBX_LOCK_SUFFIX L"-lck"
#endif
#endif /* MDBX_LOCK_SUFFIX */
/* DEBUG & LOGGING ************************************************************/
@ -2275,6 +2287,11 @@ LIBMDBX_API int mdbx_env_get_option(const MDBX_env *env,
LIBMDBX_API int mdbx_env_open(MDBX_env *env, const char *pathname,
MDBX_env_flags_t flags, mdbx_mode_t mode);
#if defined(_WIN32) || defined(_WIN64)
LIBMDBX_API int mdbx_env_openW(MDBX_env *env, const wchar_t *pathnameW,
MDBX_env_flags_t flags, mdbx_mode_t mode);
#endif /* Windows */
/** \brief Deletion modes for \ref mdbx_env_delete().
* \ingroup c_extra
* \see mdbx_env_delete() */
@ -2317,6 +2334,10 @@ typedef enum MDBX_env_delete_mode_t MDBX_env_delete_mode_t;
* so no deletion was performed. */
LIBMDBX_API int mdbx_env_delete(const char *pathname,
MDBX_env_delete_mode_t mode);
#if defined(_WIN32) || defined(_WIN64)
LIBMDBX_API int mdbx_env_deleteW(const wchar_t *pathnameW,
MDBX_env_delete_mode_t mode);
#endif /* Windows */
/** \brief Copy an MDBX environment to the specified path, with options.
* \ingroup c_extra
@ -2351,6 +2372,10 @@ LIBMDBX_API int mdbx_env_delete(const char *pathname,
* \returns A non-zero error value on failure and 0 on success. */
LIBMDBX_API int mdbx_env_copy(MDBX_env *env, const char *dest,
MDBX_copy_flags_t flags);
#if defined(_WIN32) || defined(_WIN64)
LIBMDBX_API int mdbx_env_copyW(MDBX_env *env, const wchar_t *dest,
MDBX_copy_flags_t flags);
#endif /* Windows */
/** \brief Copy an environment to the specified file descriptor, with
* options.
@ -2803,7 +2828,11 @@ LIBMDBX_API int mdbx_env_get_flags(const MDBX_env *env, unsigned *flags);
* \returns A non-zero error value on failure and 0 on success,
* some possible errors are:
* \retval MDBX_EINVAL An invalid parameter was specified. */
#if !(defined(_WIN32) || defined(_WIN64))
LIBMDBX_API int mdbx_env_get_path(const MDBX_env *env, const char **dest);
#else
LIBMDBX_API int mdbx_env_get_pathW(const MDBX_env *env, const wchar_t **dest);
#endif /* Windows */
/** \brief Return the file descriptor for the given environment.
* \ingroup c_statinfo
@ -5195,6 +5224,12 @@ LIBMDBX_API int mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor,
LIBMDBX_API int mdbx_env_open_for_recovery(MDBX_env *env, const char *pathname,
unsigned target_meta,
bool writeable);
#if defined(_WIN32) || defined(_WIN64)
LIBMDBX_API int mdbx_env_open_for_recoveryW(MDBX_env *env,
const wchar_t *pathnameW,
unsigned target_meta,
bool writeable);
#endif /* Windows */
/** \brief Turn database to the specified meta-page.
*

View File

@ -3225,6 +3225,8 @@ public:
#if defined(_WIN32) || defined(_WIN64) || defined(DOXYGEN)
env &copy(const ::std::wstring &destination, bool compactify,
bool force_dynamic_size = false);
env &copy(const wchar_t *destination, bool compactify,
bool force_dynamic_size = false);
#endif /* Windows */
env &copy(const ::std::string &destination, bool compactify,
bool force_dynamic_size = false);
@ -3260,6 +3262,8 @@ public:
#if defined(_WIN32) || defined(_WIN64) || defined(DOXYGEN)
static bool remove(const ::std::wstring &pathname,
const remove_mode mode = just_remove);
static bool remove(const wchar_t *pathname,
const remove_mode mode = just_remove);
#endif /* Windows */
static bool remove(const ::std::string &pathname,
const remove_mode mode = just_remove);
@ -3507,6 +3511,8 @@ public:
#if defined(_WIN32) || defined(_WIN64) || defined(DOXYGEN)
env_managed(const ::std::wstring &pathname, const operate_parameters &,
bool accede = true);
explicit env_managed(const wchar_t *pathname, const operate_parameters &,
bool accede = true);
#endif /* Windows */
env_managed(const ::std::string &pathname, const operate_parameters &,
bool accede = true);
@ -3531,6 +3537,8 @@ public:
#if defined(_WIN32) || defined(_WIN64) || defined(DOXYGEN)
env_managed(const ::std::wstring &pathname, const create_parameters &,
const operate_parameters &, bool accede = true);
explicit env_managed(const wchar_t *pathname, const create_parameters &,
const operate_parameters &, bool accede = true);
#endif /* Windows */
env_managed(const ::std::string &pathname, const create_parameters &,
const operate_parameters &, bool accede = true);

View File

@ -12433,7 +12433,7 @@ __cold static int mdbx_setup_dxb(MDBX_env *env, const int lck_rc,
/******************************************************************************/
/* Open and/or initialize the lock region for the environment. */
__cold static int mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
__cold static int mdbx_setup_lck(MDBX_env *env, pathchar_t *lck_pathname,
mdbx_mode_t mode) {
mdbx_assert(env, env->me_lazy_fd != INVALID_HANDLE_VALUE);
mdbx_assert(env, env->me_lfd == INVALID_HANDLE_VALUE);
@ -12816,6 +12816,21 @@ __cold int mdbx_env_turn_for_recovery(MDBX_env *env, unsigned target) {
__cold int mdbx_env_open_for_recovery(MDBX_env *env, const char *pathname,
unsigned target_meta, bool writeable) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
return mdbx_env_open_for_recoveryW(env, pathnameW, target_meta, writeable);
}
__cold int mdbx_env_open_for_recoveryW(MDBX_env *env, const wchar_t *pathname,
unsigned target_meta, bool writeable) {
#endif /* Windows */
if (unlikely(target_meta >= NUM_METAS))
return MDBX_EINVAL;
int rc = check_env(env, false);
@ -12825,35 +12840,49 @@ __cold int mdbx_env_open_for_recovery(MDBX_env *env, const char *pathname,
return MDBX_EPERM;
env->me_stuck_meta = (int8_t)target_meta;
return mdbx_env_open(
env, pathname, writeable ? MDBX_EXCLUSIVE : MDBX_EXCLUSIVE | MDBX_RDONLY,
0);
return
#if defined(_WIN32) || defined(_WIN64)
mdbx_env_openW
#else
mdbx_env_open
#endif /* Windows */
(env, pathname, writeable ? MDBX_EXCLUSIVE : MDBX_EXCLUSIVE | MDBX_RDONLY,
0);
}
typedef struct {
void *buffer_for_free;
char *lck, *dxb;
pathchar_t *lck, *dxb;
size_t ent_len;
} MDBX_handle_env_pathname;
static bool path_equal(const pathchar_t *l, const pathchar_t *r, size_t len) {
#if defined(_WIN32) || defined(_WIN64)
while (len > 0) {
pathchar_t a = *l++;
pathchar_t b = *r++;
a = (a == '\\') ? '/' : a;
b = (b == '\\') ? '/' : b;
if (a != b)
return false;
}
return true;
#else
return memcmp(l, r, len * sizeof(pathchar_t)) == 0;
#endif
}
__cold static int mdbx_handle_env_pathname(MDBX_handle_env_pathname *ctx,
const char *pathname,
const pathchar_t *pathname,
MDBX_env_flags_t *flags,
const mdbx_mode_t mode) {
int rc;
memset(ctx, 0, sizeof(*ctx));
if (unlikely(!pathname))
if (unlikely(!pathname || !*pathname))
return MDBX_EINVAL;
int rc;
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
const DWORD dwAttrib = GetFileAttributesW(pathnameW);
const DWORD dwAttrib = GetFileAttributesW(pathname);
if (dwAttrib == INVALID_FILE_ATTRIBUTES) {
rc = GetLastError();
if (rc != MDBX_ENOFILE)
@ -12863,8 +12892,7 @@ __cold static int mdbx_handle_env_pathname(MDBX_handle_env_pathname *ctx,
return rc;
/* auto-create directory if requested */
if ((*flags & MDBX_NOSUBDIR) == 0 &&
!CreateDirectoryW(pathnameW, nullptr)) {
if ((*flags & MDBX_NOSUBDIR) == 0 && !CreateDirectoryW(pathname, nullptr)) {
rc = GetLastError();
if (rc != ERROR_ALREADY_EXISTS)
return rc;
@ -12905,41 +12933,66 @@ __cold static int mdbx_handle_env_pathname(MDBX_handle_env_pathname *ctx,
}
#endif
static const char dxb_name[] = MDBX_DATANAME;
static const size_t dxb_name_len = sizeof(dxb_name) - 1;
static const char lck_name[] = MDBX_LOCKNAME;
static const char lock_suffix[] = MDBX_LOCK_SUFFIX;
static const pathchar_t dxb_name[] = MDBX_DATANAME;
static const pathchar_t lck_name[] = MDBX_LOCKNAME;
static const pathchar_t lock_suffix[] = MDBX_LOCK_SUFFIX;
ctx->ent_len = strlen(pathname);
if ((*flags & MDBX_NOSUBDIR) && ctx->ent_len >= dxb_name_len &&
!memcmp(dxb_name, pathname + ctx->ent_len - dxb_name_len, dxb_name_len)) {
#if defined(_WIN32) || defined(_WIN64)
assert(dxb_name[0] == '\\' && lck_name[0] == '\\');
const size_t pathname_len = wcslen(pathname);
#else
assert(dxb_name[0] == '/' && lck_name[0] == '/');
const size_t pathname_len = strlen(pathname);
#endif
assert(lock_suffix[0] != '\\' && lock_suffix[0] != '/');
ctx->ent_len = pathname_len;
static const size_t dxb_name_len = ARRAY_LENGTH(dxb_name) - 1;
if ((*flags & MDBX_NOSUBDIR) && ctx->ent_len > dxb_name_len &&
path_equal(pathname + ctx->ent_len - dxb_name_len, dxb_name,
dxb_name_len)) {
*flags -= MDBX_NOSUBDIR;
ctx->ent_len -= dxb_name_len;
}
const size_t bytes_needed =
ctx->ent_len * 2 + ((*flags & MDBX_NOSUBDIR)
? sizeof(lock_suffix) + 1
: sizeof(lck_name) + sizeof(dxb_name));
sizeof(pathchar_t) * ctx->ent_len * 2 +
((*flags & MDBX_NOSUBDIR) ? sizeof(lock_suffix) + sizeof(pathchar_t)
: sizeof(lck_name) + sizeof(dxb_name));
ctx->buffer_for_free = mdbx_malloc(bytes_needed);
if (!ctx->buffer_for_free)
return MDBX_ENOMEM;
ctx->lck = ctx->buffer_for_free;
ctx->dxb = ctx->buffer_for_free;
ctx->lck = ctx->dxb + ctx->ent_len + 1;
memcpy(ctx->dxb, pathname, sizeof(pathchar_t) * (ctx->ent_len + 1));
if (*flags & MDBX_NOSUBDIR) {
ctx->dxb = ctx->lck + ctx->ent_len + sizeof(lock_suffix);
sprintf(ctx->lck, "%s%s", pathname, lock_suffix);
strcpy(ctx->dxb, pathname);
memcpy(ctx->lck + ctx->ent_len, lock_suffix, sizeof(lock_suffix));
} else {
ctx->dxb = ctx->lck + ctx->ent_len + sizeof(lck_name);
sprintf(ctx->lck, "%.*s%s", (int)ctx->ent_len, pathname, lck_name);
sprintf(ctx->dxb, "%.*s%s", (int)ctx->ent_len, pathname, dxb_name);
ctx->lck += dxb_name_len;
memcpy(ctx->lck + ctx->ent_len, lck_name, sizeof(lck_name));
memcpy(ctx->dxb + ctx->ent_len, dxb_name, sizeof(dxb_name));
}
memcpy(ctx->lck, pathname, sizeof(pathchar_t) * ctx->ent_len);
return MDBX_SUCCESS;
}
__cold int mdbx_env_delete(const char *pathname, MDBX_env_delete_mode_t mode) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
return mdbx_env_deleteW(pathnameW, mode);
}
__cold int mdbx_env_deleteW(const wchar_t *pathname,
MDBX_env_delete_mode_t mode) {
#endif /* Windows */
switch (mode) {
default:
return MDBX_EINVAL;
@ -12959,7 +13012,7 @@ __cold int mdbx_env_delete(const char *pathname, MDBX_env_delete_mode_t mode) {
(mode == MDBX_ENV_ENSURE_UNUSED) ? MDBX_EXCLUSIVE : MDBX_ENV_DEFAULTS;
dummy_env->me_os_psize = (unsigned)mdbx_syspagesize();
dummy_env->me_psize = (unsigned)mdbx_default_pagesize();
dummy_env->me_pathname = (char *)pathname;
dummy_env->me_pathname = (pathchar_t *)pathname;
MDBX_handle_env_pathname env_pathname;
STATIC_ASSERT(sizeof(dummy_env->me_flags) == sizeof(MDBX_env_flags_t));
@ -13021,6 +13074,21 @@ __cold int mdbx_env_delete(const char *pathname, MDBX_env_delete_mode_t mode) {
__cold int mdbx_env_open(MDBX_env *env, const char *pathname,
MDBX_env_flags_t flags, mdbx_mode_t mode) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
return mdbx_env_openW(env, pathnameW, flags, mode);
}
__cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname,
MDBX_env_flags_t flags, mdbx_mode_t mode) {
#endif /* Windows */
int rc = check_env(env, false);
if (unlikely(rc != MDBX_SUCCESS))
return rc;
@ -13066,7 +13134,7 @@ __cold int mdbx_env_open(MDBX_env *env, const char *pathname,
goto bailout;
env->me_flags = (flags & ~MDBX_FATAL_ERROR) | MDBX_ENV_ACTIVE;
env->me_pathname = mdbx_calloc(env_pathname.ent_len + 1, 1);
env->me_pathname = mdbx_calloc(env_pathname.ent_len + 1, sizeof(pathchar_t));
env->me_dbxs = mdbx_calloc(env->me_maxdbs, sizeof(MDBX_dbx));
env->me_dbflags = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbflags[0]));
env->me_dbiseqs = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbiseqs[0]));
@ -13075,7 +13143,8 @@ __cold int mdbx_env_open(MDBX_env *env, const char *pathname,
rc = MDBX_ENOMEM;
goto bailout;
}
memcpy(env->me_pathname, env_pathname.dxb, env_pathname.ent_len);
memcpy(env->me_pathname, env_pathname.dxb,
env_pathname.ent_len * sizeof(pathchar_t));
env->me_dbxs[FREE_DBI].md_cmp = cmp_int_align4; /* aligned MDBX_INTEGERKEY */
env->me_dbxs[FREE_DBI].md_dcmp = cmp_lenfast;
@ -19911,6 +19980,21 @@ __cold int mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
__cold int mdbx_env_copy(MDBX_env *env, const char *dest_path,
MDBX_copy_flags_t flags) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, dest_path, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const dest_pathW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(dest_pathW, dest_path, wlen + 1))
return ERROR_INVALID_NAME;
return mdbx_env_copyW(env, dest_pathW, flags);
}
LIBMDBX_API int mdbx_env_copyW(MDBX_env *env, const wchar_t *dest_path,
MDBX_copy_flags_t flags) {
#endif /* Windows */
int rc = check_env(env, true);
if (unlikely(rc != MDBX_SUCCESS))
return rc;
@ -20049,6 +20133,7 @@ __cold int mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func) {
#endif
}
#if !(defined(_WIN32) || defined(_WIN64))
__cold int mdbx_env_get_path(const MDBX_env *env, const char **arg) {
int rc = check_env(env, true);
if (unlikely(rc != MDBX_SUCCESS))
@ -20060,6 +20145,19 @@ __cold int mdbx_env_get_path(const MDBX_env *env, const char **arg) {
*arg = env->me_pathname;
return MDBX_SUCCESS;
}
#else
__cold int mdbx_env_get_pathW(const MDBX_env *env, const wchar_t **arg) {
int rc = check_env(env, true);
if (unlikely(rc != MDBX_SUCCESS))
return rc;
if (unlikely(!arg))
return MDBX_EINVAL;
*arg = env->me_pathname;
return MDBX_SUCCESS;
}
#endif /* Windows */
__cold int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *arg) {
int rc = check_env(env, true);

View File

@ -1143,7 +1143,7 @@ struct MDBX_env {
MDBX_dbi me_maxdbs; /* size of the DB table */
uint32_t me_pid; /* process ID of this env */
mdbx_thread_key_t me_txkey; /* thread-key for readers */
char *me_pathname; /* path to the DB files */
pathchar_t *me_pathname; /* path to the DB files */
void *me_pbuf; /* scratch area for DUPSORT put() */
MDBX_txn *me_txn0; /* preallocated write transaction */

View File

@ -201,64 +201,6 @@ __cold bug::~bug() noexcept {}
#endif /* Unused*/
//------------------------------------------------------------------------------
template <typename PATH> struct path_to_pchar {
const std::string str;
path_to_pchar(const PATH &path) : str(path.generic_string()) {}
operator const char *() const { return str.c_str(); }
};
template <typename PATH>
MDBX_MAYBE_UNUSED PATH pchar_to_path(const char *c_str) {
return PATH(c_str);
}
#if defined(_WIN32) || defined(_WIN64)
#ifndef WC_ERR_INVALID_CHARS
static const DWORD WC_ERR_INVALID_CHARS =
(6 /* Windows Vista */ <= /* MajorVersion */ LOBYTE(LOWORD(GetVersion())))
? 0x00000080
: 0;
#endif /* WC_ERR_INVALID_CHARS */
template <> struct path_to_pchar<std::wstring> {
std::string str;
path_to_pchar(const std::wstring &path) {
if (!path.empty()) {
const int chars =
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, path.data(),
int(path.size()), nullptr, 0, nullptr, nullptr);
if (chars == 0)
mdbx::error::throw_exception(GetLastError());
str.append(chars, '\0');
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, path.data(),
int(path.size()), const_cast<char *>(str.data()),
chars, nullptr, nullptr);
}
}
operator const char *() const { return str.c_str(); }
};
template <>
MDBX_MAYBE_UNUSED std::wstring pchar_to_path<std::wstring>(const char *c_str) {
std::wstring wstr;
if (c_str && *c_str) {
const int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, c_str,
int(strlen(c_str)), nullptr, 0);
if (chars == 0)
mdbx::error::throw_exception(GetLastError());
wstr.append(chars, '\0');
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, c_str,
int(strlen(c_str)), const_cast<wchar_t *>(wstr.data()),
chars);
}
return wstr;
}
#endif /* Windows */
} // namespace
//------------------------------------------------------------------------------
@ -1239,29 +1181,20 @@ bool env::is_pristine() const {
bool env::is_empty() const { return get_stat().ms_leaf_pages == 0; }
#ifdef MDBX_STD_FILESYSTEM_PATH
env &env::copy(const MDBX_STD_FILESYSTEM_PATH &destination, bool compactify,
#if defined(_WIN32) || defined(_WIN64)
env &env::copy(const wchar_t *destination, bool compactify,
bool force_dynamic_size) {
const path_to_pchar<MDBX_STD_FILESYSTEM_PATH> utf8(destination);
error::success_or_throw(
::mdbx_env_copy(handle_, utf8,
(compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
(force_dynamic_size ? MDBX_CP_FORCE_DYNAMIC_SIZE
: MDBX_CP_DEFAULTS)));
::mdbx_env_copyW(handle_, destination,
(compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
(force_dynamic_size ? MDBX_CP_FORCE_DYNAMIC_SIZE
: MDBX_CP_DEFAULTS)));
return *this;
}
#endif /* MDBX_STD_FILESYSTEM_PATH */
#if defined(_WIN32) || defined(_WIN64)
env &env::copy(const ::std::wstring &destination, bool compactify,
bool force_dynamic_size) {
const path_to_pchar<::std::wstring> utf8(destination);
error::success_or_throw(
::mdbx_env_copy(handle_, utf8,
(compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
(force_dynamic_size ? MDBX_CP_FORCE_DYNAMIC_SIZE
: MDBX_CP_DEFAULTS)));
return *this;
return copy(destination.c_str(), compactify, force_dynamic_size);
}
#endif /* Windows */
@ -1289,26 +1222,33 @@ env &env::copy(filehandle fd, bool compactify, bool force_dynamic_size) {
return *this;
}
path env::get_path() const {
const char *c_str;
error::success_or_throw(::mdbx_env_get_path(handle_, &c_str));
return pchar_to_path<path>(c_str);
}
#ifdef MDBX_STD_FILESYSTEM_PATH
bool env::remove(const MDBX_STD_FILESYSTEM_PATH &pathname,
const remove_mode mode) {
const path_to_pchar<MDBX_STD_FILESYSTEM_PATH> utf8(pathname);
return error::boolean_or_throw(
::mdbx_env_delete(utf8, MDBX_env_delete_mode_t(mode)));
env &env::copy(const MDBX_STD_FILESYSTEM_PATH &destination, bool compactify,
bool force_dynamic_size) {
return copy(destination.native(), compactify, force_dynamic_size);
}
#endif /* MDBX_STD_FILESYSTEM_PATH */
path env::get_path() const {
#if defined(_WIN32) || defined(_WIN64)
bool env::remove(const ::std::wstring &pathname, const remove_mode mode) {
const path_to_pchar<::std::wstring> utf8(pathname);
const wchar_t *c_wstr;
error::success_or_throw(::mdbx_env_get_pathW(handle_, &c_wstr));
return path(c_wstr);
#else
const char *c_str;
error::success_or_throw(::mdbx_env_get_path(handle_, &c_str));
return path(c_str);
#endif
}
#if defined(_WIN32) || defined(_WIN64)
bool env::remove(const wchar_t *pathname, const remove_mode mode) {
return error::boolean_or_throw(
::mdbx_env_delete(utf8, MDBX_env_delete_mode_t(mode)));
::mdbx_env_deleteW(pathname, MDBX_env_delete_mode_t(mode)));
}
bool env::remove(const ::std::wstring &pathname, const remove_mode mode) {
return remove(pathname.c_str(), mode);
}
#endif /* Windows */
@ -1321,6 +1261,13 @@ bool env::remove(const ::std::string &pathname, const remove_mode mode) {
return remove(pathname.c_str(), mode);
}
#ifdef MDBX_STD_FILESYSTEM_PATH
bool env::remove(const MDBX_STD_FILESYSTEM_PATH &pathname,
const remove_mode mode) {
return remove(pathname.native(), mode);
}
#endif /* MDBX_STD_FILESYSTEM_PATH */
//------------------------------------------------------------------------------
static inline MDBX_env *create_env() {
@ -1357,66 +1304,42 @@ __cold void env_managed::setup(unsigned max_maps, unsigned max_readers) {
error::success_or_throw(::mdbx_env_set_maxdbs(handle_, max_maps));
}
#ifdef MDBX_STD_FILESYSTEM_PATH
__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname,
const operate_parameters &op, bool accede)
: env_managed(create_env()) {
setup(op.max_maps, op.max_readers);
const path_to_pchar<MDBX_STD_FILESYSTEM_PATH> utf8(pathname);
error::success_or_throw(
::mdbx_env_open(handle_, utf8, op.make_flags(accede), 0));
if (op.options.nested_write_transactions &&
!get_options().nested_write_transactions)
MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE);
}
__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname,
const env_managed::create_parameters &cp,
const env::operate_parameters &op, bool accede)
: env_managed(create_env()) {
setup(op.max_maps, op.max_readers);
const path_to_pchar<MDBX_STD_FILESYSTEM_PATH> utf8(pathname);
set_geometry(cp.geometry);
error::success_or_throw(
::mdbx_env_open(handle_, utf8, op.make_flags(accede, cp.use_subdirectory),
cp.file_mode_bits));
if (op.options.nested_write_transactions &&
!get_options().nested_write_transactions)
MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE);
}
#endif /* MDBX_STD_FILESYSTEM_PATH */
#if defined(_WIN32) || defined(_WIN64)
__cold env_managed::env_managed(const ::std::wstring &pathname,
__cold env_managed::env_managed(const wchar_t *pathname,
const operate_parameters &op, bool accede)
: env_managed(create_env()) {
setup(op.max_maps, op.max_readers);
const path_to_pchar<::std::wstring> utf8(pathname);
error::success_or_throw(
::mdbx_env_open(handle_, utf8, op.make_flags(accede), 0));
::mdbx_env_openW(handle_, pathname, op.make_flags(accede), 0));
if (op.options.nested_write_transactions &&
!get_options().nested_write_transactions)
MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE);
}
__cold env_managed::env_managed(const ::std::wstring &pathname,
__cold env_managed::env_managed(const wchar_t *pathname,
const env_managed::create_parameters &cp,
const env::operate_parameters &op, bool accede)
: env_managed(create_env()) {
setup(op.max_maps, op.max_readers);
const path_to_pchar<::std::wstring> utf8(pathname);
set_geometry(cp.geometry);
error::success_or_throw(
::mdbx_env_open(handle_, utf8, op.make_flags(accede, cp.use_subdirectory),
cp.file_mode_bits));
error::success_or_throw(::mdbx_env_openW(
handle_, pathname, op.make_flags(accede, cp.use_subdirectory),
cp.file_mode_bits));
if (op.options.nested_write_transactions &&
!get_options().nested_write_transactions)
MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE);
}
__cold env_managed::env_managed(const ::std::wstring &pathname,
const operate_parameters &op, bool accede)
: env_managed(pathname.c_str(), op, accede) {}
__cold env_managed::env_managed(const ::std::wstring &pathname,
const env_managed::create_parameters &cp,
const env::operate_parameters &op, bool accede)
: env_managed(pathname.c_str(), cp, op, accede) {}
#endif /* Windows */
__cold env_managed::env_managed(const char *pathname,
@ -1455,6 +1378,17 @@ __cold env_managed::env_managed(const ::std::string &pathname,
const env::operate_parameters &op, bool accede)
: env_managed(pathname.c_str(), cp, op, accede) {}
#ifdef MDBX_STD_FILESYSTEM_PATH
__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname,
const operate_parameters &op, bool accede)
: env_managed(pathname.native(), op, accede) {}
__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname,
const env_managed::create_parameters &cp,
const env::operate_parameters &op, bool accede)
: env_managed(pathname.native(), cp, op, accede) {}
#endif /* MDBX_STD_FILESYSTEM_PATH */
//------------------------------------------------------------------------------
txn_managed txn::start_nested() {

View File

@ -518,15 +518,9 @@ MDBX_INTERNAL_FUNC int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex) {
/*----------------------------------------------------------------------------*/
MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname) {
MDBX_INTERNAL_FUNC int mdbx_removefile(const pathchar_t *pathname) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
return DeleteFileW(pathnameW) ? MDBX_SUCCESS : (int)GetLastError();
return DeleteFileW(pathname) ? MDBX_SUCCESS : (int)GetLastError();
#else
return unlink(pathname) ? errno : MDBX_SUCCESS;
#endif
@ -536,34 +530,22 @@ MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname) {
static bool is_valid_fd(int fd) { return !(isatty(fd) < 0 && errno == EBADF); }
#endif /*! Windows */
MDBX_INTERNAL_FUNC int mdbx_removedirectory(const char *pathname) {
MDBX_INTERNAL_FUNC int mdbx_removedirectory(const pathchar_t *pathname) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
return RemoveDirectoryW(pathnameW) ? MDBX_SUCCESS : (int)GetLastError();
return RemoveDirectoryW(pathname) ? MDBX_SUCCESS : (int)GetLastError();
#else
return rmdir(pathname) ? errno : MDBX_SUCCESS;
#endif
}
MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
const MDBX_env *env, const char *pathname,
const MDBX_env *env,
const pathchar_t *pathname,
mdbx_filehandle_t *fd,
mdbx_mode_t unix_mode_bits) {
*fd = INVALID_HANDLE_VALUE;
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
DWORD CreationDisposition = unix_mode_bits ? OPEN_ALWAYS : OPEN_EXISTING;
DWORD FlagsAndAttributes =
FILE_FLAG_POSIX_SEMANTICS | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
@ -608,12 +590,12 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
break;
}
*fd = CreateFileW(pathnameW, DesiredAccess, ShareMode, NULL,
*fd = CreateFileW(pathname, DesiredAccess, ShareMode, NULL,
CreationDisposition, FlagsAndAttributes, NULL);
if (*fd == INVALID_HANDLE_VALUE) {
int err = (int)GetLastError();
if (err == ERROR_ACCESS_DENIED && purpose == MDBX_OPEN_LCK) {
if (GetFileAttributesW(pathnameW) == INVALID_FILE_ATTRIBUTES &&
if (GetFileAttributesW(pathname) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND)
err = ERROR_FILE_NOT_FOUND;
}
@ -632,7 +614,7 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_COMPRESSED);
if (AttributesDiff)
(void)SetFileAttributesW(pathnameW, info.dwFileAttributes ^ AttributesDiff);
(void)SetFileAttributesW(pathname, info.dwFileAttributes ^ AttributesDiff);
#else
int flags = unix_mode_bits ? O_CREAT : 0;
@ -1089,7 +1071,8 @@ MDBX_INTERNAL_FUNC int mdbx_msync(mdbx_mmap_t *map, size_t offset,
}
MDBX_INTERNAL_FUNC int mdbx_check_fs_rdonly(mdbx_filehandle_t handle,
const char *pathname, int err) {
const pathchar_t *pathname,
int err) {
#if defined(_WIN32) || defined(_WIN64)
(void)pathname;
(void)err;

View File

@ -224,6 +224,12 @@ mdbx_syspagesize(void) {
#endif
}
#if defined(_WIN32) || defined(_WIN64)
typedef wchar_t pathchar_t;
#else
typedef char pathchar_t;
#endif
typedef struct mdbx_mmap_param {
union {
void *address;
@ -365,12 +371,13 @@ enum mdbx_openfile_purpose {
};
MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
const MDBX_env *env, const char *pathname,
const MDBX_env *env,
const pathchar_t *pathname,
mdbx_filehandle_t *fd,
mdbx_mode_t unix_mode_bits);
MDBX_INTERNAL_FUNC int mdbx_closefile(mdbx_filehandle_t fd);
MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname);
MDBX_INTERNAL_FUNC int mdbx_removedirectory(const char *pathname);
MDBX_INTERNAL_FUNC int mdbx_removefile(const pathchar_t *pathname);
MDBX_INTERNAL_FUNC int mdbx_removedirectory(const pathchar_t *pathname);
MDBX_INTERNAL_FUNC int mdbx_is_pipe(mdbx_filehandle_t fd);
MDBX_INTERNAL_FUNC int mdbx_lockfile(mdbx_filehandle_t fd, bool wait);
@ -398,7 +405,8 @@ MDBX_INTERNAL_FUNC int mdbx_msync(mdbx_mmap_t *map, size_t offset,
size_t length,
enum mdbx_syncmode_bits mode_bits);
MDBX_INTERNAL_FUNC int mdbx_check_fs_rdonly(mdbx_filehandle_t handle,
const char *pathname, int err);
const pathchar_t *pathname,
int err);
MDBX_MAYBE_UNUSED static __inline uint32_t mdbx_getpid(void) {
STATIC_ASSERT(sizeof(mdbx_pid_t) <= sizeof(uint32_t));