1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-15 01:04:37 +02:00

Make the C version of the info command conform to the Perl version.

There were some small differences in ordering and how the C version handled missing directories.  It may be that the C version is more consistent, but for now it is more important to be compatible with the Perl version.

These differences were missed because the C info command was not wired into main.c so it was not being tested in regression.  This commit does not fix the wiring issue because there will likely be a release soon and it is too big a change to put in at the last moment.
This commit is contained in:
David Steele
2019-01-13 22:44:58 +02:00
parent f314a1f8aa
commit 8304d452b3
7 changed files with 63 additions and 58 deletions

View File

@ -29,6 +29,10 @@
<p>Ignore <id>SIGPIPE</id> signals and check <id>EPIPE</id> result instead.</p> <p>Ignore <id>SIGPIPE</id> signals and check <id>EPIPE</id> result instead.</p>
</release-item> </release-item>
<release-item>
<p>Make the <proper>C</proper> version of the <cmd>info</cmd> command conform to the <proper>Perl</proper> version.</p>
</release-item>
<release-item> <release-item>
<p>Improve accuracy of <code>strSizeFormat()</code>.</p> <p>Improve accuracy of <code>strSizeFormat()</code>.</p>
</release-item> </release-item>

View File

@ -62,6 +62,7 @@ SRCS = \
command/archive/get/get.c \ command/archive/get/get.c \
command/archive/push/push.c \ command/archive/push/push.c \
command/help/help.c \ command/help/help.c \
command/info/info.c \
command/command.c \ command/command.c \
command/control/control.c \ command/control/control.c \
common/debug.c \ common/debug.c \
@ -115,6 +116,8 @@ SRCS = \
crypto/crypto.c \ crypto/crypto.c \
info/info.c \ info/info.c \
info/infoArchive.c \ info/infoArchive.c \
info/infoBackup.c \
info/infoManifest.c \
info/infoPg.c \ info/infoPg.c \
perl/config.c \ perl/config.c \
perl/exec.c \ perl/exec.c \
@ -348,7 +351,7 @@ info/infoManifest.o: info/infoManifest.c common/error.auto.h common/error.h comm
info/infoPg.o: info/infoPg.c common/assert.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/crypto.h crypto/hash.h info/info.h info/infoPg.h postgres/interface.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h info/infoPg.o: info/infoPg.c common/assert.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/crypto.h crypto/hash.h info/info.h info/infoPg.h postgres/interface.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c info/infoPg.c -o info/infoPg.o $(CC) $(CFLAGS) -c info/infoPg.c -o info/infoPg.o
main.o: main.c command/archive/get/get.h command/archive/push/push.h command/command.h command/help/help.h common/debug.h common/error.auto.h common/error.h common/exit.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/interface.h version.h main.o: main.c command/archive/get/get.h command/archive/push/push.h command/command.h command/help/help.h command/info/info.h common/debug.h common/error.auto.h common/error.h common/exit.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/interface.h version.h
$(CC) $(CFLAGS) -c main.c -o main.o $(CC) $(CFLAGS) -c main.c -o main.o
perl/config.o: perl/config.c common/debug.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h perl/config.o: perl/config.c common/debug.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h

View File

