# Version __VERSION__, __RELEASEDATE__
#------------------------------------------------------------------------
+* Fixed FTP xfer method, with help from Holger Parplies and
+ Mirco Piccin. FTP restores are still not supported.
+
+* Fixed bug in BackupPC_sendEmail where a user only receives
+ email about one host.
+
+* Fixed bug where top-level attrib file was linked into the pool with
+ the wrong digest, caused by it being updated multiple times with
+ multiple shares. Reported by Jeff Kosowsky who also supplied a
+ patch.
+
+* Fixed bug in blackout calculation when multiple periods span midnight.
+ Report and patch from Joachim Falk.
+
+* Wrapped eval {} around attribute unpacking to make it more robust
+ to data corruption. Path submitted by Tim Connors.
+
+* Ignore fileType 8 and 9 in BackupPC_tarCreate rather than consider then
+ errors. These are sockets and unknown (eg: solaris door) files that
+ are created dynamicaly by applications - there is no meaningful restore
+ for these file types.
+
+* Changed lib/BackupPC/Lib.pm and lib/BackupPC/Storage/Text.pm based on
+ patches from Davide Brini and Holger Parplies so that main config
+ %Conf values are available in the host config file, allowing more
+ flexibility in perl expressions in the config files. Use beware,
+ since the CGI editor won't work correctly if the config file have
+ perl expressions.
+
+* Obscure password values in LOG file when CGI editor is used to change
+ values. Proposed by Steve Ling.
+
+* Added favicon.ico from Axel Beckert. Thanks to Tyler Wagner for submitting
+ another version and reminding me about the first.
+
+* Replace "sort(HostSortCompare keys(%$Hosts))" with "sort HostSortCompare keys(%$Hosts)"
+ in bin/BackupPC to avoid an error with certain versions of perl.
+
+* Fixed $Conf{XX} links in the BackupPC.html and the CGI editor so they
+ correctly reference the definition.
+
+* Support ${VAR} style variable substitution in commands, in addition to
+ existing $VAR style. Suggested by Jeffrey Kosowsky.
+
+* Clarified usage of -b and -w options to BackupPC_tarCreate. Submitted by
+ Michael Selway.
+
+* Repaired Unable_to_connect_to_BackupPC_server Lang string and added new
+ string Unable_to_connect_to_BackupPC_server_error_message. Proposed and
+ explained by Holger Parplies.
+
+* Added 'use utf8' to lib/BackupPC/Lang/pl.pm. Reported by Michal Sawicz.
+
+* Minor updates to lib/BackupPC/Lang/fr.pm from Hubert Tournier.
+
+* Minor update to lib/BackupPC/Lang/en.pm from David Relson.
+
+#------------------------------------------------------------------------
+# Version 3.2.0beta0, 5 April 2009
+#------------------------------------------------------------------------
+
* Added BackupPC::Xfer::Protocol as a common class for each Xfer
method. This simplifies some of the xfer specific code.
Implemented by Paul Mantz.
takes more than 24 hours (ie: when the next one is meant to
start). Reported by Tony Schreiner.
+* Fixed IO::Dirent run-time check. Reported by Bernhard Ott and Tino Schwarze
+ debugged it.
+
* Added more options to server backup command: rather than just forcing
an incremental or full backup, a regular (auto) backup can be queued
(ie: do nothing/incr/full based on schedule), as well as doing just
Marko Tukiainen, who both helped debugging the problem.
* Fixed bug in lib/BackupPC/Xfer/RsyncFileIO.pm that caused
- incorrected deleted attributes to be set in directories
+ incorrectly deleted attributes to be set in directories
where one of the files had an rsync phase 1 retry during
an incremental. Reported by Tony Nelson.
processing by BackupPC_link, embedded newlines in the file's path
will cause problems which are avoided by mangling.
- The CGI script undoes the mangling, so it is invisibe to the user.
+ The CGI script undoes the mangling, so it is invisible to the user.
Of course, old (unmangled) backups are still supported by the CGI
interface.
{
my $nSkip = 0;
- foreach my $host ( sort(HostSortCompare keys(%$Hosts)) ) {
+ foreach my $host ( sort HostSortCompare keys(%$Hosts) ) {
$nSkip++ if ( QueueOnePC($host, $host, 'BackupPC', 'bg', 'auto') == 2 );
}
foreach my $dhcp ( @{$Conf{DHCPAddressRanges}} ) {
|| !defined($p->{hourBegin})
|| !defined($p->{hourEnd})
);
+ my $matchWday = $wday;
if ( $p->{hourBegin} > $p->{hourEnd} ) {
$blackout = $p->{hourBegin} <= $currHours
|| $currHours <= $p->{hourEnd};
# weekday check (eg: Monday 11pm-1am means Monday 2300 to
# Tuesday 0100, not Monday 2300-2400 plus Monday 0000-0100).
#
- $wday--;
- $wday += 7 if ( $wday < 0 );
+ $matchWday--;
+ $matchWday += 7 if ( $matchWday < 0 );
}
} else {
$blackout = $p->{hourBegin} <= $currHours
&& $currHours <= $p->{hourEnd};
}
- if ( $blackout && grep($_ == $wday, @{$p->{weekDays}}) ) {
+ if ( $blackout && grep($_ == $matchWday, @{$p->{weekDays}}) ) {
# print(LOG $bpc->timeStamp, "skipping because of blackout"
# . " (alive $StatusHost{aliveCnt} times)\n");
print(STDERR "Skipping $client because of blackout\n")
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 10 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
$CurrDumpDir = "$Dir/$Backups[$num]{num}";
$Compress = $Backups[$num]{compress};
if ( open(NEW, "<", "$Dir/NewFileList.$Backups[$num]{num}") ) {
+ my(@shareAttribArgs);
binmode(NEW);
while ( <NEW> ) {
chomp;
next if ( !/(\w+) (\d+) (.*)/ );
- LinkNewFile($1, $2, "$CurrDumpDir/$3");
+ if ( $3 eq "attrib" ) {
+ #
+ # Defer linking top-level attrib file until the end
+ # since it can appear multiple times when multiple shares
+ # are dumped.
+ #
+ @shareAttribArgs = ($1, $2, "$CurrDumpDir/$3");
+ } else {
+ LinkNewFile($1, $2, "$CurrDumpDir/$3");
+ }
}
+ LinkNewFile(@shareAttribArgs) if ( @shareAttribArgs );
close(NEW);
}
unlink("$Dir/NewFileList.$Backups[$num]{num}")
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 10 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
use Data::Dumper;
use Getopt::Std;
use DirHandle ();
-use vars qw($Lang $TopDir $BinDir $LogDir %Conf);
+use vars qw($Lang $TopDir $BinDir $LogDir %Conf $Hosts);
die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
$TopDir = $bpc->TopDir();
$BinDir = $bpc->BinDir();
%Conf = $bpc->Conf();
$Lang = $bpc->Lang();
+$Hosts = $bpc->HostInfoRead();
$bpc->ChildInit();
exit(1);
}
+#
+# Upgrade legacy version of %UserEmailInfo
+#
+# Prior to 3.2.0, it was a hash with entries:
+#
+# $UserEmailInfo{$user}{lastTime}
+# $UserEmailInfo{$user}{lastSubj}
+# $UserEmailInfo{$user}{lastHost}
+#
+# However, if a user had multiple hosts, then an email about one
+# host prevents mail delivery about other hosts. Starting in 3.2.0
+# the hash is:
+#
+# $UserEmailInfo{$user}{$host}{lastTime}
+# $UserEmailInfo{$user}{$host}{lastSubj}
+#
+my $oldFormat = 0;
+foreach my $user ( keys(%UserEmailInfo) ) {
+ if ( defined($UserEmailInfo{$user}{lastTime})
+ && ref($UserEmailInfo{$user}{lastTime}) ne 'HASH' ) {
+ $oldFormat = 1;
+ last;
+ }
+}
+if ( $oldFormat ) {
+ #
+ # Convert to the new format
+ #
+ my %UserEmailInfoOld = %UserEmailInfo;
+ %UserEmailInfo = ();
+ foreach my $user ( keys(%UserEmailInfoOld) ) {
+ next if ( $user eq "" );
+ my $host = $UserEmailInfoOld{$user}{lastHost};
+ next if ( !defined($host) );
+ $UserEmailInfo{$user}{$host}{lastTime} = $UserEmailInfoOld{$user}{lastTime};
+ $UserEmailInfo{$user}{$host}{lastSubj} = $UserEmailInfoOld{$user}{lastSubj};
+ }
+}
+
+#
+# Prune hosts that no longer exist
+#
+foreach my $user ( keys(%UserEmailInfo) ) {
+ foreach my $host ( keys(%{$UserEmailInfo{$user}}) ) {
+ next if ( defined($Hosts->{$host}) );
+ delete($UserEmailInfo{$user}{$host});
+ }
+ next if ( $UserEmailInfo{$user} );
+ delete($UserEmailInfo{$user});
+}
+
my $err = $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort});
if ( $err ) {
if ( $opts{c} && $Conf{EMailAdminUserName} ne "" ) {
###########################################################################
# Generate per-host warning messages sent to each user
###########################################################################
-my $Hosts = $bpc->HostInfoRead();
my @AdminBadHosts = ();
foreach my $host ( sort(keys(%Status)) ) {
%Conf = $bpc->Conf();
my $user = $Hosts->{$host}{user};
+ next if ( $user eq "" );
+
#
# Accumulate host errors for the admin email below
#
push(@AdminBadHosts, "$host ($Status{$host}{error})");
}
- next if ( time - $UserEmailInfo{$user}{lastTime}
+ next if ( time - $UserEmailInfo{$user}{$host}{lastTime}
< $Conf{EMailNotifyMinDays} * 24*3600
|| $Conf{XferMethod} eq "archive"
|| $Conf{BackupsDisable}
$vars->{subj} = encode('MIME-Header', $subj);
$mesg =~ s/\$(\w+)/defined($vars->{$1}) ? $vars->{$1} : "\$$1"/eg;
SendMail($mesg);
- $UserEmailInfo{$user}{lastTime} = time;
- $UserEmailInfo{$user}{lastSubj} = $subj;
- $UserEmailInfo{$user}{lastHost} = $host;
+ $UserEmailInfo{$user}{$host}{lastTime} = time;
+ $UserEmailInfo{$user}{$host}{lastSubj} = $subj;
}
sub SendMail
# -t print summary totals
# -r pathRemove path prefix that will be replaced with pathAdd
# -p pathAdd new path prefix
-# -b BLOCKS BLOCKS x 512 bytes per record (default 20; same as tar)
-# -w writeBufSz write buffer size (default 1MB)
+# -b BLOCKS output write buffer size in 512-byte blocks (default 20; same as tar)
+# -w readBufSz buffer size for reading files (default 1048576 = 1MB)
# -e charset charset for encoding file names (default: value of
# $Conf{ClientCharset} when backup was done)
# -l just print a file listing; don't generate an archive
-t print summary totals
-r pathRemove path prefix that will be replaced with pathAdd
-p pathAdd new path prefix
- -b BLOCKS BLOCKS x 512 bytes per record (default 20; same as tar)
- -w writeBufSz write buffer size (default 1048576 = 1MB)
+ -b BLOCKS output write buffer size in 512-byte blocks (default 20; same as tar)
+ -w readBufSz buffer size for reading files (default 1048576 = 1MB)
-e charset charset for encoding file names (default: value of
\$Conf{ClientCharset} when backup was done)
-l just print a file listing; don't generate an archive
$hdr->{size} = 0;
TarWriteFileInfo($fh, $hdr);
$SpecialCnt++;
+ } elsif ( $hdr->{type} == BPC_FTYPE_SOCKET
+ || $hdr->{type} == BPC_FTYPE_UNKNOWN ) {
+ #
+ # ignore these two file types - these are dynamic file types created
+ # by applications as needed
+ #
} else {
print(STDERR "Got unknown type $hdr->{type} for $hdr->{name}\n");
$ErrorCnt++;
#
$Conf{FtpPasswd} = '';
+#
+# Whether passive mode is used. The correct setting depends upon
+# whether local or remote ports are accessible from the other machine,
+# which is affected by any firewall or routers between the FTP server
+# on the client and the BackupPC server.
+#
+# This setting is used only if $Conf{XferMethod} = 'ftp'.
+#
+$Conf{FtpPassive} = 1;
+
#
# Transfer block size. This sets the size of the amounts of data in
# each frame. While undefined, this value takes the default value.
#
$Conf{FtpFollowSymlinks} = 0;
-#
-# Direct restore enabling for FTP.
-#
-# Currently set to 0 since restore functionality is incomplete.
-#
-$Conf{FtpRestoreEnabled} = 0;
-
###########################################################################
# Archive Configuration
# (can be overwritten in the per-PC log file)
$fd->read(\$newData, 65536);
$data .= $newData;
}
- (
- @{$a->{files}{$fileName}}{@FldsUnixW},
- @{$a->{files}{$fileName}}{@FldsUnixN},
- $data
- ) = unpack("w$nFldsW N$nFldsN a*", $data);
+ eval {
+ (
+ @{$a->{files}{$fileName}}{@FldsUnixW},
+ @{$a->{files}{$fileName}}{@FldsUnixN},
+ $data
+ ) = unpack("w$nFldsW N$nFldsN a*", $data);
+ };
+ if ( $@ ) {
+ $a->{_errStr} = "unpack: Can't read attributes for $fileName from $file ($@)";
+ $fd->close;
+ return;
+ }
if ( $a->{files}{$fileName}{$FldsUnixN[-1]} eq "" ) {
$a->{_errStr} = "Can't read attributes for $fileName"
. " from $file";
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 5 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
{name => "FtpPasswd",
visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpPassive",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
{name => "FtpBlockSize",
visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
{name => "FtpPort",
visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
{name => "FtpFollowSymlinks",
visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
- {name => "FtpRestoreEnabled",
- visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
### Archive Settings
if ( $level == 0 ) {
my $lcVarName = lc($varName);
$content .= <<EOF;
-<tr><td class="border"><a href="?action=view&type=docs#item__conf_${lcVarName}_">$varName</a>
+<tr><td class="border"><a href="?action=view&type=docs#_conf_${lcVarName}_">$varName</a>
EOF
if ( defined($overrideVar) ) {
my $override_checked = "";
my $value = $dump->Dump;
$value =~ s/\n/\\n/g;
$value =~ s/\r/\\r/g;
+ if ( $p =~ /Passwd/ || $p =~ /Secret/ ) {
+ $value = "'*'";
+ }
+
$mesg .= eval("qq($Lang->{CfgEdit_Log_Add_param_value})");
} else {
my $dump = Data::Dumper->new([$newConf->{$p}]);
$valueOld =~ s/\n/\\n/g;
$valueNew =~ s/\r/\\r/g;
$valueOld =~ s/\r/\\r/g;
+ if ( $p =~ /Passwd/ || $p =~ /Secret/ ) {
+ $valueNew = "'*'";
+ $valueOld = "'*'";
+ }
$mesg .= eval("qq($Lang->{CfgEdit_Log_Change_param_value})");
}
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 10 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
ReadUserEmailInfo();
my(%EmailStr, $str);
foreach my $u ( keys(%UserEmailInfo) ) {
- next if ( !defined($UserEmailInfo{$u}{lastTime}) );
- my $emailTimeStr = timeStamp2($UserEmailInfo{$u}{lastTime});
- $EmailStr{$UserEmailInfo{$u}{lastTime}} .= <<EOF;
+ my $info;
+ if ( defined($UserEmailInfo{$u}{lastTime})
+ && ref($UserEmailInfo{$u}{lastTime}) ne 'HASH' ) {
+ #
+ # old format $UserEmailInfo - pre 3.2.0.
+ #
+ my $host = $UserEmailInfo{$u}{lastHost};
+ $info = {
+ $host => {
+ lastTime => $UserEmailInfo{$u}{lastTime},
+ lastSubj => $UserEmailInfo{$u}{lastSubj},
+ },
+ };
+ } else {
+ $info = $UserEmailInfo{$u};
+ }
+ foreach my $host ( keys(%$info) ) {
+ next if ( !defined($info->{$host}{lastTime}) );
+ my $emailTimeStr = timeStamp2($info->{$host}{lastTime});
+ $EmailStr{$info->{$host}{lastTime}} .= <<EOF;
<tr><td>${UserLink($u)} </td>
- <td>${HostLink($UserEmailInfo{$u}{lastHost})} </td>
+ <td>${HostLink($host)} </td>
<td>$emailTimeStr </td>
- <td>$UserEmailInfo{$u}{lastSubj} </td></tr>
+ <td>$info->{$host}{lastSubj} </td></tr>
EOF
+ }
}
foreach my $t ( sort({$b <=> $a} keys(%EmailStr)) ) {
$str .= $EmailStr{$t};
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 5 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
if ( $user ne "" ) {
$statusStr .= eval("qq{$Lang->{This_PC_is_used_by}$moreUserStr}");
}
- if ( defined($UserEmailInfo{$user})
+ if ( defined($UserEmailInfo{$user}) && defined($UserEmailInfo{$user}{$host}) ) {
+ my $mailTime = timeStamp2($UserEmailInfo{$user}{$host}{lastTime});
+ my $subj = $UserEmailInfo{$user}{$host}{lastSubj};
+ $statusStr .= eval("qq{$Lang->{Last_email_sent_to__was_at___subject}}");
+ } elsif ( defined($UserEmailInfo{$user})
&& $UserEmailInfo{$user}{lastHost} eq $host ) {
+ #
+ # Old format %UserEmailInfo - pre 3.2.0.
+ #
my $mailTime = timeStamp2($UserEmailInfo{$user}{lastTime});
my $subj = $UserEmailInfo{$user}{lastSubj};
$statusStr .= eval("qq{$Lang->{Last_email_sent_to__was_at___subject}}");
Trailer();
exit(1);
} else {
- ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"));
+ ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"),
+ eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server_error_message}}"));
}
}
}
<html><head>
<title>$title</title>
<link rel=stylesheet type="text/css" href="$Conf{CgiImageDirURL}/$Conf{CgiCSSFile}" title="CSSFile">
+<link rel=icon href="$Conf{CgiImageDirURL}/favicon.ico" type="image/x-icon">
$Conf{CgiHeaders}
<script src="$Conf{CgiImageDirURL}/sorttable.js"></script>
</head><body onLoad="document.getElementById('NavMenu').style.height=document.body.scrollHeight">
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 5 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
},
FtpUserName => "string",
FtpPasswd => "string",
+ FtpPassive => "boolean",
FtpBlockSize => "integer",
FtpPort => "integer",
FtpTimeout => "integer",
FtpFollowSymlinks => "boolean",
- FtpRestoreEnabled => "boolean",
######################################################################
# Archive Configuration
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Kann keine Verbindung zu dem BackupPC Server herstellen!",
- "Dieses CGI Script (\$MyURL) kann keine Verbindung zu dem BackupPC"
- . " Server auf \$Conf{ServerHost} Port \$Conf{ServerPort} herstellen. Der Fehler"
- . " war: \$err.",
- "Möglicherweise ist der BackupPC Server Prozess nicht gestartet oder es besteht ein"
- . " Konfigurationsfehler. Bitte teilen Sie diese Fehlermeldung dem Systemadministrator mit.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Kann keine Verbindung zu dem BackupPC Server herstellen!";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+Dieses CGI Script (\$MyURL) kann keine Verbindung zu dem BackupPC Server
+auf \$Conf{ServerHost} Port \$Conf{ServerPort} herstellen.<br>
+Der Fehler war: \$err.<br>
+Möglicherweise ist der BackupPC Server Prozess nicht gestartet oder es besteht ein
+Konfigurationsfehler. Bitte teilen Sie diese Fehlermeldung dem Systemadministrator mit.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Unable to connect to BackupPC server",
- "This CGI script (\$MyURL) is unable to connect to the BackupPC"
- . " server on \$Conf{ServerHost} port \$Conf{ServerPort}. The error"
- . " was: \$err.",
- "Perhaps the BackupPC server is not running or there is a "
- . " configuration error. Please report this to your Sys Admin.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Unable to connect to BackupPC server";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+This CGI script (\$MyURL) is unable to connect to the BackupPC
+server on \$Conf{ServerHost} port \$Conf{ServerPort}.<br>
+The error was: \$err.<br>
+Perhaps the BackupPC server is not running or there is a configuration error.
+Please report this to your Sys Admin.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
Dear $userName,
Your PC ($host) has not been successfully backed up for $days days.
-Your PC has been correctly backed up $numBackups times from $firstTime to $days
+Your PC has been correctly backed up $numBackups times from $firstTime to $days days
ago. PC backups should occur automatically when your PC is connected
to the network.
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Imposible conectar al servidor BackupPC",
- "Este script CGI (\$MyURL) no puede conectar al servidor BackupPC"
- . " en \$Conf{ServerHost} puerto \$Conf{ServerPort}. El error"
- . " fué: \$err.",
- "Quizá el servidor BackupPC no está activo o hay un "
- . " error de configuración. Por favor informe a su administrador de sistemas.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Imposible conectar al servidor BackupPC";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+Este script CGI (\$MyURL) no puede conectar al servidor BackupPC
+en \$Conf{ServerHost} puerto \$Conf{ServerPort}.<br>
+El error fué: \$err.<br>
+Quizá el servidor BackupPC no está activo o hay un
+error de configuración. Por favor informe a su administrador de sistemas.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Impossible de se connecter au serveur BackupPC",
- "Ce script CGI (\$MyURL) est incapable de se connecter au serveur BackupPC"
- . " sur \$Conf{ServerHost} au port \$Conf{ServerPort}. L'erreur"
- . " est: \$err."
- . " Il est possible que le serveur BackupPC ne fonctionne pas actuellement ou qu'il"
- . " y ait une erreur de configuration. Veuillez contacter votre administrateur système.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Impossible de se connecter au serveur BackupPC";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+Ce script CGI (\$MyURL) est incapable de se connecter au serveur BackupPC
+sur \$Conf{ServerHost} au port \$Conf{ServerPort}.<br>
+L'erreur est: \$err.<br>
+Il est possible que le serveur BackupPC ne fonctionne pas actuellement ou qu'il
+y ait une erreur de configuration. Veuillez contacter votre administrateur système.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
<ul>
<li> Le PID du serveur est \$Info{pid}, sur l\'hôte \$Conf{ServerHost},
version \$Info{Version}, démarré le \$serverStartTime.
-<li> Ce rapport à été généré le \$now.
+<li> Ce rapport a été généré le \$now.
<li> La configuration a été chargée pour la dernière fois à \$configLoadTime.
<li> La prochaine file d\'attente sera remplie à \$nextWakeupTime.
<li> Autres infos:
\$poolInfo
<li>L\'espace de stockage a été récemment rempli à \$Info{DUlastValue}%
(\$DUlastTime), le maximum aujourd\'hui a été de \$Info{DUDailyMax}% (\$DUmaxTime)
- et hier le maximum était \$Info{DUDailyMaxPrev}%.
+ et hier le maximum était de \$Info{DUDailyMaxPrev}%.
</ul>
</ul>
EOF
<li>Ce statut a été généré le \$now.
<li>L\'espace de stockage a été récemment rempli à \$Info{DUlastValue}%
(\$DUlastTime), le maximum aujourd\'hui a été de \$Info{DUDailyMax}% (\$DUmaxTime)
- et hier le maximum était \$Info{DUDailyMaxPrev}%.
+ et hier le maximum était de \$Info{DUDailyMaxPrev}%.
</ul>
</p>
$Lang{BackupPC__Start_Backup_Confirm_on__host} = "BackupPC: Confirmation du démarrage de la sauvegarde de \$host";
# --------------------------------
$Lang{Are_you_sure_start} = <<EOF;
-\${h1("Êtes vous certain ?")}
+\${h1("Êtes-vous certain ?")}
<p>
Vous allez bientôt démarrer une sauvegarde \$type depuis \$host.
# --------------------------------
$Lang{Are_you_sure_stop} = <<EOF;
-\${h1("Êtes vous certain ?")}
+\${h1("Êtes-vous certain ?")}
<p>
Vous êtes sur le point d\'arrêter/supprimer de la file les sauvegardes de \$host;
$Lang{Restore_Confirm_on__host} = "BackupPC: Confirmation de restauration sur \$host";
$Lang{Are_you_sure} = <<EOF;
-\${h1("Êtes-vous sur ?")}
+\${h1("Êtes-vous sûr ?")}
<p>
Vous êtes sur le point de démarrer une restauration directement sur
la machine \$In{hostDest}. Les fichiers suivants vont être restaurés
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Impossibile connettersi al server BackupPC",
- "Questo script CGI (\$MyURL) non è in grado di connettersi al server"
- . " BackupPC su \$Conf{ServerHost} alla porta \$Conf{ServerPort}. L'errore è:"
- . " \$err.",
- "Forse il server BackupPC non è in esecuzione o c'è un errore"
- . " nella configurazione. Contattare l'amministratore di sistema.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Impossibile connettersi al server BackupPC";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+Questo script CGI (\$MyURL) non è in grado di connettersi al server
+BackupPC su \$Conf{ServerHost} alla porta \$Conf{ServerPort}.<br>
+L'errore è: \$err.<br>
+Forse il server BackupPC non è in esecuzione o c'è un errore
+nella configurazione. Contattare l'amministratore di sistema.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Verbinding met de BackupPC server is mislukt",
- "Dit CGI script (\$MyURL) kon geen verbinding maken met de BackupPC-server"
- . " op \$Conf{ServerHost} poort \$Conf{ServerPort}."
- . " De foutmelding was: \$err.",
- "Mogelijk draait de BackupPC server niet of is er een "
- . " configuratiefout. Gelieve dit te melden aan uw systeembeheerder.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Verbinding met de BackupPC server is mislukt";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+Dit CGI script (\$MyURL) kon geen verbinding maken met de BackupPC-server
+op \$Conf{ServerHost} poort \$Conf{ServerPort}.<br>
+De foutmelding was: \$err.<br>
+Mogelijk draait de BackupPC server niet of is er een
+configuratiefout. Gelieve dit te melden aan uw systeembeheerder.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
#my %lang;
#use strict;
+use utf8;
# --------------------------------
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Nie można połączyć się z serwerem BackupPC",
- "Ten skrypt CGI (\$MyURL) nie może połączyć się z BackupPC"
- . " serwer na \$Conf{ServerHost} porcie \$Conf{ServerPort}. Błąd"
- . " to: \$err.",
- "Możliwe ,że serwer BackupPC nie jest uruchomiony albo że występuje "
- . " błąd w konfiguracji. Proszę powiadomić o tym swojego Administratora.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Nie można połączyć się z serwerem BackupPC";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+Ten skrypt CGI (\$MyURL) nie może połączyć się z BackupPC
+serwer na \$Conf{ServerHost} porcie \$Conf{ServerPort}.<br>
+Błąd to: \$err.<br>
+Możliwe ,że serwer BackupPC nie jest uruchomiony albo że występuje
+błąd w konfiguracji. Proszę powiadomić o tym swojego Administratora.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "Impossível conectar ao servidor BackupPC",
- "Este script CGI (\$MyURL) não pode conectar-se ao servidor BackupPC"
- . " em \$Conf{ServerHost} porta \$Conf{ServerPort}. O erro"
- . " foi: \$err.",
- "Talvez o servidor BackupPC não esteja ativo ou há um "
- . " erro de configuração. Por favor informe o administrador do sistema.";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "Impossível conectar ao servidor BackupPC";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+Este script CGI (\$MyURL) não pode conectar-se ao servidor BackupPC
+em \$Conf{ServerHost} porta \$Conf{ServerPort}.<br>
+O erro foi: \$err.<br>
+Talvez o servidor BackupPC não esteja ativo ou há um
+erro de configuração. Por favor informe o administrador do sistema.
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
</ul>
-->
EOF
-$Lang{Unable_to_connect_to_BackupPC_server} = "无法连接到 BackupPC 服务器",
- "CGI 脚本程序 (\$MyURL) 无法连接到 BackupPC 服务器 \$Conf{ServerHost} 端口 \$Conf{ServerPort}。错误信息:\$err。",
- "可能 BackupPC 服务器没有运行,或者服务器配置不正确。请通知网络系统管理员。";
+
+$Lang{Unable_to_connect_to_BackupPC_server} = "无法连接到 BackupPC 服务器";
+$Lang{Unable_to_connect_to_BackupPC_server_error_message} = <<EOF;
+CGI 脚本程序 (\$MyURL) 无法连接到 BackupPC 服务器 \$Conf{ServerHost} 端口 \$Conf{ServerPort}。错误信息:\$err。
+可能 BackupPC 服务器没有运行,或者服务器配置不正确。请通知网络系统管理员。
+<br><br>
+EOF
+
$Lang{Admin_Start_Server} = <<EOF;
\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
<form action="\$MyURL" method="get">
# Read host config file
#
if ( $host ne "" ) {
- ($mesg, $config) = $bpc->{storage}->ConfigDataRead($host);
+ ($mesg, $config) = $bpc->{storage}->ConfigDataRead($host, $config);
return $mesg if ( defined($mesg) );
- $bpc->{Conf} = { %{$bpc->{Conf}}, %$config };
+ $bpc->{Conf} = $config;
}
#
# Merge variables into @cmd
#
foreach my $arg ( @$template ) {
+ #
+ # Replace $VAR with ${VAR} so that both types of variable
+ # substitution are supported
+ #
+ $arg =~ s[\$(\w+)]{\${$1}}g;
#
# Replace scalar variables first
#
- $arg =~ s{\$(\w+)(\+?)}{
+ $arg =~ s[\${(\w+)}(\+?)]{
exists($vars->{$1}) && ref($vars->{$1}) ne "ARRAY"
? ($2 eq "+" ? $bpc->shellEscape($vars->{$1}) : $vars->{$1})
- : "\$$1$2"
+ : "\${$1}$2"
}eg;
#
# Now replicate any array arguments; this just works for just one
# array var in each argument.
#
- if ( $arg =~ m{(.*)\$(\w+)(\+?)(.*)} && ref($vars->{$2}) eq "ARRAY" ) {
+ if ( $arg =~ m[(.*)\${(\w+)}(\+?)(.*)] && ref($vars->{$2}) eq "ARRAY" ) {
my $pre = $1;
my $var = $2;
my $esc = $3;
#
unlink($fileName) if ( -f $fileName );
if ( $fileName =~ m{(.*)/.+} && !-d $1 ) {
- eval { mkpath($1, 0, 0777) };
+ my $newDir = $1;
+ eval { mkpath($newDir, 0, 0777) };
if ( $@ ) {
- push(@{$self->{errors}}, "Unable to create directory $1 for $self->{fileName}");
+ push(@{$self->{errors}}, "Unable to create directory $newDir for $self->{fileName}");
}
}
return $self;
sub ConfigDataRead
{
- my($s, $host) = @_;
+ my($s, $host, $prevConfig) = @_;
my($ret, $mesg, $config, @configs);
#
# TODO: add lock
#
- my $conf = {};
+ my $conf = $prevConfig || {};
my $configPath = $s->ConfigPath($host);
push(@configs, $configPath) if ( -f $configPath );
foreach $config ( @configs ) {
- %Conf = ();
+ %Conf = %$conf;
if ( !defined($ret = do $config) && ($! || $@) ) {
$mesg = "Couldn't open $config: $!" if ( $! );
$mesg = "Couldn't execute $config: $@" if ( $@ );
$mesg =~ s/[\n\r]+//;
return ($mesg, $conf);
}
- %$conf = ( %$conf, %Conf );
+ %$conf = %Conf;
}
#
return;
} elsif ( $conf->{XferMethod} eq "ftp" ) {
- return !!( $conf->{FtpRestoreEnabled} );
+ return;
} elsif ( $conf->{XferMethod} eq "rsync"
|| $conf->{XferMethod} eq "rsyncd"
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 5 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
#========================================================================
-
package BackupPC::Xfer::Ftp;
use strict;
: Net::FTP->new(%$args);
};
if ($@) {
- $t->{_errStr} = "Can't open connection to $args->{host}: $!";
+ $t->{_errStr} = "Can't open connection to $args->{Host}: $!";
$t->{xferErrCnt}++;
return;
}
+ $t->logWrite("Connected to $args->{Host}\n", 2);
#
# Log in to the ftp server and set appropriate path information.
undef $@;
eval { $t->{ftp}->login( $conf->{FtpUserName}, $conf->{FtpPasswd} ); };
if ( $@ ) {
- $t->{_errStr} = "Can't login to $args->{host}: $!";
+ $t->{_errStr} = "Can't login to $args->{Host}: $!";
$t->{xferErrCnt}++;
return;
}
+ $t->logWrite("Login successful to $conf->{FtpUserName}\@$args->{Host}\n", 2);
undef $@;
eval { $t->{ftp}->binary(); };
if ($@) {
$t->{_errStr} =
- "Can't enable binary transfer mode to $args->{host}: $!";
+ "Can't enable binary transfer mode to $args->{Host}: $!";
$t->{xferErrCnt}++;
return;
}
+ $t->logWrite("Binary command successful\n", 2);
undef $@;
eval { $t->{shareName} =~ m/^\.?$/ || $t->{ftp}->cwd( $t->{shareName} ); };
$t->{xferErrCnt}++;
return;
}
+ $t->logWrite("Set cwd to $t->{shareName}\n", 2);
undef $@;
eval { $t->{sharePath} = $t->{ftp}->pwd(); };
$t->{xferErrCnt}++;
return;
}
+ $t->logWrite("Pwd returned as $t->{sharePath}\n", 2);
#
# log the beginning of action based on type
if ( $t->{type} eq 'restore' ) {
$t->restore();
- $logMsg = "Restore of $t->{host} complete";
+ $logMsg = "Restore of $t->{host} "
+ . ($t->{xferOK} ? "complete" : "failed");
} elsif ( $t->{type} eq 'incr' ) {
$t->backup();
- $logMsg = "Incremental backup of $t->{host} complete";
+ $logMsg = "Incremental backup of $t->{host} "
+ . ($t->{xferOK} ? "complete" : "failed");
} elsif ( $t->{type} eq 'full' ) {
$t->backup();
- $logMsg = "Full backup of $t->{host} complete";
+ $logMsg = "Full backup of $t->{host} "
+ . ($t->{xferOK} ? "complete" : "failed");
}
delete $t->{_errStr};
$t->{xferErrCnt}++;
return;
}
+ $t->logWrite("Created output directory $OutDir\n", 3);
#
# determine the filetype of the shareName and back it up
FirewallType => undef, # not used
BlockSize => $conf->{FtpBlockSize} || 10240,
Port => $conf->{FtpPort} || 21,
- Timeout => $conf->{FtpTimeout} || 120,
- Debug => 0, # do not touch
- Passive => 1, # do not touch
+ Timeout => defined($conf->{FtpTimeout}) ? $conf->{FtpTimeout} : 120,
+ Debug => $t->{logLevel} >= 10 ? 1 : 0,
+ Passive => defined($conf->{FtpPassive}) ? $conf->{FtpPassive} : 1,
Hash => undef, # do not touch
- LocalAddr => "localhost", # do not touch
};
}
-
#
# usage:
# $dirList = $t->remotels($path);
my ( $dirContents, $remoteDir, $f );
+ $remoteDir = [];
undef $@;
+ $t->logWrite("remotels: about to list $path\n", 4);
eval {
$dirContents = ( $path =~ /^\.?$/ ) ? $ftp->dir()
: $ftp->dir("$path/");
};
if ($@) {
$t->{xferErrCnt}++;
+ $t->logWrite("remotels: can't retrieve remote directory contents of $path: $!\n", 1);
return "can't retrieve remote directory contents of $path: $!";
}
+ if ( $t->{logLevel} >= 4 ) {
+ my $str = join("\n", @$dirContents);
+ $t->logWrite("remotels: got dir() result:\n$str\n", 4);
+ }
foreach my $info ( @{parse_dir($dirContents)} ) {
mode => $info->[4],
};
+ $t->logWrite("remotels: adding name $f->{name}, type $f->{type}, size $f->{size}, mode $f->{mode}\n", 4);
+
$f->{utf8name} = $f->{name};
from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" )
if ( $conf->{ClientCharset} ne "" );
}
}
+ $t->logWrite("handleDir: dir->relPath = $dir->{relPath}, OutDir = $OutDir\n", 4);
+
$attrib = BackupPC::Attrib->new( { compress => $t->{compress} } );
$remoteDir = $t->remotels( $dir->{relPath} );
+ if ( ref($remoteDir) ne 'ARRAY' ) {
+ $t->logWrite("handleDir failed: $remoteDir\n", 1);
+ $t->logFileAction( "fail", $dir->{utf8name}, $dir );
+ return;
+ }
+
if ( $t->{type} eq "incr" ) {
$localDir = $view->dirAttrib( $t->{incrBaseBkupNum},
$t->{shareName}, $dir->{relPath} );
$poolFile = $OutDir . "/" . $bpc->fileNameMangle( $f->{name} );
$poolWrite = BackupPC::PoolWrite->new( $bpc, $poolFile, $f->{size},
$t->{compress} );
-
$localSize = 0;
undef $@;
if ( !*FTP || $@ || @$errs ) {
$t->logFileAction( "fail", $f->{utf8name}, $attribInfo );
+ $t->logWrite("Unlinking($poolFile) because of error on close\n", 3);
unlink($poolFile);
$t->{xferBadFileCnt}++;
$stats->{errCnt} += scalar @$errs;
#
if ( $localSize != $f->{size} ) {
$t->logFileAction( "fail", $f->{utf8name}, $attribInfo );
+ $t->logWrite("Unlinking($poolFile) because of size mismatch ($localSize vs $f->{size})\n", 3);
unlink($poolFile);
$stats->{xferBadFileCnt}++;
$stats->{errCnt}++;
#
#========================================================================
#
-# Version 3.2.0beta0, released 5 April 2009.
+# Version 3.2.0beta1, released 5 Jan 2010.
#
# See http://backuppc.sourceforge.net.
#
pipeRH => undef,
pipeWH => undef,
badFiles => [],
+ logLevel => $bpc->{Conf}{XferLogLevel},
#
# Various stats
my %ConfName;
my $ConfPod = config2pod();
+
rmtree("doc", 0, 0);
mkpath("doc", 0, 0777);
InstallFile("doc-src/BackupPC.pod", "doc/BackupPC.pod");
foreach my $file ( (@PerlSrc,
<images/*.gif>,
<images/*.png>,
+ <images/*.ico>,
qw(
conf/config.pl
conf/hosts
my($file, $dest) = @_;
unlink($dest) if ( -d $dest );
- if ( $file =~ /\.gif/ || $file =~ /\.png/ ) {
+ if ( $file =~ /\.gif/ || $file =~ /\.png/ || $file =~ /\.ico/ ) {
die("can't copy($file, $dest)\n") unless copy($file, $dest);
} else {
open(FILE, $file) || die("can't open $file for reading\n");
#
# fixup for conf links
#
- if ( !/A NAME="item_(%|_)conf/i ) {
+ if ( !/a name="_conf/i ) {
s/\$Conf{([^}]*)}/
defined($ConfName{$1})
- ? "\L<a href=\"#$ConfName{$1}\">\E\$Conf{$1}<\/A>"
+ ? "\L<a href=\"#$ConfName{$1}\">\E\$Conf{$1}<\/a>"
: "\$Conf{$1}"/eg;
}
s/^<DD>/<DD><P>/;
push(@conf, $_);
my $text = "_conf_${var}_";
$text =~ s{[\W\s]}{_}g;
- $ConfName{$var} = "item_$text";
+ $ConfName{$var} = "$text";
} elsif ( /^$/ ) {
if ( $str ne "" && @conf ) {
$out .= "=item " . join("\n\n=item ", @conf) . "\n\n";