1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-03 14:52:21 +02:00

The C library is now required.

This eliminates conditional loading and eases development of new library features.
This commit is contained in:
David Steele 2017-11-26 17:45:00 -05:00
parent c164fc5fb9
commit 7cf955425e
29 changed files with 156 additions and 780 deletions

View File

@ -16,8 +16,7 @@ use Storable qw(dclone);
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRest::Config::Define;
use pgBackRestBuild::Config::Data;
use pgBackRest::Version;
use pgBackRestBuild::Build::Common;

View File

@ -16,8 +16,7 @@ use Storable qw(dclone);
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRest::Config::Define;
use pgBackRestBuild::Config::Data;
use pgBackRest::Version;
use pgBackRestBuild::Build::Common;

View File

@ -42,7 +42,7 @@
# CFGDEF_ALLOW_LIST:
# Lists the allowable settings for the option.
####################################################################################################################################
package pgBackRest::Config::Data;
package pgBackRestBuild::Config::Data;
use strict;
use warnings FATAL => qw(all);

View File

@ -13,7 +13,7 @@ use File::Basename qw(dirname);
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRestBuild::Config::Data;
use pgBackRest::Version;
####################################################################################################################################

View File

@ -17,21 +17,72 @@ use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRest::Config::Define;
use pgBackRest::Version;
use pgBackRestBuild::Config::Data;
use BackRestDoc::Common::DocManifest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::HostTest;
use pgBackRestTest::Common::HostGroupTest;
use BackRestDoc::Common::DocManifest;
####################################################################################################################################
# User that's building the docs
####################################################################################################################################
use constant DOC_USER => getpwuid($UID) eq 'root' ? 'ubuntu' : getpwuid($UID) . '';
####################################################################################################################################
# Generate indexed defines
####################################################################################################################################
my $rhConfigDefineIndex = cfgDefine();
foreach my $strKey (sort(keys(%{$rhConfigDefineIndex})))
{
# Build options for all possible db configurations
if (defined($rhConfigDefineIndex->{$strKey}{&CFGDEF_PREFIX}) &&
$rhConfigDefineIndex->{$strKey}{&CFGDEF_PREFIX} eq CFGDEF_PREFIX_DB)
{
my $strPrefix = $rhConfigDefineIndex->{$strKey}{&CFGDEF_PREFIX};
for (my $iIndex = 1; $iIndex <= CFGDEF_INDEX_DB; $iIndex++)
{
my $strKeyNew = "${strPrefix}${iIndex}" . substr($strKey, length($strPrefix));
$rhConfigDefineIndex->{$strKeyNew} = dclone($rhConfigDefineIndex->{$strKey});
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_INDEX_TOTAL} = CFGDEF_INDEX_DB;
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_INDEX} = $iIndex - 1;
# Create the alternate name for option index 1
if ($iIndex == 1)
{
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_ALT_NAME} = $strKey;
}
else
{
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_REQUIRED} = false;
}
if (defined($rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}) &&
defined($rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}{&CFGDEF_DEPEND_OPTION}))
{
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}{&CFGDEF_DEPEND_OPTION} =
"${strPrefix}${iIndex}" .
substr(
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}{&CFGDEF_DEPEND_OPTION},
length($strPrefix));
}
}
delete($rhConfigDefineIndex->{$strKey});
}
else
{
$rhConfigDefineIndex->{$strKey}{&CFGDEF_INDEX} = 0;
}
}
####################################################################################################################################
# CONSTRUCTOR
####################################################################################################################################
@ -516,20 +567,17 @@ sub backrestConfig
}
else
{
# Get the config options hash
my $rhOptionIndex = cfgDefineIndex();
# Make sure the specified option exists
# ??? This is too simplistic to handle new indexed options. The check below works for now but it would be good
# ??? to bring back more sophisticated checking in the future.
# if (!defined($rhOptionIndex->{$strKey}))
# if (!defined($rhConfigDefineIndex->{$strKey}))
# {
# confess &log(ERROR, "option ${strKey} does not exist");
# }
# If this option is a hash and the value is already set then append to the array
if (defined($rhOptionIndex->{$strKey}) &&
$rhOptionIndex->{$strKey}{&CFGDEF_TYPE} eq CFGDEF_TYPE_HASH &&
if (defined($rhConfigDefineIndex->{$strKey}) &&
$rhConfigDefineIndex->{$strKey}{&CFGDEF_TYPE} eq CFGDEF_TYPE_HASH &&
defined(${$self->{config}}{$strHostName}{$$hCacheKey{file}}{$strSection}{$strKey}))
{
my @oValue = ();

View File

@ -12,7 +12,7 @@ use Exporter qw(import);
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRestBuild::Config::Data;
use BackRestDoc::Common::DocRender;

View File

@ -10,8 +10,14 @@
</intro>
<release-list>
<release date="XXXX-XX-XX" version="1.27dev" title="UNDER DEVELOPMENT">
<release date="XXXX-XX-XX" version="2.00dev" title="UNDER DEVELOPMENT">
<release-core-list>
<release-improvement-list>
<release-item>
<p>The C library is now required. This eliminates conditional loading and eases development of new library features.</p>
</release-item>
</release-improvement-list>
<release-development-list>
<release-item>
<p>Add <code>memGrowRaw()</code> to memory context module.</p>

View File

@ -290,7 +290,7 @@
<!-- LibC installation - disabled for better testing of the C/Perl failback mechanism -->
<p><backrest/> includes an optional companion C library that enhances performance and enables the `checksum-page` option and encryption. Pre-built packages are generally a better option than building the C library manually but the steps required are given below for completeness. Depending on the distribution a number of packages may be required which will not be enumerated here.</p>
<execute-list host="{[host-db-primary]}">
<execute-list host="{[br-install-host]}">
<title>Build and Install C Library</title>
<execute user="root">

View File

@ -16,6 +16,7 @@ use pgBackRest::Archive::Get::Get;
use pgBackRest::Backup::Common;
use pgBackRest::Backup::File;
use pgBackRest::Backup::Info;
use pgBackRest::Common::Cipher;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Exit;
use pgBackRest::Common::Ini;
@ -25,7 +26,6 @@ use pgBackRest::Common::String;
use pgBackRest::Config::Config;
use pgBackRest::Db;
use pgBackRest::DbVersion;
use pgBackRest::LibCLoad;
use pgBackRest::Manifest;
use pgBackRest::Protocol::Local::Process;
use pgBackRest::Protocol::Helper;
@ -654,7 +654,7 @@ sub process
# Generate a passphrase for the backup set if the repo is encrypted
if (defined($strCipherPassManifest) && !defined($strCipherPassBackupSet) && $strType eq CFGOPTVAL_BACKUP_TYPE_FULL)
{
$strCipherPassBackupSet = $oStorageRepo->cipherPassGen();
$strCipherPassBackupSet = cipherPassGen();
}
# If backup label is not defined then create the label and path.
@ -705,19 +705,6 @@ sub process
my $hTablespaceMap = undef;
my $hDatabaseMap = undef;
# Only allow page checksums if the C library is available
if (!libC())
{
# Warn if page checksums were expicitly requested
if (cfgOptionTest(CFGOPT_CHECKSUM_PAGE) && cfgOption(CFGOPT_CHECKSUM_PAGE))
{
&log(WARN, "page checksums disabled - pgBackRest::LibC module is not present");
}
# Disable page checksums
cfgOptionSet(CFGOPT_CHECKSUM_PAGE, false);
}
# If this is an offline backup
if (!cfgOption(CFGOPT_ONLINE))
{

View File

@ -15,7 +15,7 @@ use Exporter qw(import);
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::DbVersion qw(PG_PAGE_SIZE);
use pgBackRest::LibCLoad;
use pgBackRest::LibC qw(:checksum);
####################################################################################################################################
# Package name constant
@ -23,16 +23,6 @@ use pgBackRest::LibCLoad;
use constant BACKUP_FILTER_PAGECHECKSUM => __PACKAGE__;
push @EXPORT, qw(BACKUP_FILTER_PAGECHECKSUM);
####################################################################################################################################
# Load the C library if present
####################################################################################################################################
if (libC())
{
# Load the C library only if page checksums are required
require pgBackRest::LibC;
pgBackRest::LibC->import(qw(:checksum));
};
####################################################################################################################################
# CONSTRUCTOR
####################################################################################################################################

View File

@ -0,0 +1,48 @@
####################################################################################################################################
# Cipher Miscellaneous
####################################################################################################################################
package pgBackRest::Common::Cipher;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::LibC qw(:random :encode);
####################################################################################################################################
# cipherPassGen - generate a passphrase of the specified size (in bytes)
####################################################################################################################################
sub cipherPassGen
{
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$iKeySizeInBytes,
) =
logDebugParam
(
__PACKAGE__ . '::cipherPassGen', \@_,
{name => 'iKeySizeInBytes', default => 48},
);
# Create and base64 encode the key
my $strCipherPass = encodeToStr(ENCODE_TYPE_BASE64, randomBytes($iKeySizeInBytes));
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strCipherPass', value => $strCipherPass, redact => true}
);
}
push @EXPORT, qw(cipherPassGen);
1;

View File

@ -20,13 +20,14 @@ use pgBackRest::Common::Io::Base;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Wait;
use pgBackRest::Config::LoadFailback;
use pgBackRest::LibC qw(:config :configDefine);
use pgBackRest::Version;
####################################################################################################################################
# Export config constants and functions
####################################################################################################################################
push(@EXPORT, @pgBackRest::Config::LoadFailback::EXPORT);
push(@EXPORT, @{$pgBackRest::LibC::EXPORT_TAGS{config}});
push(@EXPORT, @{$pgBackRest::LibC::EXPORT_TAGS{configDefine}});
####################################################################################################################################
# SOURCE Constants

View File

@ -1,571 +0,0 @@
####################################################################################################################################
# Configuration Definition Interface
####################################################################################################################################
package pgBackRest::Config::Define;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use Storable qw(dclone);
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::Config::Data;
####################################################################################################################################
# Generate indexed defines
####################################################################################################################################
my $rhConfigDefineIndex = cfgDefine();
foreach my $strKey (sort(keys(%{$rhConfigDefineIndex})))
{
# Build options for all possible db configurations
if (defined($rhConfigDefineIndex->{$strKey}{&CFGDEF_PREFIX}) &&
$rhConfigDefineIndex->{$strKey}{&CFGDEF_PREFIX} eq CFGDEF_PREFIX_DB)
{
my $strPrefix = $rhConfigDefineIndex->{$strKey}{&CFGDEF_PREFIX};
for (my $iIndex = 1; $iIndex <= CFGDEF_INDEX_DB; $iIndex++)
{
my $strKeyNew = "${strPrefix}${iIndex}" . substr($strKey, length($strPrefix));
$rhConfigDefineIndex->{$strKeyNew} = dclone($rhConfigDefineIndex->{$strKey});
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_INDEX_TOTAL} = CFGDEF_INDEX_DB;
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_INDEX} = $iIndex - 1;
# Create the alternate name for option index 1
if ($iIndex == 1)
{
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_ALT_NAME} = $strKey;
}
else
{
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_REQUIRED} = false;
}
if (defined($rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}) &&
defined($rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}{&CFGDEF_DEPEND_OPTION}))
{
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}{&CFGDEF_DEPEND_OPTION} =
"${strPrefix}${iIndex}" .
substr(
$rhConfigDefineIndex->{$strKeyNew}{&CFGDEF_DEPEND}{&CFGDEF_DEPEND_OPTION},
length($strPrefix));
}
}
delete($rhConfigDefineIndex->{$strKey});
}
else
{
$rhConfigDefineIndex->{$strKey}{&CFGDEF_INDEX} = 0;
}
}
my $iOptionTotal = scalar(keys(%{$rhConfigDefineIndex}));
sub cfgDefineIndex
{
return dclone($rhConfigDefineIndex);
}
push @EXPORT, qw(cfgDefineIndex);
####################################################################################################################################
# Create maps to convert option ids to names and vice versa
####################################################################################################################################
my $rhOptionNameId;
my $rhOptionIdName;
my $rhOptionNameAlt;
{
my $iIndex = 0;
foreach my $strOption (sort(keys(%{$rhConfigDefineIndex})))
{
$rhOptionNameId->{$strOption} = $iIndex;
$rhOptionNameAlt->{$strOption} = $strOption;
$rhOptionIdName->{$iIndex} = $strOption;
if (defined(cfgDefOptionNameAlt($strOption)))
{
$rhOptionNameId->{cfgDefOptionNameAlt($strOption)} = $iIndex;
$rhOptionNameAlt->{cfgDefOptionNameAlt($strOption)} = $strOption;
}
$iIndex++;
}
}
####################################################################################################################################
# Get a define for the option from a command or default
####################################################################################################################################
sub cfgOptionDefine
{
my $strCommand = shift;
my $strOption = shift;
my $strDefine = shift;
return
defined($rhConfigDefineIndex->{$strOption}{&CFGDEF_COMMAND}{$strCommand}) &&
defined($rhConfigDefineIndex->{$strOption}{&CFGDEF_COMMAND}{$strCommand}{$strDefine}) ?
$rhConfigDefineIndex->{$strOption}{&CFGDEF_COMMAND}{$strCommand}{$strDefine} :
$rhConfigDefineIndex->{$strOption}{$strDefine};
}
####################################################################################################################################
# Functions that are noops in the Perl code since commands/options are always treated as strings
####################################################################################################################################
sub cfgCommandId {return shift()}
sub cfgCommandName {return shift()}
sub cfgOptionId
{
my $strOptionName = shift;
if (!defined($rhOptionNameId->{$strOptionName}))
{
return -1;
}
return $rhOptionNameAlt->{$strOptionName};
}
sub cfgOptionName
{
my $strOptionId = shift;
if (defined($rhOptionIdName->{$strOptionId}))
{
return $rhOptionIdName->{$strOptionId};
}
return $rhOptionNameAlt->{$strOptionId};
}
push @EXPORT, qw(cfgCommandId cfgCommandName cfgOptionId cfgOptionName);
####################################################################################################################################
# cfgOptionTotal - total number of options
####################################################################################################################################
sub cfgOptionTotal
{
return $iOptionTotal;
}
push @EXPORT, qw(cfgOptionTotal);
####################################################################################################################################
# cfgDefOptionAllowList - does the option have a specific list of allowed values?
####################################################################################################################################
sub cfgDefOptionAllowList
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $bError = shift;
my $rhAllowList = cfgOptionDefine($strCommand, $strOption, CFGDEF_ALLOW_LIST);
if (!defined($rhAllowList) && defined($bError) && $bError)
{
confess &log(ASSERT, "allow list not set for ${strCommand}, ${strOption}");
}
# The allow list must have values
if (defined($rhAllowList) && @{$rhAllowList} == 0)
{
confess &log(ASSERT, "allow list must have values for ${strCommand}, ${strOption}");
}
return defined($rhAllowList) ? true : false;
}
push @EXPORT, qw(cfgDefOptionAllowList);
####################################################################################################################################
# cfgDefOptionAllowListValue - get an allow list value
####################################################################################################################################
sub cfgDefOptionAllowListValue
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $iValueIdx = shift;
# Index shouldn't be greater than the total number of values
if ($iValueIdx >= cfgDefOptionAllowListValueTotal($strCommand, $strOption, $iValueIdx))
{
confess &log(ASSERT, "invalid allow list value index ${iValueIdx} for ${strCommand}, ${strOption}");
}
# Return value
return cfgOptionDefine($strCommand, $strOption, CFGDEF_ALLOW_LIST)->[$iValueIdx];
}
push @EXPORT, qw(cfgDefOptionAllowListValue);
####################################################################################################################################
# cfgDefOptionAllowListValueTotal - how many values are allowed for the option?
####################################################################################################################################
sub cfgDefOptionAllowListValueTotal
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
# Make sure the allow list exists
cfgDefOptionAllowList($strCommand, $strOption, true);
# Return total elements in the list
return scalar(@{cfgOptionDefine($strCommand, $strOption, CFGDEF_ALLOW_LIST)});
}
push @EXPORT, qw(cfgDefOptionAllowListValueTotal);
####################################################################################################################################
# cfgDefOptionAllowListValueValid - is the value valid for this option?
####################################################################################################################################
sub cfgDefOptionAllowListValueValid
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $strValue = shift;
# Make sure the allow list exists
cfgDefOptionAllowList($strCommand, $strOption, true);
# Check if the value is valid
foreach my $strValueMatch (@{cfgOptionDefine($strCommand, $strOption, CFGDEF_ALLOW_LIST)})
{
if ($strValue eq $strValueMatch)
{
return true;
}
}
return false;
}
push @EXPORT, qw(cfgDefOptionAllowListValueValid);
####################################################################################################################################
# cfgDefOptionAllowRange - does the option have min/max values?
####################################################################################################################################
sub cfgDefOptionAllowRange
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $bError = shift;
my $rhAllowRange = cfgOptionDefine($strCommand, $strOption, CFGDEF_ALLOW_RANGE);
if (!defined($rhAllowRange) && defined($bError) && $bError)
{
confess &log(ASSERT, "allow range not set for ${strCommand}, ${strOption}");
}
# The allow range must have two values
if (defined($rhAllowRange) && @{$rhAllowRange} != 2)
{
confess &log(ASSERT, "allow range must have two values for ${strCommand}, ${strOption}");
}
return defined($rhAllowRange) ? true : false;
}
push @EXPORT, qw(cfgDefOptionAllowRange);
####################################################################################################################################
# cfgDefOptionAllowRangeMax - get max value in allowed range
####################################################################################################################################
sub cfgDefOptionAllowRangeMax
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
# Make sure the allow range exists
cfgDefOptionAllowRange($strCommand, $strOption);
# Return value
return cfgOptionDefine($strCommand, $strOption, CFGDEF_ALLOW_RANGE)->[1];
}
push @EXPORT, qw(cfgDefOptionAllowRangeMax);
####################################################################################################################################
# cfgDefOptionAllowRangeMin - get min value in allowed range
####################################################################################################################################
sub cfgDefOptionAllowRangeMin
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
# Make sure the allow range exists
cfgDefOptionAllowRange($strCommand, $strOption);
# Return value
return cfgOptionDefine($strCommand, $strOption, CFGDEF_ALLOW_RANGE)->[0];
}
push @EXPORT, qw(cfgDefOptionAllowRangeMin);
####################################################################################################################################
# cfgDefOptionDefault - option default, if any
####################################################################################################################################
sub cfgDefOptionDefault
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
return cfgOptionDefine($strCommand, $strOption, CFGDEF_DEFAULT);
}
push @EXPORT, qw(cfgDefOptionDefault);
####################################################################################################################################
# cfgDefOptionDepend - does the option depend on another option being set or having a certain value?
####################################################################################################################################
sub cfgDefOptionDepend
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $bError = shift;
my $rhDepend = cfgOptionDefine($strCommand, $strOption, CFGDEF_DEPEND);
if (!defined($rhDepend) && defined($bError) && $bError)
{
confess &log(ASSERT, "depend define not set for ${strCommand}, ${strOption}");
}
return defined($rhDepend) ? true : false;
}
push @EXPORT, qw(cfgDefOptionDepend);
####################################################################################################################################
# cfgDefOptionDependOption - name of the option that this option depends on
####################################################################################################################################
sub cfgDefOptionDependOption
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
# Make sure the depend define exists
cfgDefOptionDepend($strCommand, $strOption, true);
# Error if the depend option does not exist
my $rhDepend = cfgOptionDefine($strCommand, $strOption, CFGDEF_DEPEND);
if (!defined($rhDepend->{&CFGDEF_DEPEND_OPTION}))
{
confess &log(ASSERT, "depend define option not set for ${strCommand}, ${strOption}");
}
return $rhDepend->{&CFGDEF_DEPEND_OPTION};
}
push @EXPORT, qw(cfgDefOptionDependOption);
####################################################################################################################################
# cfgDefOptionDependValue - get a depend option value
####################################################################################################################################
sub cfgDefOptionDependValue
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $iValueIdx = shift;
# Index shouldn't be greater than the total number of values
if ($iValueIdx >= cfgDefOptionDependValueTotal($strCommand, $strOption, $iValueIdx))
{
confess &log(ASSERT, "invalid depend value index ${iValueIdx} for ${strCommand}, ${strOption}");
}
# Return value
return cfgOptionDefine($strCommand, $strOption, CFGDEF_DEPEND)->{&CFGDEF_DEPEND_LIST}->[$iValueIdx];
}
push @EXPORT, qw(cfgDefOptionDependValue);
####################################################################################################################################
# cfgDefOptionDependValueTotal - how many values are allowed for the depend option?
#
# 0 indicates that the value of the depend option doesn't matter, only that is is set.
####################################################################################################################################
sub cfgDefOptionDependValueTotal
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
# Make sure the depend define exists
cfgDefOptionDepend($strCommand, $strOption, true);
# It's OK for the list not to be defined
my $rhDepend = cfgOptionDefine($strCommand, $strOption, CFGDEF_DEPEND);
if (!defined($rhDepend->{&CFGDEF_DEPEND_LIST}))
{
return 0;
}
# Return total elements in the list
return scalar(@{$rhDepend->{&CFGDEF_DEPEND_LIST}});
}
push @EXPORT, qw(cfgDefOptionDependValueTotal);
####################################################################################################################################
# cfgDefOptionDependValueValid - is the depend valid valid?
####################################################################################################################################
sub cfgDefOptionDependValueValid
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $strValue = shift;
# Make sure the depend define exists
cfgDefOptionDepend($strCommand, $strOption, true);
# Check if the value is valid
foreach my $strValueMatch (@{cfgOptionDefine($strCommand, $strOption, CFGDEF_DEPEND)->{&CFGDEF_DEPEND_LIST}})
{
if ($strValue eq $strValueMatch)
{
return true;
}
}
return false;
}
push @EXPORT, qw(cfgDefOptionDependValueValid);
####################################################################################################################################
# cfgOptionIndex - index for option
####################################################################################################################################
sub cfgOptionIndex
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_INDEX};
}
push @EXPORT, qw(cfgOptionIndex);
####################################################################################################################################
# cfgOptionIndexTotal - max index for options that are indexed (e.g., db)
####################################################################################################################################
sub cfgOptionIndexTotal
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_INDEX_TOTAL};
}
push @EXPORT, qw(cfgOptionIndexTotal);
####################################################################################################################################
# cfgDefOptionNameAlt - alternative or deprecated option name
####################################################################################################################################
sub cfgDefOptionNameAlt
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_ALT_NAME};
}
push @EXPORT, qw(cfgDefOptionNameAlt);
####################################################################################################################################
# cfgDefOptionNegate - is the boolean option negatable?
####################################################################################################################################
sub cfgDefOptionNegate
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_NEGATE};
}
push @EXPORT, qw(cfgDefOptionNegate);
####################################################################################################################################
# cfgDefOptionPrefix - fixed prefix for indexed options
####################################################################################################################################
sub cfgDefOptionPrefix
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_PREFIX};
}
push @EXPORT, qw(cfgDefOptionPrefix);
####################################################################################################################################
# cfgDefOptionRequired - is the option required?
####################################################################################################################################
sub cfgDefOptionRequired
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
my $rxDefine = cfgOptionDefine($strCommand, $strOption, CFGDEF_REQUIRED);
return defined($rxDefine) ? $rxDefine : true;
}
push @EXPORT, qw(cfgDefOptionRequired);
####################################################################################################################################
# cfgDefOptionSection - section to contain optio (global or stanza), all others are command-line only
####################################################################################################################################
sub cfgDefOptionSection
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_SECTION};
}
push @EXPORT, qw(cfgDefOptionSection);
####################################################################################################################################
# cfgDefOptionSecure - can the option be passed on the command-line?
####################################################################################################################################
sub cfgDefOptionSecure
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_SECURE};
}
push @EXPORT, qw(cfgDefOptionSecure);
####################################################################################################################################
# cfgDefOptionType - data type of the option (e.g. boolean, string)
####################################################################################################################################
sub cfgDefOptionType
{
my $strOption = cfgOptionName(shift);
return $rhConfigDefineIndex->{$strOption}{&CFGDEF_TYPE};
}
push @EXPORT, qw(cfgDefOptionType);
####################################################################################################################################
# cfgDefOptionValid - is the option valid for the command?
####################################################################################################################################
sub cfgDefOptionValid
{
my $strCommand = shift;
my $strOption = cfgOptionName(shift);
return
defined($rhConfigDefineIndex->{$strOption}{&CFGDEF_COMMAND}) &&
defined($rhConfigDefineIndex->{$strOption}{&CFGDEF_COMMAND}{$strCommand}) ? true : false;
}
push @EXPORT, qw(cfgDefOptionValid);
1;

