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

Working on more robust file functions.

This commit is contained in:
David Steele 2014-06-01 17:23:33 -04:00
parent 85f591f801
commit 0338369193
7 changed files with 611 additions and 173 deletions

View File

@ -34,6 +34,7 @@ IPC::System::Simple
Net::OpenSSH
JSON
IPC::Open3
Digest::SHA
## release notes

145
bin/pg_backrest_command.pl Executable file
View File

@ -0,0 +1,145 @@
#!/usr/bin/perl
####################################################################################################################################
# pg_backrest_command.pl - Simple Postgres Backup and Restore Command Helper
####################################################################################################################################
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings;
use english;
use File::Basename;
use Getopt::Long;
use Carp;
use lib dirname($0) . '/..';
use pg_backrest_utility;
use pg_backrest_file;
####################################################################################################################################
# Operation constants - basic operations that are allowed in backrest command
####################################################################################################################################
use constant
{
OP_LIST => "list",
OP_EXISTS => "exists",
OP_HASH => "hash",
OP_REMOVE => "remove",
OP_MANIFEST => "manifest"
};
####################################################################################################################################
# Command line parameters
####################################################################################################################################
my $bIgnoreMissing = false; # Ignore errors due to missing file
my $strExpression = undef; # Expression to use for filtering
my $strSort = undef; # Sort order (undef = forward)
GetOptions ("ignore-missing" => \$bIgnoreMissing,
"expression=s" => \$strExpression,
"sort=s" => \$strSort)
or die("Error in command line arguments\n");
####################################################################################################################################
# START MAIN
####################################################################################################################################
# Turn off logging
log_level_set(OFF, OFF);
# Get the operation
my $strOperation = $ARGV[0];
# Validate the operation
if (!defined($strOperation))
{
confess &log(ERROR, "operation is not defined");
}
if ($strOperation ne OP_LIST &&
$strOperation ne OP_EXISTS &&
$strOperation ne OP_HASH &&
$strOperation ne OP_REMOVE &&
$strOperation ne OP_MANIFEST)
{
confess &log(ERROR, "invalid operation ${strOperation}");
}
# Create the file object
my $oFile = pg_backrest_file->new();
####################################################################################################################################
# LIST Command
####################################################################################################################################
if ($strOperation eq OP_LIST)
{
my $strPath = $ARGV[1];
if (!defined($strPath))
{
confess "path must be specified for list operation";
}
my $bFirst = true;
foreach my $strFile ($oFile->list(PATH_ABSOLUTE, $strPath, $strExpression, $strSort))
{
$bFirst ? $bFirst = false : print "\n";
print $strFile;
}
exit 0;
}
####################################################################################################################################
# EXISTS Command
####################################################################################################################################
if ($strOperation eq OP_EXISTS)
{
my $strFile = $ARGV[1];
if (!defined($strFile))
{
confess "filename must be specified for exist operation";
}
print $oFile->exists(PATH_ABSOLUTE, $strFile) ? "Y" : "N";
exit 0;
}
####################################################################################################################################
# HASH Command
####################################################################################################################################
if ($strOperation eq OP_HASH)
{
my $strFile = $ARGV[1];
if (!defined($strFile))
{
confess "filename must be specified for hash operation";
}
print $oFile->hash(PATH_ABSOLUTE, $strFile);
exit 0;
}
####################################################################################################################################
# REMOVE Command
####################################################################################################################################
if ($strOperation eq OP_REMOVE)
{
my $strFile = $ARGV[1];
if (!defined($strFile))
{
confess "Filename must be specified for remove operation";
}
print $oFile->remove(PATH_ABSOLUTE, $strFile, undef, $bIgnoreMissing) ? "Y" : "N";
exit 0;
}

View File

@ -1,4 +1,5 @@
[global:command]
backrest_command=
#compress=pigz --rsyncable --best --stdout %file% # Ubuntu Linux
compress=/usr/bin/gzip --stdout %file%
decompress=/usr/bin/gzip -dc %file%

