From 0697368bbcef14908cd4684cf07744dc840464de Mon Sep 17 00:00:00 2001 From: cbarratt Date: Mon, 3 Feb 2003 08:31:25 +0000 Subject: [PATCH] - added $Conf{ClientNameAlias}, which allows the host name to be set. - added support for spaces in client names (ugh) - non dhcp hosts are now looked up using nmblookup, if not known by NS --- bin/BackupPC | 54 ++++-- bin/BackupPC_compressPool | 12 +- bin/BackupPC_dump | 172 ++++++++++------- bin/BackupPC_link | 6 +- bin/BackupPC_nightly | 4 +- bin/BackupPC_restore | 321 +++++++++++++++++-------------- bin/BackupPC_sendEmail | 4 +- bin/BackupPC_serverMesg | 2 +- bin/BackupPC_tarCreate | 4 +- bin/BackupPC_tarExtract | 8 +- bin/BackupPC_trashClean | 2 +- bin/BackupPC_zcat | 2 +- bin/BackupPC_zipCreate | 2 +- cgi-bin/BackupPC_Admin | 105 +++++----- conf/config.pl | 33 +++- lib/BackupPC/Attrib.pm | 2 +- lib/BackupPC/FileZIO.pm | 8 +- lib/BackupPC/Lang/en.pm | 62 +++--- lib/BackupPC/Lang/fr.pm | 62 +++--- lib/BackupPC/Lib.pm | 97 +++++++++- lib/BackupPC/PoolWrite.pm | 4 +- lib/BackupPC/View.pm | 2 +- lib/BackupPC/Xfer/Rsync.pm | 40 ++-- lib/BackupPC/Xfer/RsyncFileIO.pm | 8 +- lib/BackupPC/Xfer/Smb.pm | 58 +++--- lib/BackupPC/Xfer/Tar.pm | 17 +- lib/BackupPC/Zip/FileMember.pm | 2 +- 27 files changed, 646 insertions(+), 447 deletions(-) diff --git a/bin/BackupPC b/bin/BackupPC index 964640e..e13b60d 100755 --- a/bin/BackupPC +++ b/bin/BackupPC @@ -47,7 +47,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -325,7 +325,7 @@ sub Main_Initialize # Write out our initial status and save our PID # StatusWrite(); - if ( open(PID, ">$TopDir/log/BackupPC.pid") ) { + if ( open(PID, ">", "$TopDir/log/BackupPC.pid") ) { print(PID $$); close(PID); } @@ -364,7 +364,7 @@ sub Main_TryToRun_nightly host => $bpc->trashJob, user => "BackupPC", reqTime => time, - cmd => "$BinDir/BackupPC_trashClean" + cmd => ["$BinDir/BackupPC_trashClean"], }); $CmdQueueOn{$bpc->trashJob} = 1; } @@ -373,7 +373,7 @@ sub Main_TryToRun_nightly host => $bpc->adminJob, user => "BackupPC", reqTime => time, - cmd => "$BinDir/BackupPC_nightly" + cmd => ["$BinDir/BackupPC_nightly"], }); $CmdQueueOn{$bpc->adminJob} = 1; $RunNightlyWhenIdle = 2; @@ -420,8 +420,8 @@ sub Main_TryToRun_CmdQueue } if ( !$pid ) { setpgrp 0,0; - exec($cmd); - print(LOG $bpc->timeStamp, "can't exec $cmd for $host\n"); + exec(@$cmd); + print(LOG $bpc->timeStamp, "can't exec @$cmd for $host\n"); exit(0); } $Jobs{$host}{pid} = $pid; @@ -430,6 +430,7 @@ sub Main_TryToRun_CmdQueue vec($FDread, $Jobs{$host}{fn}, 1) = 1; $Jobs{$host}{startTime} = time; $Jobs{$host}{reqTime} = $req->{reqTime}; + $cmd = join(" ", @$cmd); $Jobs{$host}{cmd} = $cmd; $Jobs{$host}{type} = $Status{$host}{type}; $Status{$host}{state} = "Status_link_running"; @@ -560,7 +561,7 @@ sub Main_TryToRun_Bg_or_User_Queue vec($FDread, $Jobs{$host}{fn}, 1) = 1; $Jobs{$host}{startTime} = time; $Jobs{$host}{reqTime} = $req->{reqTime}; - $Jobs{$host}{cmd} = "$progName " . join(" ", @args); + $Jobs{$host}{cmd} = join(" ", $progName, @args); $Jobs{$host}{user} = $user; $Jobs{$host}{type} = $type; if ( !$req->{dhcp} ) { @@ -775,7 +776,7 @@ sub Main_Check_Job_Messages $Jobs{$host}{mesg} = $2; if ( $Jobs{$host}{dhcp} ) { if ( $mesg =~ /^DHCP (\S+) (\S+)/ ) { - my $newHost = $2; + my $newHost = $bpc->uriUnesc($2); if ( defined($Jobs{$newHost}) ) { print(LOG $bpc->timeStamp, "Backup on $newHost is already running\n"); @@ -1014,6 +1015,7 @@ sub Main_Check_Client_Messages $host = $1; my $user = $2; my $backoff = $3; + $host = $bpc->uriUnesc($host); if ( $CmdJob ne $host && defined($Status{$host}) && defined($Jobs{$host}) ) { print(LOG $bpc->timeStamp, @@ -1053,9 +1055,11 @@ sub Main_Check_Client_Messages QueueAllPCs(); } elsif ( $cmd =~ /^backup (\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ ) { my $hostIP = $1; - $host = $2; - my $user = $3; + $host = $2; + my $user = $3; my $doFull = $4; + $host = $bpc->uriUnesc($host); + $hostIP = $bpc->uriUnesc($hostIP); if ( !defined($Status{$host}) ) { print(LOG $bpc->timeStamp, "User $user requested backup of unknown host" @@ -1094,6 +1098,8 @@ sub Main_Check_Client_Messages $host = $2; my $user = $3; my $reqFileName = $4; + $host = $bpc->uriUnesc($host); + $hostIP = $bpc->uriUnesc($hostIP); if ( !defined($Status{$host}) ) { print(LOG $bpc->timeStamp, "User $user requested restore to unknown host" @@ -1143,15 +1149,20 @@ sub Main_Check_Client_Messages } elsif ( $type =~ /^hosts/ ) { push(@values, \%Status); push(@names, qw(*Status)); - } elsif ( $type =~ /^host\((.*)\)/ - && defined($Status{$1}) ) { - push(@values, { - %{$Status{$1}}, - BgQueueOn => $BgQueueOn{$1}, - UserQueueOn => $UserQueueOn{$1}, - CmdQueueOn => $CmdQueueOn{$1}, - }); - push(@names, qw(*StatusHost)); + } elsif ( $type =~ /^host\((.*)\)/ ) { + my $h = $bpc->uriUnesc($1); + if ( defined($Status{$h}) ) { + push(@values, { + %{$Status{$h}}, + BgQueueOn => $BgQueueOn{$h}, + UserQueueOn => $UserQueueOn{$h}, + CmdQueueOn => $CmdQueueOn{$h}, + }); + push(@names, qw(*StatusHost)); + } else { + print(LOG $bpc->timeStamp, + "Unknown host $h for status request\n"); + } } else { print(LOG $bpc->timeStamp, "Unknown status request $type\n"); @@ -1162,6 +1173,7 @@ sub Main_Check_Client_Messages $reply = $dump->Dump; } elsif ( $cmd =~ /^link\s+(.+)/ ) { my($host) = $1; + $host = $bpc->uriUnesc($host); QueueLink($host); } elsif ( $cmd =~ /^log\s+(.*)/ ) { print(LOG $bpc->timeStamp, "$1\n"); @@ -1255,7 +1267,7 @@ sub StatusWrite [ \%Info, \%Status], [qw(*Info *Status)]); $dump->Indent(1); - if ( open(STATUS, ">$TopDir/log/status.pl") ) { + if ( open(STATUS, ">", "$TopDir/log/status.pl") ) { print(STATUS $dump->Dump); close(STATUS); } @@ -1335,7 +1347,7 @@ sub QueueLink host => $host, user => "BackupPC", reqTime => time, - cmd => "$BinDir/BackupPC_link $host" + cmd => ["$BinDir/BackupPC_link", $host], }); $CmdQueueOn{$host} = 1; } diff --git a/bin/BackupPC_compressPool b/bin/BackupPC_compressPool index a3d3583..07f8661 100755 --- a/bin/BackupPC_compressPool +++ b/bin/BackupPC_compressPool @@ -49,7 +49,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -173,7 +173,7 @@ sub doCompress -Bufsize => 65536, -Level => $Compress, ); - if ( !open(FH, $TestMode ? "<$file" : "+<$file") ) { + if ( !open(FH, $TestMode ? "<" : "+<", $file) ) { print("Error: Can't open $file for read/write\n"); $Errors++; return; @@ -196,7 +196,7 @@ sub doCompress } $dataOut .= $fragOut; if ( !$copy && length($dataOut) > $CompMaxWrite ) { - if ( !open(OUT, "+>$file.__z") ) { + if ( !open(OUT, "+>", "$file.__z") ) { print("Error: Can't open $file.__z for write\n"); $Errors++; close(FH); @@ -237,7 +237,7 @@ sub doCompress my $newFile = cpoolFileName($file); if ( $TestMode ) { close(FH); - if ( !open(FH, ">$newFile") ) { + if ( !open(FH, ">", $newFile) ) { print("Error: Can't open $newFile for write\n"); $Errors++; close(FH); @@ -323,7 +323,7 @@ sub checkRead my($n, $nd, $r, $d, $d0); local(*FH); - if ( !open(FH, $file) ) { + if ( !open(FH, "<", $file) ) { print("can't open $file for check\n"); $Errors++; $f->close(); @@ -357,7 +357,7 @@ sub checkReadLine my($n, $nd, $r, $d, $d0); local(*FH); - if ( !open(FH, $file) ) { + if ( !open(FH, "<", $file) ) { print("can't open $file for check\n"); $Errors++; $f->close(); diff --git a/bin/BackupPC_dump b/bin/BackupPC_dump index fcb0bd7..0b46c90 100755 --- a/bin/BackupPC_dump +++ b/bin/BackupPC_dump @@ -1,11 +1,11 @@ #!/bin/perl -T #============================================================= -*-perl-*- # -# BackupPC_dump: Dump a single PC. +# BackupPC_dump: Dump a single client. # # DESCRIPTION # -# Usage: BackupPC_dump [-i] [-f] [-d] [-e] +# Usage: BackupPC_dump [-i] [-f] [-d] [-e] # # Flags: # @@ -14,33 +14,34 @@ # # -f Do a full dump, overriding any scheduling. # -# -d Host is a DHCP pool address, so initially we have no -# idea which machine this actually is. BackupPC_dump -# determines the actual PC host name by using the NetBios -# name. +# -d Host is a DHCP pool address, and the client argument +# just an IP address. We lookup the NetBios name from +# the IP address. # -# -e Just do an dump expiry check for the host. Don't do anything else. # This is used periodically by BackupPC to make sure that dhcp hosts -# have correctly expired old backups. Without this, dhcp hosts that -# are no longer on the network will not expire old backups. +# -e Just do an dump expiry check for the client. Don't do anything +# else. This is used periodically by BackupPC to make sure that +# dhcp hosts have correctly expired old backups. Without this, +# dhcp hosts that are no longer on the network will not expire +# old backups. # -# BackupPC_dump is run periodically by BackupPC to backup $host. -# The file $TopDir/pc/$host/backups is read to decide whether a +# BackupPC_dump is run periodically by BackupPC to backup $client. +# The file $TopDir/pc/$client/backups is read to decide whether a # full or incremental backup needs to be run. If no backup is -# scheduled, or a ping to $host fails, then BackupPC_dump quits. +# scheduled, or a ping to $client fails, then BackupPC_dump quits. # # The backup is done using the selected XferMethod (smb, tar, rsync etc), -# extracting the dump into $TopDir/pc/$host/new. The xfer output is -# put into $TopDir/pc/$host/XferLOG. +# extracting the dump into $TopDir/pc/$client/new. The xfer output is +# put into $TopDir/pc/$client/XferLOG. # # If the dump succeeds (based on parsing the output of the XferMethod): -# - $TopDir/pc/$host/new is renamed to $TopDir/pc/$host/nnn, where +# - $TopDir/pc/$client/new is renamed to $TopDir/pc/$client/nnn, where # nnn is the next sequential dump number. -# - $TopDir/pc/$host/XferLOG is renamed to $TopDir/pc/$host/XferLOG.nnn. -# - $TopDir/pc/$host/backups is updated. +# - $TopDir/pc/$client/XferLOG is renamed to $TopDir/pc/$client/XferLOG.nnn. +# - $TopDir/pc/$client/backups is updated. # # If the dump fails: -# - $TopDir/pc/$host/new is moved to $TopDir/trash for later removal. -# - $TopDir/pc/$host/XferLOG is renamed to $TopDir/pc/$host/XferLOG.bad +# - $TopDir/pc/$client/new is moved to $TopDir/trash for later removal. +# - $TopDir/pc/$client/XferLOG is renamed to $TopDir/pc/$client/XferLOG.bad # for later viewing. # # BackupPC_dump communicates to BackupPC via printing to STDOUT. @@ -67,7 +68,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -98,40 +99,44 @@ $bpc->ChildInit(); my %opts; getopts("defi", \%opts); if ( @ARGV != 1 ) { - print("usage: $0 [-d] [-e] [-f] [-i] \n"); + print("usage: $0 [-d] [-e] [-f] [-i] \n"); exit(1); } -if ( $ARGV[0] !~ /^([\w\.-]+)$/ ) { - print("$0: bad host name '$ARGV[0]'\n"); +if ( $ARGV[0] !~ /^([\w\.-\s]+)$/ ) { + print("$0: bad client name '$ARGV[0]'\n"); exit(1); } -my $hostIP = $1; -my($host, $user); +my $client = $1; # BackupPC's client name (might not be real host name) +my $hostIP; # this is the IP address +my $host; # this is the real host name + +my($clientURI, $user); if ( $opts{d} ) { # - # The host name $hostIP is simply a DHCP address. We need to check + # The client name $client is simply a DHCP address. We need to check # if there is any machine at this address, and if so, get the actual # host name via NetBios using nmblookup. # + $hostIP = $client; exit(1) if ( $bpc->CheckHostAlive($hostIP) < 0 ); - ($host, $user) = $bpc->NetBiosInfoGet($hostIP); + ($client, $user) = $bpc->NetBiosInfoGet($hostIP); exit(1) if ( $host !~ /^([\w\.-]+)$/ ); - my $hosts = $bpc->HostInfoRead($host); - exit(1) if ( !defined($hosts->{$host}) ); -} else { - $host = $hostIP; + my $hosts = $bpc->HostInfoRead($client); + exit(1) if ( !defined($hosts->{$client}) ); + $host = $client; } -my $Dir = "$TopDir/pc/$host"; +my $Dir = "$TopDir/pc/$client"; my $xferPid = -1; my $tarPid = -1; # # Re-read config file, so we can include the PC-specific config # -if ( defined(my $error = $bpc->ConfigRead($host)) ) { - print("Can't read PC's config file: $error\n"); +$clientURI = $bpc->uriEsc($client); +if ( defined(my $error = $bpc->ConfigRead($client)) ) { + print("dump failed: Can't read PC's config file: $error\n"); exit(1); } %Conf = $bpc->Conf(); @@ -151,11 +156,37 @@ alarm($Conf{ClientTimeout}); mkpath($Dir, 0, 0777) if ( !-d $Dir ); if ( !-f "$Dir/LOCK" ) { - open(LOCK, ">$Dir/LOCK") && close(LOCK); + open(LOCK, ">", "$Dir/LOCK") && close(LOCK); } -open(LOG, ">>$Dir/LOG"); +open(LOG, ">>", "$Dir/LOG"); select(LOG); $| = 1; select(STDOUT); +if ( !$opts{d} ) { + # + # In the non-DHCP case, make sure the host can be looked up + # via NS, or otherwise find the IP address via NetBios. + # + if ( $Conf{ClientNameAlias} ne "" ) { + $host = $Conf{ClientNameAlias}; + } else { + $host = $client; + } + if ( !defined(gethostbyname($host)) ) { + # + # Ok, NS doesn't know about it. Maybe it is a NetBios name + # instead. + # + if ( !defined($hostIP = $bpc->NetBiosHostIPFind($host)) ) { + print(LOG $bpc->timeStamp, + "dump failed: Can't find host $host\n"); + print("dump failed: Can't find host $host\n"); + exit(1); + } + } else { + $hostIP = $host; + } +} + ########################################################################### # Figure out what to do and do it ########################################################################### @@ -164,7 +195,7 @@ select(LOG); $| = 1; select(STDOUT); # For the -e option we just expire backups and quit # if ( $opts{e} ) { - BackupExpire($host); + BackupExpire($client); exit(0); } @@ -178,7 +209,7 @@ if ( $err ne "" ) { print(LOG $bpc->timeStamp, "Can't connect to server ($err)\n"); exit(1); } -my $reply = $bpc->ServerMesg("status host($host)"); +my $reply = $bpc->ServerMesg("status host($clientURI)"); $reply = $1 if ( $reply =~ /(.*)/s ); my(%StatusHost); eval($reply); @@ -192,7 +223,7 @@ if ( $opts{d} ) { # oops, something is already running for this host exit(0); } - print("DHCP $hostIP $host\n"); + print("DHCP $hostIP $clientURI\n"); } my($needLink, @Backups, $type, $lastBkupNum, $lastFullBkupNum); @@ -226,13 +257,13 @@ if ( !$opts{i} && !$opts{f} && $StatusHost{backoffTime} > time ) { # # Now see if there are any old backups we should delete # -BackupExpire($host); +BackupExpire($client); # # Read Backup information, and find times of the most recent full and # incremental backups # -@Backups = $bpc->BackupInfoRead($host); +@Backups = $bpc->BackupInfoRead($client); for ( my $i = 0 ; $i < @Backups ; $i++ ) { $needLink = 1 if ( $Backups[$i]{nFilesNew} eq "" || -f "$Dir/NewFileList.$Backups[$i]{num}" ); @@ -270,13 +301,13 @@ my $delay = $bpc->CheckHostAlive($hostIP); if ( $delay < 0 ) { print(LOG $bpc->timeStamp, "no ping response\n"); print("no ping response\n"); - print("link $host\n") if ( $needLink ); + print("link $clientURI\n") if ( $needLink ); exit(1); } elsif ( $delay > $Conf{PingMaxMsec} ) { printf(LOG "%sping too slow: %.4gmsec\n", $bpc->timeStamp, $delay); printf("ping too slow: %.4gmsec (threshold is %gmsec)\n", $delay, $Conf{PingMaxMsec}); - print("link $host\n") if ( $needLink ); + print("link $clientURI\n") if ( $needLink ); exit(1); } @@ -413,8 +444,8 @@ for my $shareName ( @$ShareNames ) { open(STDERR, ">&STDOUT"); close(STDIN); open(STDIN, "<&RH"); - exec("$BinDir/BackupPC_tarExtract '$host' '$shareName'" - . " $Conf{CompressLevel}"); + exec("$BinDir/BackupPC_tarExtract", $client, $shareName, + $Conf{CompressLevel}); print(LOG $bpc->timeStamp, "can't exec $BinDir/BackupPC_tarExtract\n"); exit(0); @@ -424,8 +455,8 @@ for my $shareName ( @$ShareNames ) { # We need to create the NewFileList output file # local(*NEW_FILES); - open(NEW_FILES, ">$TopDir/pc/$host/NewFileList") - || die("can't open $TopDir/pc/$host/NewFileList"); + open(NEW_FILES, ">", "$TopDir/pc/$client/NewFileList") + || die("can't open $TopDir/pc/$client/NewFileList"); $newFilesFH = *NEW_FILES; } @@ -434,6 +465,7 @@ for my $shareName ( @$ShareNames ) { # $xfer->args({ host => $host, + client => $client, hostIP => $hostIP, shareName => $shareName, pipeRH => *RH, @@ -453,7 +485,7 @@ for my $shareName ( @$ShareNames ) { if ( !defined($logMsg = $xfer->start()) ) { print(LOG $bpc->timeStamp, "xfer start failed: ", $xfer->errStr, "\n"); print("dump failed: ", $xfer->errStr, "\n"); - print("link $host\n") if ( $needLink ); + print("link $clientURI\n") if ( $needLink ); # # kill off the tar process, first nicely then forcefully # @@ -512,12 +544,12 @@ for my $shareName ( @$ShareNames ) { $tarOut = $2; $XferLOG->write(\"tarExtract: $_\n"); if ( /^Done: (\d+) errors, (\d+) filesExist, (\d+) sizeExist, (\d+) sizeExistComp, (\d+) filesTotal, (\d+) sizeTotal/ ) { - $tarErrs = $1; - $nFilesExist = $2; - $sizeExist = $3; - $sizeExistComp = $4; - $nFilesTotal = $5; - $sizeTotal = $6; + $tarErrs += $1; + $nFilesExist += $2; + $sizeExist += $3; + $sizeExistComp += $4; + $nFilesTotal += $5; + $sizeTotal += $6; } } } @@ -542,8 +574,13 @@ for my $shareName ( @$ShareNames ) { # # otherwise the xfer module does everything for us # - ($tarErrs, $nFilesExist, $sizeExist, $sizeExistComp, - $nFilesTotal, $sizeTotal) = $xfer->run(); + my @results = $xfer->run(); + $tarErrs += $results[0]; + $nFilesExist += $results[1]; + $sizeExist += $results[2]; + $sizeExistComp += $results[3]; + $nFilesTotal += $results[4]; + $sizeTotal += $results[5]; } # @@ -602,7 +639,7 @@ $XferLOG->close(); close($newFilesFH) if ( defined($newFilesFH) ); if ( $stat{xferOK} ) { - @Backups = $bpc->BackupInfoRead($host); + @Backups = $bpc->BackupInfoRead($client); for ( my $i = 0 ; $i < @Backups ; $i++ ) { $lastNum = $Backups[$i]{num} if ( $lastNum < $Backups[$i]{num} ); } @@ -648,14 +685,14 @@ if ( !$stat{xferOK} ) { rename("$Dir/XferLOG$fileExt", "$Dir/XferLOG.bad$fileExt"); $bpc->RmTreeDefer("$TopDir/trash", "$Dir/new") if ( -d "$Dir/new" ); print("dump failed: $stat{hostError}\n"); - print("link $host\n") if ( $needLink ); + print("link $clientURI\n") if ( $needLink ); exit(1); } # # Add the new backup information to the backup file # -@Backups = $bpc->BackupInfoRead($host); +@Backups = $bpc->BackupInfoRead($client); my $i = @Backups; $Backups[$i]{num} = $lastNum; $Backups[$i]{type} = $type; @@ -673,7 +710,7 @@ $Backups[$i]{tarErrs} = $tarErrs; $Backups[$i]{compress} = $Conf{CompressLevel}; $Backups[$i]{noFill} = $type eq "full" ? 0 : 1; $Backups[$i]{mangle} = 1; # name mangling always on for v1.04+ -$bpc->BackupInfoWrite($host, @Backups); +$bpc->BackupInfoWrite($client, @Backups); unlink("$Dir/timeStamp.level0"); @@ -712,7 +749,7 @@ print(LOG $bpc->timeStamp, . " $stat{xferErrCnt} xferErrs ($stat{xferBadFileCnt} bad files," . " $stat{xferBadShareCnt} bad shares, $otherCount other)\n"); -BackupExpire($host); +BackupExpire($client); print("$type backup complete\n"); @@ -725,7 +762,7 @@ sub NothingToDo my($needLink) = @_; print("nothing to do\n"); - print("link $host\n") if ( $needLink ); + print("link $clientURI\n") if ( $needLink ); exit(0); } @@ -761,7 +798,7 @@ sub catch_signal } else { print("dump failed: received signal=$signame\n"); } - print("link $host\n") if ( $needLink ); + print("link $clientURI\n") if ( $needLink ); exit(1); } @@ -771,9 +808,9 @@ sub catch_signal # sub BackupExpire { - my($host) = @_; - my($Dir) = "$TopDir/pc/$host"; - my(@Backups) = $bpc->BackupInfoRead($host); + my($client) = @_; + my($Dir) = "$TopDir/pc/$client"; + my(@Backups) = $bpc->BackupInfoRead($client); my($cntFull, $cntIncr, $firstFull, $firstIncr, $oldestIncr, $oldestFull); while ( 1 ) { @@ -847,7 +884,7 @@ sub BackupExpire last; } } - $bpc->BackupInfoWrite($host, @Backups); + $bpc->BackupInfoWrite($client, @Backups); } sub CorrectHostCheck @@ -870,6 +907,7 @@ sub UserCommandRun return if ( !defined($Conf{$type}) ); my $vars = { xfer => $xfer, + client => $client, host => $host, hostIP => $hostIP, share => $ShareNames->[0], diff --git a/bin/BackupPC_link b/bin/BackupPC_link index b8f7481..8bd8dc1 100755 --- a/bin/BackupPC_link +++ b/bin/BackupPC_link @@ -39,7 +39,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -70,7 +70,7 @@ if ( @ARGV != 1 ) { print("usage: $0 \n"); exit(1); } -if ( $ARGV[0] !~ /^([\w\.-]+)$/ ) { +if ( $ARGV[0] !~ /^([\w\.-\s]+)$/ ) { print("$0: bad host name '$ARGV[0]'\n"); exit(1); } @@ -105,7 +105,7 @@ while ( 1 ) { # $CurrDumpDir = "$Dir/$Backups[$num]{num}"; $Compress = $Backups[$num]{compress}; - if ( open(NEW, "$Dir/NewFileList.$Backups[$num]{num}") ) { + if ( open(NEW, "<", "$Dir/NewFileList.$Backups[$num]{num}") ) { while ( ) { chomp; next if ( !/(\w+) (\d+) (.*)/ ); diff --git a/bin/BackupPC_nightly b/bin/BackupPC_nightly index 1f2d1f4..82f1351 100755 --- a/bin/BackupPC_nightly +++ b/bin/BackupPC_nightly @@ -35,7 +35,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -101,7 +101,7 @@ if ( $mday == 1 ) { "$TopDir/pc/$host/LOG.0.z", "$TopDir/pc/$host/LOG.0", $Conf{CompressLevel}, 1); - open(LOG, ">$TopDir/pc/$host/LOG") && close(LOG); + open(LOG, ">", "$TopDir/pc/$host/LOG") && close(LOG); } } diff --git a/bin/BackupPC_restore b/bin/BackupPC_restore index c01f12c..7746a36 100755 --- a/bin/BackupPC_restore +++ b/bin/BackupPC_restore @@ -5,7 +5,7 @@ # # DESCRIPTION # -# Usage: BackupPC_restore +# Usage: BackupPC_restore # # AUTHOR # Craig Barratt @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -58,34 +58,27 @@ my $BinDir = $bpc->BinDir(); my %Conf = $bpc->Conf(); my $NeedPostCmd; -my($hostIP, $host, $reqFileName); +my($hostIP, $host, $client, $reqFileName, %stat); $bpc->ChildInit(); if ( @ARGV != 3 ) { - print("usage: $0 \n"); + print("usage: $0 \n"); exit(1); } $hostIP = $1 if ( $ARGV[0] =~ /(.+)/ ); -$host = $1 if ( $ARGV[1] =~ /(.+)/ ); +$client = $1 if ( $ARGV[1] =~ /(.+)/ ); if ( $ARGV[2] !~ /^([\w.]+)$/ ) { print("$0: bad reqFileName (arg #3): $ARGV[2]\n"); exit(1); } $reqFileName = $1; -my $Hosts = $bpc->HostInfoRead(); +my $startTime = time(); -# -# Re-read config file, so we can include the PC-specific config -# -if ( defined(my $error = $bpc->ConfigRead($host)) ) { - print("Can't read PC's config file: $error\n"); - exit(1); -} -%Conf = $bpc->Conf(); +my $Hosts = $bpc->HostInfoRead(); -my $Dir = "$TopDir/pc/$host"; +my $Dir = "$TopDir/pc/$client"; my $xferPid = -1; my $tarPid = -1; @@ -96,50 +89,90 @@ $SIG{INT} = \&catch_signal; $SIG{ALRM} = \&catch_signal; $SIG{TERM} = \&catch_signal; +mkpath($Dir, 0, 0777) if ( !-d $Dir ); +if ( !-f "$Dir/LOCK" ) { + open(LOCK, ">", "$Dir/LOCK") && close(LOCK); +} +open(LOG, ">>", "$Dir/LOG"); +select(LOG); $| = 1; select(STDOUT); + # # Read the request file # if ( !(my $ret = do "$Dir/$reqFileName") ) { - die "couldn't parse $Dir/$reqFileName: $@" if $@; - die "couldn't do $Dir/$reqFileName: $!" unless defined $ret; - die "couldn't run $Dir/$reqFileName"; + my $err; + if ( $@ ) { + $err = "couldn't parse $Dir/$reqFileName: $@"; + } elsif ( !defined($ret) ) { + $err = "couldn't do $Dir/$reqFileName: $!"; + } else { + $err = "couldn't run $Dir/$reqFileName"; + } + $stat{hostError} = $err; + exit(RestoreCleanup($client)); } +# +# Re-read config file, so we can include the PC-specific config +# +if ( defined(my $error = $bpc->ConfigRead($client)) ) { + $stat{hostError} = "Can't read PC's config file: $error"; + exit(RestoreCleanup($client)); +} +%Conf = $bpc->Conf(); + # # Make sure we eventually timeout if there is no activity from # the data transport program. # alarm($Conf{ClientTimeout}); -mkpath($Dir, 0, 0777) if ( !-d $Dir ); -if ( !-f "$Dir/LOCK" ) { - open(LOCK, ">$Dir/LOCK") && close(LOCK); +# +# See if the host name is aliased +# +if ( $Conf{ClientNameAlias} ne "" ) { + $host = $Conf{ClientNameAlias}; +} else { + $host = $client; +} + +# +# Find its IP address +# +if ( $hostIP !~ /\d+\.\d+\.\d+\.\d+/ ) { + if ( !defined(gethostbyname($host)) ) { + # + # Ok, NS doesn't know about it. Maybe it is a NetBios name + # instead. + # + if ( !defined($hostIP = $bpc->NetBiosHostIPFind($host)) ) { + $stat{hostError} = "Can't find host $host"; + exit(RestoreCleanup($client)); + } + } else { + $hostIP = $host; + } } -open(LOG, ">>$Dir/LOG"); -select(LOG); $| = 1; select(STDOUT); # # Check if $host is alive # my $delay = $bpc->CheckHostAlive($hostIP); if ( $delay < 0 ) { - print(LOG $bpc->timeStamp, "no ping response\n"); - print("no ping response\n"); - exit(1); + $stat{hostError} = "no ping response from $host ($hostIP)"; + exit(RestoreCleanup($client)); } elsif ( $delay > $Conf{PingMaxMsec} ) { - printf(LOG "%sping too slow: %.4gmsec\n", $bpc->timeStamp, $delay); - printf("ping too slow: %.4gmsec (threshold is %gmsec)\n", + $stat{hostError} = sprintf("ping too slow: %.4gmsec (max is %gmsec)\n", $delay, $Conf{PingMaxMsec}); - exit(1); + exit(RestoreCleanup($client)); } # # Make sure it is really the machine we expect # if ( (my $errMsg = CorrectHostCheck($hostIP, $host)) ) { - print(LOG $bpc->timeStamp, "restore failed: $errMsg\n"); - print("restore failed: $errMsg\n"); - exit(1); + $stat{hostError} = $errMsg; + exit(RestoreCleanup($client)); } # @@ -149,13 +182,11 @@ $Conf{CompressLevel} = 0 if ( !BackupPC::FileZIO->compOk ); my $fileExt = $Conf{CompressLevel} > 0 ? ".z" : ""; my $RestoreLOG = BackupPC::FileZIO->open("$Dir/RestoreLOG$fileExt", 1, $Conf{CompressLevel}); -my $startTime = time(); - my $tarCreateFileCnt = 0; my $tarCreateByteCnt = 0; my $tarCreateErrCnt = 1; # assume not ok until we learn otherwise my $tarCreateErr; -my($logMsg, %stat, $xfer); +my($logMsg, $xfer); $stat{xferOK} = $stat{hostAbort} = undef; $stat{hostError} = $stat{lastOutputLine} = undef; @@ -178,10 +209,9 @@ if ( $Conf{XferMethod} eq "tar" ) { # if ( !defined($xfer = BackupPC::Xfer::Rsync->new($bpc)) ) { my $errStr = BackupPC::Xfer::Rsync->errStr; - print(LOG $bpc->timeStamp, "restore failed: $errStr\n"); - print("restore failed: $errStr\n"); UserCommandRun("RestorePostUserCmd") if ( $NeedPostCmd ); - exit(1); + $stat{hostError} = $errStr; + exit(RestoreCleanup($client)); } } else { # @@ -207,6 +237,7 @@ if ( $useTar ) { # my @Backups = $bpc->BackupInfoRead($RestoreReq{hostSrc}); my $xferArgs = { + client => $client, host => $host, hostIP => $hostIP, type => "restore", @@ -227,10 +258,9 @@ my $xferArgs = { $xfer->args($xferArgs); if ( !defined($logMsg = $xfer->start()) ) { - print(LOG $bpc->timeStamp, "xfer start failed: ", $xfer->errStr, "\n"); - print($xfer->errStr, "\n"); UserCommandRun("RestorePostUserCmd") if ( $NeedPostCmd ); - exit(1); + $stat{hostError} = "xfer start failed: ", $xfer->errStr; + exit(RestoreCleanup($client)); } if ( $useTar ) { @@ -261,16 +291,16 @@ if ( $useTar ) { @tarPathOpts, @{$RestoreReq{fileList}}, ); - my $logMsg = "Running: $BinDir/BackupPC_tarCreate " - . join(" ", @tarArgs) . "\n"; + my $logMsg = "Running: " + . $bpc->execCmd2ShellCmd("$BinDir/BackupPC_tarCreate", @tarArgs) + . "\n"; $RestoreLOG->write(\$logMsg); if ( !defined($tarPid = open(TAR, "-|")) ) { - print(LOG $bpc->timeStamp, "can't fork to run tar\n"); - print("can't fork to run tar\n"); close(WH); # FIX: need to cleanup xfer UserCommandRun("RestorePostUserCmd") if ( $NeedPostCmd ); - exit(0); + $stat{hostError} = "Can't fork to run tar"; + exit(RestoreCleanup($client)); } if ( !$tarPid ) { # @@ -378,101 +408,7 @@ foreach my $k ( (keys(%stat), keys(%$newStat)) ) { } } -$stat{xferOK} = 0 if ( $stat{hostError} || $stat{hostAbort} || $tarCreateErr ); - -if ( !$stat{xferOK} ) { - # - # kill off the tranfer program, first nicely then forcefully - # - kill(2, $xferPid) if ( $xferPid > 0 ); - sleep(1); - kill(9, $xferPid) if ( $xferPid > 0 ); - # - # kill off the tar process, first nicely then forcefully - # - kill(2, $tarPid) if ( $tarPid > 0 ); - sleep(1); - kill(9, $tarPid) if ( $tarPid > 0 ); -} - -my $lastNum = -1; -my @Restores; - -# -# Do one last check to make sure it is still the machine we expect. -# -if ( $stat{xferOK} && (my $errMsg = CorrectHostCheck($hostIP, $host)) ) { - $stat{hostError} = $errMsg; - $stat{xferOK} = 0; -} -@Restores = $bpc->RestoreInfoRead($host); -for ( my $i = 0 ; $i < @Restores ; $i++ ) { - $lastNum = $Restores[$i]{num} if ( $lastNum < $Restores[$i]{num} ); -} -$lastNum++; - -# -# Run an optional post-restore command -# -UserCommandRun("RestorePostUserCmd") if ( $NeedPostCmd ); - -$RestoreLOG->close(); -rename("$Dir/RestoreLOG$fileExt", "$Dir/RestoreLOG.$lastNum$fileExt"); -rename("$Dir/$reqFileName", "$Dir/RestoreInfo.$lastNum"); -my $endTime = time(); - -# -# If the restore failed, clean up -# -if ( !$stat{xferOK} ) { - # - # wait a short while and see if the system is still alive - # - $stat{hostError} ||= $tarCreateErr if ( $tarCreateErr ne "" ); - $stat{hostError} = $stat{lastOutputLine} if ( $stat{hostError} eq "" ); - if ( $stat{hostError} ) { - print(LOG $bpc->timeStamp, - "Got fatal error during xfer ($stat{hostError})\n"); - } - sleep(2); - if ( $bpc->CheckHostAlive($hostIP) < 0 ) { - $stat{hostAbort} = 1; - } - if ( $stat{hostAbort} ) { - $stat{hostError} = "lost network connection during restore"; - } -} - -# -# Add the new restore information to the restore file -# -@Restores = $bpc->RestoreInfoRead($host); -my $i = @Restores; -$Restores[$i]{num} = $lastNum; -$Restores[$i]{startTime} = $startTime; -$Restores[$i]{endTime} = $endTime; -$Restores[$i]{result} = $stat{xferOK} ? "ok" : "failed"; -$Restores[$i]{errorMsg} = $stat{hostError}; -$Restores[$i]{nFiles} = $tarCreateFileCnt; -$Restores[$i]{size} = $tarCreateByteCnt; -$Restores[$i]{tarCreateErrs} = $tarCreateErrCnt; -$Restores[$i]{xferErrs} = $stat{xferErrCnt} || 0; - -while ( @Restores > $Conf{RestoreInfoKeepCnt} ) { - my $num = $Restores[0]{num}; - unlink("$Dir/RestoreLOG.$num.z"); - unlink("$Dir/RestoreLOG.$num"); - unlink("$Dir/RestoreInfo.$num"); - shift(@Restores); -} -$bpc->RestoreInfoWrite($host, @Restores); - -if ( !$stat{xferOK} ) { - print(LOG $bpc->timeStamp, "Restore aborted ($stat{hostError})\n"); - print("restore failed: $stat{hostError}\n"); -} else { - print("restore complete\n"); -} +exit(RestoreCleanup($client)); ########################################################################### # Subroutines @@ -512,6 +448,109 @@ sub catch_signal $stat{hostError} = "aborted by signal $signame"; } +# +# Cleanup and update the restore status +# +sub RestoreCleanup +{ + my($client) = @_; + + $stat{xferOK} = 0 if ( $stat{hostError} || $stat{hostAbort} + || $tarCreateErr ); + + if ( !$stat{xferOK} ) { + # + # kill off the tranfer program, first nicely then forcefully + # + kill(2, $xferPid) if ( $xferPid > 0 ); + sleep(1); + kill(9, $xferPid) if ( $xferPid > 0 ); + # + # kill off the tar process, first nicely then forcefully + # + kill(2, $tarPid) if ( $tarPid > 0 ); + sleep(1); + kill(9, $tarPid) if ( $tarPid > 0 ); + } + + my $lastNum = -1; + my @Restores; + + # + # Do one last check to make sure it is still the machine we expect. + # + if ( $stat{xferOK} && (my $errMsg = CorrectHostCheck($hostIP, $host)) ) { + $stat{hostError} = $errMsg; + $stat{xferOK} = 0; + } + @Restores = $bpc->RestoreInfoRead($client); + for ( my $i = 0 ; $i < @Restores ; $i++ ) { + $lastNum = $Restores[$i]{num} if ( $lastNum < $Restores[$i]{num} ); + } + $lastNum++; + + # + # Run an optional post-restore command + # + UserCommandRun("RestorePostUserCmd") if ( $NeedPostCmd ); + + $RestoreLOG->close() if ( defined($RestoreLOG) ); + rename("$Dir/RestoreLOG$fileExt", "$Dir/RestoreLOG.$lastNum$fileExt"); + rename("$Dir/$reqFileName", "$Dir/RestoreInfo.$lastNum"); + my $endTime = time(); + + # + # If the restore failed, clean up + # + if ( !$stat{xferOK} ) { + # + # wait a short while and see if the system is still alive + # + $stat{hostError} ||= $tarCreateErr if ( $tarCreateErr ne "" ); + $stat{hostError} = $stat{lastOutputLine} if ( $stat{hostError} eq "" ); + sleep(2); + if ( $bpc->CheckHostAlive($hostIP) < 0 ) { + $stat{hostAbort} = 1; + } + if ( $stat{hostAbort} && $stat{hostError} eq "" ) { + $stat{hostError} = "lost network connection during restore"; + } + } + + # + # Add the new restore information to the restore file + # + @Restores = $bpc->RestoreInfoRead($client); + my $i = @Restores; + $Restores[$i]{num} = $lastNum; + $Restores[$i]{startTime} = $startTime; + $Restores[$i]{endTime} = $endTime; + $Restores[$i]{result} = $stat{xferOK} ? "ok" : "failed"; + $Restores[$i]{errorMsg} = $stat{hostError}; + $Restores[$i]{nFiles} = $tarCreateFileCnt; + $Restores[$i]{size} = $tarCreateByteCnt; + $Restores[$i]{tarCreateErrs} = $tarCreateErrCnt; + $Restores[$i]{xferErrs} = $stat{xferErrCnt} || 0; + + while ( @Restores > $Conf{RestoreInfoKeepCnt} ) { + my $num = $Restores[0]{num}; + unlink("$Dir/RestoreLOG.$num.z"); + unlink("$Dir/RestoreLOG.$num"); + unlink("$Dir/RestoreInfo.$num"); + shift(@Restores); + } + $bpc->RestoreInfoWrite($client, @Restores); + + if ( !$stat{xferOK} ) { + print(LOG $bpc->timeStamp, "Restore aborted ($stat{hostError})\n"); + print("restore failed: $stat{hostError}\n"); + return 1; + } else { + print("restore complete\n"); + return; + } +} + # # Run an optional pre- or post-dump command # diff --git a/bin/BackupPC_sendEmail b/bin/BackupPC_sendEmail index b41eb9a..4ba2778 100755 --- a/bin/BackupPC_sendEmail +++ b/bin/BackupPC_sendEmail @@ -38,7 +38,7 @@ #======================================================================== use strict; -use lib "__INSTALLDIR__/lib"; +use lib "/usr/local/BackupPC/lib"; use BackupPC::Lib; use BackupPC::FileZIO; @@ -282,7 +282,7 @@ if ( !$opts{t} ) { my $dumpStr = Data::Dumper->Dump( [\%UserEmailInfo], [qw(*UserEmailInfo)]); - if ( open(HOST, ">$TopDir/log/UserEmailInfo.pl") ) { + if ( open(HOST, ">", "$TopDir/log/UserEmailInfo.pl") ) { print(HOST $dumpStr); close(HOST); } diff --git a/bin/BackupPC_serverMesg b/bin/BackupPC_serverMesg index 325e5d1..fb444d3 100755 --- a/bin/BackupPC_serverMesg +++ b/bin/BackupPC_serverMesg @@ -43,7 +43,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # diff --git a/bin/BackupPC_tarCreate b/bin/BackupPC_tarCreate index 04713df..3ba3bbc 100755 --- a/bin/BackupPC_tarCreate +++ b/bin/BackupPC_tarCreate @@ -48,7 +48,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -78,7 +78,7 @@ if ( @ARGV < 1 ) { exit(1); } -if ( $opts{h} !~ /^([\w\.-]+)$/ ) { +if ( $opts{h} !~ /^([\w\.-\s]+)$/ ) { print(STDERR "$0: bad host name '$opts{h}'\n"); exit(1); } diff --git a/bin/BackupPC_tarExtract b/bin/BackupPC_tarExtract index 06eaf73..7f53915 100755 --- a/bin/BackupPC_tarExtract +++ b/bin/BackupPC_tarExtract @@ -27,7 +27,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -50,7 +50,7 @@ if ( @ARGV != 3 ) { print("usage: $0 \n"); exit(1); } -if ( $ARGV[0] !~ /^([\w\.-]+)$/ ) { +if ( $ARGV[0] !~ /^([\w\.-\s]+)$/ ) { print("$0: bad host name '$ARGV[0]'\n"); exit(1); } @@ -76,7 +76,7 @@ my $Compress = $1; # Copyright 1998 Stephen Zander. All rights reserved. # my $tar_unpack_header - = 'A100 A8 A8 A8 A12 A12 A8 A1 A100 A6 A2 A32 A32 A8 A8 A155 x12'; + = 'Z100 A8 A8 A8 A12 A12 A8 A1 Z100 A6 A2 Z32 Z32 A8 A8 A155 x12'; my $tar_header_length = 512; my $BufSize = 1048576; # 1MB or 2^20 @@ -372,7 +372,7 @@ sub processClose } mkpath("$OutDir/$ShareName", 0, 0777); -open(NEW_FILES, ">>$TopDir/pc/$host/NewFileList") +open(NEW_FILES, ">>", "$TopDir/pc/$host/NewFileList") || die("can't open $TopDir/pc/$host/NewFileList"); 1 while ( TarReadFile(*STDIN) ); 1 while ( sysread(STDIN, my $discard, 1024) ); diff --git a/bin/BackupPC_trashClean b/bin/BackupPC_trashClean index 08815d2..cabeffb 100755 --- a/bin/BackupPC_trashClean +++ b/bin/BackupPC_trashClean @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # diff --git a/bin/BackupPC_zcat b/bin/BackupPC_zcat index 284988a..b7bd7e1 100755 --- a/bin/BackupPC_zcat +++ b/bin/BackupPC_zcat @@ -32,7 +32,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # diff --git a/bin/BackupPC_zipCreate b/bin/BackupPC_zipCreate index 4fa7f4a..c91d208 100755 --- a/bin/BackupPC_zipCreate +++ b/bin/BackupPC_zipCreate @@ -51,7 +51,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # diff --git a/cgi-bin/BackupPC_Admin b/cgi-bin/BackupPC_Admin index 85d8807..7e0209c 100755 --- a/cgi-bin/BackupPC_Admin +++ b/cgi-bin/BackupPC_Admin @@ -39,7 +39,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -243,15 +243,16 @@ sub Action_StartStopBackup if ( $In{doit} ) { if ( $start ) { if ( $Hosts->{$host}{dhcp} ) { - $reply = $bpc->ServerMesg("backup $In{hostIP} $host" - . " $User $doFull"); + $reply = $bpc->ServerMesg("backup $In{hostIP} ${EscURI($host)}" + . " $User $doFull"); $str = eval("qq{$Lang->{Backup_requested_on_DHCP__host}}"); } else { - $reply = $bpc->ServerMesg("backup $host $host $User $doFull"); + $reply = $bpc->ServerMesg("backup ${EscURI($host)}" + . " ${EscURI($host)} $User $doFull"); $str = eval("qq{$Lang->{Backup_requested_on__host_by__User}}"); } } else { - $reply = $bpc->ServerMesg("stop $host $User $In{backoff}"); + $reply = $bpc->ServerMesg("stop ${EscURI($host)} $User $In{backoff}"); $str = eval("qq{$Lang->{Backup_stopped_dequeued_on__host_by__User}}"); } @@ -267,7 +268,7 @@ sub Action_StartStopBackup print (eval("qq{$Lang->{Are_you_sure_start}}")); } else { my $backoff = ""; - GetStatusInfo("host($host)"); + GetStatusInfo("host(${EscURI($host)})"); if ( $StatusHost{backoffTime} > time ) { $backoff = sprintf("%.1f", ($StatusHost{backoffTime} - time) / 3600); @@ -432,13 +433,13 @@ sub Action_View print(eval("qq{$Lang->{skipped__skipped_lines}}")) if ( $skipped ); $skipped = 0; - print ${EscapeHTML($_)}; + print ${EscHTML($_)}; } } elsif ( $linkHosts ) { while ( 1 ) { $_ = $fh->readLine(); last if ( $_ eq "" ); - my $s = ${EscapeHTML($_)}; + my $s = ${EscHTML($_)}; $s =~ s/\b([\w-]+)\b/defined($Hosts->{$1}) ? ${HostLink($1)} : $1/eg; print $s; @@ -451,13 +452,13 @@ sub Action_View s/(SmbSharePasswd.*=.*['"]).*(['"])/$1$2/ig; s/(SmbShareUserName.*=.*['"]).*(['"])/$1$2/ig; s/(ServerMesgSecret.*=.*['"]).*(['"])/$1$2/ig; - print ${EscapeHTML($_)}; + print ${EscHTML($_)}; } } else { while ( 1 ) { $_ = $fh->readLine(); last if ( $_ eq "" ); - print ${EscapeHTML($_)}; + print ${EscHTML($_)}; } } $fh->close(); @@ -481,7 +482,7 @@ sub Action_LOGlist my($url0, $hdr, $root, $str); if ( $host ne "" ) { $root = "$TopDir/pc/$host/LOG"; - $url0 = "&host=$host"; + $url0 = "&host=${EscURI($host)}"; $hdr = "for host $host"; } else { $root = "$TopDir/log/LOG"; @@ -561,7 +562,7 @@ sub Action_Browse last if ( $Backups[$i]{num} == $num ); } if ( $i >= @Backups ) { - ErrorExit("Backup number $num for host ${EscapeHTML($host)} does" + ErrorExit("Backup number $num for host ${EscHTML($host)} does" . " not exist."); } my $backupTime = timeStamp2($Backups[$i]{startTime}); @@ -575,7 +576,7 @@ sub Action_Browse $share = (sort(keys(%$attr)))[0]; $dir = '/'; } else { - ErrorExit(eval("qq{$Lang->{Directory___EscapeHTML}}")); + ErrorExit(eval("qq{$Lang->{Directory___EscHTML}}")); } } my $relDir = $dir; @@ -609,9 +610,9 @@ sub Action_Browse $path = "/"; } $path =~ s{^/+}{/}; - $path =~ s/([^\w.\/-])/uc sprintf("%%%02x", ord($1))/eg; - $fURI =~ s/([^\w.\/-])/uc sprintf("%%%02x", ord($1))/eg; - $shareURI =~ s/([^\w.\/-])/uc sprintf("%%%02x", ord($1))/eg; + $path =~ s/([^\w.\/-])/uc sprintf("%%%02X", ord($1))/eg; + $fURI =~ s/([^\w.\/-])/uc sprintf("%%%02X", ord($1))/eg; + $shareURI =~ s/([^\w.\/-])/uc sprintf("%%%02X", ord($1))/eg; $dirOpen = 1 if ( defined($currDir) && $f eq $currDir ); if ( $attr->{$f}{type} == BPC_FTYPE_DIR ) { # @@ -639,7 +640,7 @@ sub Action_Browse push(@DirStr, {needTick => 1, tdArgs => $BGcolor, link => <$imgStr $bold$dirName$unbold +$imgStr $bold$dirName$unbold EOF $fileCnt++; $gotDir = 1; @@ -691,15 +692,16 @@ EOF } else { $attrStr .= " \n"; } + (my $fDisp = "${EscHTML($f)}") =~ s/ / /g; if ( $gotDir ) { $fileStr .= < ${EscapeHTML($f)} + $fDisp $attrStr EOF } else { $fileStr .= < ${EscapeHTML($f)} + $fDisp $attrStr EOF @@ -760,7 +762,7 @@ EOF my $shareURI = $share; $path =~ s/([^\w.\/-])/uc sprintf("%%%02x", ord($1))/eg; $shareURI =~ s/([^\w.\/-])/uc sprintf("%%%02x", ord($1))/eg; - push(@otherDirs, "$i"); } @@ -768,7 +770,6 @@ EOF my $otherDirs = join(",\n", @otherDirs); $filledBackup .= eval("qq{$Lang->{Visit_this_directory_in_backup}}"); } - print (eval("qq{$Lang->{Backup_browse_for__host}}")); Trailer(); } @@ -806,11 +807,11 @@ sub Action_Restore EOF $fileListStr .= < ${EscapeHTML($name)} +
  • ${EscHTML($name)} EOF } $hiddenStr .= "\n"; - $hiddenStr .= "\n"; + $hiddenStr .= "\n"; $badFileCnt++ if ( $In{pathHdr} =~ m{(^|/)\.\.(/|$)} ); $badFileCnt++ if ( $In{num} =~ m{(^|/)\.\.(/|$)} ); if ( @fileList == 0 ) { @@ -996,8 +997,8 @@ EOF } else { ErrorExit(eval("qq{$Lang->{Can_t_open_create}}")); } - $reply = $bpc->ServerMesg("restore $ipAddr" - . " $hostDest $User $reqFileName"); + $reply = $bpc->ServerMesg("restore ${EscURI($ipAddr)}" + . " ${EscURI($hostDest)} $User $reqFileName"); $str = eval("qq{$Lang->{Restore_requested_to_host__hostDest__backup___num}}"); Header(eval("qq{$Lang->{Restore_Requested_on__hostDest}}")); print (eval("qq{$Lang->{Reply_from_server_was___reply}}")); @@ -1113,7 +1114,7 @@ sub restoreFile my $view = BackupPC::View->new($bpc, $host, \@Backups); my $a = $view->fileAttrib($num, $share, $dir); if ( $dir =~ m{(^|/)\.\.(/|$)} || !defined($a) ) { - ErrorExit("Can't restore bad file ${EscapeHTML($dir)}"); + ErrorExit("Can't restore bad file ${EscHTML($dir)}"); } my $f = BackupPC::FileZIO->open($a->{fullPath}, 0, $a->{compress}); my $data; @@ -1175,7 +1176,7 @@ sub Action_HostInfo } $In{host} = $host; } - GetStatusInfo("host($host)"); + GetStatusInfo("host(${EscURI($host)})"); $bpc->ConfigRead($host); %Conf = $bpc->Conf(); my $Privileged = CheckPermission($host); @@ -1209,7 +1210,7 @@ sub Action_HostInfo (1 - $Backups[$i]{sizeNewComp} / $Backups[$i]{sizeNew})); } my $age = sprintf("%.1f", (time - $Backups[$i]{startTime}) / (24*3600)); - my $browseURL = "$MyURL?action=browse&host=$host&num=$Backups[$i]{num}"; + my $browseURL = "$MyURL?action=browse&host=${EscURI($host)}&num=$Backups[$i]{num}"; my $filled = $Backups[$i]{noFill} ? $Lang->{No} : $Lang->{Yes}; $filled .= " ($Backups[$i]{fillFromNum}) " if ( $Backups[$i]{fillFromNum} ne "" ); @@ -1255,8 +1256,8 @@ EOF $errStr .= < $Backups[$i]{num} $ltype - XferLOG, - Errors + XferLOG, + Errors $Backups[$i]{xferErrs} $Backups[$i]{xferBadFile} $Backups[$i]{xferBadShare} @@ -1277,7 +1278,7 @@ EOF my $Restores_Result = $Lang->{failed}; if ($Restores[$i]{result} ne "failed") { $Restores_Result = $Lang->{success}; } $restoreStr .= <$Restores[$i]{num} +$Restores[$i]{num} $Restores_Result $startTime $duration @@ -1340,7 +1341,7 @@ EOF $statusStr .= eval("qq{$Lang->{Last_status_is_state_StatusHost_state_reason_as_of_startTime}}"); if ( $StatusHost{error} ne "" ) { - $statusStr .= eval("qq{$Lang->{Last_error_is____EscapeHTML_StatusHost_error}}"); + $statusStr .= eval("qq{$Lang->{Last_error_is____EscHTML_StatusHost_error}}"); } my $priorStr = "Pings"; if ( $StatusHost{deadCnt} > 0 ) { @@ -1424,8 +1425,8 @@ EOF || -f "$TopDir/pc/$host/XferLOG.bad.z" ) { $XferViewStr = <XferLOG, -XferErr +XferLOG, +XferErr EOF } else { $XferViewStr = ""; @@ -1438,7 +1439,7 @@ EOF $startTime $XferViewStr $errorTime - ${EscapeHTML($shortErr)} + ${EscHTML($shortErr)} EOF } my $now = timeStamp2(time); @@ -1549,7 +1550,7 @@ sub HostLink my($host) = @_; my($s); if ( defined($Hosts->{$host}) || defined($Status{$host}) ) { - $s = "$host"; + $s = "$host"; } else { $s = $host; } @@ -1574,23 +1575,23 @@ sub UserLink return \$s; } -sub EscapeHTML +sub EscHTML { my($s) = @_; $s =~ s/&/&/g; $s =~ s/\"/"/g; $s =~ s/>/>/g; $s =~ s/NetBiosInfoGet($ipAddr); if ( $netBiosHost ne $host ) { my($tryIP); - GetStatusInfo("host($host)"); + GetStatusInfo("host(${EscURI($host)})"); if ( defined($StatusHost{dhcpHostIP}) && $StatusHost{dhcpHostIP} ne $ipAddr ) { $tryIP = eval("qq{$Lang->{tryIP}}"); @@ -1788,20 +1789,20 @@ EOF my $host = $In{host}; NavSectionTitle( eval("qq{$Lang->{Host_Inhost}}") ); NavSectionStart(); - NavLink("?host=$host", $Lang->{Home}); - NavLink("?action=view&type=LOG&host=$host", $Lang->{LOG_file}); - NavLink("?action=LOGlist&host=$host", $Lang->{Old_LOGs}); + NavLink("?host=${EscURI($host)}", $Lang->{Home}); + NavLink("?action=view&type=LOG&host=${EscURI($host)}", $Lang->{LOG_file}); + NavLink("?action=LOGlist&host=${EscURI($host)}", $Lang->{Old_LOGs}); if ( -f "$TopDir/pc/$host/SmbLOG.bad" || -f "$TopDir/pc/$host/SmbLOG.bad.z" || -f "$TopDir/pc/$host/XferLOG.bad" || -f "$TopDir/pc/$host/XferLOG.bad.z" ) { - NavLink("?action=view&type=XferLOGbad&host=$host", + NavLink("?action=view&type=XferLOGbad&host=${EscURI($host)}", $Lang->{Last_bad_XferLOG}); - NavLink("?action=view&type=XferErrbad&host=$host", + NavLink("?action=view&type=XferErrbad&host=${EscURI($host)}", $Lang->{Last_bad_XferLOG_errors_only}); } if ( -f "$TopDir/pc/$host/config.pl" ) { - NavLink("?action=view&type=config&host=$host", $Lang->{Config_file}); + NavLink("?action=view&type=config&host=${EscURI($host)}", $Lang->{Config_file}); } NavSectionEnd(); } @@ -1809,7 +1810,7 @@ EOF if ( defined($Hosts) && %$Hosts > 0 ) { NavSectionStart(0); foreach my $host ( GetUserHosts() ) { - NavLink("?host=$host", $host); + NavLink("?host=${EscURI($host)}", $host); } NavSectionEnd(); } diff --git a/conf/config.pl b/conf/config.pl index 596dd10..bd1cd47 100644 --- a/conf/config.pl +++ b/conf/config.pl @@ -531,17 +531,32 @@ $Conf{XferMethod} = 'smb'; $Conf{SmbClientPath} = '/usr/bin/smbclient'; # -# Additional optional arguments to smbclient. -# -# Some users have reported that the -b option can be used to improve -# performance of smbclient. The default value is 4096, and if you -# find smbclient has low throughput you might try a value of 2048, eg: -# -# $Conf{SmbClientArgs} = '-b 2048'; -# +# Commands to run smbclient for a full dump, incremental dump or a restore. # This setting only matters if $Conf{XferMethod} = 'smb'. # -$Conf{SmbClientArgs} = ''; +# Several variables are substituted at run-time: +# +# $smbClientPath same as $Conf{SmbClientPath} +# $host host to backup/restore +# $hostIP host IP address +# $shareName share name +# $userName user name +# $fileList list of files to backup (based on exclude/include) +# $I_option optional -I option to smbclient +# $X_option exclude option (if $fileList is an exclude list) +# $timeStampFile start time for incremental dump +# +$Conf{SmbClientFullCmd} = '$smbClientPath \\\\$host\\$shareName' + . '$I_option -U $userName -E -N -d 1' + . ' -c tarmode\\ full -Tc$X_option - $fileList'; + +$Conf{SmbClientIncrCmd} = '$smbClientPath \\\\$host\\$shareName' + . '$I_option -U $userName -E -N -d 1' + . ' -c tarmode\\ full -TcN$X_option $timeStampFile - $fileList'; + +$Conf{SmbClientRestoreCmd} = '$smbClientPath \\\\$host\\$shareName' + . '$I_option -U $userName -E -N -d 1' + . ' -c tarmode\\ full -Tx -'; # # Full command to run tar on the client. GNU tar is required. You will diff --git a/lib/BackupPC/Attrib.pm b/lib/BackupPC/Attrib.pm index b5159a3..98b0390 100644 --- a/lib/BackupPC/Attrib.pm +++ b/lib/BackupPC/Attrib.pm @@ -30,7 +30,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # diff --git a/lib/BackupPC/FileZIO.pm b/lib/BackupPC/FileZIO.pm index 05f28e6..637a39d 100644 --- a/lib/BackupPC/FileZIO.pm +++ b/lib/BackupPC/FileZIO.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -95,9 +95,9 @@ sub open $fh = $fileName; } else { if ( $write ) { - open(FH, ">$fileName") || return; + open(FH, ">", $fileName) || return; } else { - open(FH, "<$fileName") || return; + open(FH, "<", $fileName) || return; } $fh = *FH; } @@ -343,7 +343,7 @@ sub compressCopy if ( $CompZlibOK && $compress > 0 ) { my $fh = BackupPC::FileZIO->open($destFileZ, 1, $compress); my $data; - if ( defined($fh) && open(LOG, $srcFile) ) { + if ( defined($fh) && open(LOG, "<", $srcFile) ) { while ( sysread(LOG, $data, 65536) > 0 ) { $fh->write(\$data); } diff --git a/lib/BackupPC/Lang/en.pm b/lib/BackupPC/Lang/en.pm index db49746..b9a5e4d 100644 --- a/lib/BackupPC/Lang/en.pm +++ b/lib/BackupPC/Lang/en.pm @@ -288,7 +288,7 @@ You can start a restore that will restore these files directly onto selected will be overwritten!
    - + \$hiddenStr @@ -296,16 +296,16 @@ selected will be overwritten! - - + value="\${EscHTML(\$pathHdr)}" name="pathHdr">
    Restore the files to host
    Restore the files to share
    Restore the files below dir
    (relative to share)
    @@ -327,13 +327,13 @@ create and transfer the archive, and you will need enough local disk space to store it.

    - + \$hiddenStr Make archive relative -to \${EscapeHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} +to \${EscHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} (otherwise archive will contain full paths).
    Compression (0=off, 1=fast,...,9=best) @@ -370,13 +370,13 @@ create and transfer the archive, and you will need enough local disk space to store it.

    - + \$hiddenStr Make archive relative -to \${EscapeHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} +to \${EscHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} (otherwise archive will contain full paths).
    @@ -400,10 +400,10 @@ backup number \$num: - - - - + + + + \$hiddenStr @@ -576,11 +576,11 @@ $Lang{Backup_browse_for__host} = < Click on a file below to restore that file. -\${h2("Contents of \${EscapeHTML(\$dirDisplay)}")} +\${h2("Contents of \${EscHTML(\$dirDisplay)}")} - +
    @@ -662,38 +662,38 @@ $Lang{Wrong_user__my_userid_is___} = $Lang{Only_privileged_users_can_view_PC_summaries} = "Only privileged users can view PC summaries."; $Lang{Only_privileged_users_can_stop_or_start_backups} = "Only privileged users can stop or start backups on" - . " \${EscapeHTML(\$host)}."; + . " \${EscHTML(\$host)}."; $Lang{Invalid_number__num} = "Invalid number \$num"; $Lang{Unable_to_open__file__configuration_problem} = "Unable to open \$file: configuration problem?"; $Lang{Only_privileged_users_can_view_log_or_config_files} = "Only privileged users can view log or config files."; $Lang{Only_privileged_users_can_view_log_files} = "Only privileged users can view log files."; $Lang{Only_privileged_users_can_view_email_summaries} = "Only privileged users can view email summaries."; $Lang{Only_privileged_users_can_browse_backup_files} = "Only privileged users can browse backup files" - . " for host \${EscapeHTML(\$In{host})}."; + . " for host \${EscHTML(\$In{host})}."; $Lang{Empty_host_name} = "Empty host name."; -$Lang{Directory___EscapeHTML} = "Directory \${EscapeHTML(\"\$TopDir/pc/\$host/\$num\")}" +$Lang{Directory___EscHTML} = "Directory \${EscHTML(\"\$TopDir/pc/\$host/\$num\")}" . " is empty"; $Lang{Can_t_browse_bad_directory_name2} = "Can\'t browse bad directory name" - . " \${EscapeHTML(\$relDir)}"; + . " \${EscHTML(\$relDir)}"; $Lang{Only_privileged_users_can_restore_backup_files} = "Only privileged users can restore backup files" - . " for host \${EscapeHTML(\$In{host})}."; -$Lang{Bad_host_name} = "Bad host name \${EscapeHTML(\$host)}"; + . " for host \${EscHTML(\$In{host})}."; +$Lang{Bad_host_name} = "Bad host name \${EscHTML(\$host)}"; $Lang{You_haven_t_selected_any_files__please_go_Back_to} = "You haven\'t selected any files; please go Back to" . " select some files."; $Lang{Nice_try__but_you_can_t_put} = "Nice try, but you can\'t put \'..\' in any of the file names"; -$Lang{Host__doesn_t_exist} = "Host \${EscapeHTML(\$In{hostDest})} doesn\'t exist"; +$Lang{Host__doesn_t_exist} = "Host \${EscHTML(\$In{hostDest})} doesn\'t exist"; $Lang{You_don_t_have_permission_to_restore_onto_host} = "You don\'t have permission to restore onto host" - . " \${EscapeHTML(\$In{hostDest})}"; + . " \${EscHTML(\$In{hostDest})}"; $Lang{Can_t_open_create} = "Can\'t open/create " - . "\${EscapeHTML(\"\$TopDir/pc/\$hostDest/\$reqFileName\")}"; + . "\${EscHTML(\"\$TopDir/pc/\$hostDest/\$reqFileName\")}"; $Lang{Only_privileged_users_can_restore_backup_files2} = "Only privileged users can restore backup files" - . " for host \${EscapeHTML(\$host)}."; + . " for host \${EscHTML(\$host)}."; $Lang{Empty_host_name} = "Empty host name"; -$Lang{Unknown_host_or_user} = "Unknown host or user \${EscapeHTML(\$host)}"; +$Lang{Unknown_host_or_user} = "Unknown host or user \${EscHTML(\$host)}"; $Lang{Only_privileged_users_can_view_information_about} = "Only privileged users can view information about" - . " host \${EscapeHTML(\$host)}." ; + . " host \${EscHTML(\$host)}." ; $Lang{Only_privileged_users_can_view_restore_information} = "Only privileged users can view restore information."; -$Lang{Restore_number__num_for_host__does_not_exist} = "Restore number \$num for host \${EscapeHTML(\$host)} does" +$Lang{Restore_number__num_for_host__does_not_exist} = "Restore number \$num for host \${EscHTML(\$host)} does" . " not exist."; $Lang{Unable_to_connect_to_BackupPC_server} = "Unable to connect to BackupPC server", @@ -703,7 +703,7 @@ $Lang{Unable_to_connect_to_BackupPC_server} = "Unable to connect to BackupPC ser "Perhaps the BackupPC server is not running or there is a " . " configuration error. Please report this to your Sys Admin."; -$Lang{Can_t_find_IP_address_for} = "Can\'t find IP address for \${EscapeHTML(\$host)}"; +$Lang{Can_t_find_IP_address_for} = "Can\'t find IP address for \${EscHTML(\$host)}"; $Lang{host_is_a_DHCP_host} = <Last error is \"\${EscapeHTML(\$StatusHost{error})}\" +$Lang{Last_error_is____EscHTML_StatusHost_error} = <Last error is \"\${EscHTML(\$StatusHost{error})}\" EOF # ------ @@ -871,7 +871,7 @@ $Lang{No} = "no"; $Lang{Yes} = "yes"; $Lang{The_directory_is_empty} = <The directory \${EscapeHTML(\$dirDisplay)} is empty +The directory \${EscHTML(\$dirDisplay)} is empty EOF diff --git a/lib/BackupPC/Lang/fr.pm b/lib/BackupPC/Lang/fr.pm index 873f175..a729415 100644 --- a/lib/BackupPC/Lang/fr.pm +++ b/lib/BackupPC/Lang/fr.pm @@ -284,7 +284,7 @@ directement sur \$host. tous les fichiers correspondant à ceux que vous avez sélectionnés vont être effacés ! - + \$hiddenStr @@ -292,16 +292,16 @@ tous les fichiers correspondant - - + value="\${EscHTML(\$pathHdr)}" name="pathHdr">
    Restaurer les fichiers vers l\'hôte
    Restaurer les fichiers vers le partage
    Restaurer les fichiers du répertoire
    (relatif au partage)
    @@ -322,13 +322,13 @@ cette archive peut devenir tr et transférer cette archive, et vous aurez besoin d\'assez d\'espace disque pour le stocker.

    - + \$hiddenStr Faire l\'archive relative à -\${EscapeHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} +\${EscHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} (Autrement l\'archive contiendra les chemins complets).
    Compression (0=désactivée, 1=rapide,...,9=meilleure) @@ -366,13 +366,13 @@ pour cr d\'espace disque local pour la stocker.

    - + \$hiddenStr Faire l\'archive relative à -\${EscapeHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} +\${EscHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} (Autrement l\'archive contiendra des chemins absolus).
    @@ -395,10 +395,10 @@ Vous - - - - + + + + \$hiddenStr @@ -575,11 +575,11 @@ $Lang{Backup_browse_for__host} = < Cliquer dans un fichier ci-dessous pour le restaurer. -\${h2("Contenu de \${EscapeHTML(\$dirDisplay)}")} +\${h2("Contenu de \${EscHTML(\$dirDisplay)}")} - +
    @@ -664,41 +664,41 @@ $Lang{Wrong_user__my_userid_is___} = "Mauvais utilisateur: mon userid est \$>, à la place de \$uid (\$Conf{BackupPCUser})\n"; $Lang{Only_privileged_users_can_view_PC_summaries} = "Seuls les utilisateurs privilégiés peuvent voir les résumés des PC."; $Lang{Only_privileged_users_can_stop_or_start_backups} = - "Seuls les utilisateurs privilégiés peuvent arrêter ou démarrer des sauvegardes sur \${EscapeHTML(\$host)}."; + "Seuls les utilisateurs privilégiés peuvent arrêter ou démarrer des sauvegardes sur \${EscHTML(\$host)}."; $Lang{Invalid_number__num} = "Numéro invalide \$num"; $Lang{Unable_to_open__file__configuration_problem} = "Impossible d\'ouvrir \$file: problème de configuration ?"; $Lang{Only_privileged_users_can_view_log_or_config_files} = "Seuls les utilisateurs privilégiés peuvent voir les fichier de jounal ou les fichiers de configuration."; $Lang{Only_privileged_users_can_view_log_files} = "Seuls les utilisateurs privilégiés peuvent voir les fichiers de journal."; $Lang{Only_privileged_users_can_view_email_summaries} = "Seuls les utilisateurs privilégiés peuvent voir les compte-rendu des courriels."; -$Lang{Only_privileged_users_can_browse_backup_files} = "Seuls les utilisateurs privilégiés peuvent parcourir les fichiers de sauvegarde pour l'hôte \${EscapeHTML(\$In{host})}."; +$Lang{Only_privileged_users_can_browse_backup_files} = "Seuls les utilisateurs privilégiés peuvent parcourir les fichiers de sauvegarde pour l'hôte \${EscHTML(\$In{host})}."; $Lang{Empty_host_name} = "Nom d\'hôte vide."; -$Lang{Directory___EscapeHTML} = "Le répertoire \${EscapeHTML(\"\$TopDir/pc/\$host/\$num\")}" +$Lang{Directory___EscHTML} = "Le répertoire \${EscHTML(\"\$TopDir/pc/\$host/\$num\")}" . " est vide"; $Lang{Can_t_browse_bad_directory_name2} = "Ne peut pas parcourir " - . " \${EscapeHTML(\$relDir)}:" + . " \${EscHTML(\$relDir)}:" . " mauvais nom de répertoire"; $Lang{Only_privileged_users_can_restore_backup_files} = "Seuls les utilisateurs privilégiés peuvent restaurer " . " des fichiers de sauvegarde" - . " pour l\'hôte \${EscapeHTML(\$In{host})}."; -$Lang{Bad_host_name} = "Mauvais nom d\'hôte \${EscapeHTML(\$host)}"; + . " pour l\'hôte \${EscHTML(\$In{host})}."; +$Lang{Bad_host_name} = "Mauvais nom d\'hôte \${EscHTML(\$host)}"; $Lang{You_haven_t_selected_any_files__please_go_Back_to} = "Vous n'avez sélectionné aucun fichier; " . "vous pouvez revenir en arrière pour sélectionner des fichiers."; $Lang{Nice_try__but_you_can_t_put} = "Bien tenté, mais vous ne pouvez pas mettre \'..\' dans" . " n\'importe quel nom de fichier."; -$Lang{Host__doesn_t_exist} = "L'hôte \${EscapeHTML(\$In{hostDest})} n\'existe pas."; +$Lang{Host__doesn_t_exist} = "L'hôte \${EscHTML(\$In{hostDest})} n\'existe pas."; $Lang{You_don_t_have_permission_to_restore_onto_host} = "Vous n\'avez pas la permission de restaurer sur l\'hôte" - . " \${EscapeHTML(\$In{hostDest})}"; -$Lang{Can_t_open_create} = "Ne peut pas ouvrir/créer ". "\${EscapeHTML(\"\$TopDir/pc/\$hostDest/\$reqFileName\")}"; + . " \${EscHTML(\$In{hostDest})}"; +$Lang{Can_t_open_create} = "Ne peut pas ouvrir/créer ". "\${EscHTML(\"\$TopDir/pc/\$hostDest/\$reqFileName\")}"; $Lang{Only_privileged_users_can_restore_backup_files2} = "Seuls les utilisateurs privilégiés peuvent restaurer" . " des fichiers de sauvegarde" - . " pour l\'hôte \${EscapeHTML(\$host)}."; + . " pour l\'hôte \${EscHTML(\$host)}."; $Lang{Empty_host_name} = "Nom d\'hôte vide"; -$Lang{Unknown_host_or_user} = "\${EscapeHTML(\$host)}, hôte ou utilisateur inconnu."; +$Lang{Unknown_host_or_user} = "\${EscHTML(\$host)}, hôte ou utilisateur inconnu."; $Lang{Only_privileged_users_can_view_information_about} = "Seuls les utilisateurs privilégiés peuvent accéder aux " - . " informations sur l\'hôte \${EscapeHTML(\$host)}." ; + . " informations sur l\'hôte \${EscHTML(\$host)}." ; $Lang{Only_privileged_users_can_view_restore_information} = "Seuls les utilisateurs privilégiés peuvent restaurer " ."des informations."; -$Lang{Restore_number__num_for_host__does_not_exist} = "Restauration numéro \$num de l\'hôte \${EscapeHTML(\$host)} n\'existe pas"; +$Lang{Restore_number__num_for_host__does_not_exist} = "Restauration numéro \$num de l\'hôte \${EscHTML(\$host)} n\'existe pas"; $Lang{Unable_to_connect_to_BackupPC_server} = "Impossible de se connecter au server BackupPC." . "Ce script CGI (\$MyURL) ne peut pas se connecter au serveur BackupPC" @@ -707,7 +707,7 @@ $Lang{Unable_to_connect_to_BackupPC_server} = "Impossible de se connecter au ser "Peut-être que BackupPC n\'a pas été lancé ou il y a une erreur " . " de configuration. Veuillez faire suivre ce message à votre administrateur système."; -$Lang{Can_t_find_IP_address_for} = "Ne peut pas trouver d\'adresse IP pour \${EscapeHTML(\$host)}"; +$Lang{Can_t_find_IP_address_for} = "Ne peut pas trouver d\'adresse IP pour \${EscHTML(\$host)}"; $Lang{host_is_a_DHCP_host} = <La dernière erreur est \"\${EscapeHTML(\$StatusHost{error})}\" +$Lang{Last_error_is____EscHTML_StatusHost_error} = <La dernière erreur est \"\${EscHTML(\$StatusHost{error})}\" EOF # ------ @@ -879,7 +879,7 @@ $Lang{No} = "non"; $Lang{Yes} = "oui"; $Lang{The_directory_is_empty} = <Le repertoire \${EscapeHTML(\$dirDisplay)} est vide +Le repertoire \${EscHTML(\$dirDisplay)} est vide EOF diff --git a/lib/BackupPC/Lib.pm b/lib/BackupPC/Lib.pm index f0590bc..8cc1e83 100644 --- a/lib/BackupPC/Lib.pm +++ b/lib/BackupPC/Lib.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -58,7 +58,7 @@ sub new TopDir => $topDir || '/data/BackupPC', BinDir => $installDir || '/usr/local/BackupPC', LibDir => $installDir || '/usr/local/BackupPC', - Version => '1.6.0_CVS', + Version => '2.0.0_CVS', BackupFields => [qw( num type startTime endTime nFiles size nFilesExist sizeExist nFilesNew sizeNew @@ -314,8 +314,19 @@ sub HostInfoRead s/[\n\r]+//; s/#.*//; s/\s+$//; - next if ( /^\s*$/ || !/^([\w\.-]+\s+.*)/ ); - @fld = split(/\s+/, $1); + next if ( /^\s*$/ || !/^([\w\.-\\]+\s+.*)/ ); + # + # Split on white space, except if preceded by \ + # using zero-width negative look-behind assertion + # (always wanted to use one of those). + # + @fld = split(/(? $bpc->{Conf}{NmbLookupPath}, + host => $host, + }; + $nmbCmd = $bpc->cmdVarSubstitute($bpc->{Conf}{NmbLookupFindHostCmd}, $args); + my $resp = $bpc->cmdSystemOrEval($nmbCmd, undef, $args); + if ( $resp =~ /^\s*(\d+\.\d+\.\d+\.\d+)\s+\Q$host/m ) { + return $1; + } else { + return; + } +} + sub fileNameEltMangle { my($bpc, $name) = @_; @@ -791,6 +828,43 @@ sub shellEscape return $cmd; } +# +# For printing exec commands (which don't use a shell) so they look like +# a valid shell command this function should be called with the exec +# args. The shell command string is returned. +# +sub execCmd2ShellCmd +{ + my($bpc, @args) = @_; + my $str; + + foreach my $a ( @args ) { + $str .= " " if ( $str ne "" ); + $str .= $bpc->shellEscape($a); + } + return $str; +} + +# +# Do a URI-style escape to protect/encode special characters +# +sub uriEsc +{ + my($bpc, $s) = @_; + $s =~ s{([^\w.\/-])}{sprintf("%%%02X", ord($1));}eg; + return $s; +} + +# +# Do a URI-style unescape to restore special characters +# +sub uriUnesc +{ + my($bpc, $s) = @_; + $s =~ s{%(..)}{chr(hex($1))}eg; + return $s; +} + # # Do variable substitution prior to execution of a command. # @@ -806,7 +880,18 @@ sub cmdVarSubstitute if ( (ref($template) eq "ARRAY" ? $template->[0] : $template) =~ /^\&/ ) { return $template; } - $template = [split(/\s+/, $template)] if ( ref($template) ne "ARRAY" ); + if ( ref($template) ne "ARRAY" ) { + # + # Split at white space, except if escaped by \ + # + $template = [split(/(?{$1}) && ref($vars->{$1}) ne "ARRAY" + exists($vars->{$1}) && ref($vars->{$1}) ne "ARRAY" ? ($2 eq "+" ? $bpc->shellEscape($vars->{$1}) : $vars->{$1}) : "\$$1" }eg; diff --git a/lib/BackupPC/PoolWrite.pm b/lib/BackupPC/PoolWrite.pm index 123bf8d..7957f2c 100644 --- a/lib/BackupPC/PoolWrite.pm +++ b/lib/BackupPC/PoolWrite.pm @@ -56,7 +56,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -258,7 +258,7 @@ sub write # Simply create an empty file # local(*OUT); - if ( !open(OUT, ">$a->{fileName}") ) { + if ( !open(OUT, ">", $a->{fileName}) ) { push(@{$a->{errors}}, "Can't open $a->{fileName} for empty" . " output\n"); } else { diff --git a/lib/BackupPC/View.pm b/lib/BackupPC/View.pm index be87096..ae95d33 100644 --- a/lib/BackupPC/View.pm +++ b/lib/BackupPC/View.pm @@ -31,7 +31,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # diff --git a/lib/BackupPC/Xfer/Rsync.pm b/lib/BackupPC/Xfer/Rsync.pm index b07c33b..11103ca 100644 --- a/lib/BackupPC/Xfer/Rsync.pm +++ b/lib/BackupPC/Xfer/Rsync.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -128,7 +128,7 @@ sub start $remoteDir =~ s{//+}{/}g; $argList = ['--server', @$rsyncArgs, '.', $remoteDir]; $fioArgs = { - host => $t->{bkupSrcHost}, + client => $t->{bkupSrcHost}, share => $t->{bkupSrcShare}, viewNum => $t->{bkupSrcNum}, fileList => $t->{fileList}, @@ -234,7 +234,7 @@ sub start $argList = ['--server', '--sender', @$rsyncArgs, '.', $t->{shareNameSlash}]; $fioArgs = { - host => $t->{host}, + client => $t->{client}, share => $t->{shareName}, viewNum => $t->{lastFullBkupNum}, }; @@ -243,16 +243,17 @@ sub start # # Merge variables into $rsyncClientCmd # - $rsyncClientCmd = $bpc->cmdVarSubstitute($rsyncClientCmd, - { - host => $t->{host}, - hostIP => $t->{hostIP}, - shareName => $t->{shareName}, - shareNameSlash => $t->{shareNameSlash}, - rsyncPath => $conf->{RsyncClientPath}, - sshPath => $conf->{SshPath}, - argList => $argList, - }); + my $args = { + host => $t->{host}, + hostIP => $t->{hostIP}, + client => $t->{client}, + shareName => $t->{shareName}, + shareNameSlash => $t->{shareNameSlash}, + rsyncPath => $conf->{RsyncClientPath}, + sshPath => $conf->{SshPath}, + argList => $argList, + }; + $rsyncClientCmd = $bpc->cmdVarSubstitute($rsyncClientCmd, $args); # # Create the Rsync object, and tell it to use our own File::RsyncP::FileIO @@ -263,7 +264,7 @@ sub start $t->{rs} = File::RsyncP->new({ logLevel => $conf->{RsyncLogLevel}, rsyncCmd => sub { - $bpc->cmdExecOrEval($rsyncClientCmd); + $bpc->cmdExecOrEval($rsyncClientCmd, $args); }, rsyncCmdType => "full", rsyncArgs => $rsyncArgs, @@ -317,7 +318,10 @@ sub run # # Run rsync command # - $t->{XferLOG}->write(\"Running: @{$t->{rsyncClientCmd}}\n"); + my $str = "Running: " + . $t->{bpc}->execCmd2ShellCmd(@{$t->{rsyncClientCmd}}) + . "\n"; + $t->{XferLOG}->write(\$str); $rs->remoteStart($remoteSend, $remoteDir); } else { # @@ -326,6 +330,9 @@ sub run if ( defined(my $err = $rs->serverConnect($t->{hostIP}, $conf->{RsyncdClientPort})) ) { $t->{hostError} = $err; + my $str = "Error connecting to rsync daemon at $t->{hostIP}" + . ":$conf->{RsyncdClientPort}: $err\n"; + $t->{XferLOG}->write(\$str); return; } # @@ -338,6 +345,9 @@ sub run $conf->{RsyncdUserName}, $conf->{RsyncdPasswd}, $conf->{RsyncdAuthRequired})) ) { + my $str = "Error connecting to module $module at $t->{hostIP}" + . ":$conf->{RsyncdClientPort}: $err\n"; + $t->{XferLOG}->write(\$str); $t->{hostError} = $err; return; } diff --git a/lib/BackupPC/Xfer/RsyncFileIO.pm b/lib/BackupPC/Xfer/RsyncFileIO.pm index 87c50bc..44a61ad 100644 --- a/lib/BackupPC/Xfer/RsyncFileIO.pm +++ b/lib/BackupPC/Xfer/RsyncFileIO.pm @@ -12,7 +12,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -77,7 +77,7 @@ sub new $fio->{shareM} = $fio->{bpc}->fileNameEltMangle($fio->{share}); $fio->{outDir} = "$fio->{xfer}{outDir}/new/"; $fio->{outDirSh} = "$fio->{outDir}/$fio->{shareM}/"; - $fio->{view} = BackupPC::View->new($fio->{bpc}, $fio->{host}, + $fio->{view} = BackupPC::View->new($fio->{bpc}, $fio->{client}, $fio->{backups}); $fio->{full} = $fio->{xfer}{type} eq "full" ? 1 : 0; $fio->{newFilesFH} = $fio->{xfer}{newFilesFH}; @@ -723,7 +723,7 @@ sub fileDeltaRxNext # unlink("$fio->{outDirSh}RStmp") if ( -f "$fio->{outDirSh}RStmp" ); - if ( open(F, ">+$fio->{outDirSh}RStmp") ) { + if ( open(F, ">+", "$fio->{outDirSh}RStmp") ) { my $data; while ( $fh->read(\$data, 1024 * 1024) > 0 ) { if ( syswrite(F, $data) != length($data) ) { @@ -744,7 +744,7 @@ sub fileDeltaRxNext } $fh->close; } else { - if ( open(F, $attr->{fullPath}) ) { + if ( open(F, "<", $attr->{fullPath}) ) { $fio->{rxInFd} = *F; $fio->{rxInName} = $attr->{fullPath}; } else { diff --git a/lib/BackupPC/Xfer/Smb.pm b/lib/BackupPC/Xfer/Smb.pm index 124b6f0..bfd367a 100644 --- a/lib/BackupPC/Xfer/Smb.pm +++ b/lib/BackupPC/Xfer/Smb.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -79,7 +79,8 @@ sub start my $bpc = $t->{bpc}; my $conf = $t->{conf}; my $I_option = $t->{hostIP} eq $t->{host} ? "" : " -I $t->{hostIP}"; - my($fileList, $optX, $smbClientCmd, $logMsg); + my(@fileList, $X_option, $smbClientCmd, $logMsg); + my($timeStampFile); local(*SMB); # @@ -97,11 +98,7 @@ sub start return; } if ( $t->{type} eq "restore" ) { - $smbClientCmd = - "$conf->{SmbClientPath} '\\\\$t->{host}\\$t->{shareName}'" - . "$I_option -U '$conf->{SmbShareUserName}' -E -N -d 1" - . " $conf->{SmbClientArgs}" - . " -c 'tarmode full' -Tx -"; + $smbClientCmd = $conf->{SmbClientRestoreCmd}; $logMsg = "restore started for share $t->{shareName}"; } else { # @@ -126,43 +123,45 @@ sub start } if ( defined($conf->{BackupFilesOnly}{$t->{shareName}}) ) { foreach my $file ( @{$conf->{BackupFilesOnly}{$t->{shareName}}} ) { - $file =~ s/'/\\'/g; - $fileList .= "'$file' "; + push(@fileList, $file); } } elsif ( defined($conf->{BackupFilesExclude}{$t->{shareName}}) ) { foreach my $file ( @{$conf->{BackupFilesExclude}{$t->{shareName}}} ) { - $file =~ s/'/\\'/g; - $fileList .= "'$file' "; + push(@fileList, $file); } # # Allow simple wildcards in exclude list by specifying "r" option. # - $optX = "rX"; + $X_option = "rX"; } if ( $t->{type} eq "full" ) { - $smbClientCmd = - "$conf->{SmbClientPath} '\\\\$t->{host}\\$t->{shareName}'" - . "$I_option -U '$conf->{SmbShareUserName}' -E -N -d 1" - . " $conf->{SmbClientArgs}" - . " -c 'tarmode full'" - . " -Tc$optX - $fileList"; + $smbClientCmd = $conf->{SmbClientFullCmd}; $logMsg = "full backup started for share $t->{shareName}"; } else { - my $timeStampFile = "$t->{outDir}/timeStamp.level0"; - open(LEV0, ">$timeStampFile") && close(LEV0); + $timeStampFile = "$t->{outDir}/timeStamp.level0"; + open(LEV0, ">", $timeStampFile) && close(LEV0); utime($t->{lastFull} - 3600, $t->{lastFull} - 3600, $timeStampFile); - $smbClientCmd = - "$conf->{SmbClientPath} '\\\\$t->{host}\\$t->{shareName}'" - . "$I_option -U '$conf->{SmbShareUserName}' -E -N -d 1" - . " $conf->{SmbClientArgs}" - . " -c 'tarmode full'" - . " -TcN$optX $timeStampFile - $fileList"; + $smbClientCmd = $conf->{SmbClientIncrCmd}; $logMsg = "incr backup started back to " . $bpc->timeStamp($t->{lastFull} - 3600, 0) . "for share $t->{shareName}"; } } + my $args = { + smbClientPath => $conf->{SmbClientPath}, + host => $t->{host}, + hostIP => $t->{hostIP}, + client => $t->{client}, + shareName => $t->{shareName}, + userName => $conf->{SmbShareUserName}, + fileList => \@fileList, + I_option => $I_option, + X_option => $X_option, + timeStampFile => $timeStampFile, + }; + $smbClientCmd = $bpc->cmdVarSubstitute($smbClientCmd, $args); + if ( !defined($t->{xferPid} = open(SMB, "-|")) ) { $t->{_errStr} = "Can't fork to run smbclient"; return; @@ -194,14 +193,15 @@ sub start open(STDOUT, ">&$t->{pipeWH}"); } # - # exec smbclient. + # Run smbclient. # - exec($smbClientCmd); + $bpc->cmdExecOrEval($smbClientCmd, $args); # should not be reached, but just in case... $t->{_errStr} = "Can't exec $conf->{SmbClientPath}"; return; } - $t->{XferLOG}->write(\"Running: $smbClientCmd\n"); + my $str = "Running: " . $bpc->execCmd2ShellCmd(@$smbClientCmd) . "\n"; + $t->{XferLOG}->write(\$str); alarm($conf->{ClientTimeout}); $t->{_errStr} = undef; return $logMsg; diff --git a/lib/BackupPC/Xfer/Tar.pm b/lib/BackupPC/Xfer/Tar.pm index 60326e1..4637828 100644 --- a/lib/BackupPC/Xfer/Tar.pm +++ b/lib/BackupPC/Xfer/Tar.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # @@ -82,11 +82,7 @@ sub start local(*TAR); if ( $t->{type} eq "restore" ) { - if ( ref($conf->{TarClientRestoreCmd}) eq "ARRAY" ) { - $tarClientCmd = $conf->{TarClientRestoreCmd}; - } else { - $tarClientCmd = [split(/ +/, $conf->{TarClientRestoreCmd})]; - } + $tarClientCmd = $conf->{TarClientRestoreCmd}; $logMsg = "restore started below directory $t->{shareName}"; # # restores are considered to work unless we see they fail @@ -149,15 +145,17 @@ sub start # # Merge variables into @tarClientCmd # - $tarClientCmd = $bpc->cmdVarSubstitute($tarClientCmd, { + my $args = { host => $t->{host}, hostIP => $t->{hostIP}, + client => $t->{client}, incrDate => $incrDate, shareName => $t->{shareName}, fileList => \@fileList, tarPath => $conf->{TarClientPath}, sshPath => $conf->{SshPath}, - }); + }; + $tarClientCmd = $bpc->cmdVarSubstitute($tarClientCmd, $args); if ( !defined($t->{xferPid} = open(TAR, "-|")) ) { $t->{_errStr} = "Can't fork to run tar"; return; @@ -191,11 +189,12 @@ sub start # # Run the tar command # - $bpc->cmdExecOrEval($tarClientCmd); + $bpc->cmdExecOrEval($tarClientCmd, $args); # should not be reached, but just in case... $t->{_errStr} = "Can't exec @$tarClientCmd"; return; } + my $str = "Running: " . $bpc->execCmd2ShellCmd(@$tarClientCmd) . "\n"; $t->{XferLOG}->write(\"Running: @$tarClientCmd\n"); alarm($conf->{ClientTimeout}); $t->{_errStr} = undef; diff --git a/lib/BackupPC/Zip/FileMember.pm b/lib/BackupPC/Zip/FileMember.pm index d9892fe..c39589a 100644 --- a/lib/BackupPC/Zip/FileMember.pm +++ b/lib/BackupPC/Zip/FileMember.pm @@ -33,7 +33,7 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 2.0.0_CVS, released 18 Jan 2003. # # See http://backuppc.sourceforge.net. # -- 2.20.1