1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-03 00:26:59 +02:00

Add *Save() functions to most Info objects.

At the same time change the way that load constructors work (and are named) so that Ini objects do not persist after the constructors complete.

infoArchiveSave() is excluded from this commit since it is just a trivial call to infoPgSave() and won't be required soon.
This commit is contained in:
David Steele
2019-04-23 17:08:34 -04:00
parent f41112a463
commit f492f0571b
12 changed files with 379 additions and 146 deletions

View File

@ -45,6 +45,10 @@
<p>Add <code>iniSave()</code> and <code>iniMove()</code> to <code>Ini</code> object.</p>
</release-item>
<release-item>
<p>Add <code>*Save()</code> functions to most <code>Info</code> objects.</p>
</release-item>
<release-item>
<p>Extern <code>infoHash()</code> so it can be used by other modules.</p>
</release-item>

View File

@ -206,7 +206,7 @@ clean:
command/archive/common.o: command/archive/common.c command/archive/common.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.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 common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/common.c -o command/archive/common.o
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/assert.h common/compress/gzip/common.h common/compress/gzip/decompress.h common/crypto/cipherBlock.h common/crypto/common.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/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 info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/assert.h common/compress/gzip/common.h common/compress/gzip/decompress.h common/crypto/cipherBlock.h common/crypto/common.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/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 info/info.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/get/file.c -o command/archive/get/file.o
command/archive/get/get.o: command/archive/get/get.c command/archive/common.h command/archive/get/file.h command/archive/get/protocol.h command/command.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.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 common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/exec.h perl/exec.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h protocol/parallel.h protocol/parallelJob.h protocol/server.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
@ -221,7 +221,7 @@ command/archive/push/file.o: command/archive/push/file.c command/archive/common.
command/archive/push/protocol.o: command/archive/push/protocol.c command/archive/push/file.h command/archive/push/protocol.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/io.h common/io/read.h common/io/write.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 protocol/server.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/push/protocol.c -o command/archive/push/protocol.o
command/archive/push/push.o: command/archive/push/push.c command/archive/common.h command/archive/push/file.h command/archive/push/protocol.h command/command.h command/control/control.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/fork.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.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 common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/exec.h info/infoArchive.h info/infoPg.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h protocol/parallel.h protocol/parallelJob.h protocol/server.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
command/archive/push/push.o: command/archive/push/push.c command/archive/common.h command/archive/push/file.h command/archive/push/protocol.h command/command.h command/control/control.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/fork.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.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 common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/exec.h info/info.h info/infoArchive.h info/infoPg.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h protocol/parallel.h protocol/parallelJob.h protocol/server.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/push/push.c -o command/archive/push/push.o
command/backup/common.o: command/backup/common.c command/backup/common.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/string.h
@ -407,7 +407,7 @@ config/protocol.o: config/protocol.c common/assert.h common/debug.h common/error
info/info.o: info/info.c common/assert.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.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/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h version.h
$(CC) $(CFLAGS) -c info/info.c -o info/info.o
info/infoArchive.o: info/infoArchive.c common/assert.h common/crypto/common.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/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
info/infoArchive.o: info/infoArchive.c common/assert.h common/crypto/common.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/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c info/infoArchive.c -o info/infoArchive.o
info/infoBackup.o: info/infoBackup.c common/assert.h common/crypto/common.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 info/info.h info/infoBackup.h info/infoManifest.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h

View File

