mirror of
https://github.com/isar/libmdbx.git
synced 2024-12-30 01:14:12 +08:00
mdbx: native wchar_t
pathname for Windows.
This commit is contained in:
parent
98c53555ab
commit
2ff8d3c4f2
35
mdbx.h
35
mdbx.h
@ -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.
|
||||
*
|
||||
|
8
mdbx.h++
8
mdbx.h++
@ -3225,6 +3225,8 @@ public:
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(DOXYGEN)
|
||||
env ©(const ::std::wstring &destination, bool compactify,
|
||||
bool force_dynamic_size = false);
|
||||
env ©(const wchar_t *destination, bool compactify,
|
||||
bool force_dynamic_size = false);
|
||||
#endif /* Windows */
|
||||
env ©(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);
|
||||
|
174
src/core.c
174
src/core.c
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
188
src/mdbx.c++
188
src/mdbx.c++
@ -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() {
|
||||
|
39
src/osal.c
39
src/osal.c
@ -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;
|
||||
|
16
src/osal.h
16
src/osal.h
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user