View File

@ -1,37 +0,0 @@
####################################################################################################################################
# Load C or Perl Config Code
####################################################################################################################################
package pgBackRest::Config::LoadFailback;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Log;
use pgBackRest::LibCLoad;
####################################################################################################################################
# Load the C library if present, else failback to the Perl code
####################################################################################################################################
if (libC())
{
require pgBackRest::LibC;
pgBackRest::LibC->import(qw(:config :configDefine));
push(@EXPORT, @{$pgBackRest::LibC::EXPORT_TAGS{config}});
push(@EXPORT, @{$pgBackRest::LibC::EXPORT_TAGS{configDefine}});
}
else
{
require pgBackRest::Config::Data;
pgBackRest::Config::Data->import();
push(@EXPORT, @pgBackRest::Config::Data::EXPORT);
require pgBackRest::Config::Define;
pgBackRest::Config::Define->import();
push(@EXPORT, @pgBackRest::Config::Define::EXPORT);
}
1;

View File

@ -1,39 +0,0 @@
####################################################################################################################################
# Determine if C Library is Present
####################################################################################################################################
package pgBackRest::LibCLoad;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Log;
####################################################################################################################################
# Attempt to load the C Library
####################################################################################################################################
my $bLibC = false;
eval
{
# Attempt to load the C Library
require pgBackRest::LibC;
$bLibC = true;
return 1;
} or do {};
####################################################################################################################################
# libC - is the C library present?
####################################################################################################################################
sub libC
{
return $bLibC;
}
push @EXPORT, qw(libC);
1;