@ -19,7 +19,7 @@ Info Handler
/***********************************************************************************************************************************
Internal constants
***********************************************************************************************************************************/
#define INI_COPY_EXT ".copy"
#define INFO_COPY_EXT ".copy"
STRING_STATIC(INFO_SECTION_BACKREST_STR, "backrest");
STRING_STATIC(INFO_SECTION_CIPHER_STR, "cipher");
@ -35,8 +35,6 @@ Object type
struct Info
{
MemContext *memContext; // Mem context
String *fileName; // Full path name of the file
Ini *ini; // Parsed file contents
const String *cipherPass; // Cipher passphrase if set
};
@ -117,27 +115,29 @@ infoHash(const Ini *ini)
/***********************************************************************************************************************************
Load and validate the info file (or copy)
***********************************************************************************************************************************/
static bool
infoLoad(Info *this, const Storage *storage, bool copyFile, CipherType cipherType, const String *cipherPass)
static Ini *
infoLoad(Info *this, const Storage *storage, const String *fileName, bool copyFile, CipherType cipherType, const String *cipherPass)
{
FUNCTION_LOG_BEGIN(logLevelTrace)
FUNCTION_LOG_PARAM(INFO, this);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName); // Full path/filename to load
FUNCTION_LOG_PARAM(BOOL, copyFile); // Is this the copy file?
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(fileName != NULL);
bool result = false;
Ini *result = NULL;
MEM_CONTEXT_TEMP_BEGIN()
{
String *fileName = copyFile ? strCat(strDup(this->fileName), INI_COPY_EXT) : this->fileName;
const String *fileNameExt = copyFile ? strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName)) : fileName;
// Attempt to load the file
StorageFileRead *infoRead = storageNewReadNP(storage, fileName);
StorageFileRead *infoRead = storageNewReadNP(storage, fileNameExt);
if (cipherType != cipherTypeNone)
{
@ -158,22 +158,23 @@ infoLoad(Info *this, const Storage *storage, bool copyFile, CipherType cipherTyp
CATCH(CryptoError)
{
THROW_FMT(
CryptoError, "'%s' %s\nHINT: Is or was the repo encrypted?", strPtr(storagePathNP(storage, fileName)),
CryptoError, "'%s' %s\nHINT: Is or was the repo encrypted?", strPtr(storagePathNP(storage, fileNameExt)),
errorMessage());
}
TRY_END();
iniParse(this->ini, strNewBuf(buffer));
result = iniNew();
iniParse(result, strNewBuf(buffer));
// Make sure the ini is valid by testing the checksum
const String *infoChecksumJson = iniGet(this->ini, INFO_SECTION_BACKREST_STR, INFO_KEY_CHECKSUM_STR);
const String *checksum = infoHash(this->ini);
const String *infoChecksumJson = iniGet(result, INFO_SECTION_BACKREST_STR, INFO_KEY_CHECKSUM_STR);
const String *checksum = infoHash(result);
if (strSize(infoChecksumJson) == 0)
{
THROW_FMT(
ChecksumError, "invalid checksum in '%s', expected '%s' but no checksum found",
strPtr(storagePathNP(storage, fileName)), strPtr(checksum));
strPtr(storagePathNP(storage, fileNameExt)), strPtr(checksum));
}
else
{
@ -183,42 +184,32 @@ infoLoad(Info *this, const Storage *storage, bool copyFile, CipherType cipherTyp
{
THROW_FMT(
ChecksumError, "invalid checksum in '%s', expected '%s' but found '%s'",
strPtr(storagePathNP(storage, fileName)), strPtr(checksum), strPtr(infoChecksum));
strPtr(storagePathNP(storage, fileNameExt)), strPtr(checksum), strPtr(infoChecksum));
}
}
// Make sure that the format is current, otherwise error
if (jsonToUInt(iniGet(this->ini, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR)) != REPOSITORY_FORMAT)
if (jsonToUInt(iniGet(result, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR)) != REPOSITORY_FORMAT)
{
THROW_FMT(
FormatError, "invalid format in '%s', expected %d but found %d", strPtr(fileName), REPOSITORY_FORMAT,
varIntForce(VARSTR(iniGet(this->ini, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR))));
FormatError, "invalid format in '%s', expected %d but found %d", strPtr(fileNameExt), REPOSITORY_FORMAT,
varIntForce(VARSTR(iniGet(result, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR))));
}
iniMove(result, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
FUNCTION_LOG_RETURN(BOOL, result);
FUNCTION_LOG_RETURN(INI, result);
}
/***********************************************************************************************************************************
Load an Info object
// ??? Need loadFile parameter to be able to load from a string.
// ??? Need to handle modified flag, encryption and checksum, initialization, etc.
// ??? The file MUST exist currently, so this is not actually creating the object - rather it is loading it
Create new object
***********************************************************************************************************************************/
Info *
infoNew(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
infoNew(void)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName); // Full path/filename to load
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
FUNCTION_LOG_VOID(logLevelTrace);
Info *this = NULL;
@ -227,14 +218,40 @@ infoNew(const Storage *storage, const String *fileName, CipherType cipherType, c
// Create object
this = memNew(sizeof(Info));
this->memContext = MEM_CONTEXT_NEW();
}
MEM_CONTEXT_NEW_END();
this->ini = iniNew();
this->fileName = strDup(fileName);
FUNCTION_LOG_RETURN(INFO, this);
}
/***********************************************************************************************************************************
Create new object and load contents from a file
***********************************************************************************************************************************/
Info *
infoNewLoad(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass, Ini **ini)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName); // Full path/filename to load
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM_P(INI, ini);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
Info *this = infoNew();
MEM_CONTEXT_BEGIN(this->memContext)
{
Ini *iniLocal = NULL;
// Attempt to load the primary file
TRY_BEGIN()
{
infoLoad(this, storage, false, cipherType, cipherPass);
iniLocal = infoLoad(this, storage, fileName, false, cipherType, cipherPass);
}
CATCH_ANY()
{
@ -245,7 +262,7 @@ infoNew(const Storage *storage, const String *fileName, CipherType cipherType, c
TRY_BEGIN()
{
infoLoad(this, storage, true, cipherType, cipherPass);
iniLocal = infoLoad(this, storage, fileName, true, cipherType, cipherPass);
}
CATCH_ANY()
{
@ -256,8 +273,8 @@ infoNew(const Storage *storage, const String *fileName, CipherType cipherType, c
errorType() == primaryErrorType ? errorType() :
(errorType() == &FileMissingError ? primaryErrorType :
(primaryMissing ? errorType() : &FileOpenError)),
"unable to load info file '%s' or '%s" INI_COPY_EXT "':\n%s\n%s: %s",
strPtr(storagePathNP(storage, this->fileName)), strPtr(storagePathNP(storage, this->fileName)),
"unable to load info file '%s' or '%s" INFO_COPY_EXT "':\n%s\n%s: %s",
strPtr(storagePathNP(storage, fileName)), strPtr(storagePathNP(storage, fileName)),
strPtr(primaryError), errorTypeName(errorType()), errorMessage());
}
TRY_END();
@ -265,16 +282,71 @@ infoNew(const Storage *storage, const String *fileName, CipherType cipherType, c
TRY_END();
// Load the cipher passphrase if it exists
const String *cipherPass = iniGetDefault(this->ini, INFO_SECTION_CIPHER_STR, INFO_KEY_CIPHER_PASS_STR, NULL);
const String *cipherPass = iniGetDefault(iniLocal, INFO_SECTION_CIPHER_STR, INFO_KEY_CIPHER_PASS_STR, NULL);
if (cipherPass != NULL)
this->cipherPass = jsonToStr(cipherPass);
if (ini != NULL)
*ini = iniMove(iniLocal, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_NEW_END();
MEM_CONTEXT_END();
FUNCTION_LOG_RETURN(INFO, this);
}
/***********************************************************************************************************************************
Save to file
***********************************************************************************************************************************/
void
infoSave(
Info *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(INFO, this);
FUNCTION_LOG_PARAM(INI, ini);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(ini != NULL);
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
MEM_CONTEXT_TEMP_BEGIN()
{
// Add common info values
iniSet(ini, INFO_SECTION_BACKREST_STR, INFO_KEY_VERSION_STR, jsonFromStr(STRDEF(PROJECT_VERSION)));
iniSet(ini, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR, jsonFromUInt(REPOSITORY_FORMAT));
iniSet(ini, INFO_SECTION_BACKREST_STR, INFO_KEY_CHECKSUM_STR, jsonFromStr(infoHash(ini)));
// Save info file
IoWrite *infoWrite = storageFileWriteIo(storageNewWriteNP(storage, fileName));
if (cipherType != cipherTypeNone)
{
ioWriteFilterGroupSet(
infoWrite,
ioFilterGroupAdd(
ioFilterGroupNew(), cipherBlockFilter(cipherBlockNew(cipherModeEncrypt, cipherType, BUFSTR(cipherPass),
NULL))));
}
iniSave(ini, infoWrite);
// Copy to .copy file
storageCopyNP(
storageNewReadNP(storage, fileName), storageNewWriteNP(storage, strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName))));
}
MEM_CONTEXT_TEMP_END();
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Accessor functions
***********************************************************************************************************************************/
@ -290,30 +362,6 @@ infoCipherPass(const Info *this)
FUNCTION_TEST_RETURN(this->cipherPass);
}
Ini *
infoIni(const Info *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(INFO, this);
FUNCTION_TEST_END();
ASSERT(this != NULL);
FUNCTION_TEST_RETURN(this->ini);
}
String *
infoFileName(const Info *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(INFO, this);
FUNCTION_TEST_END();
ASSERT(this != NULL);
FUNCTION_TEST_RETURN(this->fileName);
}
/***********************************************************************************************************************************
Free the object
***********************************************************************************************************************************/

View File

@ -22,15 +22,17 @@ Constants
STRING_DECLARE(INFO_KEY_FORMAT_STR);
/***********************************************************************************************************************************
Constructor
Constructors
***********************************************************************************************************************************/
Info *infoNew(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
Info *infoNew(void);
Info *infoNewLoad(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass, Ini **ini);
void infoSave(
Info *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
/***********************************************************************************************************************************
Getters
***********************************************************************************************************************************/
const String *infoCipherPass(const Info *this);
String *infoFileName(const Info *this);
String *infoHash(const Ini *ini);
Ini *infoIni(const Info *this);

View File

@ -26,8 +26,7 @@ struct InfoArchive
};
/***********************************************************************************************************************************
Create a new InfoArchive object
// ??? Need loadFile parameter
Create new object and load contents from a file
***********************************************************************************************************************************/
InfoArchive *
infoArchiveNew(const Storage *storage, const String *fileName, bool ignoreMissing, CipherType cipherType, const String *cipherPass)
@ -55,7 +54,7 @@ infoArchiveNew(const Storage *storage, const String *fileName, bool ignoreMissin
// Catch file missing error and add archive-specific hints before rethrowing
TRY_BEGIN()
{
this->infoPg = infoPgNew(storage, fileName, infoPgArchive, cipherType, cipherPass);
this->infoPg = infoPgNewLoad(storage, fileName, infoPgArchive, cipherType, cipherPass, NULL);
}
CATCH_ANY()
{

View File

@ -43,9 +43,7 @@ struct InfoBackup
};
/***********************************************************************************************************************************
Create a new InfoBackup object
// ??? Need loadFile parameter
// ??? Need to handle ignoreMissing = true
Create new object and load contents from a file
***********************************************************************************************************************************/
InfoBackup *
infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing, CipherType cipherType, const String *cipherPass)
@ -66,6 +64,8 @@ infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing
MEM_CONTEXT_NEW_BEGIN("InfoBackup")
{
Ini *ini = NULL;
// Create object
this = memNew(sizeof(InfoBackup));
this->memContext = MEM_CONTEXT_NEW();
@ -73,7 +73,7 @@ infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing
// Catch file missing error and add backup-specific hints before rethrowing
TRY_BEGIN()
{
this->infoPg = infoPgNew(storage, fileName, infoPgBackup, cipherType, cipherPass);
this->infoPg = infoPgNewLoad(storage, fileName, infoPgBackup, cipherType, cipherPass, &ini);
}
CATCH_ANY()
{
@ -86,21 +86,20 @@ infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing
}
TRY_END();
const Ini *infoIni = infoPgIni(this->infoPg);
const String *backupCurrentSection = STRDEF(INFO_BACKUP_SECTION_BACKUP_CURRENT);
// If there are current backups, then parse the json for each into a list object
if (strLstExists(iniSectionList(infoIni), backupCurrentSection))
if (strLstExists(iniSectionList(ini), backupCurrentSection))
{
// Initialize the store and get the list of backup labels
this->backup = lstNew(sizeof(InfoBackupData));
const StringList *backupLabelList = iniSectionKeyList(infoIni, backupCurrentSection);
const StringList *backupLabelList = iniSectionKeyList(ini, backupCurrentSection);
// For each backup label, store the information
for (unsigned int backupLabelIdx = 0; backupLabelIdx < strLstSize(backupLabelList); backupLabelIdx++)
{
const String *backupLabelKey = strLstGet(backupLabelList, backupLabelIdx);
const KeyValue *backupKv = jsonToKv(iniGet(infoIni, backupCurrentSection, backupLabelKey));
const KeyValue *backupKv = jsonToKv(iniGet(ini, backupCurrentSection, backupLabelKey));
InfoBackupData infoBackupData =
{
@ -138,6 +137,8 @@ infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing
lstAdd(this->backup, &infoBackupData);
}
}
iniFree(ini);
}
MEM_CONTEXT_NEW_END();
@ -147,7 +148,6 @@ infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing
/***********************************************************************************************************************************
Checks the backup info file's DB section against the PG version, system id, catolog and constrol version passed in and returns
the history id of the current PG database.
// ??? Should we still check that the file exists if it is required?
***********************************************************************************************************************************/
unsigned int
infoBackupCheckPg(
@ -187,6 +187,79 @@ infoBackupCheckPg(
FUNCTION_LOG_RETURN(UINT, backupPg.id);
}
/***********************************************************************************************************************************
Save to file
***********************************************************************************************************************************/
void
infoBackupSave(
InfoBackup *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(INFO_PG, this);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
MEM_CONTEXT_TEMP_BEGIN()
{
Ini *ini = iniNew();
// Set the backup current section
for (unsigned int backupIdx = 0; backupIdx < infoBackupDataTotal(this); backupIdx++)
{
InfoBackupData backupData = infoBackupData(this, backupIdx);
KeyValue *backupDataKv = kvNew();
kvPut(backupDataKv, VARSTR(INFO_KEY_FORMAT_STR), VARUINT(backupData.backrestFormat));
kvPut(backupDataKv, VARSTR(INFO_KEY_VERSION_STR), VARSTR(backupData.backrestVersion));
kvPut(backupDataKv, INFO_KEY_DB_ID_VAR, VARUINT(backupData.backupPgId));
kvPut(backupDataKv, INFO_MANIFEST_KEY_BACKUP_ARCHIVE_START_VAR, VARSTR(backupData.backupArchiveStart));
kvPut(backupDataKv, INFO_MANIFEST_KEY_BACKUP_ARCHIVE_STOP_VAR, VARSTR(backupData.backupArchiveStop));
if (backupData.backupPrior != NULL)
kvPut(backupDataKv, INFO_MANIFEST_KEY_BACKUP_PRIOR_VAR, VARSTR(backupData.backupPrior));
if (backupData.backupReference != NULL)
{
kvPut(
backupDataKv, INFO_BACKUP_KEY_BACKUP_REFERENCE_VAR, varNewVarLst(varLstNewStrLst(backupData.backupReference)));
}
kvPut(backupDataKv, INFO_BACKUP_KEY_BACKUP_INFO_REPO_SIZE_VAR, VARUINT64(backupData.backupInfoRepoSize));
kvPut(backupDataKv, INFO_BACKUP_KEY_BACKUP_INFO_REPO_SIZE_DELTA_VAR, VARUINT64(backupData.backupInfoRepoSizeDelta));
kvPut(backupDataKv, INFO_BACKUP_KEY_BACKUP_INFO_SIZE_VAR, VARUINT64(backupData.backupInfoSize));
kvPut(backupDataKv, INFO_BACKUP_KEY_BACKUP_INFO_SIZE_DELTA_VAR, VARUINT64(backupData.backupInfoSizeDelta));
kvPut(backupDataKv, INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_START_VAR, VARUINT64(backupData.backupTimestampStart));
kvPut(backupDataKv, INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_STOP_VAR, VARUINT64(backupData.backupTimestampStop));
kvPut(backupDataKv, INFO_MANIFEST_KEY_BACKUP_TYPE_VAR, VARSTR(backupData.backupType));
kvPut(backupDataKv, INFO_MANIFEST_KEY_OPT_ARCHIVE_CHECK_VAR, VARBOOL(backupData.optionArchiveCheck));
kvPut(backupDataKv, INFO_MANIFEST_KEY_OPT_ARCHIVE_COPY_VAR, VARBOOL(backupData.optionArchiveCopy));
kvPut(backupDataKv, INFO_MANIFEST_KEY_OPT_BACKUP_STANDBY_VAR, VARBOOL(backupData.optionBackupStandby));
kvPut(backupDataKv, INFO_MANIFEST_KEY_OPT_CHECKSUM_PAGE_VAR, VARBOOL(backupData.optionChecksumPage));
kvPut(backupDataKv, INFO_MANIFEST_KEY_OPT_COMPRESS_VAR, VARBOOL(backupData.optionCompress));
kvPut(backupDataKv, INFO_MANIFEST_KEY_OPT_HARDLINK_VAR, VARBOOL(backupData.optionHardlink));
kvPut(backupDataKv, INFO_MANIFEST_KEY_OPT_ONLINE_VAR, VARBOOL(backupData.optionOnline));
iniSet(ini, STRDEF(INFO_BACKUP_SECTION_BACKUP_CURRENT), backupData.backupLabel, jsonFromKv(backupDataKv, 0));
}
infoPgSave(infoBackupPg(this), ini, storage, fileName, cipherType, cipherPass);
}
MEM_CONTEXT_TEMP_END();
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Get PostgreSQL info
***********************************************************************************************************************************/

View File

@ -37,21 +37,17 @@ Object type
struct InfoPg
{
MemContext *memContext; // Mem context
Info *info; // Info contents
List *history; // A list of InfoPgData
unsigned int historyCurrent; // Index of the current history item
Info *info; // Info contents
};
/***********************************************************************************************************************************
Load an InfoPg object
??? Need to consider adding the following parameters in order to throw errors
$bRequired, # Is archive info required? --- may not need this if ignoreMissing is enough
$bLoad, # Should the file attempt to be loaded?
$strCipherPassSub, # Passphrase to encrypt the subsequent archive files if repo is encrypted
??? Currently this assumes the file exists and loads data from it
Create new object and load contents from a file
***********************************************************************************************************************************/
InfoPg *
infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass)
infoPgNewLoad(
const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass, Ini **ini)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
@ -59,6 +55,7 @@ infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, Ciphe
FUNCTION_LOG_PARAM(ENUM, type);
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM_P(INI, ini);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
@ -72,18 +69,20 @@ infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, Ciphe
// Create object
this = memNew(sizeof(InfoPg));
this->memContext = MEM_CONTEXT_NEW();
this->info = infoNew(storage, fileName, cipherType, cipherPass);
// Load info
Ini *iniLocal = NULL;
this->info = infoNewLoad(storage, fileName, cipherType, cipherPass, &iniLocal);
// Get the pg history list
this->history = lstNew(sizeof(InfoPgData));
MEM_CONTEXT_TEMP_BEGIN()
{
const Ini *infoPgIni = infoIni(this->info);
const StringList *pgHistoryKey = iniSectionKeyList(infoPgIni, INFO_SECTION_DB_HISTORY_STR);
const StringList *pgHistoryKey = iniSectionKeyList(iniLocal, INFO_SECTION_DB_HISTORY_STR);
// Get the current history id
unsigned int pgId = jsonToUInt(iniGet(infoPgIni, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_ID_VAR)));
unsigned int pgId = jsonToUInt(iniGet(iniLocal, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_ID_VAR)));
// History must include at least one item or the file is corrupt
ASSERT(strLstSize(pgHistoryKey) > 0);
@ -95,7 +94,7 @@ infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, Ciphe
{
// Load JSON data into a KeyValue
const KeyValue *pgDataKv = jsonToKv(
iniGet(infoPgIni, INFO_SECTION_DB_HISTORY_STR, strLstGet(pgHistoryKey, pgHistoryIdx)));
iniGet(iniLocal, INFO_SECTION_DB_HISTORY_STR, strLstGet(pgHistoryKey, pgHistoryIdx)));
// Get db values that are common to all info files
InfoPgData infoPgData =
@ -128,6 +127,9 @@ infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, Ciphe
}
}
MEM_CONTEXT_TEMP_END();
if (ini != NULL)
*ini = iniMove(iniLocal, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_NEW_END();
@ -153,6 +155,60 @@ infoPgAdd(InfoPg *this, const InfoPgData *infoPgData)
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Save to file
***********************************************************************************************************************************/
void
infoPgSave(
InfoPg *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(INFO_PG, this);
FUNCTION_LOG_PARAM(INI, ini);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(ini != NULL);
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
MEM_CONTEXT_TEMP_BEGIN()
{
// Set the db section
InfoPgData pgData = infoPgDataCurrent(this);
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_ID_VAR), jsonFromUInt(pgData.id));
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_CATALOG_VERSION_VAR), jsonFromUInt(pgData.catalogVersion));
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_CONTROL_VERSION_VAR), jsonFromUInt(pgData.controlVersion));
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_SYSTEM_ID_VAR), jsonFromUInt64(pgData.systemId));
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_VERSION_VAR), jsonFromStr(pgVersionToStr(pgData.version)));
// Set the db history section
for (unsigned int pgDataIdx = 0; pgDataIdx < infoPgDataTotal(this); pgDataIdx++)
{
InfoPgData pgData = infoPgData(this, pgDataIdx);
KeyValue *pgDataKv = kvNew();
kvPut(pgDataKv, INFO_KEY_DB_CATALOG_VERSION_VAR, VARUINT(pgData.catalogVersion));
kvPut(pgDataKv, INFO_KEY_DB_CONTROL_VERSION_VAR, VARUINT(pgData.controlVersion));
kvPut(pgDataKv, INFO_KEY_DB_SYSTEM_ID_VAR, VARUINT64(pgData.systemId));
kvPut(pgDataKv, INFO_KEY_DB_VERSION_VAR, VARSTR(pgVersionToStr(pgData.version)));
iniSet(ini, INFO_SECTION_DB_HISTORY_STR, varStrForce(VARUINT(pgData.id)), jsonFromKv(pgDataKv, 0));
}
infoSave(infoPgInfo(this), ini, storage, fileName, cipherType, cipherPass);
}
MEM_CONTEXT_TEMP_END();
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Construct archive id
***********************************************************************************************************************************/
@ -232,6 +288,21 @@ infoPgDataCurrentId(const InfoPg *this)
FUNCTION_LOG_RETURN(UINT, this->historyCurrent);
}
/***********************************************************************************************************************************
Get base info
***********************************************************************************************************************************/
Info *
infoPgInfo(const InfoPg *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(INFO_PG, this);
FUNCTION_TEST_END();
ASSERT(this != NULL);
FUNCTION_TEST_RETURN(this->info);
}
/***********************************************************************************************************************************
Return total Postgres data in the history
***********************************************************************************************************************************/
@ -247,21 +318,6 @@ infoPgDataTotal(const InfoPg *this)
FUNCTION_LOG_RETURN(UINT, lstSize(this->history));
}
/***********************************************************************************************************************************
Return the ini object
***********************************************************************************************************************************/
Ini *
infoPgIni(const InfoPg *this)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(INFO_PG, this);
FUNCTION_LOG_END();
ASSERT(this != NULL);
FUNCTION_LOG_RETURN(INI, infoIni(this->info));
}
/***********************************************************************************************************************************
Render as string for logging
***********************************************************************************************************************************/