View File

@ -230,6 +230,7 @@ if ($strOperation eq OP_ARCHIVE_GET)
strBackupUser => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_USER),
strBackupHost => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HOST),
strBackupPath => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
strCommand => $0,
strCommandDecompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_DECOMPRESS, true)
);
@ -308,6 +309,7 @@ if ($strOperation eq OP_ARCHIVE_PUSH || $strOperation eq OP_ARCHIVE_PULL)
strBackupUser => config_load($strSection, CONFIG_KEY_USER),
strBackupHost => config_load($strSection, CONFIG_KEY_HOST),
strBackupPath => config_load($strSection, CONFIG_KEY_PATH, true),
strCommand => $0,
strCommandChecksum => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_CHECKSUM, $bChecksum),
strCommandCompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_COMPRESS, $bCompress),
strCommandDecompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_DECOMPRESS, $bCompress)
@ -378,6 +380,7 @@ if ($strOperation eq OP_ARCHIVE_PUSH || $strOperation eq OP_ARCHIVE_PULL)
strBackupUser => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_USER),
strBackupHost => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HOST),
strBackupPath => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
strCommand => $0,
strCommandChecksum => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_CHECKSUM, $bChecksum),
strCommandCompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_COMPRESS, $bCompress),
strCommandDecompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_DECOMPRESS, $bCompress),
@ -418,6 +421,7 @@ if ($strOperation eq OP_ARCHIVE_PUSH || $strOperation eq OP_ARCHIVE_PULL)
strStanza => $strStanza,
bNoCompression => false,
strBackupPath => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
strCommand => $0,
strCommandChecksum => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_CHECKSUM, $bChecksum),
strCommandCompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_COMPRESS, $bCompress),
strCommandDecompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_DECOMPRESS, $bCompress),
@ -504,6 +508,7 @@ my $oFile = pg_backrest_file->new
strBackupPath => config_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
strDbUser => config_load(CONFIG_SECTION_STANZA, CONFIG_KEY_USER),
strDbHost => config_load(CONFIG_SECTION_STANZA, CONFIG_KEY_HOST),
strCommand => $0,
strCommandChecksum => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_CHECKSUM, $bChecksum),
strCommandCompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_COMPRESS, $bCompress),
strCommandDecompress => config_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_DECOMPRESS, $bCompress),

View File

