1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Implement version command in C.

This commit is contained in:
David Steele 2017-11-28 21:44:05 -05:00
parent bd74711ceb
commit 915ae5662a
22 changed files with 1288 additions and 53 deletions

View File

@ -16,11 +16,11 @@ use Storable qw(dclone);
use pgBackRest::Common::Log; use pgBackRest::Common::Log;
use pgBackRest::Common::String; use pgBackRest::Common::String;
use pgBackRestBuild::Config::Data;
use pgBackRest::Version; use pgBackRest::Version;
use pgBackRestBuild::Build::Common; use pgBackRestBuild::Build::Common;
use pgBackRestBuild::Config::BuildDefine; use pgBackRestBuild::Config::BuildDefine;
use pgBackRestBuild::Config::Data;
#################################################################################################################################### ####################################################################################################################################
# Constants # Constants
@ -123,6 +123,9 @@ sub buildConfig
" )\n"; " )\n";
} }
# Add "none" command that is used to initialize the current command before anything is parsed
push(@{$rhEnum->{&BLD_LIST}}, buildConfigCommandEnum('none'));
$strBuildSource .= $strBuildSource .=
")\n"; ")\n";

View File

@ -16,10 +16,10 @@ use Storable qw(dclone);
use pgBackRest::Common::Log; use pgBackRest::Common::Log;
use pgBackRest::Common::String; use pgBackRest::Common::String;
use pgBackRestBuild::Config::Data;
use pgBackRest::Version; use pgBackRest::Version;
use pgBackRestBuild::Build::Common; use pgBackRestBuild::Build::Common;
use pgBackRestBuild::Config::Data;
#################################################################################################################################### ####################################################################################################################################
# Constants # Constants

View File

@ -0,0 +1,132 @@
####################################################################################################################################
# Auto-Generate Option Definition for Parsing with getopt_long().
####################################################################################################################################
package pgBackRestBuild::Config::BuildParse;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use Cwd qw(abs_path);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use Storable qw(dclone);
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Version;
use pgBackRestBuild::Build::Common;
use pgBackRestBuild::Config::Build;
use pgBackRestBuild::Config::Data;
####################################################################################################################################
# Constants
####################################################################################################################################
use constant BLDLCL_FILE_DEFINE => 'parse';
use constant BLDLCL_DATA_OPTION => '01-dataOption';
####################################################################################################################################
# Definitions for constants and data to build
####################################################################################################################################
my $strSummary = 'Option Parse Definition';
my $rhBuild =
{
&BLD_FILE =>
{
&BLDLCL_FILE_DEFINE =>
{
&BLD_SUMMARY => $strSummary,
&BLD_DATA =>
{
&BLDLCL_DATA_OPTION =>
{
&BLD_SUMMARY => 'Option parse data',
},
},
},
},
};
####################################################################################################################################
# Build configuration constants and data
####################################################################################################################################
sub buildConfigParse
{
# Build option parse list
#-------------------------------------------------------------------------------------------------------------------------------
my $rhConfigDefine = cfgDefine();
my $strBuildSource =
"static const struct option optionList[] =\n" .
"{\n";
foreach my $strOption (sort(keys(%{$rhConfigDefine})))
{
my $rhOption = $rhConfigDefine->{$strOption};
my $strOptionEnum = buildConfigOptionEnum($strOption);
my $strOptionArg = ($rhOption->{&CFGDEF_TYPE} ne CFGDEF_TYPE_BOOLEAN ? " .has_arg = required_argument,\n" : '');
my $strOptionPrefix = $rhConfigDefine->{$strOption}{&CFGDEF_PREFIX};
for (my $iOptionIdx = 0; $iOptionIdx <= $rhOption->{&CFGDEF_INDEX_TOTAL}; $iOptionIdx++)
{
# Don't and option indexes if it is not indexeds
next if ($iOptionIdx == 1 && $rhOption->{&CFGDEF_INDEX_TOTAL} == 1);
# Generate option name
my $strOptionName = $iOptionIdx > 0 ?
"${strOptionPrefix}${iOptionIdx}-" . substr($strOption, length($strOptionPrefix) + 1) : $strOption;
# Generate option value used for parsing (offset is added so options don't conflict with getopt_long return values)
my $strOptionVal = 'PARSE_OPTION_OFFSET + ' . $strOptionEnum . ($iOptionIdx > 1 ? " + " . ($iOptionIdx - 1) : '');
# Add option
$strBuildSource .=
" {\n" .
" .name = \"${strOptionName}\",\n" .
$strOptionArg .
" .val = ${strOptionVal},\n" .
" },\n";
# Add negation when defined
if ($rhOption->{&CFGDEF_NEGATE})
{
$strBuildSource .=
" {\n" .
" .name = \"no-${strOptionName}\",\n" .
" .val = ${strOptionVal},\n" .
" },\n";
}
}
}
# Perl options passed to the C binary should be ignored (unless calling Perl which is done elsewhere)
$strBuildSource .=
" // Perl option is ignored by normal config parsing\n" .
" {\n" .
" .name = \"perl-option\",\n" .
" .has_arg = required_argument,\n" .
" .val = 0,\n" .
" },\n";
# The option list needs to be terminated or getopt_long will just keep on reading
$strBuildSource .=
" // Terminate option list\n" .
" {\n" .
" .name = NULL\n" .
" }\n" .
"};\n";
$rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DATA}{&BLDLCL_DATA_OPTION}{&BLD_SOURCE} = $strBuildSource;
return $rhBuild;
}
push @EXPORT, qw(buildConfigParse);
1;