@ -96,7 +96,7 @@ stanzaStatus(const int code, const String *message, Variant *stanzaInfo)
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Set the data for the archive section of the stanza for the database info from the backup.info file. Set the data for the archive section of the stanza for the database info from the backup.info file.
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
void static void
archiveDbList(const String *stanza, const InfoPgData *pgData, VariantList *archiveSection, const InfoArchive *info, bool currentDb) archiveDbList(const String *stanza, const InfoPgData *pgData, VariantList *archiveSection, const InfoArchive *info, bool currentDb)
{ {
FUNCTION_TEST_BEGIN(); FUNCTION_TEST_BEGIN();
@ -149,7 +149,7 @@ archiveDbList(const String *stanza, const InfoPgData *pgData, VariantList *archi
} }
// Iterate through the directory list in the reverse so processing newest first. Cast comparison to an int for readability. // Iterate through the directory list in the reverse so processing newest first. Cast comparison to an int for readability.
for (unsigned int idx = sizeWalDir - 1; (int)idx > 0; idx--) for (unsigned int idx = sizeWalDir - 1; (int)idx >= 0; idx--)
{ {
// Get a list of all WAL in this WAL dir // Get a list of all WAL in this WAL dir
StringList *list = storageListP( StringList *list = storageListP(
@ -189,15 +189,13 @@ archiveDbList(const String *stanza, const InfoPgData *pgData, VariantList *archi
/*********************************************************************************************************************************** /***********************************************************************************************************************************
For each current backup in the backup.info file of the stanza, set the data for the backup section. For each current backup in the backup.info file of the stanza, set the data for the backup section.
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
void static void
backupList(const String *stanza, VariantList *backupSection, InfoBackup *info) backupList(VariantList *backupSection, InfoBackup *info)
{ {
FUNCTION_TEST_BEGIN(); FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, stanza);
FUNCTION_TEST_PARAM(VARIANT, backupSection); FUNCTION_TEST_PARAM(VARIANT, backupSection);
FUNCTION_TEST_PARAM(INFO_BACKUP, info); FUNCTION_TEST_PARAM(INFO_BACKUP, info);
FUNCTION_TEST_ASSERT(stanza != NULL);
FUNCTION_TEST_ASSERT(backupSection != NULL); FUNCTION_TEST_ASSERT(backupSection != NULL);
FUNCTION_TEST_ASSERT(info != NULL); FUNCTION_TEST_ASSERT(info != NULL);
FUNCTION_TEST_END(); FUNCTION_TEST_END();
@ -310,7 +308,7 @@ stanzaInfoList(const String *stanza, StringList *stanzaList)
{ {
// Attempt to load the backup info file // Attempt to load the backup info file
info = infoBackupNew( info = infoBackupNew(
storageRepo(), strNewFmt("%s/%s/%s", STORAGE_REPO_BACKUP, strPtr(stanzaListName), INFO_BACKUP_FILE), false, storageRepo(), strNewFmt(STORAGE_PATH_BACKUP "/%s/%s", strPtr(stanzaListName), INFO_BACKUP_FILE), false,
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStr(cfgOptRepoCipherPass)); cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStr(cfgOptRepoCipherPass));
} }
CATCH(FileMissingError) CATCH(FileMissingError)
@ -337,7 +335,7 @@ stanzaInfoList(const String *stanza, StringList *stanzaList)
// If the backup.info file exists, get the database history information (newest to oldest) and corresponding archive // If the backup.info file exists, get the database history information (newest to oldest) and corresponding archive
if (info != NULL) if (info != NULL)
{ {
for (unsigned int pgIdx = 0; pgIdx < infoPgDataTotal(infoBackupPg(info)); pgIdx++) for (unsigned int pgIdx = infoPgDataTotal(infoBackupPg(info)) - 1; (int)pgIdx >= 0; pgIdx--)
{ {
InfoPgData pgData = infoPgData(infoBackupPg(info), pgIdx); InfoPgData pgData = infoPgData(infoBackupPg(info), pgIdx);
Variant *pgInfo = varNewKv(); Variant *pgInfo = varNewKv();
@ -350,13 +348,13 @@ stanzaInfoList(const String *stanza, StringList *stanzaList)
// Get the archive info for the DB from the archive.info file // Get the archive info for the DB from the archive.info file
InfoArchive *info = infoArchiveNew( InfoArchive *info = infoArchiveNew(
storageRepo(), strNewFmt("%s/%s/%s", STORAGE_REPO_ARCHIVE, strPtr(stanzaListName), INFO_ARCHIVE_FILE), false, storageRepo(), strNewFmt(STORAGE_PATH_ARCHIVE "/%s/%s", strPtr(stanzaListName), INFO_ARCHIVE_FILE), false,
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStr(cfgOptRepoCipherPass)); cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStr(cfgOptRepoCipherPass));
archiveDbList(stanzaListName, &pgData, archiveSection, info, (pgIdx == 0 ? true : false)); archiveDbList(stanzaListName, &pgData, archiveSection, info, (pgIdx == 0 ? true : false));
} }
// Get data for all existing backups for this stanza // Get data for all existing backups for this stanza
backupList(stanzaListName, backupSection, info); backupList(backupSection, info);
} }
// Add the database history, backup and archive sections to the stanza info // Add the database history, backup and archive sections to the stanza info
@ -413,13 +411,13 @@ formatTextDb(const KeyValue *stanzaInfo, String *resultStr)
VariantList *backupSection = kvGetList(stanzaInfo, varNewStr(STANZA_KEY_BACKUP_STR)); VariantList *backupSection = kvGetList(stanzaInfo, varNewStr(STANZA_KEY_BACKUP_STR));
// For each database (working from oldest to newest) find the corresponding archive and backup info // For each database (working from oldest to newest) find the corresponding archive and backup info
for (unsigned int dbIdx = varLstSize(dbSection) - 1; (int)dbIdx >= 0; dbIdx--) for (unsigned int dbIdx = 0; dbIdx < varLstSize(dbSection); dbIdx++)
{ {
KeyValue *pgInfo = varKv(varLstGet(dbSection, dbIdx)); KeyValue *pgInfo = varKv(varLstGet(dbSection, dbIdx));
uint64_t dbId = varUInt64(kvGet(pgInfo, varNewStr(DB_KEY_ID_STR))); uint64_t dbId = varUInt64(kvGet(pgInfo, varNewStr(DB_KEY_ID_STR)));
// List is ordered so 0 is always the current DB index // List is ordered so 0 is always the current DB index
if (dbIdx == 0) if (dbIdx == varLstSize(dbSection) - 1)
strCat(resultStr, "\n db (current)"); strCat(resultStr, "\n db (current)");
// Get the min/max archive information for the database // Get the min/max archive information for the database
@ -515,7 +513,7 @@ formatTextDb(const KeyValue *stanzaInfo, String *resultStr)
// If there is data to display, then display it. // If there is data to display, then display it.
if (strSize(archiveResult) > 0 || strSize(backupResult) > 0) if (strSize(archiveResult) > 0 || strSize(backupResult) > 0)
{ {
if (dbIdx != 0) if (dbIdx != varLstSize(dbSection) - 1)
strCat(resultStr, "\n db (prior)"); strCat(resultStr, "\n db (prior)");
if (strSize(archiveResult) > 0) if (strSize(archiveResult) > 0)
@ -544,12 +542,12 @@ infoRender(void)
const String *stanza = cfgOptionTest(cfgOptStanza) ? cfgOptionStr(cfgOptStanza) : NULL; const String *stanza = cfgOptionTest(cfgOptStanza) ? cfgOptionStr(cfgOptStanza) : NULL;
// Get a list of stanzas in the backup directory. // Get a list of stanzas in the backup directory.
StringList *stanzaList = storageListP(storageRepo(), strNew(STORAGE_REPO_BACKUP), .errorOnMissing = true); StringList *stanzaList = storageListP(storageRepo(), STORAGE_PATH_BACKUP_STR, .errorOnMissing = false);
VariantList *infoList = varLstNew(); VariantList *infoList = varLstNew();
String *resultStr = strNew(""); String *resultStr = strNew("");
// If the backup storage exists, then search for and process any stanzas // If the backup storage exists, then search for and process any stanzas
if (strLstSize(stanzaList) > 0) if (stanzaList != NULL && strLstSize(stanzaList) > 0)
infoList = stanzaInfoList(stanza, stanzaList); infoList = stanzaInfoList(stanza, stanzaList);
// Format text output // Format text output
@ -604,7 +602,7 @@ infoRender(void)
} }
} }
else else
resultStr = strNewFmt("No stanzas exist in %s\n", strPtr(storagePathNP(storageRepo(), NULL))); resultStr = strNewFmt("No stanzas exist in %s.\n", strPtr(storagePathNP(storageRepo(), NULL)));
} }
// Format json output // Format json output
else else

View File

@ -7,6 +7,7 @@ Main
#include "command/archive/get/get.h" #include "command/archive/get/get.h"
#include "command/archive/push/push.h" #include "command/archive/push/push.h"
#include "command/help/help.h" #include "command/help/help.h"
#include "command/info/info.h"
#include "command/command.h" #include "command/command.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/error.h" #include "common/error.h"

View File

@ -17,8 +17,8 @@ Storage path constants
STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_IN_STR, STORAGE_SPOOL_ARCHIVE_IN); STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_IN_STR, STORAGE_SPOOL_ARCHIVE_IN);
STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_OUT_STR, STORAGE_SPOOL_ARCHIVE_OUT); STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_OUT_STR, STORAGE_SPOOL_ARCHIVE_OUT);
#define STORAGE_PATH_ARCHIVE "archive" STRING_EXTERN(STORAGE_PATH_ARCHIVE_STR, STORAGE_PATH_ARCHIVE);
#define STORAGE_PATH_BACKUP "backup" STRING_EXTERN(STORAGE_PATH_BACKUP_STR, STORAGE_PATH_BACKUP);
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Local variables Local variables

View File

@ -17,6 +17,11 @@ Storage path constants
#define STORAGE_REPO_ARCHIVE "<REPO:ARCHIVE>" #define STORAGE_REPO_ARCHIVE "<REPO:ARCHIVE>"
#define STORAGE_REPO_BACKUP "<REPO:BACKUP>" #define STORAGE_REPO_BACKUP "<REPO:BACKUP>"
#define STORAGE_PATH_ARCHIVE "archive"
STRING_DECLARE(STORAGE_PATH_ARCHIVE_STR);
#define STORAGE_PATH_BACKUP "backup"
STRING_DECLARE(STORAGE_PATH_BACKUP_STR);
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Repository storage types Repository storage types
***********************************************************************************************************************************/ ***********************************************************************************************************************************/

View File

@ -32,22 +32,16 @@ testRun(void)
strLstAddZ(argList, "--output=json"); strLstAddZ(argList, "--output=json");
harnessCfgLoad(strLstSize(argList), strLstPtr(argList)); harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
// No repo path
//--------------------------------------------------------------------------------------------------------------------------
TEST_ERROR_FMT(
infoRender(), PathOpenError,
"unable to open path '%s' for read: [2] No such file or directory", strPtr(backupPath));
storagePathCreateNP(storageLocalWrite(), archivePath);
storagePathCreateNP(storageLocalWrite(), backupPath);
// No stanzas have been created // No stanzas have been created
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(strPtr(infoRender()), "[]\n", "json - repo but no stanzas"); TEST_RESULT_STR(strPtr(infoRender()), "[]\n", "json - repo but no stanzas");
harnessCfgLoad(strLstSize(argListText), strLstPtr(argListText)); harnessCfgLoad(strLstSize(argListText), strLstPtr(argListText));
TEST_RESULT_STR(strPtr(infoRender()), TEST_RESULT_STR(strPtr(infoRender()),
strPtr(strNewFmt("No stanzas exist in %s\n", strPtr(storagePathNP(storageRepo(), NULL)))), "text - no stanzas"); strPtr(strNewFmt("No stanzas exist in %s.\n", strPtr(storagePathNP(storageRepo(), NULL)))), "text - no stanzas");
storagePathCreateNP(storageLocalWrite(), archivePath);
storagePathCreateNP(storageLocalWrite(), backupPath);
// Empty stanza // Empty stanza
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
@ -155,14 +149,14 @@ testRun(void)
" \"cipher\" : \"none\",\n" " \"cipher\" : \"none\",\n"
" \"db\" : [\n" " \"db\" : [\n"
" {\n" " {\n"
" \"id\" : 2,\n"
" \"system-id\" : 6569239123849665679,\n"
" \"version\" : \"9.4\"\n"
" },\n"
" {\n"
" \"id\" : 1,\n" " \"id\" : 1,\n"
" \"system-id\" : 6569239123849665666,\n" " \"system-id\" : 6569239123849665666,\n"
" \"version\" : \"9.3\"\n" " \"version\" : \"9.3\"\n"
" },\n"
" {\n"
" \"id\" : 2,\n"
" \"system-id\" : 6569239123849665679,\n"
" \"version\" : \"9.4\"\n"
" }\n" " }\n"
" ],\n" " ],\n"
" \"name\" : \"stanza1\",\n" " \"name\" : \"stanza1\",\n"
@ -249,19 +243,19 @@ testRun(void)
" \"archive\" : [\n" " \"archive\" : [\n"
" {\n" " {\n"
" \"database\" : {\n" " \"database\" : {\n"
" \"id\" : 3\n"
" },\n"
" \"id\" : \"9.4-3\",\n"
" \"max\" : null,\n"
" \"min\" : null\n"
" },\n"
" {\n"
" \"database\" : {\n"
" \"id\" : 1\n" " \"id\" : 1\n"
" },\n" " },\n"
" \"id\" : \"9.4-1\",\n" " \"id\" : \"9.4-1\",\n"
" \"max\" : \"000000020000000000000003\",\n" " \"max\" : \"000000020000000000000003\",\n"
" \"min\" : \"000000010000000000000002\"\n" " \"min\" : \"000000010000000000000002\"\n"
" },\n"
" {\n"
" \"database\" : {\n"
" \"id\" : 3\n"
" },\n"
" \"id\" : \"9.4-3\",\n"
" \"max\" : null,\n"
" \"min\" : null\n"
" }\n" " }\n"
" ],\n" " ],\n"
" \"backup\" : [\n" " \"backup\" : [\n"
@ -298,7 +292,7 @@ testRun(void)
" \"cipher\" : \"none\",\n" " \"cipher\" : \"none\",\n"
" \"db\" : [\n" " \"db\" : [\n"
" {\n" " {\n"
" \"id\" : 3,\n" " \"id\" : 1,\n"
" \"system-id\" : 6569239123849665679,\n" " \"system-id\" : 6569239123849665679,\n"
" \"version\" : \"9.4\"\n" " \"version\" : \"9.4\"\n"
" },\n" " },\n"
@ -308,7 +302,7 @@ testRun(void)
" \"version\" : \"9.3\"\n" " \"version\" : \"9.3\"\n"
" },\n" " },\n"
" {\n" " {\n"
" \"id\" : 1,\n" " \"id\" : 3,\n"
" \"system-id\" : 6569239123849665679,\n" " \"system-id\" : 6569239123849665679,\n"
" \"version\" : \"9.4\"\n" " \"version\" : \"9.4\"\n"
" }\n" " }\n"
@ -470,19 +464,19 @@ testRun(void)
" \"archive\" : [\n" " \"archive\" : [\n"
" {\n" " {\n"
" \"database\" : {\n" " \"database\" : {\n"
" \"id\" : 2\n"
" },\n"
" \"id\" : \"9.5-2\",\n"
" \"max\" : null,\n"
" \"min\" : null\n"
" },\n"
" {\n"
" \"database\" : {\n"
" \"id\" : 1\n" " \"id\" : 1\n"
" },\n" " },\n"
" \"id\" : \"9.4-1\",\n" " \"id\" : \"9.4-1\",\n"
" \"max\" : \"000000020000000000000003\",\n" " \"max\" : \"000000020000000000000003\",\n"
" \"min\" : \"000000010000000000000002\"\n" " \"min\" : \"000000010000000000000002\"\n"
" },\n"
" {\n"
" \"database\" : {\n"
" \"id\" : 2\n"
" },\n"
" \"id\" : \"9.5-2\",\n"
" \"max\" : null,\n"
" \"min\" : null\n"
" }\n" " }\n"
" ],\n" " ],\n"
" \"backup\" : [\n" " \"backup\" : [\n"
@ -582,14 +576,14 @@ testRun(void)
" \"cipher\" : \"none\",\n" " \"cipher\" : \"none\",\n"
" \"db\" : [\n" " \"db\" : [\n"
" {\n" " {\n"
" \"id\" : 2,\n"
" \"system-id\" : 6626363367545678089,\n"
" \"version\" : \"9.5\"\n"
" },\n"
" {\n"
" \"id\" : 1,\n" " \"id\" : 1,\n"
" \"system-id\" : 6625592122879095702,\n" " \"system-id\" : 6625592122879095702,\n"
" \"version\" : \"9.4\"\n" " \"version\" : \"9.4\"\n"
" },\n"
" {\n"
" \"id\" : 2,\n"
" \"system-id\" : 6626363367545678089,\n"
" \"version\" : \"9.5\"\n"
" }\n" " }\n"
" ],\n" " ],\n"
" \"name\" : \"stanza1\",\n" " \"name\" : \"stanza1\",\n"
@ -842,7 +836,7 @@ testRun(void)
// Restore normal stdout // Restore normal stdout
dup2(stdoutSave, STDOUT_FILENO); dup2(stdoutSave, STDOUT_FILENO);
const char *generalHelp = strPtr(strNewFmt("No stanzas exist in %s\n", strPtr(repoPath))); const char *generalHelp = strPtr(strNewFmt("No stanzas exist in %s.\n", strPtr(repoPath)));
Storage *storage = storageDriverPosixInterface( Storage *storage = storageDriverPosixInterface(
storageDriverPosixNew(strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, false, NULL)); storageDriverPosixNew(strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, false, NULL));