diff --git a/src/Makefile.in b/src/Makefile.in index a5369aaf5..59abc7c39 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -454,13 +454,13 @@ db/helper.o: db/helper.c build.auto.h common/assert.h common/debug.h common/erro db/protocol.o: db/protocol.c build.auto.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/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/list.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 db/protocol.h postgres/client.h postgres/interface.h protocol/client.h protocol/command.h protocol/server.h storage/info.h storage/read.h storage/storage.h storage/write.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c db/protocol.c -o db/protocol.o -info/info.o: info/info.c build.auto.h 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/filter.intern.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.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/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h +info/info.o: info/info.c build.auto.h common/assert.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.h common/debug.h common/encode.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/filter.intern.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.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/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/info.c -o info/info.o -info/infoArchive.o: info/infoArchive.c build.auto.h 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/macro.h common/memContext.h common/object.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/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h +info/infoArchive.o: info/infoArchive.c build.auto.h 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/macro.h common/memContext.h common/object.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 postgres/version.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/infoArchive.c -o info/infoArchive.o -info/infoBackup.o: info/infoBackup.c build.auto.h 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/macro.h common/memContext.h common/object.h common/regExp.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/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h +info/infoBackup.o: info/infoBackup.c build.auto.h 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/macro.h common/memContext.h common/object.h common/regExp.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 postgres/version.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/infoBackup.c -o info/infoBackup.o info/infoManifest.o: info/infoManifest.c build.auto.h common/error.auto.h common/error.h common/memContext.h common/type/buffer.h common/type/keyValue.h common/type/string.h common/type/variant.h common/type/variantList.h info/infoManifest.h diff --git a/src/info/info.c b/src/info/info.c index faaf2eb34..7f84de00a 100644 --- a/src/info/info.c +++ b/src/info/info.c @@ -10,6 +10,7 @@ Info Handler #include "common/crypto/cipherBlock.h" #include "common/crypto/hash.h" #include "common/debug.h" +#include "common/encode.h" #include "common/io/filter/filter.intern.h" #include "common/ini.h" #include "common/log.h" @@ -42,6 +43,52 @@ struct Info OBJECT_DEFINE_FREE(INFO); +/*********************************************************************************************************************************** +Internal constructor +***********************************************************************************************************************************/ +static Info * +infoNewInternal(void) +{ + FUNCTION_LOG_VOID(logLevelTrace); + + Info *this = NULL; + + MEM_CONTEXT_NEW_BEGIN("Info") + { + // Create object + this = memNew(sizeof(Info)); + this->memContext = MEM_CONTEXT_NEW(); + } + MEM_CONTEXT_NEW_END(); + + FUNCTION_LOG_RETURN(INFO, this); +} + +/*********************************************************************************************************************************** +Create new object +***********************************************************************************************************************************/ +Info * +infoNew(CipherType cipherType, const String *cipherPassSub) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(ENUM, cipherType); + FUNCTION_TEST_PARAM(STRING, cipherPassSub); // Use FUNCTION_TEST so cipher is not logged + FUNCTION_LOG_END(); + + // Ensure cipherPassSub is set and not an empty string when cipherType is not NONE and is not set when cipherType is NONE + ASSERT( + !((cipherType == cipherTypeNone && cipherPassSub != NULL) || + (cipherType != cipherTypeNone && (cipherPassSub == NULL || strSize(cipherPassSub) == 0)))); + + Info *this = infoNewInternal(); + + // Cipher used to encrypt/descrypt subsequent dependent files. Value may be NULL. + if (cipherPassSub != NULL) + this->cipherPass = cipherPassSub; + + FUNCTION_LOG_RETURN(INFO, this); +} + /*********************************************************************************************************************************** Generate hash for the contents of an ini file ***********************************************************************************************************************************/ @@ -206,27 +253,6 @@ infoLoad(Info *this, const Storage *storage, const String *fileName, bool copyFi FUNCTION_LOG_RETURN(INI, result); } -/*********************************************************************************************************************************** -Create new object -***********************************************************************************************************************************/ -Info * -infoNew(void) -{ - FUNCTION_LOG_VOID(logLevelTrace); - - Info *this = NULL; - - MEM_CONTEXT_NEW_BEGIN("Info") - { - // Create object - this = memNew(sizeof(Info)); - this->memContext = MEM_CONTEXT_NEW(); - } - MEM_CONTEXT_NEW_END(); - - FUNCTION_LOG_RETURN(INFO, this); -} - /*********************************************************************************************************************************** Create new object and load contents from a file ***********************************************************************************************************************************/ @@ -245,7 +271,7 @@ infoNewLoad(const Storage *storage, const String *fileName, CipherType cipherTyp ASSERT(fileName != NULL); ASSERT(cipherType == cipherTypeNone || cipherPass != NULL); - Info *this = infoNew(); + Info *this = infoNewInternal(); MEM_CONTEXT_BEGIN(this->memContext) { @@ -285,10 +311,10 @@ infoNewLoad(const Storage *storage, const String *fileName, CipherType cipherTyp TRY_END(); // Load the cipher passphrase if it exists - const String *cipherPass = iniGetDefault(iniLocal, INFO_SECTION_CIPHER_STR, INFO_KEY_CIPHER_PASS_STR, NULL); + const String *cipherPassSub = iniGetDefault(iniLocal, INFO_SECTION_CIPHER_STR, INFO_KEY_CIPHER_PASS_STR, NULL); - if (cipherPass != NULL) - this->cipherPass = jsonToStr(cipherPass); + if (cipherPassSub != NULL) + this->cipherPass = jsonToStr(cipherPassSub); if (ini != NULL) *ini = iniMove(iniLocal, MEM_CONTEXT_OLD()); @@ -319,6 +345,9 @@ infoSave( ASSERT(storage != NULL); ASSERT(fileName != NULL); ASSERT(cipherType == cipherTypeNone || cipherPass != NULL); + ASSERT( + !((cipherType != cipherTypeNone && this->cipherPass == NULL) || + (cipherType == cipherTypeNone && this->cipherPass != NULL))); MEM_CONTEXT_TEMP_BEGIN() { diff --git a/src/info/info.h b/src/info/info.h index 6ce3b2e47..5e87d1edf 100644 --- a/src/info/info.h +++ b/src/info/info.h @@ -29,8 +29,12 @@ Constants /*********************************************************************************************************************************** Constructors ***********************************************************************************************************************************/ -Info *infoNew(void); +Info *infoNew(CipherType cipherType, const String *cipherPassSub); Info *infoNewLoad(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass, Ini **ini); + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ void infoSave( Info *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); diff --git a/src/info/infoArchive.c b/src/info/infoArchive.c index c765924fe..989081a2a 100644 --- a/src/info/infoArchive.c +++ b/src/info/infoArchive.c @@ -16,6 +16,7 @@ Archive Info Handler #include "info/infoArchive.h" #include "info/infoPg.h" #include "postgres/interface.h" +#include "postgres/version.h" #include "storage/helper.h" /*********************************************************************************************************************************** @@ -36,6 +37,51 @@ struct InfoArchive OBJECT_DEFINE_FREE(INFO_ARCHIVE); +/*********************************************************************************************************************************** +Internal constructor +***********************************************************************************************************************************/ +static InfoArchive * +infoArchiveNewInternal(void) +{ + FUNCTION_LOG_VOID(logLevelTrace); + + InfoArchive *this = NULL; + + MEM_CONTEXT_NEW_BEGIN("InfoArchive") + { + // Create object + this = memNew(sizeof(InfoArchive)); + this->memContext = MEM_CONTEXT_NEW(); + } + MEM_CONTEXT_NEW_END(); + + FUNCTION_LOG_RETURN(INFO_ARCHIVE, this); +} + +/*********************************************************************************************************************************** +Create new object without loading it from a file +***********************************************************************************************************************************/ +InfoArchive * +infoArchiveNew(unsigned int pgVersion, uint64_t pgSystemId, CipherType cipherType, const String *cipherPassSub) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(UINT, pgVersion); + FUNCTION_LOG_PARAM(UINT64, pgSystemId); + FUNCTION_LOG_PARAM(ENUM, cipherType); + FUNCTION_TEST_PARAM(STRING, cipherPassSub); + FUNCTION_LOG_END(); + + ASSERT(pgVersion > 0 && pgSystemId > 0); + + InfoArchive *this = infoArchiveNewInternal(); + + // Initialize the pg data + this->infoPg = infoPgNew(cipherType, cipherPassSub); + infoArchivePgSet(this, pgVersion, pgSystemId); + + FUNCTION_LOG_RETURN(INFO_ARCHIVE, this); +} + /*********************************************************************************************************************************** Create new object and load contents from a file ***********************************************************************************************************************************/ @@ -53,14 +99,10 @@ infoArchiveNewLoad(const Storage *storage, const String *fileName, CipherType ci ASSERT(fileName != NULL); ASSERT(cipherType == cipherTypeNone || cipherPass != NULL); - InfoArchive *this = NULL; + InfoArchive *this = infoArchiveNewInternal(); - MEM_CONTEXT_NEW_BEGIN("InfoArchive") + MEM_CONTEXT_BEGIN(this->memContext) { - // Create object - this = memNew(sizeof(InfoArchive)); - this->memContext = MEM_CONTEXT_NEW(); - // Catch file missing error and add archive-specific hints before rethrowing TRY_BEGIN() { @@ -82,11 +124,60 @@ infoArchiveNewLoad(const Storage *storage, const String *fileName, CipherType ci // Store the archiveId for the current PG db-version db-id this->archiveId = infoPgArchiveId(this->infoPg, infoPgDataCurrentId(this->infoPg)); } - MEM_CONTEXT_NEW_END(); + MEM_CONTEXT_END(); FUNCTION_LOG_RETURN(INFO_ARCHIVE, this); } +/*********************************************************************************************************************************** +Set the infoPg data +***********************************************************************************************************************************/ +InfoArchive * +infoArchivePgSet(InfoArchive *this, unsigned int pgVersion, uint64_t pgSystemId) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(INFO_ARCHIVE, this); + FUNCTION_LOG_PARAM(UINT, pgVersion); + FUNCTION_LOG_PARAM(UINT64, pgSystemId); + FUNCTION_LOG_END(); + + ASSERT(this != NULL); + + this->infoPg = infoPgSet(this->infoPg, infoPgArchive, pgVersion, pgSystemId, 0, 0); + this->archiveId = infoPgArchiveId(this->infoPg, infoPgDataCurrentId(this->infoPg)); + + FUNCTION_LOG_RETURN(INFO_ARCHIVE, this); +} + +/*********************************************************************************************************************************** +Save to file +***********************************************************************************************************************************/ +void +infoArchiveSave( + InfoArchive *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(INFO_ARCHIVE, 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() + { + infoPgSave(infoArchivePg(this), iniNew(), storage, fileName, infoPgArchive, cipherType, cipherPass); + } + MEM_CONTEXT_TEMP_END(); + + FUNCTION_LOG_RETURN_VOID(); +} + /*********************************************************************************************************************************** Given a backrest history id and postgres systemId and version, return the archiveId of the best match ***********************************************************************************************************************************/ diff --git a/src/info/infoArchive.h b/src/info/infoArchive.h index 42606ba2f..8b647c0ef 100644 --- a/src/info/infoArchive.h +++ b/src/info/infoArchive.h @@ -29,8 +29,10 @@ Archive info filename STRING_DECLARE(INFO_ARCHIVE_PATH_FILE_COPY_STR); /*********************************************************************************************************************************** -Constructor +Constructors ***********************************************************************************************************************************/ +InfoArchive *infoArchiveNew( + const unsigned int pgVersion, const uint64_t pgSystemId, CipherType cipherType, const String *cipherPassSub); InfoArchive *infoArchiveNewLoad( const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); @@ -39,6 +41,10 @@ Functions ***********************************************************************************************************************************/ const String *infoArchiveIdHistoryMatch( const InfoArchive *this, const unsigned int historyId, const unsigned int pgVersion, const uint64_t pgSystemId); +InfoArchive *infoArchivePgSet( + InfoArchive *this, unsigned int pgVersion, uint64_t pgSystemId); +void infoArchiveSave( + InfoArchive *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); /*********************************************************************************************************************************** Getters diff --git a/src/info/infoBackup.c b/src/info/infoBackup.c index add07cb2c..aff5b5403 100644 --- a/src/info/infoBackup.c +++ b/src/info/infoBackup.c @@ -21,6 +21,7 @@ Backup Info Handler #include "info/infoManifest.h" #include "info/infoPg.h" #include "postgres/interface.h" +#include "postgres/version.h" #include "storage/helper.h" /*********************************************************************************************************************************** @@ -51,6 +52,54 @@ struct InfoBackup OBJECT_DEFINE_FREE(INFO_BACKUP); +/*********************************************************************************************************************************** +Create new object +***********************************************************************************************************************************/ +static InfoBackup * +infoBackupNewInternal(void) +{ + FUNCTION_LOG_VOID(logLevelTrace); + + InfoBackup *this = NULL; + + MEM_CONTEXT_NEW_BEGIN("InfoBackup") + { + // Create object + this = memNew(sizeof(InfoBackup)); + this->memContext = MEM_CONTEXT_NEW(); + } + MEM_CONTEXT_NEW_END(); + + FUNCTION_LOG_RETURN(INFO_BACKUP, this); +} + +/*********************************************************************************************************************************** +Create new object without loading it from a file +***********************************************************************************************************************************/ +InfoBackup * +infoBackupNew(unsigned int pgVersion, uint64_t pgSystemId, const uint32_t pgControlVersion, const uint32_t pgCatalogVersion, + CipherType cipherType, const String *cipherPassSub) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(UINT, pgVersion); + FUNCTION_LOG_PARAM(UINT64, pgSystemId); + FUNCTION_LOG_PARAM(ENUM, cipherType); + FUNCTION_TEST_PARAM(STRING, cipherPassSub); + FUNCTION_LOG_PARAM(UINT32, pgControlVersion); + FUNCTION_LOG_PARAM(UINT32, pgCatalogVersion); + FUNCTION_LOG_END(); + + ASSERT(pgVersion > 0 && pgSystemId > 0 && pgControlVersion > 0 && pgCatalogVersion > 0); + + InfoBackup *this = infoBackupNewInternal(); + + // Initialize the pg data + this->infoPg = infoPgNew(cipherType, cipherPassSub); + infoBackupPgSet(this, pgVersion, pgSystemId, pgControlVersion, pgCatalogVersion); + + FUNCTION_LOG_RETURN(INFO_BACKUP, this); +} + /*********************************************************************************************************************************** Create new object and load contents from a file ***********************************************************************************************************************************/ @@ -68,16 +117,12 @@ infoBackupNewLoad(const Storage *storage, const String *fileName, CipherType cip ASSERT(fileName != NULL); ASSERT(cipherType == cipherTypeNone || cipherPass != NULL); - InfoBackup *this = NULL; + InfoBackup *this = infoBackupNewInternal(); - MEM_CONTEXT_NEW_BEGIN("InfoBackup") + MEM_CONTEXT_BEGIN(this->memContext) { Ini *ini = NULL; - // Create object - this = memNew(sizeof(InfoBackup)); - this->memContext = MEM_CONTEXT_NEW(); - // Catch file missing error and add backup-specific hints before rethrowing TRY_BEGIN() { @@ -148,7 +193,7 @@ infoBackupNewLoad(const Storage *storage, const String *fileName, CipherType cip iniFree(ini); } - MEM_CONTEXT_NEW_END(); + MEM_CONTEXT_END(); FUNCTION_LOG_RETURN(INFO_BACKUP, this); } @@ -219,7 +264,7 @@ infoBackupSave( iniSet(ini, STRDEF(INFO_BACKUP_SECTION_BACKUP_CURRENT), backupData.backupLabel, jsonFromKv(backupDataKv, 0)); } - infoPgSave(infoBackupPg(this), ini, storage, fileName, cipherType, cipherPass); + infoPgSave(infoBackupPg(this), ini, storage, fileName, infoPgBackup, cipherType, cipherPass); } MEM_CONTEXT_TEMP_END(); @@ -241,6 +286,25 @@ infoBackupPg(const InfoBackup *this) FUNCTION_TEST_RETURN(this->infoPg); } +/*********************************************************************************************************************************** +Set the infoPg data +***********************************************************************************************************************************/ +InfoBackup * +infoBackupPgSet(InfoBackup *this, unsigned int pgVersion, uint64_t pgSystemId, uint32_t pgControlVersion, uint32_t pgCatalogVersion) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(INFO_BACKUP, this); + FUNCTION_LOG_PARAM(UINT, pgVersion); + FUNCTION_LOG_PARAM(UINT64, pgSystemId); + FUNCTION_LOG_PARAM(UINT32, pgControlVersion); + FUNCTION_LOG_PARAM(UINT32, pgCatalogVersion); + FUNCTION_LOG_END(); + + this->infoPg = infoPgSet(this->infoPg, infoPgBackup, pgVersion, pgSystemId, pgControlVersion, pgCatalogVersion); + + FUNCTION_LOG_RETURN(INFO_BACKUP, this); +} + /*********************************************************************************************************************************** Get total current backups ***********************************************************************************************************************************/ @@ -333,6 +397,21 @@ infoBackupDataLabelList(const InfoBackup *this, const String *expression) FUNCTION_LOG_RETURN(STRING_LIST, result); } +/*********************************************************************************************************************************** +Return the cipher passphrase +***********************************************************************************************************************************/ +const String * +infoBackupCipherPass(const InfoBackup *this) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(INFO_BACKUP, this); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + + FUNCTION_TEST_RETURN(infoPgCipherPass(this->infoPg)); +} + /*********************************************************************************************************************************** Render as string for logging ***********************************************************************************************************************************/ diff --git a/src/info/infoBackup.h b/src/info/infoBackup.h index 0246a5fef..e724b8960 100644 --- a/src/info/infoBackup.h +++ b/src/info/infoBackup.h @@ -57,8 +57,11 @@ typedef struct InfoBackupData } InfoBackupData; /*********************************************************************************************************************************** -Constructor +Constructors ***********************************************************************************************************************************/ +InfoBackup *infoBackupNew( + unsigned int pgVersion, uint64_t pgSystemId, const uint32_t pgControlVersion, const uint32_t pgCatalogVersion, + CipherType cipherType, const String *cipherPassSub); InfoBackup *infoBackupNewLoad( const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); @@ -67,6 +70,8 @@ Functions ***********************************************************************************************************************************/ // Remove a backup from the current section void infoBackupDataDelete(const InfoBackup *this, const String *backupDeleteLabel); +InfoBackup *infoBackupPgSet( + InfoBackup *this, unsigned int pgVersion, uint64_t pgSystemId, uint32_t pgControlVersion, uint32_t pgCatalogVersion); void infoBackupSave( InfoBackup *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); @@ -81,6 +86,7 @@ Getters InfoPg *infoBackupPg(const InfoBackup *this); InfoBackupData infoBackupData(const InfoBackup *this, unsigned int backupDataIdx); unsigned int infoBackupDataTotal(const InfoBackup *this); +const String *infoBackupCipherPass(const InfoBackup *this); /*********************************************************************************************************************************** Destructor diff --git a/src/info/infoPg.c b/src/info/infoPg.c index 211073558..0019f0813 100644 --- a/src/info/infoPg.c +++ b/src/info/infoPg.c @@ -46,6 +46,50 @@ struct InfoPg OBJECT_DEFINE_FREE(INFO_PG); +/*********************************************************************************************************************************** +Internal constructor +***********************************************************************************************************************************/ +static InfoPg * +infoPgNewInternal(void) +{ + FUNCTION_LOG_VOID(logLevelTrace); + + InfoPg *this = NULL; + + MEM_CONTEXT_NEW_BEGIN("InfoPg") + { + // Create object + this = memNew(sizeof(InfoPg)); + this->memContext = MEM_CONTEXT_NEW(); + + // Get the pg history list + this->history = lstNew(sizeof(InfoPgData)); + + this->historyCurrent = 0; + } + MEM_CONTEXT_NEW_END(); + + FUNCTION_LOG_RETURN(INFO_PG, this); +} + +/*********************************************************************************************************************************** +Create new object +***********************************************************************************************************************************/ +InfoPg * +infoPgNew(CipherType cipherType, const String *cipherPassSub) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(ENUM, cipherType); + FUNCTION_TEST_PARAM(STRING, cipherPassSub); + FUNCTION_LOG_END(); + + InfoPg *this = infoPgNewInternal(); + + this->info = infoNew(cipherType, cipherPassSub); + + FUNCTION_LOG_RETURN(INFO_PG, this); +} + /*********************************************************************************************************************************** Create new object and load contents from a file ***********************************************************************************************************************************/ @@ -66,21 +110,14 @@ infoPgNewLoad( ASSERT(fileName != NULL); ASSERT(cipherType == cipherTypeNone || cipherPass != NULL); - InfoPg *this = NULL; + InfoPg *this = infoPgNewInternal(); - MEM_CONTEXT_NEW_BEGIN("InfoPg") + MEM_CONTEXT_BEGIN(this->memContext) { - // Create object - this = memNew(sizeof(InfoPg)); - this->memContext = MEM_CONTEXT_NEW(); - // 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 StringList *pgHistoryKey = iniSectionKeyList(iniLocal, INFO_SECTION_DB_HISTORY_STR); @@ -135,7 +172,7 @@ infoPgNewLoad( if (ini != NULL) *ini = iniMove(iniLocal, MEM_CONTEXT_OLD()); } - MEM_CONTEXT_NEW_END(); + MEM_CONTEXT_END(); FUNCTION_LOG_RETURN(INFO_PG, this); } @@ -155,22 +192,78 @@ infoPgAdd(InfoPg *this, const InfoPgData *infoPgData) ASSERT(infoPgData != NULL); lstInsert(this->history, 0, infoPgData); + this->historyCurrent = 0; FUNCTION_LOG_RETURN_VOID(); } +/*********************************************************************************************************************************** +Set the InfoPg object data based on values passed. +***********************************************************************************************************************************/ +InfoPg * +infoPgSet( + InfoPg *this, InfoPgType type, const unsigned int pgVersion, const uint64_t pgSystemId, const uint32_t pgControlVersion, + const uint32_t pgCatalogVersion) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(INFO_PG, this); + FUNCTION_LOG_PARAM(ENUM, type); + FUNCTION_LOG_PARAM(UINT, pgVersion); + FUNCTION_LOG_PARAM(UINT64, pgSystemId); + FUNCTION_LOG_PARAM(UINT32, pgControlVersion); + FUNCTION_TEST_PARAM(UINT32, pgCatalogVersion); + FUNCTION_LOG_END(); + + ASSERT(this != NULL); + + MEM_CONTEXT_TEMP_BEGIN() + { + unsigned int pgDataId = 1; + + // If there is some history, then get the historyId of the most current and increment it + if (infoPgDataTotal(this) > 0) + pgDataId = infoPgCurrentDataId(this) + 1; + + // Set db values that are common to all info files + InfoPgData infoPgData = + { + .id = pgDataId, + .version = pgVersion, + + // This is different in archive.info due to a typo that can't be fixed without a format version bump + .systemId = pgSystemId, + }; + + if (type == infoPgBackup || type == infoPgManifest) + { + infoPgData.catalogVersion = pgCatalogVersion; + infoPgData.controlVersion = pgControlVersion; + } + else if (type != infoPgArchive) + THROW_FMT(AssertError, "invalid InfoPg type %u", type); + + // Add the pg data to the history list + infoPgAdd(this, &infoPgData); + } + MEM_CONTEXT_TEMP_END(); + + FUNCTION_LOG_RETURN(INFO_PG, this); +} + /*********************************************************************************************************************************** Save to file ***********************************************************************************************************************************/ void infoPgSave( - InfoPg *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass) + InfoPg *this, Ini *ini, const Storage *storage, const String *fileName, InfoPgType type, 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, type); FUNCTION_LOG_PARAM(ENUM, cipherType); FUNCTION_TEST_PARAM(STRING, cipherPass); FUNCTION_LOG_END(); @@ -187,10 +280,17 @@ infoPgSave( 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))); + iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_SYSTEM_ID_VAR), jsonFromUInt64(pgData.systemId)); + + if (type == infoPgBackup || type == infoPgManifest) + { + + 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)); + } + else if (type != infoPgArchive) + THROW_FMT(AssertError, "invalid InfoPg type %u", type); // Set the db history section in reverse so oldest history is first instead of last to be consistent with load for (unsigned int pgDataIdx = infoPgDataTotal(this) - 1; (int)pgDataIdx >= 0; pgDataIdx--) @@ -198,11 +298,17 @@ infoPgSave( 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))); + if (type == infoPgBackup || type == infoPgManifest) + { + 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)); + } + else + kvPut(pgDataKv, INFO_KEY_DB_ID_VAR, VARUINT64(pgData.systemId)); + iniSet(ini, INFO_SECTION_DB_HISTORY_STR, varStrForce(VARUINT(pgData.id)), jsonFromKv(pgDataKv, 0)); } @@ -322,6 +428,23 @@ infoPgDataTotal(const InfoPg *this) FUNCTION_LOG_RETURN(UINT, lstSize(this->history)); } +/*********************************************************************************************************************************** +Return current pgId from the history +***********************************************************************************************************************************/ +unsigned int +infoPgCurrentDataId(const InfoPg *this) +{ + FUNCTION_LOG_BEGIN(logLevelTrace); + FUNCTION_LOG_PARAM(INFO_PG, this); + FUNCTION_LOG_END(); + + ASSERT(this != NULL); + + InfoPgData currentData = infoPgDataCurrent(this); + + FUNCTION_LOG_RETURN(UINT, currentData.id); +} + /*********************************************************************************************************************************** Render as string for logging ***********************************************************************************************************************************/ diff --git a/src/info/infoPg.h b/src/info/infoPg.h index 2d43feeb8..dfdb1cfbb 100644 --- a/src/info/infoPg.h +++ b/src/info/infoPg.h @@ -48,17 +48,22 @@ typedef enum } InfoPgType; /*********************************************************************************************************************************** -Constructor +Constructors ***********************************************************************************************************************************/ +InfoPg *infoPgNew(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 ***********************************************************************************************************************************/ void infoPgAdd(InfoPg *this, const InfoPgData *infoPgData); +InfoPg *infoPgSet( + InfoPg *this, InfoPgType type, const unsigned int pgVersion, const uint64_t pgSystemId, const uint32_t pgControlVersion, + const uint32_t pgCatalogVersion); +void infoPgSave( + InfoPg *this, Ini *ini, const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, + const String *cipherPass); /*********************************************************************************************************************************** Getters @@ -70,6 +75,7 @@ InfoPgData infoPgDataCurrent(const InfoPg *this); unsigned int infoPgDataCurrentId(const InfoPg *this); Info *infoPgInfo(const InfoPg *this); unsigned int infoPgDataTotal(const InfoPg *this); +unsigned int infoPgCurrentDataId(const InfoPg *this); /*********************************************************************************************************************************** Destructor diff --git a/test/define.yaml b/test/define.yaml index a5650e1a5..5f93fb345 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -512,14 +512,14 @@ unit: test: # ---------------------------------------------------------------------------------------------------------------------------- - name: info - total: 2 + total: 3 coverage: info/info: full # ---------------------------------------------------------------------------------------------------------------------------- - name: info-pg - total: 1 + total: 2 coverage: info/infoPg: full diff --git a/test/src/module/info/infoArchiveTest.c b/test/src/module/info/infoArchiveTest.c index b0ee9f746..896da2ef1 100644 --- a/test/src/module/info/infoArchiveTest.c +++ b/test/src/module/info/infoArchiveTest.c @@ -1,6 +1,8 @@ /*********************************************************************************************************************************** Test Archive Info Handler ***********************************************************************************************************************************/ +#include + #include "storage/storage.intern.h" #include "common/harnessInfo.h" @@ -15,10 +17,14 @@ testRun(void) //-------------------------------------------------------------------------------------------------------------------------- String *content = NULL; String *fileName = strNewFmt("%s/test.ini", testPath()); + String *fileName2 = strNewFmt("%s/test2.ini", testPath()); InfoArchive *info = NULL; + String *cipherPass = strNew("123xyz"); // ***************************************************************************************************************************** - if (testBegin("infoArchiveNewLoad() and infoArchiveFree()")) + if (testBegin( + "infoArchiveNewLoad(), infoArchiveNew(), infoArchiveNewInternal(), infoArchivePg(), infoArchiveCipherPass(), " + "infoArchiveSave(), infoArchiveFree()")) { TEST_ERROR_FMT( infoArchiveNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), FileMissingError, @@ -48,10 +54,71 @@ testRun(void) storagePutNP( storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put archive info to file"); - TEST_ASSIGN(info, infoArchiveNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), " new archive info"); + TEST_ASSIGN(info, infoArchiveNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), " load new archive info"); TEST_RESULT_STR(strPtr(infoArchiveId(info)), "9.4-1", " archiveId set"); TEST_RESULT_PTR(infoArchivePg(info), info->infoPg, " infoPg set"); - TEST_RESULT_PTR(infoArchiveCipherPass(info), NULL, " no cipher passphrase"); + TEST_RESULT_PTR(infoArchiveCipherPass(info), NULL, " no cipher sub"); + + TEST_RESULT_VOID( + infoArchiveSave(info, storageLocalWrite(), fileName2, cipherTypeNone, NULL), "infoArchiveSave() - no cipher"); + TEST_RESULT_BOOL( + bufEq( + storageGetNP(storageNewReadNP(storageLocal(), fileName)), + storageGetNP(storageNewReadNP(storageLocal(), fileName2))), + true, " saved files are equal"); + + // Remove the file just written and recreate it from scratch + //-------------------------------------------------------------------------------------------------------------------------- + storageRemoveP(storageLocalWrite(), fileName2, .errorOnMissing = true); + + info = NULL; + TEST_ASSIGN( + info, infoArchiveNew(PG_VERSION_94, 6569239123849665679, cipherTypeNone, NULL), "infoArchiveNew() - no sub cipher"); + TEST_RESULT_STR(strPtr(infoArchiveId(info)), "9.4-1", " archiveId set"); + TEST_RESULT_PTR(infoArchivePg(info), info->infoPg, " infoPg set"); + TEST_RESULT_PTR(infoArchiveCipherPass(info), NULL, " no cipher sub"); + TEST_RESULT_INT(infoPgDataTotal(info->infoPg), 1, " history set"); + + TEST_RESULT_VOID( + infoArchiveSave(info, storageLocalWrite(), fileName2, cipherTypeNone, NULL), " save new"); + TEST_RESULT_BOOL( + bufEq( + storageGetNP(storageNewReadNP(storageLocal(), fileName)), + storageGetNP(storageNewReadNP(storageLocal(), fileName2))), + true, " saved files are equal"); + + // Remove both files and recreate from scratch with cipher + //-------------------------------------------------------------------------------------------------------------------------- + storageRemoveP(storageLocalWrite(), fileName, .errorOnMissing = true); + storageRemoveP(storageLocalWrite(), fileName2, .errorOnMissing = true); + + TEST_ASSIGN( + info, infoArchiveNew(PG_VERSION_10, 6569239123849665999, cipherTypeAes256Cbc, + strNew("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")), + "infoArchiveNew() - cipher sub"); + TEST_RESULT_VOID( + infoArchiveSave(info, storageLocalWrite(), fileName, cipherTypeAes256Cbc, cipherPass), " save new encrypted"); + + info = NULL; + TEST_ASSIGN(info, infoArchiveNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, cipherPass), + " load encrypted archive info"); + TEST_RESULT_STR(strPtr(infoArchiveId(info)), "10-1", " archiveId set"); + TEST_RESULT_PTR(infoArchivePg(info), info->infoPg, " infoPg set"); + TEST_RESULT_STR(strPtr(infoArchiveCipherPass(info)), + "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", " cipher sub set"); + TEST_RESULT_INT(infoPgDataTotal(info->infoPg), 1, " history set"); + + //-------------------------------------------------------------------------------------------------------------------------- + InfoPgData infoPgData = {0}; + TEST_RESULT_VOID(infoArchivePgSet(info, PG_VERSION_94, 6569239123849665679), "add another infoPg"); + TEST_RESULT_INT(infoPgDataTotal(info->infoPg), 2, " history incremented"); + TEST_ASSIGN(infoPgData, infoPgDataCurrent(info->infoPg), " get current infoPgData"); + TEST_RESULT_INT(infoPgData.version, PG_VERSION_94, " version set"); + TEST_RESULT_INT(infoPgData.systemId, 6569239123849665679, " systemId set"); + + //-------------------------------------------------------------------------------------------------------------------------- + TEST_ASSIGN(info, infoArchiveNewInternal(), "infoArchiveNewInternal()"); + TEST_RESULT_PTR(infoArchivePg(info), NULL, " infoPg not set"); // Free //-------------------------------------------------------------------------------------------------------------------------- diff --git a/test/src/module/info/infoBackupTest.c b/test/src/module/info/infoBackupTest.c index 6b1164883..34d5481fb 100644 --- a/test/src/module/info/infoBackupTest.c +++ b/test/src/module/info/infoBackupTest.c @@ -20,7 +20,8 @@ testRun(void) InfoBackup *infoBackup = NULL; // ***************************************************************************************************************************** - if (testBegin("infoBackupNewLoad(), infoBackupDataTotal(), infoBackupFree()")) + if (testBegin("infoBackupNew(), infoBackupNewLoad(), infoBackupDataTotal(), infoBackupPg(), infoBackupCipherPass(), " + "infoBackupFree()")) { // File missing //-------------------------------------------------------------------------------------------------------------------------- @@ -54,11 +55,57 @@ testRun(void) storagePutNP( storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put backup info to file"); - TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), " new backup info"); + TEST_ASSIGN( + infoBackup, infoBackupNew(PG_VERSION_94, 6569239123849665679, 942, 201409291, cipherTypeNone, NULL), + "infoBackupNew() - no cipher sub"); + TEST_RESULT_VOID( + infoBackupSave(infoBackup, storageLocalWrite(), fileName2, cipherTypeNone, NULL), " save backup info from new"); + TEST_RESULT_BOOL( + bufEq( + storageGetNP(storageNewReadNP(storageLocal(), fileName)), + storageGetNP(storageNewReadNP(storageLocal(), fileName2))), + true, " files are equal"); + + TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageLocal(), fileName2, cipherTypeNone, NULL), "load backup info"); TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackup->infoPg, " infoPg set"); + TEST_RESULT_PTR(infoBackupCipherPass(infoBackup), NULL, " cipher sub not set"); TEST_RESULT_PTR(infoBackup->backup, NULL, " backupCurrent NULL"); TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 0, " infoBackupDataTotal returns 0"); + // Remove both files and recreate from scratch with cipher + //-------------------------------------------------------------------------------------------------------------------------- + storageRemoveP(storageLocalWrite(), fileName, .errorOnMissing = true); + storageRemoveP(storageLocalWrite(), fileName2, .errorOnMissing = true); + + TEST_ASSIGN( + infoBackup, infoBackupNew(PG_VERSION_10, 6569239123849665999, 1002, 201707211, cipherTypeAes256Cbc, + strNew("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")), + "infoBackupNew() - cipher sub"); + TEST_RESULT_VOID( + infoBackupSave(infoBackup, storageLocalWrite(), fileName, cipherTypeAes256Cbc, strNew("123xyz")), " save new encrypted"); + + infoBackup = NULL; + TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("123xyz")), + " load encrypted backup info"); + TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackup->infoPg, " infoPg set"); + TEST_RESULT_STR(strPtr(infoBackupCipherPass(infoBackup)), + "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", " cipher sub set"); + TEST_RESULT_INT(infoPgDataTotal(infoBackup->infoPg), 1, " history set"); + + //-------------------------------------------------------------------------------------------------------------------------- + InfoPgData infoPgData = {0}; + TEST_RESULT_VOID(infoBackupPgSet(infoBackup, PG_VERSION_94, 6569239123849665679, 12345, 54321), "add another infoPg"); + TEST_RESULT_INT(infoPgDataTotal(infoBackup->infoPg), 2, " history incremented"); + TEST_ASSIGN(infoPgData, infoPgDataCurrent(infoBackup->infoPg), " get current infoPgData"); + TEST_RESULT_INT(infoPgData.version, PG_VERSION_94, " version set"); + TEST_RESULT_INT(infoPgData.systemId, 6569239123849665679, " systemId set"); + TEST_RESULT_INT(infoPgData.controlVersion, 12345, " catalog set"); + TEST_RESULT_INT(infoPgData.catalogVersion, 54321, " catalog set"); + + //-------------------------------------------------------------------------------------------------------------------------- + TEST_ASSIGN(infoBackup, infoBackupNewInternal(), "infoBackupNewInternal()"); + TEST_RESULT_PTR(infoBackupPg(infoBackup), NULL, " infoPg not set"); + // Free //-------------------------------------------------------------------------------------------------------------------------- TEST_RESULT_VOID(infoBackupFree(infoBackup), "infoBackupFree() - free backup info"); diff --git a/test/src/module/info/infoPgTest.c b/test/src/module/info/infoPgTest.c index 91fef2dcf..ebe9345a2 100644 --- a/test/src/module/info/infoPgTest.c +++ b/test/src/module/info/infoPgTest.c @@ -9,12 +9,91 @@ Test Run void testRun(void) { + // ***************************************************************************************************************************** + if (testBegin("infoPgNew(), infoPgNewInternal(), infoPgSet()")) + { + InfoPg *infoPg = NULL; + + TEST_ASSIGN(infoPg, infoPgNew(cipherTypeNone, NULL), "infoPgNew(cipherTypeNone, NULL)"); + TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history"); + TEST_RESULT_STR(strPtr(infoCipherPass(infoPgInfo(infoPg))), NULL, " cipherPass NULL"); + TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); + + TEST_ASSIGN(infoPg, infoPgNew(cipherTypeAes256Cbc, strNew("123xyz")), "infoPgNew(cipherTypeAes256Cbc, 123xyz)"); + TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history"); + TEST_RESULT_STR(strPtr(infoCipherPass(infoPgInfo(infoPg))), "123xyz", " cipherPass set"); + TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); + + //-------------------------------------------------------------------------------------------------------------------------- + TEST_ASSIGN( + infoPg, infoPgSet(infoPgNew(cipherTypeNone, NULL), infoPgArchive, PG_VERSION_94, 6569239123849665679, 0, 0), + "infoPgSet - infoPgArchive"); + TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history"); + TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); + InfoPgData pgData = infoPgData(infoPg, infoPgDataCurrentId(infoPg)); + TEST_RESULT_INT(pgData.id, 1, " id set"); + TEST_RESULT_INT(pgData.systemId, 6569239123849665679, " system-id set"); + TEST_RESULT_INT(pgData.version, PG_VERSION_94, " version set"); + TEST_RESULT_INT(pgData.catalogVersion, 0, " catalog-version not set"); + TEST_RESULT_INT(pgData.controlVersion, 0, " control-version set"); + + TEST_ASSIGN( + infoPg, infoPgSet(infoPg, infoPgArchive, PG_VERSION_95, 6569239123849665999, 0, 0), + "infoPgSet - infoPgArchive second db"); + TEST_RESULT_INT(infoPgDataTotal(infoPg), 2, " 2 history"); + TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); + pgData = infoPgData(infoPg, infoPgDataCurrentId(infoPg)); + TEST_RESULT_INT(pgData.id, 2, " current id updated"); + TEST_RESULT_INT(pgData.systemId, 6569239123849665999, " system-id updated"); + TEST_RESULT_INT(pgData.version, PG_VERSION_95, " version updated"); + TEST_RESULT_INT(pgData.catalogVersion, 0, " catalog-version not set"); + TEST_RESULT_INT(pgData.controlVersion, 0, " control-version not set"); + TEST_RESULT_STR(strPtr(infoCipherPass(infoPgInfo(infoPg))), NULL, " cipherPass not set"); + + //-------------------------------------------------------------------------------------------------------------------------- + TEST_ASSIGN( + infoPg, infoPgSet(infoPgNew(cipherTypeAes256Cbc, strNew("123xyz")), infoPgBackup, PG_VERSION_94, 6569239123849665679, + 201409291, 942), "infoPgSet - infoPgBackup"); + TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history"); + TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); + pgData = infoPgData(infoPg, infoPgDataCurrentId(infoPg)); + TEST_RESULT_INT(pgData.id, 1, " id set"); + TEST_RESULT_INT(pgData.systemId, 6569239123849665679, " system-id set"); + TEST_RESULT_INT(pgData.version, PG_VERSION_94, " version set"); + TEST_RESULT_INT(pgData.catalogVersion, 942, " catalog-version set"); + TEST_RESULT_INT(pgData.controlVersion, 201409291, " control-version set"); + TEST_RESULT_STR(strPtr(infoCipherPass(infoPgInfo(infoPg))), "123xyz", " cipherPass set"); + + //-------------------------------------------------------------------------------------------------------------------------- + TEST_ASSIGN( + infoPg, infoPgSet(infoPgNew(cipherTypeNone, NULL), infoPgManifest, PG_VERSION_95, 6569239123849665699, + 201510051, 950), "infoPgSet - infoPgManifest"); + TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history"); + TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); + pgData = infoPgData(infoPg, infoPgDataCurrentId(infoPg)); + TEST_RESULT_INT(pgData.id, 1, " id set"); + TEST_RESULT_INT(pgData.systemId, 6569239123849665699, " system-id set"); + TEST_RESULT_INT(pgData.version, PG_VERSION_95, " version set"); + TEST_RESULT_INT(pgData.catalogVersion, 950, " catalog-version set"); + TEST_RESULT_INT(pgData.controlVersion, 201510051, " control-version set"); + + //-------------------------------------------------------------------------------------------------------------------------- + TEST_ASSIGN(infoPg, infoPgNewInternal(), "infoPgNewInternal()"); + TEST_RESULT_PTR(infoPgInfo(infoPg), NULL, " info not set"); + + //-------------------------------------------------------------------------------------------------------------------------- + TEST_ERROR( + infoPgSet(infoPgNew(cipherTypeNone, NULL), 1000, PG_VERSION_94, 6569239123849665679, 201409291, 942), + AssertError, "invalid InfoPg type 1000"); + } + // ***************************************************************************************************************************** if (testBegin("infoPgNewLoad(), infoPgFree(), infoPgDataCurrent(), infoPgDataToLog(), infoPgAdd(), infoPgIni(), infoPgSave()")) { String *content = NULL; String *fileName = strNewFmt("%s/test.ini", testPath()); String *fileName2 = strNewFmt("%s/test2.ini", testPath()); + String *fileName3 = strNewFmt("%s/test3.ini", testPath()); // Archive info //-------------------------------------------------------------------------------------------------------------------------- @@ -39,6 +118,16 @@ testRun(void) infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgArchive, cipherTypeNone, NULL, &ini), "load file"); TEST_RESULT_STR(strPtr(iniGet(ini, strNew("db"), strNew("db-id"))), "1", " check ini"); + // Save the file and verify it + ini = iniNew(); + TEST_RESULT_VOID( + infoPgSave(infoPg, ini, storageLocalWrite(), fileName3, infoPgArchive, cipherTypeNone, NULL), "infoPgSave - archive"); + TEST_RESULT_BOOL( + bufEq( + storageGetNP(storageNewReadNP(storageLocal(), fileName)), + storageGetNP(storageNewReadNP(storageLocal(), fileName3))), + true, " saved files are equal"); + TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added"); InfoPgData infoPgData = infoPgDataCurrent(infoPg); @@ -69,10 +158,18 @@ testRun(void) TEST_RESULT_VOID( storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put info to file"); - TEST_ASSIGN( infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgBackup, cipherTypeNone, NULL, NULL), "load file"); + // Save the file and verify it + ini = iniNew(); + TEST_RESULT_VOID( + infoPgSave(infoPg, ini, storageLocalWrite(), fileName3, infoPgBackup, cipherTypeNone, NULL), "infoPgSave - backup"); + TEST_RESULT_BOOL( + bufEq( + storageGetNP(storageNewReadNP(storageLocal(), fileName)), + storageGetNP(storageNewReadNP(storageLocal(), fileName3))), + true, " saved files are equal"); TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added"); infoPgData = infoPgDataCurrent(infoPg); @@ -108,7 +205,8 @@ testRun(void) // Save the file and verify it ini = iniNew(); - TEST_RESULT_VOID(infoPgSave(infoPg, ini, storageLocalWrite(), fileName2, cipherTypeNone, NULL), "infoPgSave"); + TEST_RESULT_VOID( + infoPgSave(infoPg, ini, storageLocalWrite(), fileName2, infoPgManifest, cipherTypeNone, NULL), "infoPgSave - manifest"); TEST_RESULT_BOOL( bufEq( storageGetNP(storageNewReadNP(storageLocal(), fileName)), @@ -151,6 +249,9 @@ testRun(void) TEST_ERROR(infoPgAdd(NULL, &infoPgData), AssertError, "assertion 'this != NULL' failed"); TEST_ERROR(infoPgAdd(infoPg, NULL), AssertError, "assertion 'infoPgData != NULL' failed"); + TEST_ERROR( + infoPgSave(infoPg, ini, storageLocalWrite(), fileName2, 10000, cipherTypeNone, NULL), + AssertError, "invalid InfoPg type 10000"); // infoPgFree //-------------------------------------------------------------------------------------------------------------------------- diff --git a/test/src/module/info/infoTest.c b/test/src/module/info/infoTest.c index eb46d51cb..5784861d0 100644 --- a/test/src/module/info/infoTest.c +++ b/test/src/module/info/infoTest.c @@ -13,15 +13,40 @@ testRun(void) Storage *storageTest = storagePosixNew( strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL); + String *cipherPass = strNew("123xyz"); + String *fileName = strNewFmt("%s/test.ini", testPath()); + Info *info = NULL; + + // ***************************************************************************************************************************** + if (testBegin("infoNew()")) + { + TEST_ASSIGN(info, infoNew(cipherTypeAes256Cbc, cipherPass), "infoNew(cipher)"); + TEST_RESULT_PTR(infoCipherPass(info), cipherPass, " cipherPass is set"); + + TEST_ASSIGN(info, infoNew(cipherTypeNone, NULL), "infoNew(NULL)"); + TEST_RESULT_PTR(infoCipherPass(info), NULL, " cipherPass is NULL"); + + TEST_ERROR( + infoNew(cipherTypeNone, strNew("")), AssertError, + "assertion '!((cipherType == cipherTypeNone && cipherPassSub != NULL) || (cipherType != cipherTypeNone && " + "(cipherPassSub == NULL || strSize(cipherPassSub) == 0)))' failed"); + TEST_ERROR( + infoNew(cipherTypeAes256Cbc, strNew("")), AssertError, + "assertion '!((cipherType == cipherTypeNone && cipherPassSub != NULL) || (cipherType != cipherTypeNone && " + "(cipherPassSub == NULL || strSize(cipherPassSub) == 0)))' failed"); + TEST_ERROR( + infoNew(cipherTypeAes256Cbc, NULL), AssertError, + "assertion '!((cipherType == cipherTypeNone && cipherPassSub != NULL) || (cipherType != cipherTypeNone && " + "(cipherPassSub == NULL || strSize(cipherPassSub) == 0)))' failed"); + } + // ***************************************************************************************************************************** if (testBegin("infoNewLoad(), infoFileName(), infoIni()")) { // Initialize test variables //-------------------------------------------------------------------------------------------------------------------------- String *content = NULL; - String *fileName = strNewFmt("%s/test.ini", testPath()); String *fileNameCopy = strNewFmt("%s/test.ini.copy", testPath()); - Info *info = NULL; content = strNew ( @@ -240,31 +265,38 @@ testRun(void) // ***************************************************************************************************************************** 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"); + Info *info = infoNew(cipherTypeNone, NULL); + TEST_RESULT_VOID(infoSave(info, 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"); + TEST_RESULT_BOOL(storageExistsNP(storageTest, strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName))), true, "check copy exists"); + + TEST_ERROR( + infoSave(info, ini, storageTest, fileName, cipherTypeAes256Cbc, cipherPass), AssertError, + "assertion '!((cipherType != cipherTypeNone && this->cipherPass == NULL) || " + "(cipherType == cipherTypeNone && this->cipherPass != NULL))' failed"); // Add encryption // ------------------------------------------------------------------------------------------------------------------------- ini = iniNew(); iniSet(ini, strNew("section1"), strNew("key1"), strNew("value4")); - Info *info = infoNew(); - info->cipherPass = strNew("/badpass"); + info = infoNew(cipherTypeAes256Cbc, strNew("/hall-pass")); TEST_RESULT_VOID(infoSave(info, 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"); - TEST_RESULT_STR(strPtr(iniGet(ini, strNew("cipher"), strNew("cipher-pass"))), "\"/badpass\"", " check cipher-pass"); + TEST_RESULT_STR(strPtr(iniGet(ini, strNew("cipher"), strNew("cipher-pass"))), "\"/hall-pass\"", " check cipher-pass"); + + TEST_ERROR( + infoSave(info, ini, storageTest, fileName, cipherTypeNone, NULL), AssertError, + "assertion '!((cipherType != cipherTypeNone && this->cipherPass == NULL) || " + "(cipherType == cipherTypeNone && this->cipherPass != NULL))' failed"); } }