@ -13,12 +13,13 @@ use Net::OpenSSH;
use IPC::Open3;
use File::Basename;
use IPC::System::Simple qw(capture);
use Digest::SHA;
use lib dirname($0);
use pg_backrest_utility;
use Exporter qw(import);
our @EXPORT = qw(PATH_DB PATH_DB_ABSOLUTE PATH_BACKUP PATH_BACKUP_ABSOLUTE PATH_BACKUP_CLUSTER PATH_BACKUP_TMP PATH_BACKUP_ARCHIVE);
our @EXPORT = qw(PATH_ABSOLUTE PATH_DB PATH_DB_ABSOLUTE PATH_BACKUP PATH_BACKUP_ABSOLUTE PATH_BACKUP_CLUSTER PATH_BACKUP_TMP PATH_BACKUP_ARCHIVE);
# Extension and permissions
has strCompressExtension => (is => 'ro', default => 'gz');
@ -26,6 +27,7 @@ has strDefaultPathPermission => (is => 'bare', default => '0750');
has strDefaultFilePermission => (is => 'ro', default => '0640');
# Command strings
has strCommand => (is => 'bare');
has strCommandChecksum => (is => 'bare');
has strCommandCompress => (is => 'bare');
has strCommandDecompress => (is => 'bare');
@ -55,11 +57,21 @@ has bNoCompression => (is => 'bare');
has strStanza => (is => 'bare');
has iThreadIdx => (is => 'bare');
####################################################################################################################################
# COMMAND Error Constants
####################################################################################################################################
use constant
{
COMMAND_ERR_FILE_MISSING => 1,
COMMAND_ERR_FILE_READ => 2
};
####################################################################################################################################
# PATH_GET Constants
####################################################################################################################################
use constant
{
PATH_ABSOLUTE => 'absolute',
PATH_DB => 'db',
PATH_DB_ABSOLUTE => 'db:absolute',
PATH_BACKUP => 'backup',
@ -78,14 +90,12 @@ sub BUILD
my $self = shift;
# Make sure the backup path is defined
if (!defined($self->{strBackupPath}))
if (defined($self->{strBackupPath}))
{
confess &log(ERROR, "common:backup_path undefined");
# Create the backup cluster path
$self->{strBackupClusterPath} = $self->{strBackupPath} . "/" . $self->{strStanza};
}
# Create the backup cluster path
$self->{strBackupClusterPath} = $self->{strBackupPath} . "/" . $self->{strStanza};
# Create the ssh options string
if (defined($self->{strBackupHost}) || defined($self->{strDbHost}))
{
@ -139,15 +149,14 @@ sub clone
strCompressExtension => $self->{strCompressExtension},
strDefaultPathPermission => $self->{strDefaultPathPermission},
strDefaultFilePermission => $self->{strDefaultFilePermission},
strCommand => $self->{strCommand},
strCommandChecksum => $self->{strCommandChecksum},
strCommandCompress => $self->{strCommandCompress},
strCommandDecompress => $self->{strCommandDecompress},
strCommandCat => $self->{strCommandCat},
strCommandManifest => $self->{strCommandManifest},
# oDbSSH => $self->{strDbSSH},
strDbUser => $self->{strDbUser},
strDbHost => $self->{strDbHost},
# oBackupSSH => $self->{strBackupSSH},
strBackupUser => $self->{strBackupUser},
strBackupHost => $self->{strBackupHost},
strBackupPath => $self->{strBackupPath},
@ -223,6 +232,12 @@ sub path_get
confess &log(ASSERT, "temp file not supported on path " . $strType);
}
# Get absolute path
if ($strType eq PATH_ABSOLUTE)
{
return $strFile;
}
# Get absolute db path
if ($strType eq PATH_DB_ABSOLUTE)
{
@ -760,47 +775,73 @@ sub file_copy
}
####################################################################################################################################
# FILE_HASH_GET
# HASH
####################################################################################################################################
sub file_hash_get
sub hash
{
my $self = shift;
my $strPathType = shift;
my $strFile = shift;
my $strHashType = shift;
# For now this operation is not supported remotely. Not currently needed.
if ($self->is_remote($strPathType))
{
confess &log(ASSERT, "remote operation not supported");
}
if (!defined($self->{strCommandChecksum}))
{
confess &log(ASSERT, "\$strCommandChecksum not defined");
}
my $strHash;
my $strErrorPrefix = "File->hash";
my $bRemote = $self->is_remote($strPathType);
my $strPath = $self->path_get($strPathType, $strFile);
my $strCommand;
if (-e $strPath)
&log(TRACE, "${strErrorPrefix}: " . ($bRemote ? "remote" : "local") . " ${strPathType}:${strPath}");
if ($bRemote)
{
$strCommand = $self->{strCommandChecksum};
$strCommand =~ s/\%file\%/${strPath}/g;
}
elsif (-e $strPath . ".$self->{strCompressExtension}")
{
$strCommand = $self->{strCommandDecompress};
$strCommand =~ s/\%file\%/${strPath}/g;
$strCommand .= " | " . $self->{strCommandChecksum};
$strCommand =~ s/\%file\%//g;
# Run remotely
my $oSSH = $self->remote_get($strPathType);
my $strOutput = $oSSH->capture($self->{strCommand} . " hash ${strPath}");
# Capture any errors
if ($oSSH->error)
{
confess &log(ERROR, "${strErrorPrefix} remote: " . (defined($strOutput) ? $strOutput : $oSSH->error));
}
$strHash = $strOutput;
}
else
{
confess &log(ASSERT, "unable to find $strPath(.$self->{strCompressExtension}) for checksum");
my $hFile;
if (!open($hFile, "<", $strPath))
{
my $strError = "${strPath} could not be read" . $!;
my $iErrorCode = 2;
unless (-e $strPath)
{
$strError = "${strPath} does not exist";
$iErrorCode = 1;
}
if ($strPathType eq PATH_ABSOLUTE)
{
print $strError;
exit ($iErrorCode);
}
confess &log(ERROR, "${strErrorPrefix}: " . $strError);
}
my $oSHA = Digest::SHA->new(defined($strHashType) ? $strHashType : 'sha1');
$oSHA->addfile($hFile);
close($hFile);
$strHash = $oSHA->hexdigest();
}
return trim(capture($strCommand)) or confess &log(ERROR, "unable to checksum ${strPath}");
return $strHash;
}
####################################################################################################################################
# FILE_COMPRESS
####################################################################################################################################
@ -832,9 +873,9 @@ sub file_compress
}
####################################################################################################################################
# FILE_LIST_GET
# LIST
####################################################################################################################################
sub file_list_get
sub list
{
my $self = shift;
my $strPathType = shift;
@ -843,161 +884,206 @@ sub file_list_get
my $strSortOrder = shift;
# Get the root path for the file list
my $strPathList = $self->path_get($strPathType, $strPath);
my @stryFileList;
my $strErrorPrefix = "File->list";
my $bRemote = $self->is_remote($strPathType);
my $strPathOp = $self->path_get($strPathType, $strPath);
# Builds the file list command
# my $strCommand = "ls ${strPathList} | egrep \"$strExpression\"";
my $strCommand = "ls -1 ${strPathList}";
# Run the file list command
my $strFileList = "";
&log(TRACE, "${strErrorPrefix}: " . ($bRemote ? "remote" : "local") . " ${strPathType}:${strPathOp}" .
", expression " . (defined($strExpression) ? $strExpression : "[UNDEF]") .
", sort " . (defined($strSortOrder) ? $strSortOrder : "[UNDEF]"));
# Run remotely
if ($self->is_remote($strPathType))
{
&log(TRACE, "file_list_get: remote ${strPathType}:${strPathList} ${strCommand}");
my $strCommand = $self->{strCommand} .
(defined($strSortOrder) && $strSortOrder eq "reverse" ? " --sort=reverse" : "") .
(defined($strExpression) ? " --expression=\"" . $strExpression . "\"" : "") .
" list ${strPathOp}";
# Run via SSH
my $oSSH = $self->remote_get($strPathType);
$strFileList = $oSSH->capture($strCommand);
my $strOutput = $oSSH->capture($strCommand);
# Handle any errors
if ($oSSH->error)
{
confess &log(ERROR, "unable to execute file list (${strCommand}): " . $self->error_get());
confess &log(ERROR, "${strErrorPrefix} remote (${strCommand}): " . (defined($strOutput) ? $strOutput : $oSSH->error));
}
@stryFileList = split(/\n/, $strOutput);
}
# Run locally
else
{
&log(TRACE, "file_list_get: local ${strPathType}:${strPathList} ${strCommand}");
$strFileList = capture($strCommand);
my $hPath;
if (!opendir($hPath, $strPathOp))
{
my $strError = "${strPathOp} could not be read:" . $!;
my $iErrorCode = 2;
unless (-e $strPath)
{
$strError = "${strPathOp} does not exist";
$iErrorCode = 1;
}
if ($strPathType eq PATH_ABSOLUTE)
{
print $strError;
exit ($iErrorCode);
}
confess &log(ERROR, "${strErrorPrefix}: " . $strError);
}
@stryFileList = grep(!/^(\.)|(\.\.)$/i, readdir($hPath));
close($hPath);
if (defined($strExpression))
{
@stryFileList = grep(/$strExpression/i, @stryFileList);
}
# Reverse sort
if (defined($strSortOrder) && $strSortOrder eq "reverse")
{
@stryFileList = sort {$b cmp $a} @stryFileList;
}
# Normal sort
else
{
@stryFileList = sort @stryFileList;
}
}
# Split the files into an array
my @stryFileList;
if (defined($strExpression))
{
@stryFileList = grep(/$strExpression/i, split(/\n/, $strFileList));
}
else
{
@stryFileList = split(/\n/, $strFileList);
}
# Return the array in reverse order if specified
if (defined($strSortOrder) && $strSortOrder eq "reverse")
{
return sort {$b cmp $a} @stryFileList;
}
# Return in normal sorted order
return sort @stryFileList;
# Return file list
return @stryFileList;
}
####################################################################################################################################
# FILE_EXISTS
# EXISTS - Checks for the existence of a file, but does not imply that the file is readable/writeable.
#
# Return: true if file exists, false otherwise
####################################################################################################################################
sub file_exists
sub exists
{
my $self = shift;
my $strPathType = shift;
my $strPath = shift;
# Get the root path for the manifest
my $strPathExists = $self->path_get($strPathType, $strPath);
# Set error prefix, remote, and path
my $bExists = false;
my $strErrorPrefix = "File->exists";
my $bRemote = $self->is_remote($strPathType);
my $strPathOp = $self->path_get($strPathType, $strPath);
&log(TRACE, "file_exists: " . ($self->is_remote($strPathType) ? "remote" : "local") . " ${strPathType}:${strPathExists}");
&log(TRACE, "${strErrorPrefix}: " . ($bRemote ? "remote" : "local") . " ${strPathType}:${strPathOp}");
# Run remotely
if ($self->is_remote($strPathType))
if ($bRemote)
{
# Builds the exists command
my $strCommand = "ls ${strPathExists}";
# Run the file exists command
my $strExists;
my $strError;
&log(TRACE, "file_exists: command: ${strCommand}");
# Build the command
my $strCommand = $self->{strCommand} . " exists ${strPathOp}";
# Run it remotely
my $oSSH = $self->remote_get($strPathType);
$strExists = $oSSH->capture({stderr_file => $self->path_get(PATH_LOCK_ERR, "file")}, $strCommand);
&log(TRACE, "file_exists: search = ${strPathExists}, result = " . (defined($strExists) ? $strExists : "<undef>"));
my $strOutput = $oSSH->capture($strCommand);
# Capture any errors
if ($oSSH->error)
{
my $strError = $self->error_get();
&log(TRACE, "error detected: $strError");
if ($strError =~ /.*ls.*No such file or directory.*/)
{
return(false);
}
confess &log(ERROR, "unable to execute file exists (${strCommand}): " . $strError);
confess &log(ERROR, "${strErrorPrefix} remote (${strCommand}): " . (defined($strOutput) ? $strOutput : $oSSH->error));
}
# If the return from ls eq strPathExists then true
return trim($strExists) eq $strPathExists;
$bExists = $strOutput eq "Y";
}
# Run locally
else
{
if (-e $strPathExists)
if (-e $strPathOp)
{
return true;
}
else
{
return false;
$bExists = true;
}
}
confess &log(ASSERT, "file_exists: true or false should have been returned");
return $bExists;
}
####################################################################################################################################
# FILE_REMOVE
# REMOVE
####################################################################################################################################
sub file_remove
sub remove
{
my $self = shift;
my $strPathType = shift;
my $strPath = shift;
my $bTemp = shift;
my $bErrorIfNotExists = shift;
my $bIgnoreMissing = shift;
if (!defined($bErrorIfNotExists))
if (!defined($bIgnoreMissing))
{
$bErrorIfNotExists = false;
$bIgnoreMissing = true;
}
# Get the root path for the manifest
my $strPathRemove = $self->path_get($strPathType, $strPath, $bTemp);
my $bRemoved = true;
my $strErrorPrefix = "File->remove";
my $bRemote = $self->is_remote($strPathType);
my $strPathOp = $self->path_get($strPathType, $strPath, $bTemp);
# Builds the exists command
my $strCommand = "rm -f ${strPathRemove}";
&log(TRACE, "${strErrorPrefix}: " . ($bRemote ? "remote" : "local") . " ${strPathType}:${strPathOp}");
# Run remotely
if ($self->is_remote($strPathType))
if ($bRemote)
{
&log(TRACE, "file_remove: remote ${strPathType}:${strPathRemove}");
my $oSSH = $self->remote_get($strPathType);
$oSSH->system($strCommand) or $bErrorIfNotExists ? confess &log(ERROR, "unable to remove remote ${strPathType}:${strPathRemove}") : true;
# Build the command
my $strCommand = $self->{strCommand} . ($bIgnoreMissing ? " --ignore-missing" : "") . " remove ${strPathOp}";
# Run it remotely
my $oSSH = $self->remote_get($strPathType);
my $strOutput = $oSSH->capture($strCommand);
if ($oSSH->error)
{
confess &log(ERROR, "unable to execute file_remove (${strCommand}): " . $self->error_get());
confess &log(ERROR, "${strErrorPrefix} remote (${strCommand}): " . (defined($strOutput) ? $strOutput : $oSSH->error));
}
$bRemoved = $strOutput eq "Y";
}
# Run locally
else
{
&log(TRACE, "file_remove: local ${strPathType}:${strPathRemove}");
system($strCommand) == 0 or $bErrorIfNotExists ? confess &log(ERROR, "unable to remove local ${strPathType}:${strPathRemove}") : true;
if (unlink($strPathOp) != 1)
{
$bRemoved = false;
if (-e $strPathOp || !$bIgnoreMissing)
{
my $strError = "${strPathOp} could not be removed: " . $!;
my $iErrorCode = 2;
unless (-e $strPathOp)
{
$strError = "${strPathOp} does not exist";
$iErrorCode = 1;
}
if ($strPathType eq PATH_ABSOLUTE)
{
print $strError;
exit ($iErrorCode);
}
confess &log(ERROR, "${strErrorPrefix}: " . $strError);
}
}
}
return $bRemoved;
}
####################################################################################################################################
@ -1046,4 +1132,4 @@ sub manifest_get
}
no Moose;
__PACKAGE__->meta->make_immutable;
__PACKAGE__->meta->make_immutable;