View File

@ -13,6 +13,7 @@ use English '-no_match_vars';
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Cipher;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
@ -450,9 +451,7 @@ sub infoObject
# else existed in the repo so a passphrase is generated to store in the file. If it exists and the repo is encrypted then
# the generated passphrase passed will not be used - the one from the info file will be read.
my $oParamRef =
{bIgnoreMissing => $bIgnoreMissing,
strCipherPassSub => defined(storageRepo()->cipherType()) ?
storageRepo()->cipherPassGen() : undef};
{bIgnoreMissing => $bIgnoreMissing, strCipherPassSub => defined(storageRepo()->cipherType()) ? cipherPassGen() : undef};
$oInfo = ($strPathType eq STORAGE_REPO_BACKUP ?
new pgBackRest::Backup::Info($strParentPath, false, $bRequired, $oParamRef) :
@ -498,9 +497,7 @@ sub infoObject
}
my $oParamRef =
{bLoad => false,
strCipherPassSub => defined(storageRepo()->cipherType()) ?
storageRepo()->cipherPassGen() : undef};
{bLoad => false, strCipherPassSub => defined(storageRepo()->cipherType()) ? cipherPassGen() : undef};
$oInfo = ($strPathType eq STORAGE_REPO_BACKUP ?
new pgBackRest::Backup::Info($strParentPath, false, false, $oParamRef) :

View File

@ -909,39 +909,6 @@ sub encryptionValid
);
}
####################################################################################################################################
# cipherPassGen - generate a passphrase of the specified size (in bytes)
####################################################################################################################################
sub cipherPassGen
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$iKeySizeInBytes,
) =
logDebugParam
(
__PACKAGE__ . '->cipherPassGen', \@_,
{name => 'iKeySizeInBytes', default => 48},
);
require pgBackRest::LibC;
pgBackRest::LibC->import(qw(:random :encode));
# ??? Constant for base64 encoding can't used here because it is not loaded at parse time -- fix when the C library required
my $strCipherPass = encodeToStr(0, randomBytes($iKeySizeInBytes));
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strCipherPassSub', value => $strCipherPass, redact => true}
);
}
####################################################################################################################################
# Getters
####################################################################################################################################