View File

@ -23,6 +23,10 @@
</release-improvement-list> </release-improvement-list>
<release-development-list> <release-development-list>
<release-item>
<p>Implement <cmd>version</cmd> command in C.</p>
</release-item>
<release-item> <release-item>
<p>Add <code>memGrowRaw()</code> to memory context module.</p> <p>Add <code>memGrowRaw()</code> to memory context module.</p>
</release-item> </release-item>

View File

@ -2,12 +2,30 @@ CC=gcc
CFLAGS=-I. -Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -std=c99 -funroll-loops -ftree-vectorize CFLAGS=-I. -Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -std=c99 -funroll-loops -ftree-vectorize
DESTDIR= DESTDIR=
pgbackrest: main.o \ pgbackrest: \
common/error.o common/errorType.o common/memContext.o common/type/list.o common/type/string.o common/type/stringList.o \ common/error.o \
perl/exec.o common/errorType.o \
$(CC) $(CFLAGS) -o pgbackrest main.o \ common/memContext.o \
common/error.o common/errorType.o common/memContext.o common/type/list.o common/type/string.o common/type/stringList.o \ common/type/list.o \
perl/exec.o common/type/string.o \
common/type/stringList.o \
config/config.o \
config/define.o \
config/parse.o \
perl/exec.o \
main.o
$(CC) $(CFLAGS) -o pgbackrest \
common/error.o \
common/errorType.o \
common/memContext.o \
common/type/list.o \
common/type/string.o \
common/type/stringList.o \
config/config.o \
config/define.o \
config/parse.o \
perl/exec.o \
main.o
install: pgbackrest install: pgbackrest
sudo install -d $(DESTDIR)/usr/bin sudo install -d $(DESTDIR)/usr/bin

View File

@ -31,6 +31,8 @@ Define errors
ERROR_DEFINE(ERROR_CODE_MIN, AssertError, RuntimeError); ERROR_DEFINE(ERROR_CODE_MIN, AssertError, RuntimeError);
ERROR_DEFINE(ERROR_CODE_MIN + 04, FormatError, RuntimeError); ERROR_DEFINE(ERROR_CODE_MIN + 04, FormatError, RuntimeError);
ERROR_DEFINE(ERROR_CODE_MIN + 23, CommandInvalidError, FormatError);
ERROR_DEFINE(ERROR_CODE_MIN + 31, OptionInvalidError, FormatError);
ERROR_DEFINE(ERROR_CODE_MIN + 69, MemoryError, RuntimeError); ERROR_DEFINE(ERROR_CODE_MIN + 69, MemoryError, RuntimeError);
ERROR_DEFINE(ERROR_CODE_MIN + 70, CipherError, FormatError); ERROR_DEFINE(ERROR_CODE_MIN + 70, CipherError, FormatError);

View File

@ -17,6 +17,8 @@ typedef struct ErrorType ErrorType;
ERROR_DECLARE(AssertError); ERROR_DECLARE(AssertError);
ERROR_DECLARE(FormatError); ERROR_DECLARE(FormatError);
ERROR_DECLARE(CommandInvalidError);
ERROR_DECLARE(OptionInvalidError);
ERROR_DECLARE(MemoryError); ERROR_DECLARE(MemoryError);
ERROR_DECLARE(CipherError); ERROR_DECLARE(CipherError);

View File