View File

@ -25,85 +25,285 @@ sub BackRestTestFile
{
my $strLockPath = dirname(abs_path($0)) . "/lock";
my $strTestPath = dirname(abs_path($0)) . "/test";
my $iRun = 0;
log_level_set(OFF, OFF);
my $iRun;
# !!! NEED TO TEST WHERE LOCK PATH IS UNDEF
my $strStanza = "db";
my $strCommand = "/Users/dsteele/pg_backrest/bin/pg_backrest_command.pl";
my $strHost = "127.0.0.1";
my $strUser = "dsteele";
log_level_set(TRACE, TRACE);
# Test list()
$iRun = 0;
print "\ntest File->list()\n";
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
my $oFile = pg_backrest_file->new
(
strStanza => $strStanza,
bNoCompression => true,
strCommand => $strCommand,
strBackupClusterPath => ${strTestPath},
strBackupPath => ${strTestPath},
strBackupHost => $bRemote ? $strHost : undef,
strBackupUser => $bRemote ? $strUser : undef
);
# Loop through exists
for (my $bSort = 0; $bSort <= 1; $bSort++)
{
my $strSort = $bSort ? undef : "reverse";
# Loop through expression
for (my $iExpression = 0; $iExpression <= 2; $iExpression++)
{
my $strExpression;
# Expression tha returns results
if ($iExpression == 1)
{
$strExpression = "^test2\\..*\$";
}
# Expression that does not return results
elsif ($iExpression == 2)
{
$strExpression = "^du\$";
}
# Loop through exists
for (my $bExists = 0; $bExists <= 1; $bExists++)
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, exists $bExists, " .
"expression " . (defined($strExpression) ? $strExpression : "[undef]") . ", " .
"sort " . (defined($strSort) ? $strSort : "[undef]") . "\n";
my $strPath = "${strTestPath}";
# Drop the old test directory and create a new one
system("rm -rf test");
if ($bExists)
{
system("mkdir test") == 0 or confess "Unable to create test directory";
system("echo 'TESTDATA' > ${strPath}/test.txt");
system("echo 'TESTDATA2' > ${strPath}/test2.txt");
}
my @stryFileCompare = split(/\n/, "test.txt\ntest2.txt");
# Execute in eval in case of error
eval
{
my @stryFileList = $oFile->list(PATH_BACKUP_ABSOLUTE, $strPath, $strExpression, $strSort);
if (defined($strExpression))
{
@stryFileCompare = grep(/$strExpression/i, @stryFileCompare);
}
if (defined($strSort))
{
@stryFileCompare = sort {$b cmp $a} @stryFileCompare;
}
my $strFileList = sprintf("@stryFileList");
my $strFileCompare = sprintf("@stryFileCompare");
if ($strFileList ne $strFileCompare)
{
confess "list (${strFileList})[" . @stryFileList .
"] does not match compare (${strFileCompare})[" . @stryFileCompare . "]";
}
};
if ($@ && $bExists)
{
confess " error raised: " . $@ . "\n";
}
}
}
}
}
# Test remove()
$iRun = 0;
print "test File->remove()\n";
# Test file_exists()
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
my $strHost = $bRemote ? "127.0.0.1" : undef;
my $strUser = $bRemote ? "dsteele" : undef;
system("rm -rf lock");
system("mkdir -p lock") == 0 or confess "Unable to create lock directory";
my $oFile = pg_backrest_file->new
(
strStanza => "db",
strStanza => $strStanza,
bNoCompression => true,
strCommand => ${strCommand},
strBackupClusterPath => ${strTestPath},
strBackupPath => ${strTestPath},
strBackupHost => $strHost,
strBackupUser => $strUser,
strLockPath => $strLockPath
strBackupHost => $bRemote ? $strHost : undef,
strBackupUser => $bRemote ? $strUser : undef
);
# Loop through exists
for (my $bExists = 0; $bExists <= 1; $bExists++)
{
# Loop through error
for (my $bError = 0; $bError <= $bRemote ? 1 : 0; $bError++)
# Loop through temp
for (my $bTemp = 0; $bTemp <= 1; $bTemp++)
{
$iRun++;
# Loop through ignore missing
for (my $bIgnoreMissing = 0; $bIgnoreMissing <= 1; $bIgnoreMissing++)
{
$iRun++;
print "run ${iRun} - " .
"rmt $bRemote, exist $bExists, error $bError\n";
print "run ${iRun} - " .
"remote ${bRemote}, exists ${bExists}, temp ${bTemp}, ignore missing ${bIgnoreMissing}\n";
# Drop the old test directory and create a new one
system("rm -rf test");
system("mkdir test") == 0 or confess "Unable to create test directory";
# Drop the old test directory and create a new one
system("rm -rf test");
system("mkdir test") == 0 or confess "Unable to create test directory";
my $strFile = "${strTestPath}/test.txt";
my $strFile = "${strTestPath}/test.txt";
if ($bExists)
{
system("echo 'TESTDATA' > ${strFile}" . ($bTemp ? ".backrest.tmp" : ""));
}
# Execute in eval in case of error
eval
{
if ($oFile->remove(PATH_BACKUP_ABSOLUTE, $strFile, $bTemp, $bIgnoreMissing) != $bExists)
{
confess "hash did not match expected";
}
};
if ($@ && $bExists)
{
confess " error raised: " . $@ . "\n";
}
if (-e ($strFile . ($bTemp ? ".backrest.tmp" : "")))
{
confess "file still exists";
}
}
}
}
}
# Test hash()
$iRun = 0;
print "\ntest File->hash()\n";
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
my $oFile = pg_backrest_file->new
(
strStanza => $strStanza,
bNoCompression => true,
strCommand => $strCommand,
strBackupClusterPath => ${strTestPath},
strBackupPath => ${strTestPath},
strBackupHost => $bRemote ? $strHost : undef,
strBackupUser => $bRemote ? $strUser : undef
);
# Loop through exists
for (my $bExists = 0; $bExists <= 1; $bExists++)
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, exists $bExists\n";
# Drop the old test directory and create a new one
system("rm -rf test");
system("mkdir test") == 0 or confess "Unable to create test directory";
my $strFile = "${strTestPath}/test.txt";
if ($bExists)
{
system("echo 'TESTDATA' > ${strFile}");
}
# Execute in eval in case of error
eval
{
if ($oFile->hash(PATH_BACKUP_ABSOLUTE, $strFile) ne '06364afe79d801433188262478a76d19777ef351')
{
confess "bExists is set to ${bExists}, but exists() returned " . !$bExists;
}
};
if ($@)
{
if ($bExists)
{
system("echo 'TESTDATA' > ${strFile}");
confess " error raised: " . $@ . "\n";
}
}
}
}
if ($bError)
# Test exists()
$iRun = 0;
print "\ntest File->exists()\n";
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
my $oFile = pg_backrest_file->new
(
strStanza => $strStanza,
bNoCompression => true,
strCommand => $strCommand,
strBackupClusterPath => ${strTestPath},
strBackupPath => ${strTestPath},
strBackupHost => $bRemote ? $strHost : undef,
strBackupUser => $bRemote ? $strUser : undef
);
# Loop through exists
for (my $bExists = 0; $bExists <= 1; $bExists++)
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, exists $bExists\n";
# Drop the old test directory and create a new one
system("rm -rf test");
system("mkdir test") == 0 or confess "Unable to create test directory";
my $strFile = "${strTestPath}/test.txt";
if ($bExists)
{
system("echo 'TESTDATA' > ${strFile}");
}
# Execute in eval in case of error
eval
{
if ($oFile->exists(PATH_BACKUP_ABSOLUTE, $strFile) != $bExists)
{
$strFile = "--backrest-error " . $strFile;
}
# Execute in eval in case of error
eval
{
if ($oFile->file_exists(PATH_BACKUP_ABSOLUTE, $strFile) != $bExists)
{
confess "bExists is set to $bExists, but file_exists() returned " . !$bExists;
}
};
if ($@)
{
if (!$bError)
{
confess 'error was returned but no error generated';
}
my $strError = $oFile->error_get();
if (!defined($strError) || ($strError eq ''))
{
confess 'no error message returned';
}
print " error raised: ${strError}\n";
next;
confess "bExists is set to ${bExists}, but exists() returned " . !$bExists;
}
};
if ($@)
{
confess " error raised: " . $@ . "\n";
}
}
}

View File

@ -22,4 +22,4 @@ use BackRestTest::FileTest;
####################################################################################################################################
BackRestTestFile();
print "TEST COMPLETED SUCCESSFULLY (DESPITE ANY ERROR MESSAGES YOU SAW)\n";
print "\nTEST COMPLETED SUCCESSFULLY (DESPITE ANY ERROR MESSAGES YOU SAW)\n";