View File

@ -35,7 +35,7 @@ use constant BACKREST_BIN => abs_path(
# Defines the current version of the BackRest executable. The version number is used to track features but does not affect what
# repositories or manifests can be read - that's the job of the format number.
#-----------------------------------------------------------------------------------------------------------------------------------
use constant BACKREST_VERSION => '1.27dev';
use constant BACKREST_VERSION => '2.00dev';
push @EXPORT, qw(BACKREST_VERSION);
# Format Format Number

View File

@ -19,7 +19,7 @@ use lib dirname($0) . '/../lib';
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRestBuild::Config::Data;
use pgBackRest::Storage::Local;
use pgBackRest::Storage::Posix::Driver;
use pgBackRest::Version;

View File

@ -16,8 +16,7 @@ use Storable qw(dclone);
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRest::Config::Define;
use pgBackRestBuild::Config::Data;
use pgBackRest::Version;
use pgBackRestBuild::Build::Common;

View File

@ -16,8 +16,7 @@ use Storable qw(dclone);
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Data;
use pgBackRest::Config::Define;
use pgBackRestBuild::Config::Data;
use pgBackRest::Version;
use pgBackRestBuild::Build::Common;

View File

@ -6,7 +6,7 @@ package pgBackRest::LibCAuto;
# Library version (.999 indicates development version)
sub libcAutoVersion
{
return '1.27.999';
return '2.00.999';
}
# Configuration option value constants

View File

@ -43,9 +43,6 @@ use constant TESTDEF_EXPECT => 'expect';
# Is this a C test (instead of Perl)?
use constant TESTDEF_C => 'c';
push @EXPORT, qw(TESTDEF_C);
# Is the C library required? This only applies to unit tests, the C library is always supplied for integration tests.
use constant TESTDEF_CLIB => 'clib';
push @EXPORT, qw(TESTDEF_CLIB);
# Determines if each run in a test will be run in a new container
use constant TESTDEF_INDIVIDUAL => 'individual';
push @EXPORT, qw(TESTDEF_INDIVIDUAL);
@ -142,7 +139,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'encode-perl',
&TESTDEF_TOTAL => 1,
&TESTDEF_CLIB => true,
},
{
&TESTDEF_NAME => 'http-client',
@ -156,7 +152,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'ini',
&TESTDEF_TOTAL => 10,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -316,7 +311,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'filter-cipher-block',
&TESTDEF_TOTAL => 2,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -389,7 +383,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'local',
&TESTDEF_TOTAL => 10,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -399,7 +392,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'helper',
&TESTDEF_TOTAL => 5,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -445,7 +437,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 2,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -473,7 +464,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'push',
&TESTDEF_TOTAL => 8,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -494,7 +484,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'info-unit',
&TESTDEF_TOTAL => 4,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -504,7 +493,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'get',
&TESTDEF_TOTAL => 2,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -533,7 +521,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'info-unit',
&TESTDEF_TOTAL => 3,
&TESTDEF_CLIB => true,
&TESTDEF_COVERAGE =>
{
@ -570,7 +557,6 @@ my $oTestDef =
{
&TESTDEF_NAME => 'all',
&TESTDEF_TOTAL => 8,
&TESTDEF_CLIB => true,
&TESTDEF_CONTAINER => true,
&TESTDEF_COVERAGE =>
@ -664,7 +650,7 @@ foreach my $hModule (@{$oTestDef->{&TESTDEF_MODULE}})
# Resolve variables that can be set in the module or the test
foreach my $strVar (
TESTDEF_C, TESTDEF_CLIB, TESTDEF_CONTAINER, TESTDEF_EXPECT, TESTDEF_DB, TESTDEF_INDIVIDUAL, TESTDEF_VM)
TESTDEF_C, TESTDEF_CONTAINER, TESTDEF_EXPECT, TESTDEF_DB, TESTDEF_INDIVIDUAL, TESTDEF_VM)
{
$hTestDefHash->{$strModule}{$strTest}{$strVar} = coalesce(
$hModuleTest->{$strVar}, $hModule->{$strVar}, $strVar eq TESTDEF_VM ? undef : false);

View File

@ -165,23 +165,20 @@ sub run
{bSuppressStdErr => true});
# Install Perl C Library
if ($self->{oTest}->{&TEST_CLIB})
{
my $oVm = vmGet();
my $strOS = $self->{oTest}->{&TEST_VM};
my $strBuildPath = $self->{strBackRestBase} . "/test/.vagrant/libc/$strOS/libc/";
my $strPerlAutoPath = $$oVm{$strOS}{&VMDEF_PERL_ARCH_PATH} . '/auto/pgBackRest/LibC';
my $strPerlModulePath = $$oVm{$strOS}{&VMDEF_PERL_ARCH_PATH} . '/pgBackRest';
my $oVm = vmGet();
my $strOS = $self->{oTest}->{&TEST_VM};
my $strBuildPath = $self->{strBackRestBase} . "/test/.vagrant/libc/$strOS/libc/";
my $strPerlAutoPath = $$oVm{$strOS}{&VMDEF_PERL_ARCH_PATH} . '/auto/pgBackRest/LibC';
my $strPerlModulePath = $$oVm{$strOS}{&VMDEF_PERL_ARCH_PATH} . '/pgBackRest';
executeTest(
"docker exec -i -u root ${strImage} bash -c '" .
"mkdir -p -m 755 ${strPerlAutoPath} && " .
"cp ${strBuildPath}/blib/arch/auto/pgBackRest/LibC/LibC.so ${strPerlAutoPath} && " .
"cp ${strBuildPath}/blib/lib/auto/pgBackRest/LibC/autosplit.ix ${strPerlAutoPath} && " .
"mkdir -p -m 755 ${strPerlModulePath} && " .
"cp ${strBuildPath}/blib/lib/pgBackRest/LibC.pm ${strPerlModulePath} && " .
"cp ${strBuildPath}/blib/lib/pgBackRest/LibCAuto.pm ${strPerlModulePath}'");
}
executeTest(
"docker exec -i -u root ${strImage} bash -c '" .
"mkdir -p -m 755 ${strPerlAutoPath} && " .
"cp ${strBuildPath}/blib/arch/auto/pgBackRest/LibC/LibC.so ${strPerlAutoPath} && " .
"cp ${strBuildPath}/blib/lib/auto/pgBackRest/LibC/autosplit.ix ${strPerlAutoPath} && " .
"mkdir -p -m 755 ${strPerlModulePath} && " .
"cp ${strBuildPath}/blib/lib/pgBackRest/LibC.pm ${strPerlModulePath} && " .
"cp ${strBuildPath}/blib/lib/pgBackRest/LibCAuto.pm ${strPerlModulePath}'");
}
}