@ -26,6 +26,7 @@ typedef enum
cfgCmdStart, cfgCmdStart,
cfgCmdStop, cfgCmdStop,
cfgCmdVersion, cfgCmdVersion,
cfgCmdNone,
} ConfigCommand; } ConfigCommand;
/*********************************************************************************************************************************** /***********************************************************************************************************************************

View File

@ -52,6 +52,31 @@ Include the automatically generated configuration data
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include "config.auto.c" #include "config.auto.c"
/***********************************************************************************************************************************
Store the current command
This is generally set by the command parser but can also be set by during execute to change commands, i.e. backup -> expire.
***********************************************************************************************************************************/
ConfigCommand command = cfgCmdNone;
/***********************************************************************************************************************************
Get the current command
***********************************************************************************************************************************/
ConfigCommand
cfgCommand()
{
return command;
}
/***********************************************************************************************************************************
Set the current command
***********************************************************************************************************************************/
void
cfgCommandSet(ConfigCommand commandParam)
{
command = commandParam;
}
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Ensure that command id is valid Ensure that command id is valid
***********************************************************************************************************************************/ ***********************************************************************************************************************************/

View File

@ -12,9 +12,11 @@ Command and Option Configuration
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Functions Functions
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
ConfigCommand cfgCommand();
int cfgCommandId(const char *commandName); int cfgCommandId(const char *commandName);
const char *cfgCommandName(ConfigCommand commandId); const char *cfgCommandName(ConfigCommand commandId);
ConfigDefineCommand cfgCommandDefIdFromId(ConfigCommand commandId); ConfigDefineCommand cfgCommandDefIdFromId(ConfigCommand commandId);
void cfgCommandSet(ConfigCommand commandParam);
unsigned int cfgCommandTotal(); unsigned int cfgCommandTotal();
int cfgOptionId(const char *optionName); int cfgOptionId(const char *optionName);

797
src/config/parse.auto.c Normal file
View File

