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

copy() works when both files are local or both files are remote.

This commit is contained in:
David Steele 2014-06-21 11:05:29 -04:00
parent 4a113cae66
commit e1903d53d0
2 changed files with 100 additions and 76 deletions

View File

@ -52,6 +52,25 @@ use constant
# exit COMMAND_ERR_PARAM; # exit COMMAND_ERR_PARAM;
# } # }
####################################################################################################################################
# PARAM_GET - helper function that returns the param or an error if required and it does not exist
####################################################################################################################################
sub param_get
{
my $oParamHashRef = shift;
my $strParam = shift;
my $bRequired = shift;
my $strValue = ${$oParamHashRef}{$strParam};
if (!defined($strValue) && (!defined($bRequired) || $bRequired))
{
confess "${strParam} must be defined";
}
return $strValue;
}
#################################################################################################################################### ####################################################################################################################################
# START MAIN # START MAIN
#################################################################################################################################### ####################################################################################################################################
@ -90,36 +109,31 @@ while ($strCommand ne OP_EXIT)
confess "path must be defined"; confess "path must be defined";
} }
$oRemote->output_write($oFile->exists(PATH_ABSOLUTE, $oParamHash{path}) ? "Y" : "N"); $oRemote->output_write($oFile->exists(PATH_ABSOLUTE, param_get(\%oParamHash, 'path')) ? 'Y' : 'N');
}
elsif ($strCommand eq OP_FILE_COPY)
{
$oFile->copy(PATH_ABSOLUTE, param_get(\%oParamHash, 'source_file'),
PATH_ABSOLUTE, param_get(\%oParamHash, 'destination_file'),
param_get(\%oParamHash, 'source_compressed'),
param_get(\%oParamHash, 'destination_compress'));
$oRemote->output_write();
} }
elsif ($strCommand eq OP_FILE_COPY_IN) elsif ($strCommand eq OP_FILE_COPY_IN)
{ {
if (!defined($oParamHash{destination_file})) $oFile->copy(PIPE_STDIN, undef,
{ PATH_ABSOLUTE, param_get(\%oParamHash, 'destination_file'),
confess "destination_file must be defined"; undef, param_get(\%oParamHash, 'destination_compress'));
}
if (!defined($oParamHash{destination_compress}))
{
confess "destination_compress must be defined";
}
$oFile->copy(PIPE_STDIN, undef, PATH_ABSOLUTE, $oParamHash{destination_file}, undef, $oParamHash{destination_compress});
$oRemote->output_write(); $oRemote->output_write();
} }
elsif ($strCommand eq OP_FILE_COPY_OUT) elsif ($strCommand eq OP_FILE_COPY_OUT)
{ {
if (!defined($oParamHash{source_file})) $oFile->copy(PATH_ABSOLUTE, param_get(\%oParamHash, 'source_file'),
{ PIPE_STDOUT, undef,
confess "source_file must be defined"; param_get(\%oParamHash, 'source_compressed'), undef);
}
if (!defined($oParamHash{source_compressed}))
{
confess "source_file must be defined";
}
$oFile->copy(PATH_ABSOLUTE, $oParamHash{source_file}, PIPE_STDOUT, undef, $oParamHash{source_compressed}, undef);
$oRemote->output_write(); $oRemote->output_write();
} }
else else

View File

