You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-07-05 00:28:52 +02:00
strCat() did not follow our convention of appending Z to functions that accept zero-terminated strings rather than String objects. Add strCatZ() to accept zero-terminated strings and update strCat() to accept String objects. Use LF_STR where appropriate but don't use other String constants because they do not improve readability.
179 lines
5.6 KiB
C
179 lines
5.6 KiB
C
/***********************************************************************************************************************************
|
|
Common Functions and Definitions for Backup and Expire Commands
|
|
***********************************************************************************************************************************/
|
|
#include "build.auto.h"
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "command/backup/common.h"
|
|
#include "common/debug.h"
|
|
#include "common/log.h"
|
|
#include "storage/helper.h"
|
|
|
|
/***********************************************************************************************************************************
|
|
Constants
|
|
***********************************************************************************************************************************/
|
|
#define DATE_TIME_REGEX "[0-9]{8}\\-[0-9]{6}"
|
|
#define BACKUP_LINK_LATEST "latest"
|
|
|
|
STRING_EXTERN(BACKUP_TYPE_FULL_STR, BACKUP_TYPE_FULL);
|
|
STRING_EXTERN(BACKUP_TYPE_DIFF_STR, BACKUP_TYPE_DIFF);
|
|
STRING_EXTERN(BACKUP_TYPE_INCR_STR, BACKUP_TYPE_INCR);
|
|
|
|
/**********************************************************************************************************************************/
|
|
String *
|
|
backupRegExp(BackupRegExpParam param)
|
|
{
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
FUNCTION_LOG_PARAM(BOOL, param.full);
|
|
FUNCTION_LOG_PARAM(BOOL, param.differential);
|
|
FUNCTION_LOG_PARAM(BOOL, param.incremental);
|
|
FUNCTION_LOG_PARAM(BOOL, param.noAnchorEnd);
|
|
FUNCTION_LOG_END();
|
|
|
|
ASSERT(param.full || param.differential || param.incremental);
|
|
|
|
String *result = NULL;
|
|
|
|
// Start the expression with the anchor, date/time regexp and full backup indicator
|
|
result = strNew("^" DATE_TIME_REGEX "F");
|
|
|
|
// Add the diff and/or incr expressions if requested
|
|
if (param.differential || param.incremental)
|
|
{
|
|
// If full requested then diff/incr is optional
|
|
if (param.full)
|
|
{
|
|
strCatZ(result, "(\\_");
|
|
}
|
|
// Else diff/incr is required
|
|
else
|
|
{
|
|
strCatZ(result, "\\_");
|
|
}
|
|
|
|
// Append date/time regexp for diff/incr
|
|
strCatZ(result, DATE_TIME_REGEX);
|
|
|
|
// Filter on both diff/incr
|
|
if (param.differential && param.incremental)
|
|
{
|
|
strCatZ(result, "(D|I)");
|
|
}
|
|
// Else just diff
|
|
else if (param.differential)
|
|
{
|
|
strCatChr(result, 'D');
|
|
}
|
|
// Else just incr
|
|
else
|
|
{
|
|
strCatChr(result, 'I');
|
|
}
|
|
|
|
// If full requested then diff/incr is optional
|
|
if (param.full)
|
|
{
|
|
strCatZ(result, "){0,1}");
|
|
}
|
|
}
|
|
|
|
// Append the end anchor
|
|
if (!param.noAnchorEnd)
|
|
strCatZ(result, "$");
|
|
|
|
FUNCTION_LOG_RETURN(STRING, result);
|
|
}
|
|
|
|
/**********************************************************************************************************************************/
|
|
BackupType
|
|
backupType(const String *type)
|
|
{
|
|
FUNCTION_TEST_BEGIN();
|
|
FUNCTION_TEST_PARAM(STRING, type);
|
|
FUNCTION_TEST_END();
|
|
|
|
ASSERT(type != NULL);
|
|
|
|
BackupType result;
|
|
|
|
if (strEq(type, BACKUP_TYPE_FULL_STR))
|
|
result = backupTypeFull;
|
|
else if (strEq(type, BACKUP_TYPE_DIFF_STR))
|
|
result = backupTypeDiff;
|
|
else if (strEq(type, BACKUP_TYPE_INCR_STR))
|
|
result = backupTypeIncr;
|
|
else
|
|
THROW_FMT(AssertError, "invalid backup type '%s'", strPtr(type));
|
|
|
|
FUNCTION_TEST_RETURN(result);
|
|
}
|
|
|
|
const String *backupTypeStr(BackupType type)
|
|
{
|
|
FUNCTION_TEST_BEGIN();
|
|
FUNCTION_TEST_PARAM(ENUM, type);
|
|
FUNCTION_TEST_END();
|
|
|
|
ASSERT(type <= backupTypeIncr);
|
|
|
|
const String *result = NULL;
|
|
|
|
switch (type)
|
|
{
|
|
case backupTypeFull:
|
|
{
|
|
result = BACKUP_TYPE_FULL_STR;
|
|
break;
|
|
}
|
|
|
|
case backupTypeDiff:
|
|
{
|
|
result = BACKUP_TYPE_DIFF_STR;
|
|
break;
|
|
}
|
|
|
|
case backupTypeIncr:
|
|
{
|
|
result = BACKUP_TYPE_INCR_STR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
FUNCTION_TEST_RETURN(result);
|
|
}
|
|
|
|
/**********************************************************************************************************************************/
|
|
void
|
|
backupLinkLatest(const String *backupLabel)
|
|
{
|
|
FUNCTION_TEST_BEGIN();
|
|
FUNCTION_TEST_PARAM(STRING, backupLabel);
|
|
FUNCTION_TEST_END();
|
|
|
|
MEM_CONTEXT_TEMP_BEGIN()
|
|
{
|
|
// Create a symlink to the most recent backup if supported. This link is purely informational for the user and is never
|
|
// used by us since symlinks are not supported on all storage types.
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
const String *const latestLink = storagePathP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/" BACKUP_LINK_LATEST));
|
|
|
|
// Remove an existing latest link/file in case symlink capabilities have changed
|
|
storageRemoveP(storageRepoWrite(), latestLink);
|
|
|
|
if (storageFeature(storageRepoWrite(), storageFeatureSymLink))
|
|
{
|
|
THROW_ON_SYS_ERROR_FMT(
|
|
symlink(strPtr(backupLabel), strPtr(latestLink)) == -1, FileOpenError,
|
|
"unable to create symlink '%s' to '%s'", strPtr(latestLink), strPtr(backupLabel));
|
|
}
|
|
|
|
// Sync backup path if required
|
|
if (storageFeature(storageRepoWrite(), storageFeaturePathSync))
|
|
storagePathSyncP(storageRepoWrite(), STORAGE_REPO_BACKUP_STR);
|
|
}
|
|
MEM_CONTEXT_TEMP_END();
|
|
|
|
FUNCTION_TEST_RETURN_VOID();
|
|
}
|