@ -0,0 +1,797 @@
/***********************************************************************************************************************************
Option Parse Definition
Automatically generated by Build.pm -- do not modify directly.
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Option parse data
***********************************************************************************************************************************/
static const struct option optionList[] =
{
{
.name = "archive-async",
.val = PARSE_OPTION_OFFSET + cfgOptArchiveAsync,
},
{
.name = "no-archive-async",
.val = PARSE_OPTION_OFFSET + cfgOptArchiveAsync,
},
{
.name = "archive-check",
.val = PARSE_OPTION_OFFSET + cfgOptArchiveCheck,
},
{
.name = "no-archive-check",
.val = PARSE_OPTION_OFFSET + cfgOptArchiveCheck,
},
{
.name = "archive-copy",
.val = PARSE_OPTION_OFFSET + cfgOptArchiveCopy,
},
{
.name = "no-archive-copy",
.val = PARSE_OPTION_OFFSET + cfgOptArchiveCopy,
},
{
.name = "archive-queue-max",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptArchiveQueueMax,
},
{
.name = "archive-timeout",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptArchiveTimeout,
},
{
.name = "backup-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptBackupCmd,
},
{
.name = "backup-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptBackupConfig,
},
{
.name = "backup-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptBackupHost,
},
{
.name = "backup-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptBackupSshPort,
},
{
.name = "backup-standby",
.val = PARSE_OPTION_OFFSET + cfgOptBackupStandby,
},
{
.name = "no-backup-standby",
.val = PARSE_OPTION_OFFSET + cfgOptBackupStandby,
},
{
.name = "backup-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptBackupUser,
},
{
.name = "buffer-size",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptBufferSize,
},
{
.name = "checksum-page",
.val = PARSE_OPTION_OFFSET + cfgOptChecksumPage,
},
{
.name = "no-checksum-page",
.val = PARSE_OPTION_OFFSET + cfgOptChecksumPage,
},
{
.name = "cmd-ssh",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptCmdSsh,
},
{
.name = "command",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptCommand,
},
{
.name = "compress",
.val = PARSE_OPTION_OFFSET + cfgOptCompress,
},
{
.name = "no-compress",
.val = PARSE_OPTION_OFFSET + cfgOptCompress,
},
{
.name = "compress-level",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptCompressLevel,
},
{
.name = "compress-level-network",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptCompressLevelNetwork,
},
{
.name = "config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptConfig,
},
{
.name = "no-config",
.val = PARSE_OPTION_OFFSET + cfgOptConfig,
},
{
.name = "db-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd,
},
{
.name = "db1-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd,
},
{
.name = "db2-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 1,
},
{
.name = "db3-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 2,
},
{
.name = "db4-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 3,
},
{
.name = "db5-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 4,
},
{
.name = "db6-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 5,
},
{
.name = "db7-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 6,
},
{
.name = "db8-cmd",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 7,
},
{
.name = "db-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig,
},
{
.name = "db1-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig,
},
{
.name = "db2-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 1,
},
{
.name = "db3-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 2,
},
{
.name = "db4-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 3,
},
{
.name = "db5-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 4,
},
{
.name = "db6-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 5,
},
{
.name = "db7-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 6,
},
{
.name = "db8-config",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 7,
},
{
.name = "db-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost,
},
{
.name = "db1-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost,
},
{
.name = "db2-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost + 1,
},
{
.name = "db3-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost + 2,
},
{
.name = "db4-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost + 3,
},
{
.name = "db5-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost + 4,
},
{
.name = "db6-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost + 5,
},
{
.name = "db7-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost + 6,
},
{
.name = "db8-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbHost + 7,
},
{
.name = "db-include",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbInclude,
},
{
.name = "db-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath,
},
{
.name = "db1-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath,
},
{
.name = "db2-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath + 1,
},
{
.name = "db3-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath + 2,
},
{
.name = "db4-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath + 3,
},
{
.name = "db5-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath + 4,
},
{
.name = "db6-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath + 5,
},
{
.name = "db7-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath + 6,
},
{
.name = "db8-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPath + 7,
},
{
.name = "db-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort,
},
{
.name = "db1-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort,
},
{
.name = "db2-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort + 1,
},
{
.name = "db3-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort + 2,
},
{
.name = "db4-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort + 3,
},
{
.name = "db5-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort + 4,
},
{
.name = "db6-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort + 5,
},
{
.name = "db7-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort + 6,
},
{
.name = "db8-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbPort + 7,
},
{
.name = "db-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath,
},
{
.name = "db1-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath,
},
{
.name = "db2-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 1,
},
{
.name = "db3-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 2,
},
{
.name = "db4-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 3,
},
{
.name = "db5-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 4,
},
{
.name = "db6-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 5,
},
{
.name = "db7-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 6,
},
{
.name = "db8-socket-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 7,
},
{
.name = "db-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort,
},
{
.name = "db1-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort,
},
{
.name = "db2-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 1,
},
{
.name = "db3-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 2,
},
{
.name = "db4-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 3,
},
{
.name = "db5-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 4,
},
{
.name = "db6-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 5,
},
{
.name = "db7-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 6,
},
{
.name = "db8-ssh-port",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 7,
},
{
.name = "db-timeout",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbTimeout,
},
{
.name = "db-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser,
},
{
.name = "db1-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser,
},
{
.name = "db2-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser + 1,
},
{
.name = "db3-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser + 2,
},
{
.name = "db4-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser + 3,
},
{
.name = "db5-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser + 4,
},
{
.name = "db6-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser + 5,
},
{
.name = "db7-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser + 6,
},
{
.name = "db8-user",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptDbUser + 7,
},
{
.name = "delta",
.val = PARSE_OPTION_OFFSET + cfgOptDelta,
},
{
.name = "force",
.val = PARSE_OPTION_OFFSET + cfgOptForce,
},
{
.name = "hardlink",
.val = PARSE_OPTION_OFFSET + cfgOptHardlink,
},
{
.name = "no-hardlink",
.val = PARSE_OPTION_OFFSET + cfgOptHardlink,
},
{
.name = "host-id",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptHostId,
},
{
.name = "link-all",
.val = PARSE_OPTION_OFFSET + cfgOptLinkAll,
},
{
.name = "no-link-all",
.val = PARSE_OPTION_OFFSET + cfgOptLinkAll,
},
{
.name = "link-map",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptLinkMap,
},
{
.name = "lock-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptLockPath,
},
{
.name = "log-level-console",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptLogLevelConsole,
},
{
.name = "log-level-file",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptLogLevelFile,
},
{
.name = "log-level-stderr",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptLogLevelStderr,
},
{
.name = "log-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptLogPath,
},
{
.name = "log-timestamp",
.val = PARSE_OPTION_OFFSET + cfgOptLogTimestamp,
},
{
.name = "no-log-timestamp",
.val = PARSE_OPTION_OFFSET + cfgOptLogTimestamp,
},
{
.name = "manifest-save-threshold",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptManifestSaveThreshold,
},
{
.name = "neutral-umask",
.val = PARSE_OPTION_OFFSET + cfgOptNeutralUmask,
},
{
.name = "no-neutral-umask",
.val = PARSE_OPTION_OFFSET + cfgOptNeutralUmask,
},
{
.name = "online",
.val = PARSE_OPTION_OFFSET + cfgOptOnline,
},
{
.name = "no-online",
.val = PARSE_OPTION_OFFSET + cfgOptOnline,
},
{
.name = "output",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptOutput,
},
{
.name = "process",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptProcess,
},
{
.name = "process-max",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptProcessMax,
},
{
.name = "protocol-timeout",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptProtocolTimeout,
},
{
.name = "recovery-option",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRecoveryOption,
},
{
.name = "repo-cipher-pass",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoCipherPass,
},
{
.name = "repo-cipher-type",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoCipherType,
},
{
.name = "repo-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoPath,
},
{
.name = "repo-s3-bucket",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3Bucket,
},
{
.name = "repo-s3-ca-file",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3CaFile,
},
{
.name = "repo-s3-ca-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3CaPath,
},
{
.name = "repo-s3-endpoint",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3Endpoint,
},
{
.name = "repo-s3-host",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3Host,
},
{
.name = "repo-s3-key",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3Key,
},
{
.name = "repo-s3-key-secret",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3KeySecret,
},
{
.name = "repo-s3-region",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3Region,
},
{
.name = "repo-s3-verify-ssl",
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3VerifySsl,
},
{
.name = "no-repo-s3-verify-ssl",
.val = PARSE_OPTION_OFFSET + cfgOptRepoS3VerifySsl,
},
{
.name = "repo-type",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRepoType,
},
{
.name = "resume",
.val = PARSE_OPTION_OFFSET + cfgOptResume,
},
{
.name = "no-resume",
.val = PARSE_OPTION_OFFSET + cfgOptResume,
},
{
.name = "retention-archive",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRetentionArchive,
},
{
.name = "retention-archive-type",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRetentionArchiveType,
},
{
.name = "retention-diff",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRetentionDiff,
},
{
.name = "retention-full",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptRetentionFull,
},
{
.name = "set",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptSet,
},
{
.name = "spool-path",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptSpoolPath,
},
{
.name = "stanza",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptStanza,
},
{
.name = "start-fast",
.val = PARSE_OPTION_OFFSET + cfgOptStartFast,
},
{
.name = "no-start-fast",
.val = PARSE_OPTION_OFFSET + cfgOptStartFast,
},
{
.name = "stop-auto",
.val = PARSE_OPTION_OFFSET + cfgOptStopAuto,
},
{
.name = "no-stop-auto",
.val = PARSE_OPTION_OFFSET + cfgOptStopAuto,
},
{
.name = "tablespace-map",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptTablespaceMap,
},
{
.name = "tablespace-map-all",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptTablespaceMapAll,
},
{
.name = "target",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptTarget,
},
{
.name = "target-action",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptTargetAction,
},
{
.name = "target-exclusive",
.val = PARSE_OPTION_OFFSET + cfgOptTargetExclusive,
},
{
.name = "target-timeline",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptTargetTimeline,
},
{
.name = "test",
.val = PARSE_OPTION_OFFSET + cfgOptTest,
},
{
.name = "test-delay",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptTestDelay,
},
{
.name = "test-point",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptTestPoint,
},
{
.name = "type",
.has_arg = required_argument,
.val = PARSE_OPTION_OFFSET + cfgOptType,
},
// Perl option is ignored by normal config parsing
{
.name = "perl-option",
.has_arg = required_argument,
.val = 0,
},
// Terminate option list
{
.name = NULL
}
};

