1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-10-30 23:37:45 +02:00

Fix issues when a path option is / terminated.

This condition was not being properly checked for in the C code and it caused problems in the info command, at the very least.

Instead of applying a local fix, introduce a new path option type that will rigorously check the format of any incoming paths.

Reported by Marc Cousin.
This commit is contained in:
David Steele
2019-03-14 13:48:33 +04:00
parent b8ebea6b1c
commit 9382283586
13 changed files with 124 additions and 27 deletions

View File

@@ -553,6 +553,8 @@ use constant CFGDEF_TYPE_INTEGER => 'integer'
push @EXPORT, qw(CFGDEF_TYPE_INTEGER);
use constant CFGDEF_TYPE_LIST => 'list';
push @EXPORT, qw(CFGDEF_TYPE_LIST);
use constant CFGDEF_TYPE_PATH => 'path';
push @EXPORT, qw(CFGDEF_TYPE_PATH);
use constant CFGDEF_TYPE_STRING => 'string';
push @EXPORT, qw(CFGDEF_TYPE_STRING);
use constant CFGDEF_TYPE_SIZE => 'size';
@@ -712,6 +714,7 @@ my %hConfigDefine =
&CFGOPT_CONFIG_INCLUDE_PATH =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_INHERIT => CFGOPT_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_INCLUDE_PATH,
&CFGDEF_NEGATE => false,
@@ -719,6 +722,7 @@ my %hConfigDefine =
&CFGOPT_CONFIG_PATH =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_INHERIT => CFGOPT_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_PATH,
&CFGDEF_NEGATE => false,
@@ -1268,7 +1272,7 @@ my %hConfigDefine =
&CFGOPT_LOCK_PATH =>
{
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
&CFGDEF_TYPE => CFGDEF_TYPE_STRING,
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_DEFAULT => '/tmp/' . PROJECT_EXE,
&CFGDEF_COMMAND =>
{
@@ -1293,7 +1297,7 @@ my %hConfigDefine =
&CFGOPT_LOG_PATH =>
{
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
&CFGDEF_TYPE => CFGDEF_TYPE_STRING,
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_DEFAULT => '/var/log/' . PROJECT_EXE,
&CFGDEF_COMMAND =>
{
@@ -1520,12 +1524,14 @@ my %hConfigDefine =
&CFGOPT_REPO_HOST_CONFIG_PATH =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_INHERIT => CFGOPT_REPO_HOST_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_PATH,
},
&CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_INHERIT => CFGOPT_REPO_HOST_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_INCLUDE_PATH,
},
@@ -1571,7 +1577,7 @@ my %hConfigDefine =
&CFGOPT_REPO_PATH =>
{
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
&CFGDEF_TYPE => CFGDEF_TYPE_STRING,
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_PREFIX => CFGDEF_PREFIX_REPO,
&CFGDEF_INDEX_TOTAL => CFGDEF_INDEX_REPO,
&CFGDEF_DEFAULT => '/var/lib/' . PROJECT_EXE,
@@ -1692,6 +1698,7 @@ my %hConfigDefine =
&CFGOPT_REPO_S3_CA_PATH =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_INHERIT => CFGOPT_REPO_S3_HOST,
&CFGDEF_NAME_ALT =>
{
@@ -1848,7 +1855,7 @@ my %hConfigDefine =
&CFGOPT_SPOOL_PATH =>
{
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
&CFGDEF_TYPE => CFGDEF_TYPE_STRING,
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_DEFAULT => '/var/spool/' . PROJECT_EXE,
&CFGDEF_COMMAND =>
{
@@ -2357,12 +2364,14 @@ my %hConfigDefine =
&CFGOPT_PG_HOST_CONFIG_PATH =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_INHERIT => CFGOPT_PG_HOST_CMD,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_PATH,
},
&CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_INHERIT => CFGOPT_PG_HOST_CMD,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_INCLUDE_PATH,
},
@@ -2395,7 +2404,7 @@ my %hConfigDefine =
&CFGOPT_PG_PATH =>
{
&CFGDEF_SECTION => CFGDEF_SECTION_STANZA,
&CFGDEF_TYPE => CFGDEF_TYPE_STRING,
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_PREFIX => CFGDEF_PREFIX_PG,
&CFGDEF_INDEX_TOTAL => CFGDEF_INDEX_PG,
&CFGDEF_REQUIRED => true,
@@ -2471,7 +2480,7 @@ my %hConfigDefine =
&CFGOPT_PG_SOCKET_PATH =>
{
&CFGDEF_INHERIT => CFGOPT_PG_PORT,
&CFGDEF_TYPE => CFGDEF_TYPE_STRING,
&CFGDEF_TYPE => CFGDEF_TYPE_PATH,
&CFGDEF_DEFAULT => undef,
&CFGDEF_REQUIRED => false,
&CFGDEF_NAME_ALT =>

View File

@@ -14,6 +14,16 @@
<release-list>
<release date="XXXX-XX-XX" version="2.12dev" title="UNDER DEVELOPMENT">
<release-core-list>
<release-bug-list>
<release-item>
<release-item-contributor-list>
<release-item-ideator id="marc.cousin"/>
</release-item-contributor-list>
<p>Fix issues when a path option is / terminated.</p>
</release-item>
</release-bug-list>
<release-development-list>
<release-item>
<p>Add separate <cmd>archive-push-async</cmd> command.</p>

View File

@@ -52,8 +52,9 @@ sub libcAutoConstant
CFGDEF_TYPE_HASH => 2,
CFGDEF_TYPE_INTEGER => 3,
CFGDEF_TYPE_LIST => 4,
CFGDEF_TYPE_SIZE => 5,
CFGDEF_TYPE_STRING => 6,
CFGDEF_TYPE_PATH => 5,
CFGDEF_TYPE_SIZE => 6,
CFGDEF_TYPE_STRING => 7,
ENCODE_TYPE_BASE64 => 0,
@@ -297,6 +298,7 @@ sub libcAutoExportTag
'CFGDEF_TYPE_HASH',
'CFGDEF_TYPE_INTEGER',
'CFGDEF_TYPE_LIST',
'CFGDEF_TYPE_PATH',
'CFGDEF_TYPE_SIZE',
'CFGDEF_TYPE_STRING',
'cfgCommandId',

View File

@@ -461,6 +461,7 @@ cfgOptionDefault(ConfigOption optionId)
break;
}
case cfgDefOptTypePath:
case cfgDefOptTypeString:
configOptionValue[optionId].defaultValue = varDup(defaultValue);
break;
@@ -858,13 +859,16 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
break;
}
case cfgDefOptTypePath:
case cfgDefOptTypeString:
{
if (varType(value) == varTypeString)
configOptionValue[optionId].value = varDup(value);
else
THROW_FMT(AssertError, "option '%s' must be set with String variant", cfgOptionName(optionId));
break;
}
}
}
else

View File

@@ -837,7 +837,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("config-include-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionCommandLine)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -883,7 +883,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("config-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionCommandLine)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -1278,7 +1278,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("lock-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -1530,7 +1530,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("log-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -2049,7 +2049,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("pg-host-config-include-path")
CFGDEFDATA_OPTION_REQUIRED(false)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionStanza)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(8)
@@ -2090,7 +2090,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("pg-host-config-path")
CFGDEFDATA_OPTION_REQUIRED(false)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionStanza)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(8)
@@ -2214,7 +2214,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("pg-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionStanza)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(8)
@@ -2344,7 +2344,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("pg-socket-path")
CFGDEFDATA_OPTION_REQUIRED(false)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionStanza)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(8)
@@ -2860,7 +2860,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("repo-host-config-include-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -2902,7 +2902,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("repo-host-config-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -3031,7 +3031,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("repo-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -3345,7 +3345,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("repo-s3-ca-path")
CFGDEFDATA_OPTION_REQUIRED(false)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
@@ -3907,7 +3907,7 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_NAME("spool-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypePath)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)

View File

@@ -41,6 +41,7 @@ typedef enum
cfgDefOptTypeHash,
cfgDefOptTypeInteger,
cfgDefOptTypeList,
cfgDefOptTypePath,
cfgDefOptTypeSize,
cfgDefOptTypeString,
} ConfigDefineOptionType;

View File

@@ -909,6 +909,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
}
// String is output with quotes
case cfgDefOptTypePath:
case cfgDefOptTypeString:
{
strLstAdd(dependValueList, strNewFmt("'%s'", dependValue));
@@ -1030,6 +1031,37 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
cfgOptionName(optionId));
}
}
// Else if path make sure it is valid
else if (optionDefType == cfgDefOptTypePath)
{
// Make sure it is long enough to be a path
if (strSize(value) == 0)
{
THROW_FMT(
OptionInvalidValueError, "'%s' must be >= 1 character for '%s' option", strPtr(value),
cfgOptionName(optionId));
}
// Make sure it starts with /
if (!strBeginsWithZ(value, "/"))
{
THROW_FMT(
OptionInvalidValueError, "'%s' must begin with / for '%s' option", strPtr(value),
cfgOptionName(optionId));
}
// Make sure there are no occurences of //
if (strstr(strPtr(value), "//") != NULL)
{
THROW_FMT(
OptionInvalidValueError, "'%s' cannot contain // for '%s' option", strPtr(value),
cfgOptionName(optionId));
}
// If the path ends with a / we'll strip it off (unless the value is just /)
if (strEndsWithZ(value, "/") && strSize(value) != 1)
strTrunc(value, (int)strSize(value) - 1);
}
// If the option has an allow list then check it
if (cfgDefOptionAllowList(commandDefId, optionDefId) &&

View File

@@ -71,6 +71,7 @@ perlOptionJson(void)
case cfgDefOptTypeBoolean:
case cfgDefOptTypeFloat:
case cfgDefOptTypeInteger:
case cfgDefOptTypePath:
case cfgDefOptTypeSize:
case cfgDefOptTypeString:
{

View File

@@ -10164,8 +10164,9 @@ static const EmbeddedModule embeddedModule[] =
"CFGDEF_TYPE_HASH => 2,\n"
"CFGDEF_TYPE_INTEGER => 3,\n"
"CFGDEF_TYPE_LIST => 4,\n"
"CFGDEF_TYPE_SIZE => 5,\n"
"CFGDEF_TYPE_STRING => 6,\n"
"CFGDEF_TYPE_PATH => 5,\n"
"CFGDEF_TYPE_SIZE => 6,\n"
"CFGDEF_TYPE_STRING => 7,\n"
"\n"
"ENCODE_TYPE_BASE64 => 0,\n"
"\n"
@@ -10408,6 +10409,7 @@ static const EmbeddedModule embeddedModule[] =
"'CFGDEF_TYPE_HASH',\n"
"'CFGDEF_TYPE_INTEGER',\n"
"'CFGDEF_TYPE_LIST',\n"
"'CFGDEF_TYPE_PATH',\n"
"'CFGDEF_TYPE_SIZE',\n"
"'CFGDEF_TYPE_STRING',\n"
"'cfgCommandId',\n"

View File

@@ -70,7 +70,7 @@ P00 WARN: option repo1-retention-full is not set, the repository may run out o
P00 ERROR: [070]: link '[TEST_PATH]/db-master/db/base/postgresql.conf.bad' -> '../pg_config/postgresql.conf.link' cannot reference another link
full backup - create pg_stat link, pg_clog dir (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --manifest-save-threshold=3 --protocol-timeout=2 --db-timeout=1 --cmd-ssh=/usr/bin/ssh --pg1-port=9999 --pg1-socket-path =/test_socket_path --buffer-size=16384 --checksum-page --process-max=1 --type=full --stanza=db backup
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --manifest-save-threshold=3 --protocol-timeout=2 --db-timeout=1 --cmd-ssh=/usr/bin/ssh --pg1-port=9999 --pg1-socket-path=/test_socket_path --buffer-size=16384 --checksum-page --process-max=1 --type=full --stanza=db backup
------------------------------------------------------------------------------------------------------------------------------------
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.

View File

@@ -400,7 +400,7 @@ sub run
# Pass bogus ssh port to make sure it is passed through the protocol layer (it won't be used)
($bRemote ? ' --' . cfgOptionName(CFGOPT_PG_PORT) . '=9999' : '') .
# Pass bogus socket path to make sure it is passed through the protocol layer (it won't be used)
($bRemote ? ' --' . cfgOptionName(CFGOPT_PG_SOCKET_PATH) . ' =/test_socket_path' : '') .
($bRemote ? ' --' . cfgOptionName(CFGOPT_PG_SOCKET_PATH) . '=/test_socket_path' : '') .
' --' . cfgOptionName(CFGOPT_BUFFER_SIZE) . '=16384 --' . cfgOptionName(CFGOPT_CHECKSUM_PAGE) .
' --' . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1',
strRepoType => $bS3 ? undef : CFGOPTVAL_REPO_TYPE_CIFS, strTest => $strTestPoint, fTestDelay => 0});

View File

@@ -25,7 +25,7 @@ testRun(void)
{
StringList *argList = strLstNew();
strLstAddZ(argList, "pgbackrest");
strLstAdd(argList, strNewFmt("--repo-path=%s", strPtr(repoPath)));
strLstAdd(argList, strNewFmt("--repo-path=%s/", strPtr(repoPath)));
strLstAddZ(argList, "info");
StringList *argListText = strLstDup(argList);

View File

@@ -689,6 +689,42 @@ testRun(void)
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList), false), OptionInvalidValueError,
"'225179981368524800000000000000000000' is out of range for 'manifest-save-threshold' option");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew(TEST_COMMAND_BACKUP));
strLstAdd(argList, strNew("--stanza=db"));
strLstAdd(argList, strNew("--pg1-path="));
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList), false), OptionInvalidValueError,
"'' must be >= 1 character for 'pg1-path' option");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew(TEST_COMMAND_BACKUP));
strLstAdd(argList, strNew("--stanza=db"));
strLstAdd(argList, strNew("--pg1-path=bogus"));
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList), false), OptionInvalidValueError,
"'bogus' must begin with / for 'pg1-path' option");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew(TEST_COMMAND_BACKUP));
strLstAdd(argList, strNew("--stanza=db"));
strLstAdd(argList, strNew("--pg1-path=/path1//path2"));
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList), false), OptionInvalidValueError,
"'/path1//path2' cannot contain // for 'pg1-path' option");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew(TEST_COMMAND_BACKUP));
strLstAdd(argList, strNew("--stanza=db"));
strLstAdd(argList, strNew("--pg1-path=/path1/path2//"));
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList), false), OptionInvalidValueError,
"'/path1/path2//' cannot contain // for 'pg1-path' option");
// Local and remove commands should not modify log levels during parsing
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
@@ -1059,7 +1095,7 @@ testRun(void)
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew("--stanza=db"));
strLstAdd(argList, strNew("--pg1-path=/path/to/db"));
strLstAdd(argList, strNew("--pg1-path=/path/to/db/"));
strLstAdd(argList, strNew("--no-online"));
strLstAdd(argList, strNew("--no-config"));
strLstAdd(argList, strNew("--repo1-type=s3"));