View File

@ -26,8 +26,6 @@ use constant TEST_DB => 'db';
push @EXPORT, qw(TEST_DB);
use constant TEST_C => 'c';
push @EXPORT, qw(TEST_C);
use constant TEST_CLIB => 'clib';
push @EXPORT, qw(TEST_CLIB);
use constant TEST_CONTAINER => 'container';
push @EXPORT, qw(TEST_CONTAINER);
use constant TEST_MODULE => 'module';
@ -144,7 +142,6 @@ sub testListGet
{
&TEST_VM => $strTestOS,
&TEST_C => coalesce($hTest->{&TESTDEF_C}, $hModule->{&TESTDEF_C}, false),
&TEST_CLIB => coalesce($hTest->{&TESTDEF_CLIB}, $hModule->{&TESTDEF_CLIB}, false),
&TEST_CONTAINER => defined($hTest->{&TESTDEF_CONTAINER}) ?
$hTest->{&TESTDEF_CONTAINER} : $hModule->{&TESTDEF_CONTAINER},
&TEST_PGSQL_BIN => $strPgSqlBin,

View File

@ -15,7 +15,7 @@ use English '-no_match_vars';
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRest::Config::Data;
use pgBackRestBuild::Config::Data;
use constant CONFIGENVTEST => 'ConfigEnvTest';

View File

@ -17,6 +17,7 @@ use Storable qw(dclone);
use pgBackRest::Archive::Info;
use pgBackRest::Backup::Info;
use pgBackRest::Common::Cipher;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Lock;
@ -222,7 +223,7 @@ sub run
storageRepoCacheClear($self->stanza());
# Create an encrypted storage and generate an encyption sub passphrase to store in the file
my $strCipherPassSub = storageRepo()->cipherPassGen();
my $strCipherPassSub = cipherPassGen();
# Error on encrypted repo but no passphrase passed to store in the file
$self->testException(sub {new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false,

View File

@ -17,6 +17,7 @@ use Storable qw(dclone);
use pgBackRest::Archive::Info;
use pgBackRest::Backup::Info;
use pgBackRest::Common::Cipher;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Lock;
use pgBackRest::Common::Log;
@ -225,7 +226,7 @@ sub run
{bIgnoreMissing => true})}, ERROR_ASSERT,
'a user passphrase and sub passphrase are both required when encrypting');
my $strCipherPassSub = storageRepo()->cipherPassGen();
my $strCipherPassSub = cipherPassGen();
# Create encrypted files
$oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false,

View File

@ -18,6 +18,7 @@ use Storable qw(dclone);
use pgBackRest::Archive::Common;
use pgBackRest::Archive::Info;
use pgBackRest::Backup::Info;
use pgBackRest::Common::Cipher;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Lock;
@ -325,7 +326,7 @@ sub run
# Get the encryption passphrase and create the new manifest
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
$oBackupManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94,
strCipherPass => $oBackupInfo->cipherPassSub(), strCipherPassSub => storageRepo()->cipherPassGen()});
strCipherPass => $oBackupInfo->cipherPassSub(), strCipherPassSub => cipherPassGen()});
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef, $strBackupLabel);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK, undef, true);
@ -518,11 +519,11 @@ sub run
# Create encrypted info files with prior passphrase then attempt to change
#---------------------------------------------------------------------------------------------------------------------------
$oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true,
strCipherPassSub => storageRepo()->cipherPassGen()});
strCipherPassSub => cipherPassGen()});
$oArchiveInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), true);
$oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true,
strCipherPassSub => storageRepo()->cipherPassGen()});
strCipherPassSub => cipherPassGen()});
$oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), '937', '201306121', true);
# Attempt to upgrade with a different passphrase