78
src/config/parse.c Normal file
View File

@ -0,0 +1,78 @@
/***********************************************************************************************************************************
Command and Option Configuration
***********************************************************************************************************************************/
#include <getopt.h>
#include <string.h>
#include "common/error.h"
#include "config/config.h"
/***********************************************************************************************************************************
Include the automatically generated configuration data
***********************************************************************************************************************************/
// Offset the option values so they don't conflict with getopt_long return codes
#define PARSE_OPTION_OFFSET 100000
#include "parse.auto.c"
/***********************************************************************************************************************************
Map command names to ids and vice versa
***********************************************************************************************************************************/
void
configParse(int argListSize, const char *argList[])
{
// Reset optind to 1 in case getopt_long has been called before
optind = 1;
// Don't error automatically on unknown options - they will be processed in the loop below
opterr = false;
// Only the first non-option parameter should be treated as a command so track if the command has been set
bool commandSet = false;
// Parse options
int option;
int optionIdx;
while ((option = getopt_long(argListSize, (char **)argList, "-", optionList, &optionIdx)) != -1)
{
switch (option)
{
// Perl options that should be ignored
case 0:
break;
// Parse parameters that are not options, i.e. commands and parameters passed to commands
case 1:
// The first parameter should be the command
if (!commandSet)
{
// Try getting the command from the valid command list
TRY_BEGIN()
{
cfgCommandSet(cfgCommandId(argList[optind - 1]));
}
// Assert error means the command does not exist, which is correct for all usages but this one (since we don't
// have any control over what the user passes), so modify the error code and message.
CATCH(AssertError)
{
THROW(CommandInvalidError, "invalid command '%s'", argList[optind - 1]);
}
TRY_END();
}
// Else implement additional parameters here for more complex commands
commandSet = true;
break;
// If the option is unknown generate an error
case '?':
THROW(OptionInvalidError, "invalid option '%s'", argList[optind - 1]);
break; // {uncoverable - case statement does not return}
// Parse valid option
default:
break;
}
}
}

