"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "bin/BackupPC_archive" between
BackupPC-4.3.2.tar.gz and BackupPC-4.4.0.tar.gz

About: BackupPC is a high-performance, enterprise-grade system for backing up Linux and WinXX PCs and laptops to a server’s disk (http/cgi user interface).

BackupPC_archive  (BackupPC-4.3.2):BackupPC_archive  (BackupPC-4.4.0)
skipping to change at line 31 skipping to change at line 31
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
#======================================================================== #========================================================================
# #
# Version 4.3.2, released 17 Feb 2020. # Version 4.4.0, released 20 Jun 2020.
# #
# See http://backuppc.sourceforge.net. # See http://backuppc.sourceforge.net.
# #
#======================================================================== #========================================================================
use strict; use strict;
no utf8; no utf8;
use lib "__INSTALLDIR__/lib"; use lib "__INSTALLDIR__/lib";
use BackupPC::Lib; use BackupPC::Lib;
use BackupPC::XS; use BackupPC::XS;
use BackupPC::Xfer::Archive; use BackupPC::Xfer::Archive;
use Getopt::Std; use Getopt::Std;
use vars qw( %ArchiveReq ); use vars qw( %ArchiveReq );
########################################################################### ###########################################################################
# Initialize # Initialize
########################################################################### ###########################################################################
die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) ); die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
my $TopDir = $bpc->TopDir(); my $TopDir = $bpc->TopDir();
my $BinDir = $bpc->BinDir(); my $BinDir = $bpc->BinDir();
my %Conf = $bpc->Conf(); my %Conf = $bpc->Conf();
my $NeedPostCmd; my $NeedPostCmd;
my($user, $host, $client, $reqFileName, %stat); my($user, $host, $client, $reqFileName, %stat);
$bpc->ChildInit(); $bpc->ChildInit();
my %opts; my %opts;
if ( !getopts("m", \%opts) || @ARGV != 3 ) { if ( !getopts("m", \%opts) || @ARGV != 3 ) {
print("usage: $0 [-m] <user> <archiveclient> <reqFileName>\n"); print("usage: $0 [-m] <user> <archiveclient> <reqFileName>\n");
exit(1); exit(1);
} }
$user = $1 if ( $ARGV[0] =~ /(.+)/ ); $user = $1 if ( $ARGV[0] =~ /(.+)/ );
$client = $1 if ( $ARGV[1] =~ /(.+)/ ); $client = $1 if ( $ARGV[1] =~ /(.+)/ );
if ( $ARGV[2] !~ /^([\w\.\s-]+)$/ ) { if ( $ARGV[2] !~ /^([\w\.\s-]+)$/ ) {
print("$0: bad reqFileName (arg #3): $ARGV[2]\n"); print("$0: bad reqFileName (arg #3): $ARGV[2]\n");
exit(1); exit(1);
} }
$reqFileName = $1; $reqFileName = $1;
if ( !$opts{m} && !defined($bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPo if ( !$opts{m}
rt})) && !defined($bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort}))
&& (my $status = $bpc->ServerMesg("hostMutex $client 1 BackupPC_ar && (my $status = $bpc->ServerMesg("hostMutex $client 1 BackupPC_archive")) =
chive")) =~ /fail/ ) { ~ /fail/ ) {
print(STDERR "$0: $status (use -m option to force running)\n"); print(STDERR "$0: $status (use -m option to force running)\n");
exit(1); exit(1);
} }
my $startTime = time(); my $startTime = time();
my $Dir = "$TopDir/pc/$client"; my $Dir = "$TopDir/pc/$client";
my @xferPid = (); my @xferPid = ();
# #
skipping to change at line 114 skipping to change at line 117
# #
# Read the request file # Read the request file
# #
if ( !(my $ret = do "$Dir/$reqFileName") ) { if ( !(my $ret = do "$Dir/$reqFileName") ) {
my $err; my $err;
if ( $@ ) { if ( $@ ) {
$err = "couldn't parse $Dir/$reqFileName: $@"; $err = "couldn't parse $Dir/$reqFileName: $@";
} elsif ( !defined($ret) ) { } elsif ( !defined($ret) ) {
$err = "couldn't do $Dir/$reqFileName: $!"; $err = "couldn't do $Dir/$reqFileName: $!";
} else { } else {
$err = "couldn't run $Dir/$reqFileName"; $err = "couldn't run $Dir/$reqFileName";
} }
$stat{hostError} = $err; $stat{hostError} = $err;
exit(ArchiveCleanup($client)); exit(ArchiveCleanup($client));
} }
# #
# Re-read config file, so we can include the PC-specific config # Re-read config file, so we can include the PC-specific config
# #
if ( defined(my $error = $bpc->ConfigRead($client)) ) { if ( defined(my $error = $bpc->ConfigRead($client)) ) {
$stat{hostError} = "Can't read PC's config file: $error"; $stat{hostError} = "Can't read PC's config file: $error";
skipping to change at line 146 skipping to change at line 149
# #
# See if the host name is aliased # See if the host name is aliased
# #
if ( $Conf{ClientNameAlias} ne "" ) { if ( $Conf{ClientNameAlias} ne "" ) {
$host = $Conf{ClientNameAlias}; $host = $Conf{ClientNameAlias};
} else { } else {
$host = $client; $host = $client;
} }
my $fileExt = $Conf{CompressLevel} > 0 ? ".z" : ""; my $fileExt = $Conf{CompressLevel} > 0 ? ".z" : "";
my $ArchiveLOG = BackupPC::XS::FileZIO::open("$Dir/ArchiveLOG$fileExt", 1, my $ArchiveLOG = BackupPC::XS::FileZIO::open("$Dir/ArchiveLOG$fileExt", 1, $Conf
$Conf{CompressLevel}); {CompressLevel});
my($logMsg, $xfer); my($logMsg, $xfer);
$stat{xferOK} = 1; $stat{xferOK} = 1;
$stat{hostAbort} = undef; $stat{hostAbort} = undef;
$stat{hostError} = $stat{lastOutputLine} = undef; $stat{hostError} = $stat{lastOutputLine} = undef;
local(*RH, *WH); local(*RH, *WH);
# #
# Run an optional pre-archive command # Run an optional pre-archive command
# #
UserCommandRun("ArchivePreUserCmd"); UserCommandRun("ArchivePreUserCmd");
if ( $? && $Conf{UserCmdCheckStatus} ) { if ( $? && $Conf{UserCmdCheckStatus} ) {
$stat{hostError} = "ArchivePreUserCmd returned error status $?"; $stat{hostError} = "ArchivePreUserCmd returned error status $?";
skipping to change at line 173 skipping to change at line 175
} }
$NeedPostCmd = 1; $NeedPostCmd = 1;
$xfer = BackupPC::Xfer::Archive->new($bpc); $xfer = BackupPC::Xfer::Archive->new($bpc);
# #
# Run the transport program # Run the transport program
# #
my $xferArgs = { my $xferArgs = {
client => $client, client => $client,
host => $host, host => $host,
user => $ArchiveReq{user}, user => $ArchiveReq{user},
type => "archive", type => "archive",
XferLOG => $ArchiveLOG, XferLOG => $ArchiveLOG,
XferMethod => $Conf{XferMethod}, XferMethod => $Conf{XferMethod},
pathHdrSrc => $ArchiveReq{pathHdrSrc}, pathHdrSrc => $ArchiveReq{pathHdrSrc},
pathHdrDest => $ArchiveReq{pathHdrDest}, pathHdrDest => $ArchiveReq{pathHdrDest},
HostList => \@{$ArchiveReq{HostList}}, HostList => \@{$ArchiveReq{HostList}},
BackupList => \@{$ArchiveReq{BackupList}}, BackupList => \@{$ArchiveReq{BackupList}},
archiveloc => $ArchiveReq{archiveloc}, archiveloc => $ArchiveReq{archiveloc},
parfile => $ArchiveReq{parfile}, parfile => $ArchiveReq{parfile},
compression => $ArchiveReq{compression}, compression => $ArchiveReq{compression},
compext => $ArchiveReq{compext}, compext => $ArchiveReq{compext},
splitsize => $ArchiveReq{splitsize}, splitsize => $ArchiveReq{splitsize},
pidHandler => \&pidHandler, pidHandler => \&pidHandler,
}; };
$xfer->args($xferArgs); $xfer->args($xferArgs);
if ( !defined($logMsg = $xfer->start()) ) { if ( !defined($logMsg = $xfer->start()) ) {
UserCommandRun("ArchivePostUserCmd") if ( $NeedPostCmd ); UserCommandRun("ArchivePostUserCmd") if ( $NeedPostCmd );
$stat{hostError} = "xfer start failed: ", $xfer->errStr; $stat{hostError} = "xfer start failed: ", $xfer->errStr;
exit(ArchiveCleanup($client)); exit(ArchiveCleanup($client));
} }
skipping to change at line 233 skipping to change at line 235
return if ( $Pid != $$ ); return if ( $Pid != $$ );
# #
# Note: needs to be tested for each kind of XferMethod # Note: needs to be tested for each kind of XferMethod
# #
print($LogFd $bpc->timeStamp, "cleaning up after signal $signame\n"); print($LogFd $bpc->timeStamp, "cleaning up after signal $signame\n");
$SIG{$signame} = 'IGNORE'; $SIG{$signame} = 'IGNORE';
$ArchiveLOG->write(\"exiting after signal $signame\n"); $ArchiveLOG->write(\"exiting after signal $signame\n");
$stat{xferOK} = 0; $stat{xferOK} = 0;
if ( $signame eq "INT" ) { if ( $signame eq "INT" ) {
$stat{hostError} = "aborted by user (signal=$signame)"; $stat{hostError} = "aborted by user (signal=$signame)";
} else { } else {
$stat{hostError} = "aborted by signal=$signame"; $stat{hostError} = "aborted by signal=$signame";
} }
exit(ArchiveCleanup($client)); exit(ArchiveCleanup($client));
} }
# #
# Cleanup and update the archive status # Cleanup and update the archive status
# #
sub ArchiveCleanup sub ArchiveCleanup
{ {
my($client) = @_; my($client) = @_;
$stat{xferOK} = 0 if ( $stat{hostError} || $stat{hostAbort} ); $stat{xferOK} = 0 if ( $stat{hostError} || $stat{hostAbort} );
if ( !$stat{xferOK} ) { if ( !$stat{xferOK} ) {
# #
# Kill off the transfer program, first nicely then forcefully. # Kill off the transfer program, first nicely then forcefully.
# We use negative PIDs to make sure all processes in each # We use negative PIDs to make sure all processes in each
# group get the signal. # group get the signal.
# #
if ( @xferPid ) { if ( @xferPid ) {
foreach my $pid ( @xferPid ) { foreach my $pid ( @xferPid ) {
kill($bpc->sigName2num("INT"), -$pid); kill($bpc->sigName2num("INT"), -$pid);
} }
sleep(1); sleep(1);
foreach my $pid ( @xferPid ) { foreach my $pid ( @xferPid ) {
kill($bpc->sigName2num("KILL"), -$pid); kill($bpc->sigName2num("KILL"), -$pid);
} }
} }
} }
my $lastNum = -1; my $lastNum = -1;
my @Archives; my @Archives;
@Archives = $bpc->ArchiveInfoRead($client); @Archives = $bpc->ArchiveInfoRead($client);
for ( my $i = 0 ; $i < @Archives ; $i++ ) { for ( my $i = 0 ; $i < @Archives ; $i++ ) {
$lastNum = $Archives[$i]{num} if ( $lastNum < $Archives[$i]{num} ); $lastNum = $Archives[$i]{num} if ( $lastNum < $Archives[$i]{num} );
} }
$lastNum++; $lastNum++;
# #
# Run an optional post-archive command # Run an optional post-archive command
# #
if ( $NeedPostCmd ) { if ( $NeedPostCmd ) {
UserCommandRun("ArchivePostUserCmd"); UserCommandRun("ArchivePostUserCmd");
if ( $? && $Conf{UserCmdCheckStatus} ) { if ( $? && $Conf{UserCmdCheckStatus} ) {
$stat{hostError} = "RestorePreUserCmd returned error status $?"; $stat{hostError} = "ArchivePostUserCmd returned error status $?";
$stat{xferOK} = 0; $stat{xferOK} = 0;
} }
} }
rename("$Dir/ArchiveLOG$fileExt", "$Dir/ArchiveLOG.$lastNum$fileExt"); rename("$Dir/ArchiveLOG$fileExt", "$Dir/ArchiveLOG.$lastNum$fileExt");
rename("$Dir/$reqFileName", "$Dir/ArchiveInfo.$lastNum"); rename("$Dir/$reqFileName", "$Dir/ArchiveInfo.$lastNum");
my $endTime = time(); my $endTime = time();
# #
# If the archive failed, clean up # If the archive failed, clean up
# #
if ( !$stat{xferOK} ) { if ( !$stat{xferOK} ) {
$stat{hostError} = $stat{lastOutputLine} if ( $stat{hostError} eq "" ); $stat{hostError} = $stat{lastOutputLine} if ( $stat{hostError} eq "" );
$stat{hostAbort} = 1; $stat{hostAbort} = 1;
$ArchiveLOG->write(\"Archive failed: $stat{hostError}") $ArchiveLOG->write(\"Archive failed: $stat{hostError}")
if ( defined($ArchiveLOG) ); if ( defined($ArchiveLOG) );
} }
$ArchiveLOG->close() if ( defined($ArchiveLOG) ); $ArchiveLOG->close() if ( defined($ArchiveLOG) );
# #
# Add the new archive information to the archive file # Add the new archive information to the archive file
# #
@Archives = $bpc->ArchiveInfoRead($client); @Archives = $bpc->ArchiveInfoRead($client);
my $i = @Archives; my $i = @Archives;
$Archives[$i]{num} = $lastNum; $Archives[$i]{num} = $lastNum;
$Archives[$i]{startTime} = $startTime; $Archives[$i]{startTime} = $startTime;
$Archives[$i]{endTime} = $endTime; $Archives[$i]{endTime} = $endTime;
$Archives[$i]{result} = $stat{xferOK} ? "ok" : "failed"; $Archives[$i]{result} = $stat{xferOK} ? "ok" : "failed";
$Archives[$i]{errorMsg} = $stat{hostError}; $Archives[$i]{errorMsg} = $stat{hostError};
while ( @Archives > $Conf{ArchiveInfoKeepCnt} ) { while ( @Archives > $Conf{ArchiveInfoKeepCnt} ) {
my $num = $Archives[0]{num}; my $num = $Archives[0]{num};
unlink("$Dir/ArchiveLOG.$num.z"); unlink("$Dir/ArchiveLOG.$num.z");
unlink("$Dir/ArchiveLOG.$num"); unlink("$Dir/ArchiveLOG.$num");
unlink("$Dir/ArchiveInfo.$num"); unlink("$Dir/ArchiveInfo.$num");
shift(@Archives); shift(@Archives);
} }
$bpc->ArchiveInfoWrite($client, @Archives); $bpc->ArchiveInfoWrite($client, @Archives);
if ( !$stat{xferOK} ) { if ( !$stat{xferOK} ) {
print($LogFd $bpc->timeStamp, "Archive failed ($stat{hostError})\n"); print($LogFd $bpc->timeStamp, "Archive failed ($stat{hostError})\n");
print("archive failed: $stat{hostError}\n"); print("archive failed: $stat{hostError}\n");
return 1; return 1;
} else { } else {
print($LogFd $bpc->timeStamp, "Archive Complete\n"); print($LogFd $bpc->timeStamp, "Archive Complete\n");
print("archive complete\n"); print("archive complete\n");
return; return;
} }
} }
# #
# The Xfer method might tell us from time to time about processes # The Xfer method might tell us from time to time about processes
# it forks. We tell BackupPC about this (for status displays) and # it forks. We tell BackupPC about this (for status displays) and
# keep track of the pids in case we cancel the backup # keep track of the pids in case we cancel the backup
# #
sub pidHandler sub pidHandler
{ {
@xferPid = @_; @xferPid = @_;
@xferPid = grep(/./, @xferPid); @xferPid = grep(/./, @xferPid);
return if ( !@xferPid ); return if ( !@xferPid );
my @pids = @xferPid; my @pids = @xferPid;
my $str = join(",", @pids); my $str = join(",", @pids);
$ArchiveLOG->write(\"Xfer PIDs are now $str\n") if ( defined($ArchiveLOG) ); $ArchiveLOG->write(\"Xfer PIDs are now $str\n") if ( defined($ArchiveLOG) );
print("xferPids $str\n"); print("xferPids $str\n");
} }
# #
# Run an optional pre- or post-dump command # Run an optional pre- or post-dump command
# #
sub UserCommandRun sub UserCommandRun
{ {
my($cmdType) = @_; my($cmdType) = @_;
return if ( !defined($Conf{$cmdType}) ); return if ( !defined($Conf{$cmdType}) );
my $vars = { my $vars = {
xfer => $xfer, xfer => $xfer,
client => $client, client => $client,
host => $host, host => $host,
user => $user, user => $user,
share => $ArchiveReq{shareDest}, share => $ArchiveReq{shareDest},
XferMethod => $Conf{XferMethod}, XferMethod => $Conf{XferMethod},
HostList => \@{$ArchiveReq{HostList}}, HostList => \@{$ArchiveReq{HostList}},
BackupList => \@{$ArchiveReq{BackupList}}, BackupList => \@{$ArchiveReq{BackupList}},
archiveloc => $ArchiveReq{archiveloc}, archiveloc => $ArchiveReq{archiveloc},
parfile => $ArchiveReq{parfile}, parfile => $ArchiveReq{parfile},
compression => $ArchiveReq{compression}, compression => $ArchiveReq{compression},
compext => $ArchiveReq{compext}, compext => $ArchiveReq{compext},
splitsize => $ArchiveReq{splitsize}, splitsize => $ArchiveReq{splitsize},
sshPath => $Conf{SshPath}, sshPath => $Conf{SshPath},
LOG => $LogFd, LOG => $LogFd,
XferLOG => $ArchiveLOG, XferLOG => $ArchiveLOG,
stat => \%stat, stat => \%stat,
xferOK => $stat{xferOK} || 0, xferOK => $stat{xferOK} || 0,
type => "archive", type => "archive",
cmdType => $cmdType, cmdType => $cmdType,
}; };
my $cmd = $bpc->cmdVarSubstitute($Conf{$cmdType}, $vars); my $cmd = $bpc->cmdVarSubstitute($Conf{$cmdType}, $vars);
$ArchiveLOG->write(\"Executing $cmdType: @$cmd\n"); $ArchiveLOG->write(\"Executing $cmdType: @$cmd\n");
# #
# Run the user's command, dumping the stdout/stderr into the # Run the user's command, dumping the stdout/stderr into the
# Xfer log file. Also supply the optional $vars and %Conf in # Xfer log file. Also supply the optional $vars and %Conf in
# case the command is really perl code instead of a shell # case the command is really perl code instead of a shell
# command. # command.
# #
$bpc->cmdSystemOrEval($cmd, $bpc->cmdSystemOrEval(
sub { $cmd,
$ArchiveLOG->write(\$_[0]); sub {
if ( $ArchiveLOG && length($_[0]) ) { $ArchiveLOG->write(\$_[0]);
$ArchiveLOG->write(\$_[0]); if ( $ArchiveLOG && length($_[0]) ) {
} elsif ( $LogFd && length($_[0]) ) { $ArchiveLOG->write(\$_[0]);
print($LogFd $bpc->timeStamp, "Output from $cmdType: ", $_[0 } elsif ( $LogFd && length($_[0]) ) {
]); print($LogFd $bpc->timeStamp, "Output from $cmdType: ", $_[0]);
} }
}, },
$vars, \%Conf); $vars,
\%Conf
);
} }
 End of changes. 25 change blocks. 
102 lines changed or deleted 106 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)