summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin15/mir_full.sln22
-rw-r--r--bin15/miranda32.sln22
-rw-r--r--libs/libmdbx/src/src/osal.h4
-rw-r--r--libs/libmdbx/src/src/tools/wingetopt.c2
-rw-r--r--tools/mdbx_dump/mdbx_dump.vcxproj48
-rw-r--r--tools/mdbx_dump/mdbx_dump.vcxproj.filters17
-rw-r--r--tools/mdbx_dump/src/mdbx_dump.cc336
-rw-r--r--tools/mdbx_dump/src/stdafx.cxx20
-rw-r--r--tools/mdbx_dump/src/stdafx.h24
-rw-r--r--tools/mdbx_load/mdbx_load.vcxproj46
-rw-r--r--tools/mdbx_load/mdbx_load.vcxproj.filters17
-rw-r--r--tools/mdbx_load/src/mdbx_load.cc520
-rw-r--r--tools/mdbx_load/src/stdafx.cxx20
-rw-r--r--tools/mdbx_load/src/stdafx.h78
14 files changed, 1173 insertions, 3 deletions
diff --git a/bin15/mir_full.sln b/bin15/mir_full.sln
index c76729cd40..dfbace0efb 100644
--- a/bin15/mir_full.sln
+++ b/bin15/mir_full.sln
@@ -449,6 +449,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProxySwitch", "..\plugins\P
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmdbx", "..\libs\libmdbx\libmdbx.vcxproj", "{6D19209B-ECE7-4B9C-941C-0AA2B484F199}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_dump", "..\tools\mdbx_dump\mdbx_dump.vcxproj", "{EE383404-7976-4E87-BD13-A9B7B47C0C10}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_load", "..\tools\mdbx_load\mdbx_load.vcxproj", "{63BA600E-86BF-4502-9EF0-8C090292E161}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -2015,6 +2019,22 @@ Global
{6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|Win32.Build.0 = Release|Win32
{6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x64.ActiveCfg = Release|x64
{6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x64.Build.0 = Release|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|Win32.Build.0 = Debug|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|x64.ActiveCfg = Debug|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|x64.Build.0 = Debug|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|Win32.ActiveCfg = Release|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|Win32.Build.0 = Release|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|x64.ActiveCfg = Release|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|x64.Build.0 = Release|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|Win32.ActiveCfg = Debug|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|Win32.Build.0 = Debug|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|x64.ActiveCfg = Debug|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|x64.Build.0 = Debug|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|Win32.ActiveCfg = Release|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|Win32.Build.0 = Release|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|x64.ActiveCfg = Release|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2141,6 +2161,8 @@ Global
{5D14CFF3-0D17-4528-99EA-DE9DCA47CC2E} = {37EDFBEA-8446-4BF3-9F2E-655908CDFB62}
{7DC23E4E-2448-4811-AABD-F5D069F6E74A} = {F9C41695-3353-4564-A154-58106829B19C}
{6D19209B-ECE7-4B9C-941C-0AA2B484F199} = {37EDFBEA-8446-4BF3-9F2E-655908CDFB62}
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10} = {F13387B0-1C74-48EC-9AEC-65E3B9DE29E4}
+ {63BA600E-86BF-4502-9EF0-8C090292E161} = {F13387B0-1C74-48EC-9AEC-65E3B9DE29E4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {29A0C2A8-07A4-4A8B-8BED-8F7D024013D6}
diff --git a/bin15/miranda32.sln b/bin15/miranda32.sln
index f98587fce8..568ab259e5 100644
--- a/bin15/miranda32.sln
+++ b/bin15/miranda32.sln
@@ -143,6 +143,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmdbx", "..\libs\libmdbx\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlite3", "..\libs\sqlite3\sqlite3.vcxproj", "{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_dump", "..\tools\mdbx_dump\mdbx_dump.vcxproj", "{EE383404-7976-4E87-BD13-A9B7B47C0C10}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_load", "..\tools\mdbx_load\mdbx_load.vcxproj", "{63BA600E-86BF-4502-9EF0-8C090292E161}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -527,6 +531,22 @@ Global
{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}.Release|Win32.Build.0 = Release|Win32
{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}.Release|x64.ActiveCfg = Release|x64
{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}.Release|x64.Build.0 = Release|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|Win32.Build.0 = Debug|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|x64.ActiveCfg = Debug|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Debug|x64.Build.0 = Debug|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|Win32.ActiveCfg = Release|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|Win32.Build.0 = Release|Win32
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|x64.ActiveCfg = Release|x64
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10}.Release|x64.Build.0 = Release|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|Win32.ActiveCfg = Debug|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|Win32.Build.0 = Debug|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|x64.ActiveCfg = Debug|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Debug|x64.Build.0 = Debug|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|Win32.ActiveCfg = Release|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|Win32.Build.0 = Release|Win32
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|x64.ActiveCfg = Release|x64
+ {63BA600E-86BF-4502-9EF0-8C090292E161}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -578,6 +598,8 @@ Global
{5D14CFF3-0D17-4528-99EA-DE9DCA47CC2E} = {52282CDE-49DF-4662-B582-CCF971A9FEC2}
{6D19209B-ECE7-4B9C-941C-0AA2B484F199} = {52282CDE-49DF-4662-B582-CCF971A9FEC2}
{0C02E395-E73F-47E3-8B95-B7924C0C7A6A} = {52282CDE-49DF-4662-B582-CCF971A9FEC2}
+ {EE383404-7976-4E87-BD13-A9B7B47C0C10} = {52282CDE-49DF-4662-B582-CCF971A9FEC2}
+ {63BA600E-86BF-4502-9EF0-8C090292E161} = {52282CDE-49DF-4662-B582-CCF971A9FEC2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5A4CD630-DD83-4096-AA4D-7A141E43E853}
diff --git a/libs/libmdbx/src/src/osal.h b/libs/libmdbx/src/src/osal.h
index a1feb998d2..065128103e 100644
--- a/libs/libmdbx/src/src/osal.h
+++ b/libs/libmdbx/src/src/osal.h
@@ -652,7 +652,7 @@ static __inline uint32_t mdbx_atomic_add32(volatile uint32_t *p, uint32_t v) {
return __sync_fetch_and_add(p, v);
#else
#ifdef _MSC_VER
- return _InterlockedExchangeAdd(p, v);
+ return _InterlockedExchangeAdd((volatile long *)p, v);
#endif
#ifdef __APPLE__
return OSAtomicAdd32(v, (volatile int32_t *)p);
@@ -692,7 +692,7 @@ static __inline bool mdbx_atomic_compare_and_swap32(volatile uint32_t *p,
return __sync_bool_compare_and_swap(p, c, v);
#else
#ifdef _MSC_VER
- return c == _InterlockedCompareExchange(p, v, c);
+ return c == _InterlockedCompareExchange((volatile long*)p, v, c);
#endif
#ifdef __APPLE__
return c == OSAtomicCompareAndSwap32Barrier(c, v, (volatile int32_t *)p);
diff --git a/libs/libmdbx/src/src/tools/wingetopt.c b/libs/libmdbx/src/src/tools/wingetopt.c
index 1dd0d069fb..6ed6dc3cc8 100644
--- a/libs/libmdbx/src/src/tools/wingetopt.c
+++ b/libs/libmdbx/src/src/tools/wingetopt.c
@@ -66,7 +66,7 @@ int getopt(int argc, char *const argv[], const char *opts) {
}
}
optopt = c = argv[optind][sp];
- if (c == ':' || (cp = strchr(opts, c)) == NULL) {
+ if (c == ':' || (cp = (char *)strchr(opts, c)) == NULL) {
ERR(": illegal option -- ", c);
if (argv[optind][++sp] == '\0') {
optind++;
diff --git a/tools/mdbx_dump/mdbx_dump.vcxproj b/tools/mdbx_dump/mdbx_dump.vcxproj
new file mode 100644
index 0000000000..693194c994
--- /dev/null
+++ b/tools/mdbx_dump/mdbx_dump.vcxproj
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{EE383404-7976-4E87-BD13-A9B7B47C0C10}</ProjectGuid>
+ <ProjectName>mdbx_dump</ProjectName>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\app.props" />
+ </ImportGroup>
+ <ItemGroup>
+ <ClCompile Include="src\*.cc">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libs\libmdbx\libmdbx.vcxproj">
+ <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemDefinitionGroup>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <DelayLoadDLLs Condition="'$(Configuration)'=='Debug'">libmdbx.mir;ucrtbased.dll;vcruntime140d.dll</DelayLoadDLLs>
+ <DelayLoadDLLs Condition="'$(Configuration)'=='Release'">libmdbx.mir;ucrtbase.dll;api-ms-win-crt-string-l1-1-0.dll;api-ms-win-crt-heap-l1-1-0.dll;api-ms-win-crt-locale-l1-1-0.dll;api-ms-win-crt-math-l1-1-0.dll;api-ms-win-crt-runtime-l1-1-0.dll;api-ms-win-crt-stdio-l1-1-0.dll;VCRUNTIME140.dll</DelayLoadDLLs>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+</Project> \ No newline at end of file
diff --git a/tools/mdbx_dump/mdbx_dump.vcxproj.filters b/tools/mdbx_dump/mdbx_dump.vcxproj.filters
new file mode 100644
index 0000000000..b158554128
--- /dev/null
+++ b/tools/mdbx_dump/mdbx_dump.vcxproj.filters
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
+ <ItemGroup>
+ <ClCompile Include="src\stdafx.cxx">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\*.cc">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\*.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/tools/mdbx_dump/src/mdbx_dump.cc b/tools/mdbx_dump/src/mdbx_dump.cc
new file mode 100644
index 0000000000..989c7a0d24
--- /dev/null
+++ b/tools/mdbx_dump/src/mdbx_dump.cc
@@ -0,0 +1,336 @@
+/* mdbx_dump.c - memory-mapped database dump tool */
+
+/*
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>. */
+
+#ifdef _MSC_VER
+#if _MSC_VER > 1800
+#pragma warning(disable : 4464) /* relative include path contains '..' */
+#endif
+#pragma warning(disable : 4996) /* The POSIX name is deprecated... */
+#endif /* _MSC_VER (warnings) */
+
+#include "../../libs/libmdbx/src/src/bits.h"
+#include <ctype.h>
+
+#define PRINT 1
+static int mode;
+
+typedef struct flagbit {
+ int bit;
+ char *name;
+} flagbit;
+
+flagbit dbflags[] = {{MDBX_REVERSEKEY, "reversekey"},
+ {MDBX_DUPSORT, "dupsort"},
+ {MDBX_INTEGERKEY, "integerkey"},
+ {MDBX_DUPFIXED, "dupfixed"},
+ {MDBX_INTEGERDUP, "integerdup"},
+ {MDBX_REVERSEDUP, "reversedup"},
+ {0, NULL}};
+
+#if defined(_WIN32) || defined(_WIN64)
+#include "../../libs/libmdbx/src/src/tools/wingetopt.h"
+#include "../../libs/libmdbx/src/src/tools/wingetopt.c"
+
+static volatile BOOL user_break;
+static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
+ (void)dwCtrlType;
+ user_break = true;
+ return true;
+}
+
+#else /* WINDOWS */
+
+static volatile sig_atomic_t user_break;
+static void signal_handler(int sig) {
+ (void)sig;
+ user_break = 1;
+}
+
+#endif /* !WINDOWS */
+
+static const char hexc[] = "0123456789abcdef";
+
+static void dumpbyte(unsigned char c) {
+ putchar(hexc[c >> 4]);
+ putchar(hexc[c & 0xf]);
+}
+
+static void text(MDBX_val *v) {
+ unsigned char *c, *end;
+
+ putchar(' ');
+ c = (BYTE*)v->iov_base;
+ end = c + v->iov_len;
+ while (c < end) {
+ if (isprint(*c) && *c != '\\') {
+ putchar(*c);
+ } else {
+ putchar('\\');
+ dumpbyte(*c);
+ }
+ c++;
+ }
+ putchar('\n');
+}
+
+static void dumpval(MDBX_val *v) {
+ unsigned char *c, *end;
+
+ putchar(' ');
+ c = (BYTE*)v->iov_base;
+ end = c + v->iov_len;
+ while (c < end) {
+ dumpbyte(*c++);
+ }
+ putchar('\n');
+}
+
+/* Dump in BDB-compatible format */
+static int dumpit(MDBX_txn *txn, MDBX_dbi dbi, char *name) {
+ MDBX_cursor *mc;
+ MDBX_stat ms;
+ MDBX_val key, data;
+ MDBX_envinfo info;
+ unsigned int flags;
+ int rc, i;
+
+ rc = mdbx_dbi_flags(txn, dbi, &flags);
+ if (rc)
+ return rc;
+
+ rc = mdbx_dbi_stat(txn, dbi, &ms, sizeof(ms));
+ if (rc)
+ return rc;
+
+ rc = mdbx_env_info(mdbx_txn_env(txn), &info, sizeof(info));
+ if (rc)
+ return rc;
+
+ printf("VERSION=3\n");
+ printf("format=%s\n", mode & PRINT ? "print" : "bytevalue");
+ if (name)
+ printf("database=%s\n", name);
+ printf("type=btree\n");
+ printf("mapsize=%" PRIu64 "\n", info.mi_mapsize);
+ printf("maxreaders=%u\n", info.mi_maxreaders);
+
+ for (i = 0; dbflags[i].bit; i++)
+ if (flags & dbflags[i].bit)
+ printf("%s=1\n", dbflags[i].name);
+
+ printf("db_pagesize=%d\n", ms.ms_psize);
+ printf("HEADER=END\n");
+
+ rc = mdbx_cursor_open(txn, dbi, &mc);
+ if (rc)
+ return rc;
+
+ while ((rc = mdbx_cursor_get(mc, &key, &data, MDBX_NEXT)) == MDBX_SUCCESS) {
+ if (user_break) {
+ rc = MDBX_EINTR;
+ break;
+ }
+ if (mode & PRINT) {
+ text(&key);
+ text(&data);
+ } else {
+ dumpval(&key);
+ dumpval(&data);
+ }
+ }
+ printf("DATA=END\n");
+ if (rc == MDBX_NOTFOUND)
+ rc = MDBX_SUCCESS;
+
+ return rc;
+}
+
+static void usage(char *prog) {
+ fprintf(stderr,
+ "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n",
+ prog);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[]) {
+ int i, rc;
+ MDBX_env *env;
+ MDBX_txn *txn;
+ MDBX_dbi dbi;
+ char *prog = argv[0];
+ char *envname;
+ char *subname = NULL;
+ int alldbs = 0, envflags = 0, list = 0;
+
+ if (argc < 2) {
+ usage(prog);
+ }
+
+ /* -a: dump main DB and all subDBs
+ * -s: dump only the named subDB
+ * -n: use NOSUBDIR flag on env_open
+ * -p: use printable characters
+ * -f: write to file instead of stdout
+ * -V: print version and exit
+ * (default) dump only the main DB
+ */
+ while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) {
+ switch (i) {
+ case 'V':
+ //printf("%s (%s, build %s)\n", mdbx_version.git.describe, mdbx_version.git.datetime, mdbx_build.datetime);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'l':
+ list = 1;
+ /*FALLTHROUGH*/;
+ __fallthrough;
+ case 'a':
+ if (subname)
+ usage(prog);
+ alldbs++;
+ break;
+ case 'f':
+ if (freopen(optarg, "w", stdout) == NULL) {
+ fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'n':
+ envflags |= MDBX_NOSUBDIR;
+ break;
+ case 'p':
+ mode |= PRINT;
+ break;
+ case 's':
+ if (alldbs)
+ usage(prog);
+ subname = optarg;
+ break;
+ default:
+ usage(prog);
+ }
+ }
+
+ if (optind != argc - 1)
+ usage(prog);
+
+#if defined(_WIN32) || defined(_WIN64)
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
+#else
+#ifdef SIGPIPE
+ signal(SIGPIPE, signal_handler);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, signal_handler);
+#endif
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+#endif /* !WINDOWS */
+
+ envname = argv[optind];
+ rc = mdbx_env_create(&env);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ return EXIT_FAILURE;
+ }
+
+ if (alldbs || subname) {
+ mdbx_env_set_maxdbs(env, 2);
+ }
+
+ rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
+ if (rc) {
+ fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ rc = mdbx_dbi_open(txn, subname, 0, &dbi);
+ if (rc) {
+ fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ if (alldbs) {
+ MDBX_cursor *cursor;
+ MDBX_val key;
+ int count = 0;
+
+ rc = mdbx_cursor_open(txn, dbi, &cursor);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) {
+ if (user_break) {
+ rc = MDBX_EINTR;
+ break;
+ }
+ char *str;
+ MDBX_dbi db2;
+ if (memchr(key.iov_base, '\0', key.iov_len))
+ continue;
+ count++;
+ str = (char*)malloc(key.iov_len + 1);
+ memcpy(str, key.iov_base, key.iov_len);
+ str[key.iov_len] = '\0';
+ rc = mdbx_dbi_open(txn, str, 0, &db2);
+ if (rc == MDBX_SUCCESS) {
+ if (list) {
+ printf("%s\n", str);
+ list++;
+ } else {
+ rc = dumpit(txn, db2, str);
+ if (rc)
+ break;
+ }
+ mdbx_dbi_close(env, db2);
+ }
+ free(str);
+ if (rc)
+ continue;
+ }
+ mdbx_cursor_close(cursor);
+ if (!count) {
+ fprintf(stderr, "%s: %s does not contain multiple databases\n", prog,
+ envname);
+ rc = MDBX_NOTFOUND;
+ } else if (rc == MDBX_INCOMPATIBLE) {
+ /* LY: the record it not a named sub-db. */
+ rc = MDBX_SUCCESS;
+ }
+ } else {
+ rc = dumpit(txn, dbi, subname);
+ }
+ if (rc && rc != MDBX_NOTFOUND)
+ fprintf(stderr, "%s: %s: %s\n", prog, envname, mdbx_strerror(rc));
+
+ mdbx_dbi_close(env, dbi);
+txn_abort:
+ mdbx_txn_abort(txn);
+env_close:
+ mdbx_env_close(env);
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/tools/mdbx_dump/src/stdafx.cxx b/tools/mdbx_dump/src/stdafx.cxx
new file mode 100644
index 0000000000..813117c18e
--- /dev/null
+++ b/tools/mdbx_dump/src/stdafx.cxx
@@ -0,0 +1,20 @@
+/*
+Copyright (C) 2012-18 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+
+#include "..\..\build\appstub\appstub.cpp"
diff --git a/tools/mdbx_dump/src/stdafx.h b/tools/mdbx_dump/src/stdafx.h
new file mode 100644
index 0000000000..4b89e46ea8
--- /dev/null
+++ b/tools/mdbx_dump/src/stdafx.h
@@ -0,0 +1,24 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#include <stdio.h>
+#include <windows.h>
diff --git a/tools/mdbx_load/mdbx_load.vcxproj b/tools/mdbx_load/mdbx_load.vcxproj
new file mode 100644
index 0000000000..32031b8acb
--- /dev/null
+++ b/tools/mdbx_load/mdbx_load.vcxproj
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{63BA600E-86BF-4502-9EF0-8C090292E161}</ProjectGuid>
+ <ProjectName>mdbx_load</ProjectName>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\app.props" />
+ </ImportGroup>
+ <ItemGroup>
+ <ClCompile Include="src\*.cc"/>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libs\libmdbx\libmdbx.vcxproj">
+ <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemDefinitionGroup>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <DelayLoadDLLs Condition="'$(Configuration)'=='Debug'">libmdbx.mir;ucrtbased.dll;vcruntime140d.dll</DelayLoadDLLs>
+ <DelayLoadDLLs Condition="'$(Configuration)'=='Release'">libmdbx.mir;ucrtbase.dll;api-ms-win-crt-string-l1-1-0.dll;api-ms-win-crt-heap-l1-1-0.dll;api-ms-win-crt-locale-l1-1-0.dll;api-ms-win-crt-math-l1-1-0.dll;api-ms-win-crt-runtime-l1-1-0.dll;api-ms-win-crt-stdio-l1-1-0.dll;VCRUNTIME140.dll</DelayLoadDLLs>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+</Project> \ No newline at end of file
diff --git a/tools/mdbx_load/mdbx_load.vcxproj.filters b/tools/mdbx_load/mdbx_load.vcxproj.filters
new file mode 100644
index 0000000000..b158554128
--- /dev/null
+++ b/tools/mdbx_load/mdbx_load.vcxproj.filters
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
+ <ItemGroup>
+ <ClCompile Include="src\stdafx.cxx">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\*.cc">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\*.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/tools/mdbx_load/src/mdbx_load.cc b/tools/mdbx_load/src/mdbx_load.cc
new file mode 100644
index 0000000000..5f08504b70
--- /dev/null
+++ b/tools/mdbx_load/src/mdbx_load.cc
@@ -0,0 +1,520 @@
+/* mdbx_load.c - memory-mapped database load tool */
+
+/*
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>. */
+
+#include "stdafx.h"
+
+#ifdef _MSC_VER
+#if _MSC_VER > 1800
+#pragma warning(disable : 4464) /* relative include path contains '..' */
+#endif
+#pragma warning(disable : 4996) /* The POSIX name is deprecated... */
+#endif /* _MSC_VER (warnings) */
+
+#include <ctype.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+#include "../../libs/libmdbx/src/src/tools/wingetopt.h"
+#include "../../libs/libmdbx/src/src/tools/wingetopt.c"
+
+static volatile BOOL user_break;
+static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
+ (void)dwCtrlType;
+ user_break = true;
+ return true;
+}
+
+#else /* WINDOWS */
+
+static volatile sig_atomic_t user_break;
+static void signal_handler(int sig) {
+ (void)sig;
+ user_break = 1;
+}
+
+#endif /* !WINDOWS */
+
+#define PRINT 1
+#define NOHDR 2
+static int mode;
+
+static char *subname = NULL;
+static size_t lineno;
+static int version;
+
+static int dbi_flags;
+static char *prog;
+static int Eof;
+
+static MDBX_envinfo envinfo;
+static MDBX_val kbuf, dbuf;
+
+#define STRLENOF(s) (sizeof(s) - 1)
+
+typedef struct flagbit {
+ int bit;
+ char *name;
+ int len;
+} flagbit;
+
+#define S(s) s, STRLENOF(s)
+
+flagbit dbflags[] = {{MDBX_REVERSEKEY, S("reversekey")},
+ {MDBX_DUPSORT, S("dupsort")},
+ {MDBX_INTEGERKEY, S("integerkey")},
+ {MDBX_DUPFIXED, S("dupfixed")},
+ {MDBX_INTEGERDUP, S("integerdup")},
+ {MDBX_REVERSEDUP, S("reversedup")},
+ {0, NULL, 0}};
+
+static void readhdr(void) {
+ char *ptr;
+
+ dbi_flags = 0;
+ while (fgets((char *)dbuf.iov_base, (int)dbuf.iov_len, stdin) != NULL) {
+ lineno++;
+ if (!strncmp((char *)dbuf.iov_base, "db_pagesize=", STRLENOF("db_pagesize=")) ||
+ !strncmp((char *)dbuf.iov_base, "duplicates=", STRLENOF("duplicates="))) {
+ /* LY: silently ignore information fields. */
+ continue;
+ } else if (!strncmp((char *)dbuf.iov_base, "VERSION=", STRLENOF("VERSION="))) {
+ version = atoi((char *)dbuf.iov_base + STRLENOF("VERSION="));
+ if (version > 3) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported VERSION %d\n",
+ prog, lineno, version);
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp((char *)dbuf.iov_base, "HEADER=END", STRLENOF("HEADER=END"))) {
+ break;
+ } else if (!strncmp((char *)dbuf.iov_base, "format=", STRLENOF("format="))) {
+ if (!strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "print",
+ STRLENOF("print")))
+ mode |= PRINT;
+ else if (strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "bytevalue",
+ STRLENOF("bytevalue"))) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported FORMAT %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("FORMAT="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp((char *)dbuf.iov_base, "database=", STRLENOF("database="))) {
+ ptr = (char *)memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ if (subname)
+ free(subname);
+ subname = strdup((char *)dbuf.iov_base + STRLENOF("database="));
+ } else if (!strncmp((char *)dbuf.iov_base, "type=", STRLENOF("type="))) {
+ if (strncmp((char *)dbuf.iov_base + STRLENOF("type="), "btree",
+ STRLENOF("btree"))) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported type %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("type="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp((char *)dbuf.iov_base, "mapaddr=", STRLENOF("mapaddr="))) {
+ int i;
+ ptr = (char *)memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ void *unused;
+ i = sscanf((char *)dbuf.iov_base + STRLENOF("mapaddr="), "%p", &unused);
+ if (i != 1) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapaddr %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("mapaddr="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp((char *)dbuf.iov_base, "mapsize=", STRLENOF("mapsize="))) {
+ int i;
+ ptr = (char *)memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ i = sscanf((char *)dbuf.iov_base + STRLENOF("mapsize="), "%" PRIu64,
+ &envinfo.mi_mapsize);
+ if (i != 1) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapsize %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("mapsize="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp((char *)dbuf.iov_base, "maxreaders=", STRLENOF("maxreaders="))) {
+ int i;
+ ptr = (char *)memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ i = sscanf((char *)dbuf.iov_base + STRLENOF("maxreaders="), "%u",
+ &envinfo.mi_maxreaders);
+ if (i != 1) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": invalid maxreaders %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("maxreaders="));
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ int i;
+ for (i = 0; dbflags[i].bit; i++) {
+ if (!strncmp((char *)dbuf.iov_base, dbflags[i].name, dbflags[i].len) &&
+ ((char *)dbuf.iov_base)[dbflags[i].len] == '=') {
+ if (((char *)dbuf.iov_base)[dbflags[i].len + 1] == '1')
+ dbi_flags |= dbflags[i].bit;
+ break;
+ }
+ }
+ if (!dbflags[i].bit) {
+ ptr = (char *)memchr(dbuf.iov_base, '=', dbuf.iov_len);
+ if (!ptr) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected format\n", prog,
+ lineno);
+ exit(EXIT_FAILURE);
+ } else {
+ *ptr = '\0';
+ fprintf(stderr,
+ "%s: line %" PRIiSIZE ": unrecognized keyword ignored: %s\n",
+ prog, lineno, (char *)dbuf.iov_base);
+ }
+ }
+ }
+ }
+}
+
+static void badend(void) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected end of input\n", prog,
+ lineno);
+}
+
+static int unhex(unsigned char *c2) {
+ int x, c;
+ x = *c2++ & 0x4f;
+ if (x & 0x40)
+ x -= 55;
+ c = x << 4;
+ x = *c2 & 0x4f;
+ if (x & 0x40)
+ x -= 55;
+ c |= x;
+ return c;
+}
+
+static int readline(MDBX_val *out, MDBX_val *buf) {
+ unsigned char *c1, *c2, *end;
+ size_t len, l2;
+ int c;
+
+ if (!(mode & NOHDR)) {
+ c = fgetc(stdin);
+ if (c == EOF) {
+ Eof = 1;
+ return EOF;
+ }
+ if (c != ' ') {
+ lineno++;
+ if (fgets((char *)buf->iov_base, (int)buf->iov_len, stdin) == NULL) {
+ badend:
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ if (c == 'D' && !strncmp((char *)buf->iov_base, "ATA=END", STRLENOF("ATA=END")))
+ return EOF;
+ goto badend;
+ }
+ }
+ if (fgets((char *)buf->iov_base, (int)buf->iov_len, stdin) == NULL) {
+ Eof = 1;
+ return EOF;
+ }
+ lineno++;
+
+ c1 = (BYTE *)buf->iov_base;
+ len = strlen((char *)c1);
+ l2 = len;
+
+ /* Is buffer too short? */
+ while (c1[len - 1] != '\n') {
+ buf->iov_base = realloc(buf->iov_base, buf->iov_len * 2);
+ if (!buf->iov_base) {
+ Eof = 1;
+ fprintf(stderr, "%s: line %" PRIiSIZE ": out of memory, line too long\n",
+ prog, lineno);
+ return EOF;
+ }
+ c1 = (BYTE *)buf->iov_base;
+ c1 += l2;
+ if (fgets((char *)c1, (int)buf->iov_len + 1, stdin) == NULL) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ buf->iov_len *= 2;
+ len = strlen((char *)c1);
+ l2 += len;
+ }
+ c1 = c2 = (BYTE*)buf->iov_base;
+ len = l2;
+ c1[--len] = '\0';
+ end = c1 + len;
+
+ if (mode & PRINT) {
+ while (c2 < end) {
+ if (*c2 == '\\') {
+ if (c2[1] == '\\') {
+ c1++;
+ c2 += 2;
+ } else {
+ if (c2 + 3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ *c1++ = (char)unhex(++c2);
+ c2 += 2;
+ }
+ } else {
+ /* copies are redundant when no escapes were used */
+ *c1++ = *c2++;
+ }
+ }
+ } else {
+ /* odd length not allowed */
+ if (len & 1) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ while (c2 < end) {
+ if (!isxdigit(*c2) || !isxdigit(c2[1])) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ *c1++ = (char)unhex(c2);
+ c2 += 2;
+ }
+ }
+ c2 = (BYTE*)(out->iov_base = buf->iov_base);
+ out->iov_len = c1 - c2;
+
+ return 0;
+}
+
+static void usage(void) {
+ fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n",
+ prog);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[]) {
+ int i, rc;
+ MDBX_env *env = NULL;
+ MDBX_txn *txn = NULL;
+ MDBX_cursor *mc = NULL;
+ MDBX_dbi dbi;
+ char *envname = NULL;
+ int envflags = 0, putflags = 0;
+
+ prog = argv[0];
+
+ if (argc < 2) {
+ usage();
+ }
+
+ /* -f: load file instead of stdin
+ * -n: use NOSUBDIR flag on env_open
+ * -s: load into named subDB
+ * -N: use NOOVERWRITE on puts
+ * -T: read plaintext
+ * -V: print version and exit
+ */
+ while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
+ switch (i) {
+ case 'V':
+ // printf("%s (%s, build %s)\n", mdbx_version.git.describe, mdbx_version.git.datetime, mdbx_build.datetime);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'f':
+ if (freopen(optarg, "r", stdin) == NULL) {
+ fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'n':
+ envflags |= MDBX_NOSUBDIR;
+ break;
+ case 's':
+ subname = strdup(optarg);
+ break;
+ case 'N':
+ putflags = MDBX_NOOVERWRITE | MDBX_NODUPDATA;
+ break;
+ case 'T':
+ mode |= NOHDR | PRINT;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc - 1)
+ usage();
+
+#if defined(_WIN32) || defined(_WIN64)
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
+#else
+#ifdef SIGPIPE
+ signal(SIGPIPE, signal_handler);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, signal_handler);
+#endif
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+#endif /* !WINDOWS */
+
+ dbuf.iov_len = 4096;
+ dbuf.iov_base = malloc(dbuf.iov_len);
+
+ if (!(mode & NOHDR))
+ readhdr();
+
+ envname = argv[optind];
+ rc = mdbx_env_create(&env);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ return EXIT_FAILURE;
+ }
+
+ mdbx_env_set_maxdbs(env, 2);
+
+ if (envinfo.mi_maxreaders)
+ mdbx_env_set_maxreaders(env, envinfo.mi_maxreaders);
+
+ if (envinfo.mi_mapsize) {
+ if (envinfo.mi_mapsize > SIZE_MAX) {
+ fprintf(stderr, "mdbx_env_set_mapsize failed, error %d %s\n", rc,
+ mdbx_strerror(MDBX_TOO_LARGE));
+ return EXIT_FAILURE;
+ }
+ mdbx_env_set_mapsize(env, (size_t)envinfo.mi_mapsize);
+ }
+
+#ifdef MDBX_FIXEDMAP
+ if (info.mi_mapaddr)
+ envflags |= MDBX_FIXEDMAP;
+#endif
+
+ rc = mdbx_env_open(env, envname, envflags, 0664);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ kbuf.iov_len = mdbx_env_get_maxkeysize(env) * 2 + 2;
+ kbuf.iov_base = malloc(kbuf.iov_len);
+
+ while (!Eof) {
+ if (user_break) {
+ rc = MDBX_EINTR;
+ break;
+ }
+
+ MDBX_val key, data;
+ int batch = 0;
+
+ rc = mdbx_txn_begin(env, NULL, 0, &txn);
+ if (rc) {
+ fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ if (!stricmp(subname, "eventids"))
+ rc = mdbx_dbi_open_ex(txn, subname, dbi_flags | MDBX_CREATE, &dbi, &DBEventIdKey::Compare, nullptr);
+ else if (!stricmp(subname, "eventsrt"))
+ rc = mdbx_dbi_open_ex(txn, subname, dbi_flags | MDBX_CREATE, &dbi, &DBEventSortingKey::Compare, nullptr);
+ else if (!stricmp(subname, "settings"))
+ rc = mdbx_dbi_open_ex(txn, subname, dbi_flags | MDBX_CREATE, &dbi, &DBSettingKey::Compare, nullptr);
+ else
+ rc = mdbx_dbi_open(txn, subname, dbi_flags | MDBX_CREATE, &dbi);
+ if (rc) {
+ fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ rc = mdbx_cursor_open(txn, dbi, &mc);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ while (1) {
+ rc = readline(&key, &kbuf);
+ if (rc) /* rc == EOF */
+ break;
+
+ rc = readline(&data, &dbuf);
+ if (rc) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": failed to read key value\n",
+ prog, lineno);
+ goto txn_abort;
+ }
+
+ rc = mdbx_cursor_put(mc, &key, &data, putflags);
+ if (rc == MDBX_KEYEXIST && putflags)
+ continue;
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_put failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ batch++;
+ if (batch == 100) {
+ rc = mdbx_txn_commit(txn);
+ if (rc) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog,
+ lineno, mdbx_strerror(rc));
+ goto env_close;
+ }
+ rc = mdbx_txn_begin(env, NULL, 0, &txn);
+ if (rc) {
+ fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+ rc = mdbx_cursor_open(txn, dbi, &mc);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ batch = 0;
+ }
+ }
+ rc = mdbx_txn_commit(txn);
+ txn = NULL;
+ if (rc) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog, lineno,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+ mdbx_dbi_close(env, dbi);
+ if (!(mode & NOHDR))
+ readhdr();
+ }
+
+txn_abort:
+ mdbx_txn_abort(txn);
+env_close:
+ mdbx_env_close(env);
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/tools/mdbx_load/src/stdafx.cxx b/tools/mdbx_load/src/stdafx.cxx
new file mode 100644
index 0000000000..e0d3e0e311
--- /dev/null
+++ b/tools/mdbx_load/src/stdafx.cxx
@@ -0,0 +1,20 @@
+/*
+Copyright (C) 2012-18 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+
+#include "..\..\build\appstub\appstub.cpp" \ No newline at end of file
diff --git a/tools/mdbx_load/src/stdafx.h b/tools/mdbx_load/src/stdafx.h
new file mode 100644
index 0000000000..706de4dbe5
--- /dev/null
+++ b/tools/mdbx_load/src/stdafx.h
@@ -0,0 +1,78 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#include <stdio.h>
+#include <stdint.h>
+#include <windows.h>
+
+#include "../../libs/libmdbx/src/src/bits.h"
+
+#define CMP_UINT(x, y) { if ((x) != (y)) return (x) < (y) ? -1 : 1; }
+
+struct DBEventSortingKey
+{
+ uint32_t hContact;
+ uint32_t hEvent;
+ uint64_t ts;
+
+ static int Compare(const MDBX_val *ax, const MDBX_val *bx)
+ {
+ const DBEventSortingKey *a = (DBEventSortingKey*)ax->iov_base;
+ const DBEventSortingKey *b = (DBEventSortingKey*)bx->iov_base;
+
+ CMP_UINT(a->hContact, b->hContact);
+ CMP_UINT(a->ts, b->ts);
+ CMP_UINT(a->hEvent, b->hEvent);
+ return 0;
+ }
+};
+
+struct DBEventIdKey
+{
+ uint32_t iModuleId; // offset to a DBModuleName struct of the name of
+ char szEventId[256]; // string id
+
+ static int Compare(const MDBX_val *ax, const MDBX_val *bx)
+ {
+ const DBEventIdKey *a = (DBEventIdKey*)ax->iov_base;
+ const DBEventIdKey *b = (DBEventIdKey*)bx->iov_base;
+ CMP_UINT(a->iModuleId, b->iModuleId);
+ return strcmp(a->szEventId, b->szEventId);
+ }
+};
+
+struct DBSettingKey
+{
+ uint32_t hContact;
+ uint32_t dwModuleId;
+ char szSettingName[1];
+
+ static int Compare(const MDBX_val *ax, const MDBX_val *bx)
+ {
+ const DBSettingKey *a = (DBSettingKey*)ax->iov_base;
+ const DBSettingKey *b = (DBSettingKey*)bx->iov_base;
+
+ CMP_UINT(a->hContact, b->hContact);
+ CMP_UINT(a->dwModuleId, b->dwModuleId);
+ return strcmp(a->szSettingName, b->szSettingName);
+ }
+};