12
src/config/parse.h Normal file
View File

@ -0,0 +1,12 @@
/***********************************************************************************************************************************
Parse Configuration
***********************************************************************************************************************************/
#ifndef CONFIG_PARSE_H
#define CONFIG_PARSE_H
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
void configParse(int argListSize, char *argList[]);
#endif

View File

@ -1,10 +1,38 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Main Main
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "common/error.h"
#include "config/config.h"
#include "config/parse.h"
#include "perl/exec.h" #include "perl/exec.h"
#include "version.h"
int main(int argListSize, char *argList[]) int main(int argListSize, char *argList[])
{ {
// Execute Perl since nothing is implemented in C (yet) TRY_BEGIN()
{
// Parse command line
configParse(argListSize, argList);
// Display version
if (cfgCommand() == cfgCmdVersion)
{
printf(PGBACKREST_NAME " " PGBACKREST_VERSION "\n");
fflush(stdout);
exit(0);
}
// Execute Perl for commands not implemented in C
perlExec(perlCommand(argListSize, argList)); perlExec(perlCommand(argListSize, argList));
} }
CATCH_ANY()
{
fprintf(stderr, "ERROR: [%03d]: %s\n", errorCode(), errorMessage());
fflush(stderr);
exit(errorCode());
}
TRY_END();
}

View File