@ -12,6 +12,7 @@ use Moose;
use Net::OpenSSH; use Net::OpenSSH;
use IPC::Open3; use IPC::Open3;
use File::Basename; use File::Basename;
use File::Copy qw(cp);
use Digest::SHA; use Digest::SHA;
use File::stat; use File::stat;
use Fcntl ':mode'; use Fcntl ':mode';
@ -34,7 +35,7 @@ our @EXPORT = qw(PATH_ABSOLUTE PATH_DB PATH_DB_ABSOLUTE PATH_BACKUP PATH_BACKUP_
PIPE_STDIN PIPE_STDOUT PIPE_STDERR PIPE_STDIN PIPE_STDOUT PIPE_STDERR
OP_FILE_LIST OP_FILE_EXISTS OP_FILE_HASH OP_FILE_REMOVE OP_FILE_MANIFEST OP_FILE_COMPRESS OP_FILE_LIST OP_FILE_EXISTS OP_FILE_HASH OP_FILE_REMOVE OP_FILE_MANIFEST OP_FILE_COMPRESS
OP_FILE_MOVE OP_FILE_COPY_OUT OP_FILE_COPY_IN OP_FILE_PATH_CREATE); OP_FILE_MOVE OP_FILE_COPY OP_FILE_COPY_OUT OP_FILE_COPY_IN OP_FILE_PATH_CREATE);
# Extension and permissions # Extension and permissions
@ -125,6 +126,7 @@ use constant
OP_FILE_MANIFEST => "File->manifest", OP_FILE_MANIFEST => "File->manifest",
OP_FILE_COMPRESS => "File->compress", OP_FILE_COMPRESS => "File->compress",
OP_FILE_MOVE => "File->move", OP_FILE_MOVE => "File->move",
OP_FILE_COPY => "File->copy",
OP_FILE_COPY_OUT => "File->copy_out", OP_FILE_COPY_OUT => "File->copy_out",
OP_FILE_COPY_IN => "File->copy_in", OP_FILE_COPY_IN => "File->copy_in",
OP_FILE_PATH_CREATE => "File->path_create" OP_FILE_PATH_CREATE => "File->path_create"
@ -779,7 +781,7 @@ sub copy
undef : $self->path_get($strDestinationPathType, $strDestinationFile, true); undef : $self->path_get($strDestinationPathType, $strDestinationFile, true);
# Set operation and debug string # Set operation and debug string
my $strOperation = "File->copy[unknown]"; # my $strOperation = "File->copy[unknown]";
my $strDebug = ($bSourceRemote ? " remote" : " local") . " ${strSourcePathType}" . my $strDebug = ($bSourceRemote ? " remote" : " local") . " ${strSourcePathType}" .
(defined($strSourceFile) ? ":${strSourceFile}" : "") . (defined($strSourceFile) ? ":${strSourceFile}" : "") .
" to" . ($bDestinationRemote ? " remote" : " local") . " ${strDestinationPathType}" . " to" . ($bDestinationRemote ? " remote" : " local") . " ${strDestinationPathType}" .
@ -791,46 +793,37 @@ sub copy
my $hSourceFile; my $hSourceFile;
my $hDestinationFile; my $hDestinationFile;
if ($bSourceRemote || $bDestinationRemote) if (!$bSourceRemote)
{ {
if (!$bSourceRemote) if (!open($hSourceFile, "<", $strSourceOp))
{ {
if (!open($hSourceFile, "<", $strSourceOp)) my $strError = $!;
my $iErrorCode = COMMAND_ERR_FILE_READ;
if ($!{ENOENT})
{ {
my $strError = $!; # $strError = 'file is missing';
my $iErrorCode = COMMAND_ERR_FILE_READ; $iErrorCode = COMMAND_ERR_FILE_MISSING;
if ($!{ENOENT})
{
# $strError = 'file is missing';
$iErrorCode = COMMAND_ERR_FILE_MISSING;
}
$strError = "cannot open source file ${strSourceOp}: " . $strError;
if ($strSourcePathType eq PATH_ABSOLUTE)
{
$self->{oRemote}->write_line(*STDOUT, "block 0");
confess &log(ERROR, $strError, $iErrorCode);
}
confess &log(ERROR, "${strDebug}: " . $strError, $iErrorCode);
} }
}
if (!$bDestinationRemote) $strError = "cannot open source file ${strSourceOp}: " . $strError;
{
# # Determine of the file needs a compression extension
# if ($bDestinationCompress)
# {
# $strDestinationOp .= "." . $self->{strCompressExtension};
# }
open($hDestinationFile, ">", $strDestinationTmpOp) if ($strSourcePathType eq PATH_ABSOLUTE)
or confess &log(ERROR, "cannot open ${strDestinationTmpOp}: " . $!); {
$self->{oRemote}->write_line(*STDOUT, "block 0");
confess &log(ERROR, $strError, $iErrorCode);
}
confess &log(ERROR, "${strDebug}: " . $strError, $iErrorCode);
} }
} }
if (!$bDestinationRemote)
{
open($hDestinationFile, ">", $strDestinationTmpOp)
or confess &log(ERROR, "cannot open ${strDestinationTmpOp}: " . $!);
}
# If source or destination are remote # If source or destination are remote
if ($bSourceRemote || $bDestinationRemote) if ($bSourceRemote || $bDestinationRemote)
{ {
@ -840,6 +833,7 @@ sub copy
my $hIn, my $hIn,
my $hOut; my $hOut;
my $strRemote; my $strRemote;
my $strOperation;
# If source is remote and destination is local # If source is remote and destination is local
if ($bSourceRemote && !$bDestinationRemote) if ($bSourceRemote && !$bDestinationRemote)
@ -854,7 +848,7 @@ sub copy
} }
else else
{ {
$oParamHash{source_file} = ${strSourceOp}; $oParamHash{source_file} = $strSourceOp;
$oParamHash{source_compressed} = $bSourceCompressed; $oParamHash{source_compressed} = $bSourceCompressed;
$hIn = $self->{oRemote}->{hOut}; $hIn = $self->{oRemote}->{hOut};
@ -873,7 +867,7 @@ sub copy
} }
else else
{ {
$oParamHash{destination_file} = ${strDestinationOp}; $oParamHash{destination_file} = $strDestinationOp;
$oParamHash{destination_compress} = $bDestinationCompress; $oParamHash{destination_compress} = $bDestinationCompress;
$hOut = $self->{oRemote}->{hIn}; $hOut = $self->{oRemote}->{hIn};
@ -882,13 +876,12 @@ sub copy
# Else source and destination are remote # Else source and destination are remote
else else
{ {
if ($self->path_type_get($strSourcePathType) ne $self->path_type_get($strDestinationPathType)) $strOperation = OP_FILE_COPY;
{
confess &log(ASSERT, "remote source and destination not supported");
}
# !!! MULTIPLE REMOTE COPY NOT YET IMPLEMENTED $oParamHash{source_file} = $strSourceOp;
return false; $oParamHash{source_compressed} = $bSourceCompressed;
$oParamHash{destination_file} = $strDestinationOp;
$oParamHash{destination_compress} = $bDestinationCompress;
} }
# Build debug string # Build debug string
@ -902,8 +895,11 @@ sub copy
$self->{oRemote}->command_write($strOperation, \%oParamHash); $self->{oRemote}->command_write($strOperation, \%oParamHash);
} }
# Transfer the file # Transfer the file (skip this for copies where both sides are remote)
$self->{oRemote}->binary_xfer($hIn, $hOut, $strRemote, $bSourceCompressed, $bDestinationCompress); if ($strOperation ne OP_FILE_COPY)
{
$self->{oRemote}->binary_xfer($hIn, $hOut, $strRemote, $bSourceCompressed, $bDestinationCompress);
}
# If this is the controlling process then wait for OK from remote # If this is the controlling process then wait for OK from remote
if (%oParamHash) if (%oParamHash)
@ -911,29 +907,43 @@ sub copy
$self->{oRemote}->output_read(false, $strDebug); $self->{oRemote}->output_read(false, $strDebug);
} }
} }
# Else this is a local operation
else else
{ {
# if (!defined($strCompress)) $strDebug = OP_FILE_COPY . ": $strDebug";
# { &log(DEBUG, $strDebug);
#
# } # If the source is compressed and the destination is not then decompress
# !!! Implement this with pipes from above (refactor copy_in and and copy_out) if ($bSourceCompressed && !$bDestinationCompress)
# !!! LOCAL COPY NOT YET IMPLEMENTED {
return false; gunzip($hSourceFile => $hDestinationFile)
or die confess &log(ERROR, "${strDebug}: unable to uncompress: " . $GunzipError);
}
elsif (!$bSourceCompressed && $bDestinationCompress)
{
gzip($hSourceFile => $hDestinationFile)
or die confess &log(ERROR, "${strDebug}: unable to compress: " . $GzipError);
}
else
{
cp($hSourceFile, $hDestinationFile)
or die confess &log(ERROR, "${strDebug}: unable to copy: " . $!);
}
} }
# Close the source file # Close the source file (if open)
if (defined($hSourceFile)) if (defined($hSourceFile))
{ {
close($hSourceFile) or confess &log(ERROR, "cannot close file ${strSourceOp}"); close($hSourceFile) or confess &log(ERROR, "cannot close file ${strSourceOp}");
} }
# Close the destination file # Close the destination file (if open)
if (defined($hDestinationFile)) if (defined($hDestinationFile))
{ {
close($hDestinationFile) or confess &log(ERROR, "cannot close file ${strDestinationTmpOp}"); close($hDestinationFile) or confess &log(ERROR, "cannot close file ${strDestinationTmpOp}");
} }
# Where the destination is local, set permissions, modification time, and perform move to final location
if (!$bDestinationRemote) if (!$bDestinationRemote)
{ {
# Set the file permission if required # Set the file permission if required
@ -943,7 +953,7 @@ sub copy
or confess &log(ERROR, "unable to set permissions for local ${strDestinationTmpOp}"); or confess &log(ERROR, "unable to set permissions for local ${strDestinationTmpOp}");
} }
# Set the file modification time if required (this only works locally for now) # Set the file modification time if required
if (defined($lModificationTime)) if (defined($lModificationTime))
{ {
utime($lModificationTime, $lModificationTime, $strDestinationTmpOp) utime($lModificationTime, $lModificationTime, $strDestinationTmpOp)