View File

@ -13,6 +13,7 @@ typedef struct InfoPg InfoPg;
#include "common/crypto/common.h"
#include "common/ini.h"
#include "info/info.h"
#include "storage/storage.h"
/***********************************************************************************************************************************
@ -46,7 +47,10 @@ typedef enum
/***********************************************************************************************************************************
Constructor
***********************************************************************************************************************************/
InfoPg *infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass);
InfoPg *infoPgNewLoad(
const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass, Ini **ini);
void infoPgSave(
InfoPg *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
/***********************************************************************************************************************************
Functions
@ -61,8 +65,8 @@ const String *infoPgCipherPass(const InfoPg *this);
InfoPgData infoPgData(const InfoPg *this, unsigned int pgDataIdx);
InfoPgData infoPgDataCurrent(const InfoPg *this);
unsigned int infoPgDataCurrentId(const InfoPg *this);
Info *infoPgInfo(const InfoPg *this);
unsigned int infoPgDataTotal(const InfoPg *this);
Ini *infoPgIni(const InfoPg *this);
/***********************************************************************************************************************************
Destructor

View File

@ -576,7 +576,7 @@ unit:
test:
# ----------------------------------------------------------------------------------------------------------------------------
- name: info
total: 1
total: 2
coverage:
info/info: full

View File

@ -13,6 +13,7 @@ testRun(void)
//--------------------------------------------------------------------------------------------------------------------------
String *content = NULL;
String *fileName = strNewFmt("%s/test.ini", testPath());
String *fileName2 = strNewFmt("%s/test2.ini", testPath());
InfoBackup *infoBackup = NULL;
// *****************************************************************************************************************************
@ -94,13 +95,6 @@ testRun(void)
//--------------------------------------------------------------------------------------------------------------------------
content = strNew
(
"[db]\n"
"db-catalog-version=201409291\n"
"db-control-version=942\n"
"db-id=1\n"
"db-system-id=6569239123849665679\n"
"db-version=\"9.4\"\n"
"\n"
"[backup:current]\n"
"20161219-212741F={\"backrest-format\":5,\"backrest-version\":\"2.04\","
"\"backup-archive-start\":\"00000007000000000000001C\",\"backup-archive-stop\":\"00000007000000000000001C\","
@ -125,6 +119,13 @@ testRun(void)
"\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
"\"option-checksum-page\":false,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
"\n"
"[db]\n"
"db-catalog-version=201409291\n"
"db-control-version=942\n"
"db-id=1\n"
"db-system-id=6569239123849665679\n"
"db-version=\"9.4\"\n"
"\n"
"[db:history]\n"
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
"\"db-version\":\"9.4\"}\n"
@ -133,8 +134,16 @@ testRun(void)
TEST_RESULT_VOID(
storagePutNP(
storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put backup info current to file");
TEST_ASSIGN(infoBackup, infoBackupNew(storageLocal(), fileName, false, cipherTypeNone, NULL), " new backup info");
// Save the file and verify it
TEST_RESULT_VOID(infoBackupSave(infoBackup, storageLocalWrite(), fileName2, cipherTypeNone, NULL), "save file");
TEST_RESULT_BOOL(
bufEq(
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
storageGetNP(storageNewReadNP(storageLocal(), fileName2))),
true, "files are equal");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 3, " backup list contains backups");
InfoBackupData backupData = infoBackupData(infoBackup, 0);

View File

@ -10,10 +10,11 @@ void
testRun(void)
{
// *****************************************************************************************************************************
if (testBegin("infoPgNew(), infoPgFree(), infoPgDataCurrent(), infoPgDataToLog(), infoPgAdd(), infoPgIni()"))
if (testBegin("infoPgNewLoad(), infoPgFree(), infoPgDataCurrent(), infoPgDataToLog(), infoPgAdd(), infoPgIni()"))
{
String *content = NULL;
String *fileName = strNewFmt("%s/test.ini", testPath());
String *fileName2 = strNewFmt("%s/test2.ini", testPath());
// Archive info
//--------------------------------------------------------------------------------------------------------------------------
@ -32,9 +33,11 @@ testRun(void)
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put info to file");
InfoPg *infoPg = NULL;
Ini *ini = NULL;
TEST_ASSIGN(
infoPg, infoPgNew(storageLocal(), fileName, infoPgArchive, cipherTypeNone, NULL), "new infoPg archive - load file");
infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgArchive, cipherTypeNone, NULL, &ini), "load file");
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("db"), strNew("db-id"))), "1", " check ini");
TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added");
@ -68,7 +71,7 @@ testRun(void)
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put info to file");
TEST_ASSIGN(
infoPg, infoPgNew(storageLocal(), fileName, infoPgBackup, cipherTypeNone, NULL), "new infoPg backup - load file");
infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgBackup, cipherTypeNone, NULL, NULL), "load file");
TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added");
@ -97,11 +100,20 @@ testRun(void)
"\"db-version\":\"9.5\"}\n"
);
// Put the file and load it
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put info to file");
TEST_ASSIGN(
infoPg, infoPgNew(storageLocal(), fileName, infoPgManifest, cipherTypeNone, NULL), "new infoPg manifest - load file");
infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgManifest, cipherTypeNone, NULL, NULL), "load file");
// Save the file and verify it
ini = iniNew();
TEST_RESULT_VOID(infoPgSave(infoPg, ini, storageLocalWrite(), fileName2, cipherTypeNone, NULL), "save file");
TEST_RESULT_BOOL(
bufEq(
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
storageGetNP(storageNewReadNP(storageLocal(), fileName2))),
true, "files are equal");
TEST_RESULT_INT(lstSize(infoPg->history), 2, "history record added");
@ -128,17 +140,11 @@ testRun(void)
TEST_RESULT_INT(infoPgDataTest.catalogVersion, 201608131, " catalog-version set");
TEST_RESULT_INT(infoPgDataTest.controlVersion, 960, " control-version set");
// infoPgIni
//--------------------------------------------------------------------------------------------------------------------------
Ini *infoIni = NULL;
TEST_ASSIGN(infoIni, infoPgIni(infoPg), "get ini from infoPg");
TEST_RESULT_BOOL(strLstExists(iniSectionList(infoIni), strNew("backrest")), true, " section exists in ini");
// Errors
//--------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(infoPgNew(storageLocal(), fileName, 10, cipherTypeNone, NULL), AssertError, "invalid InfoPg type 10");
TEST_ERROR(infoPgNewLoad(storageLocal(), fileName, 10, cipherTypeNone, NULL, NULL), AssertError, "invalid InfoPg type 10");
TEST_ERROR(
infoPgNew(storageLocal(), NULL, infoPgManifest, cipherTypeNone, NULL), AssertError,
infoPgNewLoad(storageLocal(), NULL, infoPgManifest, cipherTypeNone, NULL, NULL), AssertError,
"assertion 'fileName != NULL' failed");
TEST_ERROR(infoPgDataCurrent(NULL), AssertError, "assertion 'this != NULL' failed");

View File

@ -1,6 +1,7 @@
/***********************************************************************************************************************************
Test Info Handler
***********************************************************************************************************************************/
#include "storage/driver/posix/storage.h"
/***********************************************************************************************************************************
Test Run
@ -8,8 +9,12 @@ Test Run
void
testRun(void)
{
// Create default storage object for testing
Storage *storageTest = storageDriverPosixInterface(
storageDriverPosixNew(strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL));
// *****************************************************************************************************************************
if (testBegin("infoNew(), infoExists(), infoFileName(), infoIni()"))
if (testBegin("infoNewLoad(), infoFileName(), infoIni()"))
{
// Initialize test variables
//--------------------------------------------------------------------------------------------------------------------------
@ -37,7 +42,7 @@ testRun(void)
// Info files missing and at least one is required
//--------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(
infoNew(storageLocal(), fileName, cipherTypeNone, NULL), FileMissingError,
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), FileMissingError,
strPtr(
strNewFmt(
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
@ -50,10 +55,8 @@ testRun(void)
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileNameCopy), BUFSTR(content)), "put info.copy to file");
TEST_ASSIGN(info, infoNew(storageLocal(), fileName, cipherTypeNone, NULL), "infoNew() - load copy file");
TEST_RESULT_STR(strPtr(infoFileName(info)), strPtr(fileName), " infoFileName() is set");
TEST_ASSIGN(info, infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), "load copy file");
TEST_RESULT_PTR(infoIni(info), info->ini, " infoIni() returns pointer to info->ini");
TEST_RESULT_PTR(infoCipherPass(info), NULL, " cipherPass is not set");
// Remove the copy and store only the main info file and encrypt it. One is required.
@ -87,9 +90,10 @@ testRun(void)
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.4\"}\n"));
// Only main info exists and is required
TEST_ASSIGN(info, infoNew(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("12345678")), "infoNew() - load file");
Ini *ini = NULL;
TEST_ASSIGN(info, infoNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("12345678"), &ini), "load file");
TEST_RESULT_STR(strPtr(infoFileName(info)), strPtr(fileName), " infoFileName() is set");
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("cipher"), strNew("cipher-pass"))), "\"ABCDEFGH\"", " check ini");
TEST_RESULT_STR(strPtr(infoCipherPass(info)), "ABCDEFGH", " cipherPass is set");
// Invalid format
@ -120,7 +124,7 @@ testRun(void)
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), BUFSTR(content)), "put invalid br format to file");
TEST_ERROR(
infoNew(storageLocal(), fileName, cipherTypeNone, NULL), FormatError,
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), FormatError,
strPtr(
strNewFmt(
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
@ -152,7 +156,7 @@ testRun(void)
storageNewWriteNP(storageLocalWrite(), fileNameCopy), BUFSTR(content)), "put invalid info to copy file");
TEST_ERROR(
infoNew(storageLocal(), fileName, cipherTypeNone, NULL), FileOpenError,
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), FileOpenError,
strPtr(
strNewFmt(
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
@ -210,7 +214,7 @@ testRun(void)
// Copy file error
TEST_ERROR(
infoNew(storageLocal(), fileName, cipherTypeNone, NULL), ChecksumError,
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), ChecksumError,
strPtr(
strNewFmt(
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
@ -224,7 +228,7 @@ testRun(void)
//--------------------------------------------------------------------------------------------------------------------------
storageRemoveNP(storageLocalWrite(), fileName);
TEST_ERROR(
infoNew(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("12345678")), CryptoError,
infoNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("12345678"), NULL), CryptoError,
strPtr(
strNewFmt(
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
@ -240,4 +244,32 @@ testRun(void)
TEST_RESULT_VOID(infoFree(info), "infoFree() - free info memory context");
TEST_RESULT_VOID(infoFree(NULL), " NULL ptr");
}
// *****************************************************************************************************************************
if (testBegin("infoSave()"))
{
const String *fileName = strNew("test.info");
const String *cipherPass = strNew("12345");
Ini *ini = iniNew();
iniSet(ini, strNew("section1"), strNew("key1"), strNew("value1"));
TEST_RESULT_VOID(infoSave(infoNew(), ini, storageTest, fileName, cipherTypeNone, NULL), "save info");
ini = NULL;
TEST_RESULT_VOID(infoNewLoad(storageTest, fileName, cipherTypeNone, NULL, &ini), " reload info");
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("section1"), strNew("key1"))), "value1", " check ini");
TEST_RESULT_BOOL(storageExistsNP(storageTest, fileName), true, "check main exists");
TEST_RESULT_BOOL(storageExistsNP(storageTest, strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName))), true, "check main exists");
// Add encryption
// -------------------------------------------------------------------------------------------------------------------------
ini = iniNew();
iniSet(ini, strNew("section1"), strNew("key1"), strNew("value4"));
TEST_RESULT_VOID(infoSave(infoNew(), ini, storageTest, fileName, cipherTypeAes256Cbc, cipherPass), "save encrypted info");
ini = NULL;
TEST_RESULT_VOID(infoNewLoad(storageTest, fileName, cipherTypeAes256Cbc, cipherPass, &ini), " reload info");
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("section1"), strNew("key1"))), "value4", " check ini");
}
}