@ -44,6 +44,9 @@ StringList *perlCommand(int argListSize, char *argList[])
// Reset optind to 1 in case getopt_long has been called before // Reset optind to 1 in case getopt_long has been called before
optind = 1; optind = 1;
// Don't error on unknown options -- they are expected since we are passing options through to Perl
opterr = false;
// Struct with all valid options // Struct with all valid options
static struct option optionList[] = static struct option optionList[] =
{ {
@ -54,7 +57,6 @@ StringList *perlCommand(int argListSize, char *argList[])
// Parse options // Parse options
int option; int option;
int optionIdx; int optionIdx;
opterr = false;
while ((option = getopt_long(argListSize, argList, "-", optionList, &optionIdx)) != -1) while ((option = getopt_long(argListSize, argList, "-", optionList, &optionIdx)) != -1)
{ {

View File

@ -9,4 +9,9 @@ Official name of the software, also used for Perl package name
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#define PGBACKREST_NAME "pgBackRest" #define PGBACKREST_NAME "pgBackRest"
/***********************************************************************************************************************************
Version of the software. Currently this value is maintained in Version.pm and updated by test.pl.
***********************************************************************************************************************************/
#define PGBACKREST_VERSION "2.00dev"
#endif #endif

View File

@ -318,7 +318,7 @@ my $oTestDef =
}, },
{ {
&TESTDEF_NAME => 'config', &TESTDEF_NAME => 'config',
&TESTDEF_TOTAL => 1, &TESTDEF_TOTAL => 2,
&TESTDEF_C => true, &TESTDEF_C => true,
&TESTDEF_COVERAGE => &TESTDEF_COVERAGE =>
@ -327,6 +327,17 @@ my $oTestDef =
'config/config.auto' => TESTDEF_COVERAGE_NOCODE, 'config/config.auto' => TESTDEF_COVERAGE_NOCODE,
}, },
}, },
{
&TESTDEF_NAME => 'parse',
&TESTDEF_TOTAL => 1,
&TESTDEF_C => true,
&TESTDEF_COVERAGE =>
{
'config/parse' => TESTDEF_COVERAGE_FULL,
'config/parse.auto' => TESTDEF_COVERAGE_NOCODE,
},
},
{ {
&TESTDEF_NAME => 'unit', &TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 1, &TESTDEF_TOTAL => 1,

View File

@ -25,7 +25,7 @@ Test that an expected error is actually thrown and error when it isn't
{ \ { \
bool TEST_ERROR_catch = false; \ bool TEST_ERROR_catch = false; \
\ \
printf(" l%04d - expect error: %s\n", __LINE__, errorMessageExpected); \ printf(" l%04d - expect %s: %s\n", __LINE__, errorTypeName(&errorTypeExpected), errorMessageExpected); \
fflush(stdout); \ fflush(stdout); \
\ \
TRY_BEGIN() \ TRY_BEGIN() \
@ -89,6 +89,15 @@ Compare types
#define TEST_TYPE_COMPARE(result, value, typeOp, valueExpected) \ #define TEST_TYPE_COMPARE(result, value, typeOp, valueExpected) \
result = value typeOp valueExpected; result = value typeOp valueExpected;
/***********************************************************************************************************************************
Output information about the test
***********************************************************************************************************************************/
#define TEST_RESULT_INFO(...) \
printf(" l%04d - ", __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
fflush(stdout);
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Test the result of a statement and make sure it matches the expected value. This macro can test any C type given the correct Test the result of a statement and make sure it matches the expected value. This macro can test any C type given the correct
parameters. parameters.
@ -99,10 +108,7 @@ parameters.
const type TEST_RESULT_resultExpected = (type)(resultExpectedValue); \ const type TEST_RESULT_resultExpected = (type)(resultExpectedValue); \
\ \
/* Output test info */ \ /* Output test info */ \
printf(" l%04d - ", __LINE__); \ TEST_RESULT_INFO(__VA_ARGS__); \
printf(__VA_ARGS__); \
printf("\n"); \
fflush(stdout); \
\ \
/* Format the expected result */ \ /* Format the expected result */ \
formatMacro(type, format, TEST_RESULT_resultExpected); \ formatMacro(type, format, TEST_RESULT_resultExpected); \
@ -141,6 +147,27 @@ parameters.
} \ } \
} }
/***********************************************************************************************************************************
Test that a void statement returns and does not throw an error
***********************************************************************************************************************************/
#define TEST_RESULT_VOID(statement, ...) \
{ \
/* Output test info */ \
TEST_RESULT_INFO(__VA_ARGS__); \
\
TRY_BEGIN() \
{ \
statement; \
} \
/* Catch any errors */ \
CATCH_ANY() \
{ \
/* No errors were expected so error */ \
THROW(AssertError, "statement '%s' threw error %s, '%s' but void expected", #statement, errorName(), errorMessage()); \
} \
TRY_END(); \
}
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Macros to ease the use of common data types Macros to ease the use of common data types
***********************************************************************************************************************************/ ***********************************************************************************************************************************/

View File

@ -67,4 +67,12 @@ void testRun()
TEST_ERROR(cfgOptionName(-1), AssertError, optionIdInvalidLowError); TEST_ERROR(cfgOptionName(-1), AssertError, optionIdInvalidLowError);
TEST_RESULT_STR(cfgOptionName(cfgOptBackupStandby), "backup-standby", "option id from name"); TEST_RESULT_STR(cfgOptionName(cfgOptBackupStandby), "backup-standby", "option id from name");
} }
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("configuration"))
{
TEST_RESULT_INT(cfgCommand(), cfgCmdNone, "command begins as none");
TEST_RESULT_VOID(cfgCommandSet(cfgCmdBackup), "command set to backup");
TEST_RESULT_INT(cfgCommand(), cfgCmdBackup, "command is backup");
}
} }

View File

@ -0,0 +1,52 @@
/***********************************************************************************************************************************
Test Configuration Parse
***********************************************************************************************************************************/
#define TEST_BACKREST_EXE "pgbackrest"
#define TEST_COMMAND_HELP "help"
#define TEST_COMMAND_VERSION "version"
/***********************************************************************************************************************************
Test run
***********************************************************************************************************************************/
void testRun()
{
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("configParse()"))
{
StringList *argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), "exe only");
// -------------------------------------------------------------------------------------------------------------------------
strLstAdd(argList, strNew(TEST_COMMAND_VERSION));
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_VERSION " command");
TEST_RESULT_INT(cfgCommand(), cfgCmdVersion, "command is " TEST_COMMAND_VERSION);
// -------------------------------------------------------------------------------------------------------------------------
strLstAdd(argList, strNew("--perl-option=value"));
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), "perl option");
// -------------------------------------------------------------------------------------------------------------------------
strLstAdd(argList, strNewFmt("--%s", cfgOptionName(cfgOptDelta)));
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), "delta option");
// -------------------------------------------------------------------------------------------------------------------------
strLstAdd(argList, strNew("--" BOGUS_STR));
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList)), OptionInvalidError, "invalid option '--BOGUS'");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew("--no-archive-check"));
strLstAdd(argList, strNew(TEST_COMMAND_HELP));
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_HELP " command");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew(BOGUS_STR));
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList)), CommandInvalidError, "invalid command 'BOGUS'");
}
}

View File

@ -38,6 +38,6 @@ main(void)
// End test run an make sure all tests ran // End test run an make sure all tests ran
testComplete(); testComplete();
printf("\nTESTS COMPLETED SUCCESSFULLY (DESPITE ANY ERROR MESSAGES YOU SAW)\n"); printf("\nTESTS COMPLETED SUCCESSFULLY\n");
fflush(stdout); fflush(stdout);
} }

View File

@ -41,6 +41,7 @@ use pgBackRestBuild::Build;
use pgBackRestBuild::Build::Common; use pgBackRestBuild::Build::Common;
use pgBackRestBuild::Config::Build; use pgBackRestBuild::Config::Build;
use pgBackRestBuild::Config::BuildDefine; use pgBackRestBuild::Config::BuildDefine;
use pgBackRestBuild::Config::BuildParse;
use BackRestDoc::Custom::DocCustomRelease; use BackRestDoc::Custom::DocCustomRelease;
@ -281,41 +282,6 @@ eval
my $oStorageBackRest = new pgBackRest::Storage::Local( my $oStorageBackRest = new pgBackRest::Storage::Local(
$strBackRestBase, new pgBackRest::Storage::Posix::Driver({bFileSync => false, bPathSync => false})); $strBackRestBase, new pgBackRest::Storage::Posix::Driver({bFileSync => false, bPathSync => false}));
################################################################################################################################
# Auto-generate C files
################################################################################################################################
my $rhBuild =
{
'config' =>
{
&BLD_DATA => buildConfig(),
&BLD_PATH => 'config',
},
'configDefine' =>
{
&BLD_DATA => buildConfigDefine(),
&BLD_PATH => 'config',
},
};
buildAll("${strBackRestBase}/src", $rhBuild);
################################################################################################################################
# Auto-generate XS files
#
# Use statements are put here so this will be easy to get ride of someday.
################################################################################################################################
use lib dirname(dirname($0)) . '/libc/build/lib';
use pgBackRestLibC::Build; ## no critic (Modules::ProhibitConditionalUseStatements)
buildXsAll("${strBackRestBase}/libc");
if ($bGenOnly)
{
exit 0;
}
################################################################################################################################ ################################################################################################################################
# Build Docker containers # Build Docker containers
################################################################################################################################ ################################################################################################################################
@ -330,6 +296,45 @@ eval
################################################################################################################################ ################################################################################################################################
if (!defined($iVmId)) if (!defined($iVmId))
{ {
# Auto-generate C files
#---------------------------------------------------------------------------------------------------------------------------
my $rhBuild =
{
'config' =>
{
&BLD_DATA => buildConfig(),
&BLD_PATH => 'config',
},
'configDefine' =>
{
&BLD_DATA => buildConfigDefine(),
&BLD_PATH => 'config',
},
'configParse' =>
{
&BLD_DATA => buildConfigParse(),
&BLD_PATH => 'config',
},
};
buildAll("${strBackRestBase}/src", $rhBuild);
# Auto-generate XS files
#
# Use statements are put here so this will be easy to get rid of someday.
#---------------------------------------------------------------------------------------------------------------------------
use lib dirname(dirname($0)) . '/libc/build/lib';
use pgBackRestLibC::Build; ## no critic (Modules::ProhibitConditionalUseStatements)
buildXsAll("${strBackRestBase}/libc");
if ($bGenOnly)
{
exit 0;
}
# Sync time to prevent build failures when running on VirtualBox. # Sync time to prevent build failures when running on VirtualBox.
my $strVBoxService = '/usr/sbin/VBoxService'; my $strVBoxService = '/usr/sbin/VBoxService';
@ -370,6 +375,27 @@ eval
confess 'unable to find version ' . BACKREST_VERSION . " as the most recent release in ${strReleaseFile}"; confess 'unable to find version ' . BACKREST_VERSION . " as the most recent release in ${strReleaseFile}";
} }
# Update version for the C code based on the current Perl version
#---------------------------------------------------------------------------------------------------------------------------
my $strCVersionFile = "${strBackRestBase}/src/version.h";
my $strCVersionOld = ${$oStorageTest->get($strCVersionFile)};
my $strCVersionNew;
foreach my $strLine (split("\n", $strCVersionOld))
{
if ($strLine =~ /^#define PGBACKREST_VERSION/)
{
$strLine = '#define PGBACKREST_VERSION' . (' ' x 42) . '"' . BACKREST_VERSION . '"';
}
$strCVersionNew .= "${strLine}\n";
}
if ($strCVersionNew ne $strCVersionOld)
{
$oStorageTest->put($strCVersionFile, $strCVersionNew);
}
# Clean up # Clean up
#--------------------------------------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------------------------------------
my $iTestFail = 0; my $iTestFail = 0;