From 1a2fa2c2a1e0db12dc788216d9f3ba73301a131f Mon Sep 17 00:00:00 2001 From: cbarratt Date: Fri, 21 May 2004 02:11:34 +0000 Subject: [PATCH] * On the phase 2 retry pass with rsync, verify the cached checksums if checksum caching is turned on. This will catch the case of cached checksums being incorrectly appended to the compressed pool file. Added new config parameter $Conf{RsyncCsumCacheVerifyProb} so that cached checksums are verified with a selectable probability. Also, increased File::RsyncP version number to 0.51. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * configure.pl now supports an optional batch mode. Command-line options are used to specify all the information that configure.pl needs. This is useful for buidling auto-install packages. Also, configure.pl now includes pod documentation, so you can do "perldoc configure.pl" to see all the command-line options. Suggested, tested and tweaked by Stuart Herbert for possible Gentoo inclusion. * At each wakeup, clients are now queued based on how old the most recent backup is. Clients with errors are queued first, with the oldest error times going first. Clients with good backups are queued next, with the oldest backup going first. Previously the clients were simply queued in alphabetic order. Suggested by Tony Nelson. * Added config parameter $Conf{PartialAgeMax} that controls whether partials are saved at all, and if so, whether the partial will be ignored at the next full backup if it is too old. * BackupPC_tarExtract now allows empty archives without reporting an error. Reported by Don Silvia. * Removed Browse Backups link from Nav Bar in Archive Info display. Reported by Ralph Paßgang. * Fixed documentation display for regular users. Reported by Ralph Paßgang. * Status and PC Summary now work for regular users and only show that user's hosts. Server general status information only appears for admins. Suggested by Ralph Paßgang. * Moved the last three navigation-bar links (docs, FAQ and SF) to a new config parameter $Conf{CgiNavBarLinks}. This allows these links to be locally configured. Based on a patch submitted by Ralph Paßgang. * Allow the navigation bar search box to be disabled by setting $Conf{CgiSearchBoxEnable} to 0. Based on a patch submitted by Ralph Paßgang. * Updates to de.pm from Ralph Paßgang. * Made the BackupPC icon a link to the SF BackupPC project page. --- ChangeLog | 59 ++++- bin/BackupPC | 14 +- bin/BackupPC_dump | 17 +- bin/BackupPC_tarExtract | 21 +- cgi-bin/BackupPC_Admin | 2 - conf/config.pl | 73 +++++- configure.pl | 376 ++++++++++++++++++++++++++----- doc-src/BackupPC.pod | 150 ++++++------ lib/BackupPC/CGI/ArchiveInfo.pm | 2 +- lib/BackupPC/CGI/GeneralInfo.pm | 6 +- lib/BackupPC/CGI/HostInfo.pm | 13 +- lib/BackupPC/CGI/Lib.pm | 41 ++-- lib/BackupPC/CGI/Summary.pm | 5 +- lib/BackupPC/CGI/View.pm | 14 +- lib/BackupPC/Lang/de.pm | 221 +++++++++--------- lib/BackupPC/Lang/en.pm | 14 +- lib/BackupPC/Lang/es.pm | 194 ++++++++-------- lib/BackupPC/Lang/fr.pm | 14 +- lib/BackupPC/Lang/it.pm | 18 +- lib/BackupPC/Xfer/Rsync.pm | 5 +- lib/BackupPC/Xfer/RsyncDigest.pm | 294 ++++++++++++++++++------ lib/BackupPC/Xfer/RsyncFileIO.pm | 66 +++++- lib/BackupPC/Xfer/Smb.pm | 1 + makeDist | 9 +- 24 files changed, 1138 insertions(+), 491 deletions(-) diff --git a/ChangeLog b/ChangeLog index d372dba..ef5db9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,63 @@ # Version __VERSION__, __RELEASEDATE__ #------------------------------------------------------------------------ +** Add checksum caching info and file format to the docs. + +* On the phase 2 retry pass with rsync, verify the cached checksums + if checksum caching is turned on. This will catch the case of + cached checksums being incorrectly appended to the compressed + pool file. Added new config parameter $Conf{RsyncCsumCacheVerifyProb} + so that cached checksums are verified with a selectable probability. + Also, increased File::RsyncP version number to 0.51. + +* configure.pl now supports an optional batch mode. Command-line + options are used to specify all the information that configure.pl + needs. This is useful for buidling auto-install packages. + Also, configure.pl now includes pod documentation, so you can do + "perldoc configure.pl" to see all the command-line options. + Suggested, tested and tweaked by Stuart Herbert for possible + Gentoo inclusion. + +* At each wakeup, clients are now queued based on how old the most + recent backup is. Clients with errors are queued first, with + the oldest error times going first. Clients with good backups + are queued next, with the oldest backup going first. Previously + the clients were simply queued in alphabetic order. Suggested + by Tony Nelson. + +* Added config parameter $Conf{PartialAgeMax} that controls whether + partials are saved at all, and if so, whether the partial will be + ignored at the next full backup if it is too old. + +* BackupPC_tarExtract now allows empty archives without reporting + an error. Reported by Don Silvia. + +* Removed Browse Backups link from Nav Bar in Archive Info display. + Reported by Ralph Paßgang. + +* Fixed documentation display for regular users. Reported by Ralph Paßgang. + +* Status and PC Summary now work for regular users and only show + that user's hosts. Server general status information only appears + for admins. Suggested by Ralph Paßgang. + +* Moved the last three navigation-bar links (docs, FAQ and SF) to + a new config parameter $Conf{CgiNavBarLinks}. This allows + these links to be locally configured. Based on a patch + submitted by Ralph Paßgang. + +* Allow the navigation bar search box to be disabled by + setting $Conf{CgiSearchBoxEnable} to 0. Based on a patch + submitted by Ralph Paßgang. + +* Updates to de.pm from Ralph Paßgang. + +* Made the BackupPC icon a link to the SF BackupPC project page. + +#------------------------------------------------------------------------ +# Version 2.1.0beta1, 4 Apr 2004 +#------------------------------------------------------------------------ + * The CSS definition has been removed from the config.pl file and is now a separate file, BackupPC_stnd.css. A new config variable, $Conf{CgiCSSFile}, gives the name of the CSS file to use. @@ -41,7 +98,7 @@ Wayne Scott. * Allow several BackupPC_nightly processes to run in parallel based - on new $Conf{MaxBackupPCNightlyJobs} setting. This speeds up the + on new $Conf{BackupPCNightlyJobs} setting. This speeds up the traversal of the pool, reducing the overall run time for BackupPC_nightly. diff --git a/bin/BackupPC b/bin/BackupPC index 585eec1..3d86d96 100755 --- a/bin/BackupPC +++ b/bin/BackupPC @@ -1531,6 +1531,18 @@ sub StatusWrite } } +# +# Compare function for host sort. Hosts with errors go first, +# sorted with the oldest errors first. The remaining hosts +# are sorted so that those with the oldest backups go first. +# +sub HostSortCompare +{ + return -1 if ( $Status{$a}{error} ne "" && $Status{$b}{error} eq "" ); + return 1 if ( $Status{$a}{error} eq "" && $Status{$b}{error} ne "" ); + return $Status{$a}{endTime} <=> $Status{$b}{endTime}; +} + # # Queue all the hosts for backup. This means queuing all the fixed # ip hosts and all the dhcp address ranges. We also additionally @@ -1538,7 +1550,7 @@ sub StatusWrite # sub QueueAllPCs { - foreach my $host ( sort(keys(%$Hosts)) ) { + foreach my $host ( sort(HostSortCompare keys(%$Hosts)) ) { delete($Status{$host}{backoffTime}) if ( defined($Status{$host}{backoffTime}) && $Status{$host}{backoffTime} < time ); diff --git a/bin/BackupPC_dump b/bin/BackupPC_dump index 3ac9ebc..5ea4259 100755 --- a/bin/BackupPC_dump +++ b/bin/BackupPC_dump @@ -276,6 +276,7 @@ my $lastFull = 0; my $lastIncr = 0; my $partialIdx = -1; my $partialNum; +my $lastPartial = 0; if ( $Conf{FullPeriod} == -1 && !$opts{f} && !$opts{i} || $Conf{FullPeriod} == -2 ) { @@ -375,8 +376,9 @@ for ( my $i = 0 ; $i < @Backups ; $i++ ) { $lastIncr = $Backups[$i]{startTime} if ( $lastIncr < $Backups[$i]{startTime} ); } elsif ( $Backups[$i]{type} eq "partial" ) { - $partialIdx = $i; - $partialNum = $Backups[$i]{num}; + $partialIdx = $i; + $lastPartial = $Backups[$i]{startTime}; + $partialNum = $Backups[$i]{num}; } } @@ -444,10 +446,10 @@ if ( !defined($XferLOG) ) { } # -# Ignore the partial dump in the case of an incremental. -# A partial is a partial full. +# Ignore the partial dump in the case of an incremental +# or when the partial is too old. A partial is a partial full. # -if ( $type ne "full" ) { +if ( $type ne "full" || time - $lastPartial > $Conf{PartialAgeMax} * 24*3600 ) { $partialNum = undef; $partialIdx = -1; } @@ -1008,6 +1010,11 @@ sub BackupFailCleanup } } + # + # Don't keep partials if they are disabled + # + $keepPartial = 0 if ( $Conf{PartialAgeMax} < 0 ); + if ( !$keepPartial ) { # # No point in saving this dump; get rid of eveything. diff --git a/bin/BackupPC_tarExtract b/bin/BackupPC_tarExtract index fdef553..c18dc95 100755 --- a/bin/BackupPC_tarExtract +++ b/bin/BackupPC_tarExtract @@ -115,6 +115,7 @@ my $ExistFileSize = 0; my $ExistFileCompSize = 0; my $TotalFileCnt = 0; my $TotalFileSize = 0; +my $TarReadHdrCnt = 0; sub TarRead { @@ -128,6 +129,7 @@ sub TarRead substr($data, $numBytes, $totBytes - $numBytes), $totBytes - $numBytes); if ( $newBytes <= 0 ) { + return if ( $TarReadHdrCnt == 1 ); # empty tar file ok print("Unexpected end of tar archive (tot = $totBytes," . " num = $numBytes, posn = " . sysseek($fh, 0, 1) . ")\n"); $Abort = 1; @@ -144,6 +146,7 @@ sub TarReadHeader { my($fh) = @_; + $TarReadHdrCnt++; return $1 if ( TarRead($fh, $tar_header_length) =~ /(.*)/s ); return; } @@ -423,26 +426,30 @@ sub attributeWrite my $poolWrite = BackupPC::PoolWrite->new($bpc, $fileName, length($data), $Compress); $poolWrite->write(\$data); - processClose($poolWrite, $Attrib{$d}->fileName($d), length($data)); + processClose($poolWrite, $Attrib{$d}->fileName($d), length($data), 1); } delete($Attrib{$d}); } sub processClose { - my($poolWrite, $fileName, $origSize) = @_; + my($poolWrite, $fileName, $origSize, $noStats) = @_; my($exists, $digest, $outSize, $errs) = $poolWrite->close; if ( @$errs ) { print(join("", @$errs)); $Errors += @$errs; } - $TotalFileCnt++; - $TotalFileSize += $origSize; + if ( !$noStats ) { + $TotalFileCnt++; + $TotalFileSize += $origSize; + } if ( $exists ) { - $ExistFileCnt++; - $ExistFileSize += $origSize; - $ExistFileCompSize += $outSize; + if ( !$noStats ) { + $ExistFileCnt++; + $ExistFileSize += $origSize; + $ExistFileCompSize += $outSize; + } } elsif ( $outSize > 0 ) { print(NEW_FILES "$digest $origSize $fileName\n"); } diff --git a/cgi-bin/BackupPC_Admin b/cgi-bin/BackupPC_Admin index a3fbe87..81b85ad 100755 --- a/cgi-bin/BackupPC_Admin +++ b/cgi-bin/BackupPC_Admin @@ -86,8 +86,6 @@ my %ActionDispatch = ( # Set default actions, then call sub handler # $In{action} ||= "hostInfo" if ( defined($In{host}) ); -## rk default non admin users to pc summary for their hosts -$In{action} = "summary" if ( !defined($ActionDispatch{$In{action}}) && !CheckPermission()); $In{action} = "generalInfo" if ( !defined($ActionDispatch{$In{action}}) ); my $action = $ActionDispatch{$In{action}}; diff --git a/conf/config.pl b/conf/config.pl index d8bf145..47d7ac7 100644 --- a/conf/config.pl +++ b/conf/config.pl @@ -504,6 +504,21 @@ $Conf{IncrKeepCnt} = 6; $Conf{IncrKeepCntMin} = 1; $Conf{IncrAgeMax} = 30; +# +# A failed full backup is saved as a partial backup. The rsync +# XferMethod can take advantage of the partial full when the next +# backup is run. This parameter sets the age of the partial full +# in days: if the partial backup is older than this number of +# days, then rsync will ignore (not use) the partial full when +# the next backup is run. If you set this to a negative value +# then no partials will be saved. If you set this to 0, partials +# will be saved, but will not be used by the next backup. +# +# The default setting of 3 days means that a partial older than +# 3 days is ignored when the next full backup is done. +# +$Conf{PartialAgeMax} = 3; + # # Whether incremental backups are filled. "Filling" means that the # most recent full (or filled) dump is merged into the new incremental @@ -980,6 +995,29 @@ $Conf{RsyncdPasswd} = ''; # $Conf{RsyncdAuthRequired} = 1; +# +# When rsync checksum caching is enabled (by adding the +# --checksum-seed=32761 option to $Conf{RsyncArgs}), the cached +# checksums can be occaisonally verified to make sure the file +# contents matches the cached checksums. This is to avoid the +# risk that disk problems might cause the pool file contents to +# get corrupted, but the cached checksums would make BackupPC +# think that the file still matches the client. +# +# This setting is the probability (0 means never and 1 means always) +# that a file will be rechecked. Setting it to 0 means the checksums +# will not be rechecked (unless there is a phase 0 failure). Setting +# it to 1 (ie: 100%) means all files will be checked, but that is +# not a desirable setting since you are better off simply turning +# caching off (ie: remove the --checksum-seed option). +# +# The default of 0.01 means 1% (on average) of the files during a full +# backup will have their cached checksum re-checked. +# +# This setting has no effect unless checksum caching is turned on. +# +$Conf{RsyncCsumCacheVerifyProb} = 0.01; + # # Arguments to rsync for backup. Do not edit the first set unless you # have a thorough understanding of how File::RsyncP works. @@ -1010,10 +1048,10 @@ $Conf{RsyncArgs} = [ # # If you are using a patched client rsync that supports the - # --fixed-csumseed option (see http://backuppc.sourceforge.net), + # --checksum-seed option (see http://backuppc.sourceforge.net), # then uncomment this to enabled rsync checksum cachcing # - #'--fixed-csumseed', + #'--checksum-seed=32761', # # Add additional arguments here @@ -1046,10 +1084,10 @@ $Conf{RsyncRestoreArgs} = [ # # If you are using a patched client rsync that supports the - # --fixed-csumseed option (see http://backuppc.sourceforge.net), + # --checksum-seed option (see http://backuppc.sourceforge.net), # then uncomment this to enabled rsync checksum cachcing # - #'--fixed-csumseed', + #'--checksum-seed=32761', # # Add additional arguments here @@ -1605,6 +1643,33 @@ $Conf{CgiDateFormatMMDD} = 1; # $Conf{CgiNavBarAdminAllHosts} = 1; +# +# Enable/disable the search box in the navigation bar. +# +$Conf{CgiSearchBoxEnable} = 1; + +# +# Additional navigation bar links. These appear for both regular users +# and administrators. This is a list of hashes giving the link (URL) +# and the text (name) for the link. Specifying lname instead of name +# uses the language specific string (ie: $Lang->{lname}) instead of +# just literally displaying name. +# +$Conf{CgiNavBarLinks} = [ + { + link => "?action=view&type=docs", + lname => "Documentation", # actually displays $Lang->{Documentation} + }, + { + link => "http://backuppc.sourceforge.net/faq", + name => "FAQ", # displays literal "FAQ" + }, + { + link => "http://backuppc.sourceforge.net", + name => "SourceForge", # displays literal "SourceForge" + }, +]; + # # Hilight colors based on status that are used in the PC summary page. # diff --git a/configure.pl b/configure.pl index 09d99b7..dfc9006 100755 --- a/configure.pl +++ b/configure.pl @@ -33,7 +33,7 @@ # #======================================================================== # -# Version 2.0.0_CVS, released 18 Jan 2003. +# Version 2.1.0beta1, released 9 Apr 2004. # # See http://backuppc.sourceforge.net. # @@ -44,13 +44,27 @@ no utf8; use vars qw(%Conf %OrigConf); use lib "./lib"; -my @Packages = qw(ExtUtils::MakeMaker File::Path File::Spec File::Copy - DirHandle Digest::MD5 Data::Dumper Getopt::Std - BackupPC::Lib BackupPC::FileZIO); +my @Packages = qw(File::Path File::Spec File::Copy DirHandle Digest::MD5 + Data::Dumper Getopt::Std Getopt::Long Pod::Usage + BackupPC::Lib BackupPC::FileZIO); foreach my $pkg ( @Packages ) { eval "use $pkg"; next if ( !$@ ); + if ( $pkg =~ /BackupPC/ ) { + die < 0, -verbose => 2) if $opts{man}; + +my $DestDir = $opts{"dest-dir"}; + if ( $< != 0 ) { print < Do you want to continue?", "y") =~ /y/i; + exit(1) if ( prompt("--> Do you want to continue?", + "y") !~ /y/i ); + exit(1) if ( $opts{batch} && !$opts{"uid-ignore"} ); } print < Full path to existing conf/config.pl", - $ConfigPath); + $ConfigPath, + "config-path"); last if ( $ConfigPath eq "" || ($ConfigPath =~ /^\// && -r $ConfigPath && -w $ConfigPath) ); my $problem = "is not an absolute path"; @@ -95,6 +136,10 @@ while ( 1 ) { $problem = "is not readable" if ( !-r $ConfigPath ); $problem = "doesn't exist" if ( !-f $ConfigPath ); print("The file '$ConfigPath' $problem.\n"); + if ( $opts{batch} ) { + print("Need to specify a valid --config-path for upgrade\n"); + exit(1); + } } my $bpc; if ( $ConfigPath ne "" && -r $ConfigPath ) { @@ -141,10 +186,10 @@ my %Programs = ( foreach my $prog ( sort(keys(%Programs)) ) { my $path; foreach my $subProg ( split(/\//, $prog) ) { - $path ||= FindProgram("$ENV{PATH}:/bin:/usr/bin:/sbin:/usr/sbin", - $subProg); + $path = FindProgram("$ENV{PATH}:/bin:/usr/bin:/sbin:/usr/sbin", + $subProg) if ( !length($path) ); } - $Conf{$Programs{$prog}} ||= $path; + $Conf{$Programs{$prog}} = $path if ( !length($Conf{$Programs{$prog}}) ); } while ( 1 ) { @@ -185,7 +230,9 @@ Please tell me the hostname of the machine that BackupPC will run on. EOF chomp($Conf{ServerHost} = `$Conf{HostnamePath}`) if ( defined($Conf{HostnamePath}) && !defined($Conf{ServerHost}) ); -$Conf{ServerHost} = prompt("--> BackupPC will run on host", $Conf{ServerHost}); +$Conf{ServerHost} = prompt("--> BackupPC will run on host", + $Conf{ServerHost}, + "hostname"); print < BackupPC should run as user", - $Conf{BackupPCUser} || "backuppc"); + $Conf{BackupPCUser} || "backuppc", + "username"); ($name, $passwd, $Uid, $Gid) = getpwnam($Conf{BackupPCUser}); last if ( $name ne "" ); print < Install directory (full path)", - $Conf{InstallDir}); + $Conf{InstallDir}, + "install-dir"); last if ( $Conf{InstallDir} =~ /^\// ); + if ( $opts{batch} ) { + print("Need to specify --install-dir for new installation\n"); + exit(1); + } } print < Data directory (full path)", $Conf{TopDir}); + $Conf{TopDir} = prompt("--> Data directory (full path)", + $Conf{TopDir}, + "data-dir"); last if ( $Conf{TopDir} =~ /^\// ); + if ( $opts{batch} ) { + print("Need to specify --data-dir for new installation\n"); + exit(1); + } } if ( !defined($Conf{CompressLevel}) ) { @@ -318,8 +378,14 @@ Leave this path empty if you don't want to install the CGI interface. EOF while ( 1 ) { - $Conf{CgiDir} = prompt("--> CGI bin directory (full path)", $Conf{CgiDir}); + $Conf{CgiDir} = prompt("--> CGI bin directory (full path)", + $Conf{CgiDir}, + "cgi-dir"); last if ( $Conf{CgiDir} =~ /^\// || $Conf{CgiDir} eq "" ); + if ( $opts{batch} ) { + print("Need to specify --cgi-dir for new installation\n"); + exit(1); + } } if ( $Conf{CgiDir} ne "" ) { @@ -339,13 +405,23 @@ The URL for the image directory should start with a slash. EOF while ( 1 ) { $Conf{CgiImageDir} = prompt("--> Apache image directory (full path)", - $Conf{CgiImageDir}); + $Conf{CgiImageDir}, + "html-dir"); last if ( $Conf{CgiImageDir} =~ /^\// ); + if ( $opts{batch} ) { + print("Need to specify --html-dir for new installation\n"); + exit(1); + } } while ( 1 ) { $Conf{CgiImageDirURL} = prompt("--> URL for image directory (omit http://host; starts with '/')", - $Conf{CgiImageDirURL}); + $Conf{CgiImageDirURL}, + "html-dir-url"); last if ( $Conf{CgiImageDirURL} =~ /^\// ); + if ( $opts{batch} ) { + print("Need to specify --html-dir-url for new installation\n"); + exit(1); + } } } @@ -371,13 +447,13 @@ foreach my $dir ( qw(bin doc lib/BackupPC/Xfer lib/BackupPC/Zip ) ) { - next if ( -d "$Conf{InstallDir}/$dir" ); - mkpath("$Conf{InstallDir}/$dir", 0, 0775); - if ( !-d "$Conf{InstallDir}/$dir" - || !chown($Uid, $Gid, "$Conf{InstallDir}/$dir") ) { - die("Failed to create or chown $Conf{InstallDir}/$dir\n"); + next if ( -d "$DestDir$Conf{InstallDir}/$dir" ); + mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0775); + if ( !-d "$DestDir$Conf{InstallDir}/$dir" + || !chown($Uid, $Gid, "$DestDir$Conf{InstallDir}/$dir") ) { + die("Failed to create or chown $DestDir$Conf{InstallDir}/$dir\n"); } else { - print("Created $Conf{InstallDir}/$dir\n"); + print("Created $DestDir$Conf{InstallDir}/$dir\n"); } } @@ -386,11 +462,11 @@ foreach my $dir ( qw(bin doc # foreach my $dir ( ($Conf{CgiImageDir}) ) { next if ( $dir eq "" || -d $dir ); - mkpath($dir, 0, 0775); - if ( !-d $dir || !chown($Uid, $Gid, $dir) ) { - die("Failed to create or chown $dir"); + mkpath("$DestDir$dir", 0, 0775); + if ( !-d "$DestDir$dir" || !chown($Uid, $Gid, "$DestDir$dir") ) { + die("Failed to create or chown $DestDir$dir"); } else { - print("Created $dir\n"); + print("Created $DestDir$dir\n"); } } @@ -398,30 +474,25 @@ foreach my $dir ( ($Conf{CgiImageDir}) ) { # Create $TopDir's top-level directories # foreach my $dir ( qw(. conf pool cpool pc trash log) ) { - mkpath("$Conf{TopDir}/$dir", 0, 0750) if ( !-d "$Conf{TopDir}/$dir" ); - if ( !-d "$Conf{TopDir}/$dir" - || !chown($Uid, $Gid, "$Conf{TopDir}/$dir") ) { - die("Failed to create or chown $Conf{TopDir}/$dir\n"); + mkpath("$DestDir$Conf{TopDir}/$dir", 0, 0750) if ( !-d "$DestDir$Conf{TopDir}/$dir" ); + if ( !-d "$DestDir$Conf{TopDir}/$dir" + || !chown($Uid, $Gid, "$DestDir$Conf{TopDir}/$dir") ) { + die("Failed to create or chown $DestDir$Conf{TopDir}/$dir\n"); } else { - print("Created $Conf{TopDir}/$dir\n"); + print("Created $DestDir$Conf{TopDir}/$dir\n"); } } -printf("Installing binaries in $Conf{InstallDir}/bin\n"); +printf("Installing binaries in $DestDir$Conf{InstallDir}/bin\n"); foreach my $prog ( qw(BackupPC BackupPC_dump BackupPC_link BackupPC_nightly BackupPC_sendEmail BackupPC_tarCreate BackupPC_trashClean BackupPC_tarExtract BackupPC_compressPool BackupPC_zcat BackupPC_archive BackupPC_archiveHost BackupPC_restore BackupPC_serverMesg BackupPC_zipCreate ) ) { - InstallFile("bin/$prog", "$Conf{InstallDir}/bin/$prog", 0555); + InstallFile("bin/$prog", "$DestDir$Conf{InstallDir}/bin/$prog", 0555); } -# -# Remove unused binaries from older versions -# -unlink("$Conf{InstallDir}/bin/BackupPC_queueAll"); - -printf("Installing library in $Conf{InstallDir}/lib\n"); +printf("Installing library in $DestDir$Conf{InstallDir}/lib\n"); foreach my $lib ( qw( BackupPC/Lib.pm BackupPC/FileZIO.pm @@ -461,25 +532,25 @@ foreach my $lib ( qw( BackupPC/CGI/Summary.pm BackupPC/CGI/View.pm ) ) { - InstallFile("lib/$lib", "$Conf{InstallDir}/lib/$lib", 0444); + InstallFile("lib/$lib", "$DestDir$Conf{InstallDir}/lib/$lib", 0444); } if ( $Conf{CgiImageDir} ne "" ) { - printf("Installing images in $Conf{CgiImageDir}\n"); + printf("Installing images in $DestDir$Conf{CgiImageDir}\n"); foreach my $img ( ) { (my $destImg = $img) =~ s{^images/}{}; - InstallFile($img, "$Conf{CgiImageDir}/$destImg", 0444, 1); + InstallFile($img, "$DestDir$Conf{CgiImageDir}/$destImg", 0444, 1); } # # Install new CSS file, making a backup copy if necessary # - my $cssBackup = "$Conf{CgiImageDir}/BackupPC_stnd.css.pre-__VERSION__"; - if ( -f "$Conf{CgiImageDir}/BackupPC_stnd.css" && !-f $cssBackup ) { - rename("$Conf{CgiImageDir}/BackupPC_stnd.css", $cssBackup); + my $cssBackup = "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css.pre-__VERSION__"; + if ( -f "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css" && !-f $cssBackup ) { + rename("$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", $cssBackup); } InstallFile("conf/BackupPC_stnd.css", - "$Conf{CgiImageDir}/BackupPC_stnd.css", 0444, 0); + "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", 0444, 0); } printf("Making init.d scripts\n"); @@ -488,21 +559,21 @@ foreach my $init ( qw(gentoo-backuppc gentoo-backuppc.conf linux-backuppc InstallFile("init.d/src/$init", "init.d/$init", 0444); } -printf("Installing docs in $Conf{InstallDir}/doc\n"); +printf("Installing docs in $DestDir$Conf{InstallDir}/doc\n"); foreach my $doc ( qw(BackupPC.pod BackupPC.html) ) { - InstallFile("doc/$doc", "$Conf{InstallDir}/doc/$doc", 0444); + InstallFile("doc/$doc", "$DestDir$Conf{InstallDir}/doc/$doc", 0444); } -printf("Installing config.pl and hosts in $Conf{TopDir}/conf\n"); -InstallFile("conf/hosts", "$Conf{TopDir}/conf/hosts", 0644) - if ( !-f "$Conf{TopDir}/conf/hosts" ); +printf("Installing config.pl and hosts in $DestDir$Conf{TopDir}/conf\n"); +InstallFile("conf/hosts", "$DestDir$Conf{TopDir}/conf/hosts", 0644) + if ( !-f "$DestDir$Conf{TopDir}/conf/hosts" ); # # Now do the config file. If there is an existing config file we # merge in the new config file, adding any new configuration # parameters and deleting ones that are no longer needed. # -my $dest = "$Conf{TopDir}/conf/config.pl"; +my $dest = "$DestDir$Conf{TopDir}/conf/config.pl"; my ($newConf, $newVars) = ConfigParse("conf/config.pl"); my ($oldConf, $oldVars); if ( -f $dest ) { @@ -656,9 +727,9 @@ if ( !defined($oldConf) ) { } if ( $Conf{CgiDir} ne "" ) { - printf("Installing cgi script BackupPC_Admin in $Conf{CgiDir}\n"); - mkpath("$Conf{CgiDir}", 0, 0755); - InstallFile("cgi-bin/BackupPC_Admin", "$Conf{CgiDir}/BackupPC_Admin", + printf("Installing cgi script BackupPC_Admin in $DestDir$Conf{CgiDir}\n"); + mkpath("$DestDir$Conf{CgiDir}", 0, 0755); + InstallFile("cgi-bin/BackupPC_Admin", "$DestDir$Conf{CgiDir}/BackupPC_Admin", 04554); } @@ -705,9 +776,9 @@ EOF } eval "use File::RsyncP;"; -if ( !$@ && $File::RsyncP::VERSION < 0.50 ) { +if ( !$@ && $File::RsyncP::VERSION < 0.51 ) { print("\nWarning: you need to upgrade File::RsyncP;" - . " I found $File::RsyncP::VERSION and BackupPC needs 0.50\n"); + . " I found $File::RsyncP::VERSION and BackupPC needs 0.51\n"); } exit(0); @@ -764,10 +835,15 @@ sub InstallFile sub FindProgram { my($path, $prog) = @_; + + if ( defined($opts{"bin-path"}{$prog}) ) { + return $opts{"bin-path"}{$prog}; + } foreach my $dir ( split(/:/, $path) ) { my $file = File::Spec->catfile($dir, $prog); return $file if ( -x $file ); } + return; } sub ConfigParse @@ -864,3 +940,189 @@ sub ConfigMerge } return $res; } + +sub prompt +{ + my($question, $default, $option) = @_; + + $default = $opts{$option} if ( defined($opts{$option}) ); + if ( $opts{batch} ) { + print("$question [$default]\n"); + return $default; + } + print("$question [$default]? "); + my $reply = ; + $reply =~ s/[\n\r]*//g; + return $reply if ( $reply !~ /^$/ ); + return $default; +} + +__END__ + +=head1 SYNOPSIS + +configure.pl [options] + +=head1 DESCRIPTION + +configure.pl is a script that is used to install or upgrade a BackupPC +installation. It is usually run interactively without arguments. It +also supports a batch mode where all the options can be specified +via the command-line. + +For upgrading BackupPC you need to make sure that BackupPC is not +running prior to running BackupPC. + +Typically configure.pl needs to run as the super user (root). + +=head1 OPTIONS + +=over 8 + +=item B<--batch> + +Run configure.pl in batch mode. configure.pl will run without +prompting the user. The other command-line options are used +to specify the settings that the user is usually prompted for. + +=item B<--bin-path PROG=PATH> + +Specify the path for various external programs that BackupPC +uses. Several --bin-path options may be specified. configure.pl +usually finds sensible defaults based on searching the PATH. +The format is: + + --bin-path PROG=PATH + +where PROG is one of perl, tar, smbclient, nmblookup, rsync, ping, +df, ssh, sendmail, hostname, split, par2, cat, gzip, bzip2 and +PATH is that full path to that program. + +Examples + + --bin-path cat=/bin/cat --bin-path bzip2=/home/user/bzip2 + +=item B<--config-path CONFIG_PATH> + +Path to the existing config.pl configuration file for BackupPC. +This option should be specified for batch upgrades to an +existing installation. The option should be omitted when +doing a batch new install. + +=item B<--cgi-dir CGI_DIR> + +Path to Apache's cgi-bin directory where the BackupPC_Admin +script will be installed. This option only needs to be +specified for a batch new install. + +=item B<--data-dir DATA_DIR> + +Path to the BackupPC data directory. This is where all the backup +data is stored, and it should be on a large file system. This option +only needs to be specified for a batch new install. + +Example: + + --data-dir /data/BackupPC + +=item B<--dest-dir DEST_DIR> + +An optional prefix to apply to all installation directories. +Usually this is not needed, but certain auto-installers like +to stage an install in a temporary directory, and then copy +the files to their real destination. This option can be used +to specify the temporary directory prefix. Note that if you +specify this option, BackupPC won't run correctly if you try +to run it from below the --dest-dir directory, since all the +paths are set assuming BackupPC is installed in the intended +final locations. + +=item B<--help|?> + +Print a brief help message and exits. + +=item B<--hostname HOSTNAME> + +Host name (this machine's name) on which BackupPC is being installed. +This option only needs to be specified for a batch new install. + +=item B<--html-dir HTML_DIR> + +Path to an Apache html directory where various BackupPC image files +and the CSS files will be installed. This is typically a directory +below Apache's DocumentRoot directory. This option only needs to be +specified for a batch new install. + +Example: + + --html-dir /usr/local/apache/htdocs/BackupPC + +=item B<--html-dir-url URL> + +The URL (without http://hostname) required to access the BackupPC html +directory specified with the --html-dir option. This option only needs +to be specified for a batch new install. + +Example: + + --html-dir-url /BackupPC + +=item B<--install-dir INSTALL_DIR> + +Installation directory for BackupPC scripts, libraries, and +documentation. This option only needs to be specified for a +batch new install. + +Example: + + --install-dir /usr/local/BackupPC + +=item B<--man> + +Prints the manual page and exits. + +=item B<--uid-ignore> + +configure.pl verifies that the script is being run as the super user +(root). Without the --uid-ignore option, in batch mode the script will +exit with an error if not run as the super user, and in interactive mode +the user will be prompted. Specifying this option will cause the script +to continue even if the user id is not root. + +=head1 EXAMPLES + +For a standard interactive install, run without arguments: + + configure.pl + +For a batch new install you need to specify answers to all the +questions that are normally prompted: + + configure.pl \ + --batch \ + --cgi-dir /var/www/cgi-bin/BackupPC \ + --data-dir /data/BackupPC \ + --hostname myHost \ + --html-dir /var/www/html/BackupPC \ + --html-dir-url /BackupPC \ + --install-dir /usr/local/BackupPC + +For a batch upgrade, you only need to specify the path to the +configuration file: + + configure.pl --batch --config-path /data/BackupPC/conf/config.pl + +=head1 AUTHOR + +Craig Barratt + +=head1 COPYRIGHT + +Copyright (C) 2001-2004 Craig Barratt. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +=cut diff --git a/doc-src/BackupPC.pod b/doc-src/BackupPC.pod index 75bcc63..1362a97 100644 --- a/doc-src/BackupPC.pod +++ b/doc-src/BackupPC.pod @@ -204,6 +204,13 @@ Three BackupPC mailing lists exist for announcements (backuppc-announce), developers (backuppc-devel), and a general user list for support, asking questions or any other topic relevant to BackupPC (backuppc-users). +The lists are archived on SourceForge and Gmane. The SourceForge lists +are not always up to date and the searching is limited, so Gmane is +a good alternative. See: + + http://news.gmane.org/index.php?prefix=gmane.comp.sysutils.backup.backuppc + http://sourceforge.net/mailarchive/forum.php?forum_id=503 + You can subscribe to these lists by visiting: http://lists.sourceforge.net/lists/listinfo/backuppc-announce @@ -267,12 +274,30 @@ releases of BackupPC: =item * -Develop a FAQ and move some significant parts of this document -to the FAQ (eg: ssh setup, this roadmap etc). Volunteers? +Adding hardlink support to rsync. Currently the tar XferMethod +correctly saves/restores hardlinks, but rsync does not. Rsync +2.6.2 has greatly improved the efficiency of saving hardlink +information, so File::RsyncP and BackupPC::Xfer::RsyncFileIO need +the corresponding changes. Hardlink support is necessary for +doing a bare-metal restore of a *nix system. =item * -Adding hardlink support to rsync. +Adding more complete utf8 support. BackupPC should use utf8 as the +native charset for storing file names, and the CGI script should emit +utf8 so that the file names can be rendered correctly. Additional +configuration parameters should allow you to specify the client Xfer +charset (ie: the filcharset delivered by the XferMethod). BackupPC +should encode/decode between this charset and utf8 when doing a +backup/restore. That way BackupPC can store all files in utf8 no +matter what charset is used by the XferMethod to deliver the file +names. Secondly, the CGI charset should be configurable (default +utf8) and the CGI script BackupPC_Admin should encode the utf8 file +names in the desired output charset. Finally, the charset used to +deliver file names when restoring individual file names should also +be configurable, and again BackupPC_Admin should encode the file +names in this charset (again, utf8 default). That should allow the +"Save As" IE dialog to default to the correct file name. =item * @@ -297,6 +322,17 @@ be specified (eg: MySQL, ascii text etc). =item * +Because of file name mangling (adding "f" to start of each file +name) and with pending utf8 changes, BackupPC is not able to +store files whose file name length is 255 bytes or greater. The +format of the attrib file should be extended so that very long +file names (ie: >= 255) are abbreviated on the file system, but +the full name is stored in the attrib file. This could also be +used to eliminate the leading "f", since that is there to avoid +collisions with the attrib file. + +=item * + Replacing smbclient with the perl module FileSys::SmbClient. This gives much more direct control of the smb transfer, allowing incrementals to depend on any attribute change (eg: exist, mtime, @@ -304,71 +340,42 @@ file size, uid, gid), and better support for include and exclude. Currently smbclient incrementals only depend upon mtime, so deleted files or renamed files are not detected. FileSys::SmbClient would also allow resuming of incomplete full backups in the -same manner as rsync will. (I'm not sure if FileSys::SmbClient -has been updated for samba 3.x.) +same manner as rsync will. =item * -Possibly support --listed-incremental or --incremental for tar, so that -incrementals will depend upon any attribute change (eg: exist, mtime, -file size, uid, gid), rather than just mtime. This will allow tar to -be to as capable as FileSys::SmbClient and rsync. +Support --listed-incremental or --incremental for tar, +so that incrementals will depend upon any attribute change (eg: exist, +mtime, file size, uid, gid), rather than just mtime. This will allow +tar to be to as capable as FileSys::SmbClient and rsync. This is +low priority since rsync is really the preferred method. + +=item * + +In addition to allowing a specific backup (incremental or full) to +be started from the CGI interface, also allow a "regular" backup +to be started. This would behave just like a regular background +backup and determine whether a full, incremental or nothing +should be done. =item * For rysnc (and smb when FileSys::SmbClient is supported, and tar when --listed-incremental is supported) support multi-level incrementals. In fact, since incrementals will now be more "accurate", you could -choose to never to full dumps (except the first time), or at a +choose to never do full backups (except the first time), or at a minimum do them infrequently: each incremental would depend upon -the last, giving a continuous chain of differential dumps. - -=item * - -Improve the warning messages about locked files on WinXX machines, -so that more file types than just outlook pst files will produce -warning emails (and configuration settings for specifying the -file extensions that produce email warngings). - -=item * - -Long term, support bare metal restore. For *nix machines there's -not a lot to do (althought rsync needs hardlink support). For -WinXX machines the file locking problem has to get resolved. -Plus ACL save/restore would need to be supported. This is -really long term. +the last, giving a continuous chain of differential backups. =item * -Support client pull for restores. For example, BackupPC could -emulate an rsync server. That way you could boot a knoppix cd, -and you wouldn't need perl, BackupPC, ssh setup or anything on -the client to restore. You would just run an rsync command like: - - rsync -aH BackupPCServer::moduleName /path/to/emtpy/disk - -ModuleName could contain the client name, share name and backup number. -There would have to be some way of specifying the password; perhaps -the CGI could be used to "turn on" rsynd for a specific client and -a specific time period (eg: only listens for X minutes, only serves -up a specific client backup, accepts connections from a specific IP). -BackupPC listens for and serves the request; it's not a real rsyncd on -the server. - -=item * - -Add support for wget as an XferMethod. This would allow ftp and http -files to be backed up. This might be useful, for example, for backing -up the configuration of a router (via http), so that you have a -backup copy of all the router setup screens in case the router -fails. - -=item * - -Possibly support client push for backups, in addition to the -existing server pull. This would be helpful for clients behind -firewalls who can connect to the server, but the server cannot -see the client. +Allow diffs between two different backed up files to be displayed. +The history feature in 2.1.0 does show files that are the same +between backups. Most often we would like to just take the diff of +the same host, path and file between different backups, but it would +be nice to generalize it to any pair of files (ie: different hosts, +backups, paths etc). But I'm not sure how the user interface would +look. =item * @@ -381,7 +388,7 @@ around 15-20%, which isn't spectacular, and likely not worth the implementation effort. The program xdelta (v1) on SourceForge (see L) uses an rsync algorithm for doing efficient binary file deltas. Rather than using an external -program, File::RsyncP will eventually get the necessary delta +program, File::RsyncP would eventually get the necessary delta generation code from rsync. =back @@ -407,7 +414,7 @@ time and money) for marketing, PR and advertising, so it's up to all of you! Also, everyone is encouraged to contribute patches, bug reports, feature -and design suggestions, code, and documentation corrections or +and design suggestions, new code, and documentation corrections or improvements. =head1 Installing BackupPC @@ -443,8 +450,8 @@ compression is on. =item * Perl version 5.6.0 or later. BackupPC has been tested with -version 5.6.0, 5.6.1 and 5.8.0. If you don't have perl, please -see L. +version 5.6.0, 5.6.1, 5.8.0, 5.8.1 and 5.8.2. If you don't +have perl, please see L. =item * @@ -465,6 +472,7 @@ you are backing up linux/unix DHCP machines. See L. Version 2.2.0 or later of Samba is required (smbclient's tar feature in 2.0.8 and prior has bugs for file path lengths around 100 characters and generates bad output when file lengths change during the backup). +Samba versions 3.x are stable and recommended instead of 2.x. See L for source and binaries. It's pretty easy to fetch and compile samba, and just grab smbclient and nmblookup, without @@ -488,7 +496,8 @@ version. For BackupPC to use Rsync you will also need to install the perl File::RsyncP module, which is available from -L. Version 0.44 or later is required. +L. +Version 0.51 or later is required. =item * @@ -600,8 +609,16 @@ BackupPC-__VERSION__.tar.gz, run these commands as root: cd BackupPC-__VERSION__ perl configure.pl -You will be prompted for the full paths of various executables, and -you will be prompted for the following information: +The configure.pl also accepts command-line options if you wish +to run it in a non-interactive manner. It has self-contained +documentation for all the command-line options, which you can +read with perldoc: + + perldoc configure.pl + +When you run configure.pl you will be prompted for the full paths +of various executables, and you will be prompted for the following +information: =over 4 @@ -2309,15 +2326,6 @@ are using that file). Again, to avoid race conditions, BackupPC_nightly is only run when there are no BackupPC_dump or BackupPC_link processes running. -To improve the running time for BackupPC_nightly, several -BackupPC_nightly processes can be run concurrently, based on -the $Conf{MaxBackupPCNightlyJobs} setting. - -If BackupPC_nightly still takes too long to run, -$Conf{BackupPCNightlyPeriod} can be used to split -BackupPC_nightly's pool traversal across multiple nights, -proportionally reducing its runtime each night. - =back BackupPC also listens for TCP connections on $Conf{ServerPort}, which diff --git a/lib/BackupPC/CGI/ArchiveInfo.pm b/lib/BackupPC/CGI/ArchiveInfo.pm index 4de942b..2ee5836 100644 --- a/lib/BackupPC/CGI/ArchiveInfo.pm +++ b/lib/BackupPC/CGI/ArchiveInfo.pm @@ -80,7 +80,7 @@ EOF } my $content = eval("qq{$Lang->{Archive___num_details_for__host2 }}"); - Header(eval("qq{$Lang->{Archive___num_details_for__host}}"),$content); + Header(eval("qq{$Lang->{Archive___num_details_for__host}}"), $content, 1); Trailer(); } diff --git a/lib/BackupPC/CGI/GeneralInfo.pm b/lib/BackupPC/CGI/GeneralInfo.pm index 0323d5e..8e1968a 100644 --- a/lib/BackupPC/CGI/GeneralInfo.pm +++ b/lib/BackupPC/CGI/GeneralInfo.pm @@ -49,6 +49,7 @@ sub action my $startTime = timeStamp2($Jobs{$host}{startTime}); next if ( $host eq $bpc->trashJob && $Jobs{$host}{processState} ne "running" ); + next if ( !$Privileged && !CheckPermission($host) ); $Jobs{$host}{type} = $Status{$host}{type} if ( $Jobs{$host}{type} eq "" && defined($Status{$host})); (my $cmd = $Jobs{$host}{cmd}) =~ s/$BinDir\///g; @@ -70,6 +71,7 @@ EOF && $Status{$host}{reason} ne "Reason_restore_failed" && (!$Status{$host}{userReq} || $Status{$host}{reason} ne "Reason_no_ping") ); + next if ( !$Privileged && !CheckPermission($host) ); my $startTime = timeStamp2($Status{$host}{startTime}); my($errorTime, $XferViewStr); if ( $Status{$host}{errorTime} > 0 ) { @@ -124,7 +126,9 @@ EOF } elsif ( $Info{cpoolFileCnt} > 0 ) { $poolInfo = $cpoolInfo; } - my $content = eval ("qq{$Lang->{BackupPC_Server_Status}}"); + my $generalInfo = eval("qq{$Lang->{BackupPC_Server_Status_General_Info}}") + if ( $Privileged ); + my $content = eval("qq{$Lang->{BackupPC_Server_Status}}"); Header($Lang->{H_BackupPC_Server_Status}, $content); Trailer(); } diff --git a/lib/BackupPC/CGI/HostInfo.pm b/lib/BackupPC/CGI/HostInfo.pm index 7af47e9..109e21b 100644 --- a/lib/BackupPC/CGI/HostInfo.pm +++ b/lib/BackupPC/CGI/HostInfo.pm @@ -46,14 +46,16 @@ sub action $host =~ s/^\s+//; $host =~ s/\s+$//; - return Action_GeneralInfo() if ( $host eq "" ); + if ( $host eq "" ) { + ErrorExit(eval("qq{$Lang->{Unknown_host_or_user}}")); + } $host = lc($host) - if ( !-d "$TopDir/pc/$host" && -d "$TopDir/pc/" . lc($host) ); + if ( !-d "$TopDir/pc/$host" && -d "$TopDir/pc/" . lc($host) ); if ( $host =~ /\.\./ || !-d "$TopDir/pc/$host" ) { # # try to lookup by user name # - if ( !defined($Hosts->{$host}) ) { + if ( $host eq "" || !defined($Hosts->{$host}) ) { foreach my $h ( keys(%$Hosts) ) { if ( $Hosts->{$h}{user} eq $host || lc($Hosts->{$h}{user}) eq lc($host) ) { @@ -63,7 +65,7 @@ sub action } CheckPermission(); ErrorExit(eval("qq{$Lang->{Unknown_host_or_user}}")) - if ( !defined($Hosts->{$host}) ); + if ( !defined($Hosts->{$host}) ); } $In{host} = $host; } @@ -286,7 +288,8 @@ EOF if ( $StatusHost{aliveCnt} > 0 ) { $statusStr .= eval("qq{$Lang->{priorStr_to_host_have_succeeded_StatusHostaliveCnt_consecutive_times}}"); - if ( $StatusHost{aliveCnt} >= $Conf{BlackoutGoodCnt} + if ( (@{$Conf{BlackoutPeriods}} || defined($Conf{BlackoutHourBegin})) + && $StatusHost{aliveCnt} >= $Conf{BlackoutGoodCnt} && $Conf{BlackoutGoodCnt} >= 0 ) { # # Handle backward compatibility with original separate scalar diff --git a/lib/BackupPC/CGI/Lib.pm b/lib/BackupPC/CGI/Lib.pm index 1133b3a..307e441 100644 --- a/lib/BackupPC/CGI/Lib.pm +++ b/lib/BackupPC/CGI/Lib.pm @@ -392,23 +392,23 @@ sub Header { my($title, $content, $noBrowse, $contentSub, $contentPost) = @_; my @adminLinks = ( - { link => "", name => $Lang->{Status}, + { link => "", name => $Lang->{Status}}, + { link => "?action=adminOpts", name => $Lang->{Admin_Options}, priv => 1}, - { link => "?action=adminOpts", name => $Lang->{Admin_Options} }, - { link => "?action=summary", name => $Lang->{PC_Summary}, + { link => "?action=summary", name => $Lang->{PC_Summary}}, + { link => "?action=view&type=LOG", name => $Lang->{LOG_file}, priv => 1}, - { link => "?action=view&type=LOG", name => $Lang->{LOG_file} }, - { link => "?action=LOGlist", name => $Lang->{Old_LOGs} }, - { link => "?action=emailSummary", name => $Lang->{Email_summary} }, - { link => "?action=view&type=config", name => $Lang->{Config_file} }, - { link => "?action=view&type=hosts", name => $Lang->{Hosts_file} }, - { link => "?action=queue", name => $Lang->{Current_queues} }, - { link => "?action=view&type=docs", name => $Lang->{Documentation}, + { link => "?action=LOGlist", name => $Lang->{Old_LOGs}, priv => 1}, - { link => "http://backuppc.sourceforge.net/faq", name => "FAQ", + { link => "?action=emailSummary", name => $Lang->{Email_summary}, priv => 1}, - { link => "http://backuppc.sourceforge.net", name => "SourceForge", + { link => "?action=view&type=config", name => $Lang->{Config_file}, priv => 1}, + { link => "?action=view&type=hosts", name => $Lang->{Hosts_file}, + priv => 1}, + { link => "?action=queue", name => $Lang->{Current_queues}, + priv => 1}, + @{$Conf{CgiNavBarLinks}}, ); my $host = $In{host}; @@ -420,12 +420,12 @@ sub Header $Conf{CgiHeaders} -
+
EOF if ( defined($Hosts) && defined($host) && defined($Hosts->{$host}) ) { print "
"; - NavSectionTitle("${EscURI($host)}"); + NavSectionTitle("${EscHTML($host)}"); print < EOF diff --git a/lib/BackupPC/CGI/Summary.pm b/lib/BackupPC/CGI/Summary.pm index 6c7459e..a485cd3 100644 --- a/lib/BackupPC/CGI/Summary.pm +++ b/lib/BackupPC/CGI/Summary.pm @@ -58,9 +58,8 @@ sub action $bpc->ConfigRead($host); %Conf = $bpc->Conf(); - if ( $Conf{XferMethod} eq "archive" ) { - next; - } + next if ( $Conf{XferMethod} eq "archive" ); + next if ( !$Privileged && !CheckPermission($host) ); for ( my $i = 0 ; $i < @Backups ; $i++ ) { if ( $Backups[$i]{type} eq "full" ) { diff --git a/lib/BackupPC/CGI/View.pm b/lib/BackupPC/CGI/View.pm index fc99fee..7fc95a0 100644 --- a/lib/BackupPC/CGI/View.pm +++ b/lib/BackupPC/CGI/View.pm @@ -28,7 +28,7 @@ # #======================================================================== # -# Version 2.1.0beta1, released 9 Apr 2004. +# Version 2.1.0beta2, released 9 May 2004. # # See http://backuppc.sourceforge.net. # @@ -97,7 +97,7 @@ sub action $file = "$TopDir/log/LOG$ext"; $linkHosts = 1; } - if ( !$Privileged ) { + if ( $type ne "docs" && !$Privileged ) { ErrorExit($Lang->{Only_privileged_users_can_view_log_or_config_files}); } if ( !-f $file && -f "$file.z" ) { @@ -186,16 +186,16 @@ sub action last if ( $s eq "" ); $s =~ s/[\n\r]+//g; # remove any passwords and user names - $s =~ s/(SmbSharePasswd.*=.*['"]).*(['"])/$1$2/ig; - $s =~ s/(SmbShareUserName.*=.*['"]).*(['"])/$1$2/ig; - $s =~ s/(RsyncdPasswd.*=.*['"]).*(['"])/$1$2/ig; - $s =~ s/(ServerMesgSecret.*=.*['"]).*(['"])/$1$2/ig; + $s =~ s/(SmbSharePasswd.*=.*['"]).*(['"])/$1****$2/ig; + $s =~ s/(SmbShareUserName.*=.*['"]).*(['"])/$1****$2/ig; + $s =~ s/(RsyncdPasswd.*=.*['"]).*(['"])/$1****$2/ig; + $s =~ s/(ServerMesgSecret.*=.*['"]).*(['"])/$1****$2/ig; $s = ${EscHTML($s)}; $s =~ s[(\$Conf\{.*?\})][ my $c = $1; my $s = lc($c); $s =~ s{(\W)}{sprintf("%%%02x", ord($1) )}gxe; - "$c" + "$c" ]eg; $c .= $s . "\n"; } diff --git a/lib/BackupPC/Lang/de.pm b/lib/BackupPC/Lang/de.pm index 1e487fc..b799ac6 100644 --- a/lib/BackupPC/Lang/de.pm +++ b/lib/BackupPC/Lang/de.pm @@ -1,5 +1,6 @@ #!/bin/perl # +# by Ralph Passgang (06.05.2004 for V2.1.0beta2) # by Manfred Herrmann (11.03.2004 for V2.1.0beta0) # by Manfred Herrmann (V1.1) (some typo errors + 3 new strings) # CVS-> Revision ??? @@ -12,18 +13,18 @@ $Lang{Start_Archive} = "Archivierung starten"; $Lang{Stop_Dequeue_Archive} = "Archivierung stoppen"; -$Lang{Start_Full_Backup} = "Starte Backup vollständig"; -$Lang{Start_Incr_Backup} = "Starte Backup incrementell"; -$Lang{Stop_Dequeue_Backup} = "Stoppen/Aussetzen Backup"; -$Lang{Restore} = "Wiederherstellung"; +$Lang{Start_Full_Backup} = "Starte vollständiges Backup"; +$Lang{Start_Incr_Backup} = "Starte inkrementelles Backup"; +$Lang{Stop_Dequeue_Backup} = "Backup Stoppen/Aussetzen"; +$Lang{Restore} = "Wiederherstellen"; $Lang{Type_full} = "voll"; $Lang{Type_incr} = "inkrementell"; # ----- -$Lang{Only_privileged_users_can_view_admin_options} = "Nur privilegierte Nutzer können Admin Optionen einsehen."; -$Lang{H_Admin_Options} = "BackupPC Server: Admin Optionen"; +$Lang{Only_privileged_users_can_view_admin_options} = "Nur privilegierte Nutzer können die Administrator Optionen einsehen."; +$Lang{H_Admin_Options} = "BackupPC Server: Administrations Optionen"; $Lang{Admin_Options} = "Admin Optionen"; $Lang{Admin_Options_Page} = < --> EOF -$Lang{Unable_to_connect_to_BackupPC_server} = "Kann keine Verbindung zu BackupPC server herstellen", - "Dieses CGI script (\$MyURL) kann keine Verbindung zu BackupPC" - . " server auf \$Conf{ServerHost} port \$Conf{ServerPort} herstellen. Der Fehler" +$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" + "Möglicherweise ist der BackupPC Server Prozess nicht gestartet oder es besteht ein" . " Konfigurationsfehler. Bitte teilen Sie diese Fehlermeldung dem Systemadministrator mit."; $Lang{Admin_Start_Server} = < -Der BackupPC Server auf \$Conf{ServerHost} port \$Conf{ServerPort} +Der BackupPC Server auf \$Conf{ServerHost} Port \$Conf{ServerPort} ist momentan nicht aktiv (möglicherweise wurde er gestoppt, oder noch nicht gestartet).
Möchten Sie den Server starten? @@ -62,39 +63,45 @@ EOF # ----- -$Lang{H_BackupPC_Server_Status} = "BackupServer Server Status"; +$Lang{H_BackupPC_Server_Status} = "BackupPC Server Status"; -$Lang{BackupPC_Server_Status}= < -\${h2(\"Allgemeine Server Information\")} +\${h2(\"Allgemeine Server Informationen\")}
    -
  • Die Server Prozess ID (PID) ist \$Info{pid}, auf Computer \$Conf{ServerHost}, +
  • Die Server Prozess ID (PID) ist \$Info{pid}, auf Computer \$Conf{ServerHost}, Version \$Info{Version}, gestartet am \$serverStartTime.
  • Dieser Status wurde am \$now generiert. -
  • Die Konfiguration wurde neu geladen am \$configLoadTime. +
  • Die Konfiguration wurde am \$configLoadTime neu geladen.
  • Computer werden am \$nextWakeupTime auf neue Aufträge geprüft.
  • Weitere Informationen:
      -
    • \$numBgQueue wartende backup Aufträge der letzten Prüfung, +
    • \$numBgQueue wartende Backup Aufträge der letzten Prüfung,
    • \$numUserQueue wartende Aufträge von Benutzern,
    • \$numCmdQueue wartende Kommando Aufträge. \$poolInfo
    • Das Pool Filesystem (Backup-Speicherplatz) ist zu \$Info{DUlastValue}% - (\$DUlastTime) gefüllt, das Maximum-Heute ist \$Info{DUDailyMax}% (\$DUmaxTime) - und Maximum-Gestern war \$Info{DUDailyMaxPrev}%. (Hinweis: sollten ca. 70% überschritten werden, so - ist evtl. bald eine Erweiterung des Backup-Speichers erforderlich. Planung erforderlich?) + (\$DUlastTime) voll, das Maximum heute ist \$Info{DUDailyMax}% (\$DUmaxTime) + und das Maximum gestern war \$Info{DUDailyMaxPrev}%. (Hinweis: Sollten ca. 70% überschritten werden, so + ist evtl. bald eine Erweiterung des Backupspeichers erforderlich. Weitere Planung nötig?)
+EOF + +$Lang{BackupPC_Server_Status} = < +\$generalInfo \${h2("Aktuell laufende Aufträge")}

- + @@ -109,43 +116,43 @@ $Lang{BackupPC_Server_Status}= < - + - + \$statusStr
Computer Typ User Benutzer Startzeit Kommando PID
Computer Typ User Benutzer letzter Versuch Details Fehlerzeit Letzter Fehler (außer "kein ping")
Letzter Fehler (ausser "kein ping")
EOF # -------------------------------- -$Lang{BackupPC__Server_Summary} = "BackupServer: Übersicht"; +$Lang{BackupPC__Server_Summary} = "BackupPC: Übersicht"; $Lang{BackupPC__Archive} = "BackupPC: Archivierung"; $Lang{BackupPC_Summary}=< -Dieser Status wurde generiert am \$now. +Dieser Status wurde am \$now generiert.

\${h2("Computer mit erfolgreichen Backups")}

Es gibt \$hostCntGood Computer die erfolgreich gesichert wurden, mit insgesamt:

    -
  • \$fullTot Voll Backups, Gesamtgröße \${fullSizeTot}GB - (vor pooling und Komprimierung), -
  • \$incrTot Incrementelle Backups, Gesamtgröße \${incrSizeTot}GB - (vor pooling und Komprimierung). +
  • \$fullTot Volle Backups, Gesamtgröße \${fullSizeTot}GB + (vor Pooling und Komprimierung), +
  • \$incrTot Inkrementelle Backups, Gesamtgröße \${incrSizeTot}GB + (vor Pooling und Komprimierung).

- + - + - - + + @@ -154,16 +161,16 @@ Es gibt \$hostCntGood Computer die erfolgreich gesichert wurden, mit insgesamt:

\${h2("Computer ohne Backups")}

-Es gibt \$hostCntNone Computer ohne Backups !!!. +Es gibt \$hostCntNone Computer ohne Backups !!!

Computer User Benutzer #Voll Alter/Tage Alter/Tagen Größe/GB MB/sec #Incr MB/Sek #Inkr Alter/Tage Status Letzte Aktion
- + - + @@ -267,7 +274,7 @@ EOF $Lang{BackupPC_Archive2_split} = < - + EOF @@ -330,23 +337,23 @@ M EOF # -------------------------------- -$Lang{Only_privileged_users_can_view_queues_} = "Nur berechtigte User können die Warteschlangen einsehen."; +$Lang{Only_privileged_users_can_view_queues_} = "Nur berechtigte Benutzer können die Warteschlangen einsehen."; # -------------------------------- -$Lang{Only_privileged_users_can_archive} = "Nur berechtigte Personen könnnen archivieren."; +$Lang{Only_privileged_users_can_archive} = "Nur berechtigte Benutzer könnnen archivieren."; # -------------------------------- $Lang{BackupPC__Queue_Summary} = "BackupServer: Warteschlangen Übersicht"; # -------------------------------- $Lang{Backup_Queue_Summary} = <
-\${h2("User Warteschlange Übersicht")} +\${h2("Benutzer Warteschlange Übersicht")}

-Die folgenden User Aufträge sind eingereiht: +Die folgenden Benutzer Aufträge sind eingereiht:

Computer User Benutzer #Voll Alter/Tage Größe/GB MB/sec #Incr #Inkr Alter/Tage Status Letzter Versuch
Aufteilen inMegabytes Megabytes
- + \$strUser
Computer Uhrzeit User
Benutzer


@@ -358,7 +365,7 @@ Die folgenden Hintergrund Auftr - + \$strBg
Computer Uhrzeit User
Benutzer


@@ -369,7 +376,7 @@ Die folgenden Kommando Auftr - + \$strCmd
Computer Uhrzeit User Benutzer Kommando
@@ -406,7 +413,7 @@ EOF # ------------------------------- $Lang{Recent_Email_Summary} = < @@ -426,7 +433,7 @@ $Lang{Restore_Options_for__host} = "BackupServer: Restore Optionen f $Lang{Restore_Options_for__host2} = < -Sie haben die folgenden Dateien/Verzeichnisse von Freigabe \$share selektiert, von Backup Nummer #\$num: +Sie haben die folgenden Dateien/Verzeichnisse von der Freigabe \$share aus der Backup Nummer #\$num selektiert:
    \$fileListStr
@@ -434,7 +441,7 @@ Sie haben die folgenden Dateien/Verzeichnisse von Freigabe \$share selektiert, v Sie haben drei verschiedene Möglichkeiten zur Wiederherstellung (Restore) der Dateien/Verzeichnisse. Bitte wählen Sie eine der folgenden Möglichkeiten:.

-\${h2("Möglichkeit 1: Direct Restore")} +\${h2("Möglichkeit 1: Direkte Wiederherstellung")}

EOF @@ -443,9 +450,9 @@ Sie k \$host wiederherzustellen. Alternativ können Sie einen anderen Computer und/oder Freigabe als Ziel angeben.

Warnung: alle aktuell existierenden Dateien/Verzeichnisse die bereits vorhanden sind -werden überschrieben! (Tip: alternativ eine spezielle Freigabe erstellen mit schreibrecht für den -Backup-User und die wiederhergestellten Dateien/Verzeichnisse durch Stichproben prüfen, ob die beabsichtigte -Wiederherstellung korrekt ist) +werden überschrieben! (Tip: alternativ eine spezielle Freigabe erstellen mit Schreibrecht für den +Backup-Benutzer und die wiederhergestellten Dateien/Verzeichnisse durch Stichproben prüfen, ob die beabsichtigte +Wiederherstellung korrekt ist.)

@@ -476,7 +483,7 @@ Wiederherstellung korrekt ist)
- +
Empfänger
EOF @@ -489,9 +496,9 @@ EOF # ------------------------------ $Lang{Option_2__Download_Zip_archive} = < -\${h2("Möglichkeit 2: Download als Zip Archiv Datei")} +\${h2("Möglichkeit 2: Download als Zip Archiv")}

-Sie können eine ZIP Archiv Datei downloaden, die alle selektierten Dateien/Verzeichnisse +Sie können eine ZIP Archivdatei downloaden, die alle selektierten Dateien/Verzeichnisse enthält. Mit einer lokalen Anwendung (z.B. WinZIP, WinXP-ZIP-Ordner...) können Sie dann beliebige Dateien entpacken.

@@ -513,7 +520,7 @@ evtl. die Dateien/Verzeichnisse erneut und lassen sehr gro Kompression (0=aus, 1=schnelle,...,9=höchste)
- + EOF @@ -521,20 +528,20 @@ EOF $Lang{Option_2__Download_Zip_archive2} = < -\${h2("Möglichkeit 2: Download als Zip Archiv Datei")} +\${h2("Möglichkeit 2: Download als Zip Archiv")}

Archive::Zip ist nicht installiert. Der Download als Zip Archiv Datei ist daher nicht möglich. Bitte lassen Sie bei Bedarf von Ihrem Administrator die Perl-Erweiterung Archive::Zip von -www.cpan.org installieren. +www.cpan.org installieren. Vielen Dank!

EOF # ------------------------------ $Lang{Option_3__Download_Zip_archive} = < -Sie können eine Tar Archiv Datei downloaden, die alle selektierten Dateien/Verzeichnisse +Sie können eine Tar Archivdatei downloaden, die alle selektierten Dateien/Verzeichnisse enthält. Mit einer lokalen Anwendung (z.B. tar, WinZIP...) können Sie dann beliebige Dateien entpacken.

@@ -553,7 +560,7 @@ evtl. die Dateien/Verzeichnisse erneut und lassen sehr gro \${EscHTML(\$pathHdr eq "" ? "/" : \$pathHdr)} (andernfalls enthält die Archiv Datei vollständige Pfade).
- + EOF @@ -565,11 +572,11 @@ $Lang{Are_you_sure} = < Sie starten eine direkte Wiederherstellung auf den Computer \$In{hostDest}. -Die folgenden Dateien werden auf die Freigabe \$In{shareDest} wiederhergestellt, vom -Backup Nummer \$num: +Die folgenden Dateien werden auf die Freigabe \$In{shareDest} wiederhergestellt, von +der Backup Nummer \$num:

- + \$fileListStr
Original Datei/VerzeichnisWird wiederhergestellt nach
Original Datei/Verzeichnis:Wird wiederhergestellt nach:
@@ -615,7 +622,7 @@ $Lang{Host__host_Backup_Summary2} = <

-\${h2("User Aktionen")} +\${h2("Benutzer Aktionen")}

@@ -626,14 +633,14 @@ $Lang{Host__host_Backup_Summary2} = < \${h2("Backup Übersicht")}

-Klicken Sie auf die Backup-Nummer um Dateien zu browsen und bei Bedarf wiederherzustellen. +Klicken Sie auf die Backup Nummer um durch Dateien zu browsen und bei Bedarf wiederherzustellen.

- + @@ -663,7 +670,7 @@ Klicken Sie auf die Backup-Nummer um Dateien zu browsen und bei Bedarf wiederher

"Bestehende Dateien" bedeutet bereits im Pool vorhanden. "Neue Dateien" bedeutet neu zum Pool hinzugefügt. -Leere Dateien und Datei-Fehler sind nicht in den Summen enthalten. +Leere Dateien und eventuelle Datei Fehler sind nicht in den Summen enthalten.

Backup# Typ Filled Start Zeitpunkt Dauer/mins Dauer/min Alter/Tage Server Backup Pfad
@@ -686,7 +693,7 @@ Leere Dateien und Datei-Fehler sind nicht in den Summen enthalten.


-\${h2("Kompression Übersicht")} +\${h2("Kompressions Übersicht")}

Kompressionsergebnisse für bereits im Backup-Pool vorhandene und für neu komprimierte Dateien.

@@ -697,7 +704,7 @@ Kompressionsergebnisse f Backup# Typ - Comp Level + Komp Level Größe/MB Comp/MB Comp @@ -719,7 +726,7 @@ $Lang{Host__host_Archive_Summary2} = < -\${h2("User Aktionen")} +\${h2("Benutzer Aktionen")}

@@ -744,7 +751,7 @@ $Lang{NavSectionTitle_} = "Server"; # ------------------------- $Lang{Backup_browse_for__host} = < EOF @@ -898,7 +905,7 @@ $Lang{Archive___num_details_for__host} = "BackupPC: Archiv #\$num Details f $Lang{Archive___num_details_for__host2 } = < - +
@@ -921,37 +928,37 @@ $Lang{Archive___num_details_for__host2 } = <, anstatt \$uid" + "Falscher Benutzer: Meine userid ist \$>, anstelle \$uid" . "(\$Conf{BackupPCUser})\n"; -# $Lang{Only_privileged_users_can_view_PC_summaries} = "Nur berechtigte User können die Computer Übersicht einsehen."; +# $Lang{Only_privileged_users_can_view_PC_summaries} = "Nur berechtigte Benutzer können die Computer Übersicht einsehen."; $Lang{Only_privileged_users_can_stop_or_start_backups} = - "Nur berechtigte User können Backups starten und stoppen für" + "Nur berechtigte Benutzer können Backups starten und stoppen für" . " \${EscHTML(\$host)}."; $Lang{Invalid_number__num} = "ungültige Nummer \$num"; $Lang{Unable_to_open__file__configuration_problem} = "kann Datei nicht öffnen \$file: Konfigurationsproblem?"; -$Lang{Only_privileged_users_can_view_log_or_config_files} = "Nur berechtigte User können LOG oder config Dateien einsehen."; -$Lang{Only_privileged_users_can_view_log_files} = "Nur berechtigte User können LOG Dateien einsehen."; -$Lang{Only_privileged_users_can_view_email_summaries} = "Nur berechtigte User können die Email Übersicht einsehen."; -$Lang{Only_privileged_users_can_browse_backup_files} = "Nur berechtigte User können Backup Dateien browsen" +$Lang{Only_privileged_users_can_view_log_or_config_files} = "Nur berechtigte Benutzer können Log oder Config Dateien einsehen."; +$Lang{Only_privileged_users_can_view_log_files} = "Nur berechtigte Benutzer können LOG Dateien einsehen."; +$Lang{Only_privileged_users_can_view_email_summaries} = "Nur berechtigte Benutzer können die Email Übersicht einsehen."; +$Lang{Only_privileged_users_can_browse_backup_files} = "Nur berechtigte Benutzer können Backup Dateien browsen" . " für computer \${EscHTML(\$In{host})}."; -$Lang{Empty_host_name} = "Empty host name."; +$Lang{Empty_host_name} = "Kein Hostname."; $Lang{Directory___EscHTML} = "Verzeichnis \${EscHTML(\"\$TopDir/pc/\$host/\$num\")}" . " ist leer"; -$Lang{Can_t_browse_bad_directory_name2} = "Kann fehlerhaften Verzeichnisnamen nicht browsen" +$Lang{Can_t_browse_bad_directory_name2} = "Kann fehlerhaften Verzeichnisnamen nicht durchsuchen" . " \${EscHTML(\$relDir)}"; -$Lang{Only_privileged_users_can_restore_backup_files} = "Nur berechtigte User können Dateien wiederherstellen" +$Lang{Only_privileged_users_can_restore_backup_files} = "Nur berechtigte Benutzer können Dateien wiederherstellen" . " für Computer \${EscHTML(\$In{host})}."; $Lang{Bad_host_name} = "Falscher Computer Name \${EscHTML(\$host)}"; $Lang{You_haven_t_selected_any_files__please_go_Back_to} = "Sie haben keine Dateien selektiert; bitte gehen Sie zurück um" . " Dateien zu selektieren."; -$Lang{You_haven_t_selected_any_hosts} = "Sie haben keinen Computer gewählt, bitte zurückgehen um einen auszuwählen."; +$Lang{You_haven_t_selected_any_hosts} = "Sie haben keinen Computer gewählt, bitte zurück gehen um einen auszuwählen."; $Lang{Nice_try__but_you_can_t_put} = "Sie dürfen \'..\' nicht in Dateinamen verwenden"; $Lang{Host__doesn_t_exist} = "Computer \${EscHTML(\$In{hostDest})} existiert nicht"; $Lang{You_don_t_have_permission_to_restore_onto_host} = "Sie haben keine Berechtigung zum Restore auf Computer" @@ -961,11 +968,11 @@ $Lang{Can_t_open_create} = "Kann Datei nicht $Lang{Only_privileged_users_can_restore_backup_files2} = "Nur berechtigte Benutzer dürfen Backup und Restore von Dateien" . " für Computer \${EscHTML(\$host)} durchführen."; $Lang{Empty_host_name} = "leerer Computer Name"; -$Lang{Unknown_host_or_user} = "Unbekannter Computer oder User \${EscHTML(\$host)}"; -$Lang{Only_privileged_users_can_view_information_about} = "Nur berechtigte User können Informationen sehen über" +$Lang{Unknown_host_or_user} = "Unbekannter Computer oder Benutzer \${EscHTML(\$host)}"; +$Lang{Only_privileged_users_can_view_information_about} = "Nur berechtigte Benutzer können Informationen sehen über" . " Computer \${EscHTML(\$host)}." ; -$Lang{Only_privileged_users_can_view_archive_information} = "Nur berechtigte User können Archiv Informationen einsehen."; -$Lang{Only_privileged_users_can_view_restore_information} = "Nur berechtigte User können Restore Informationen einsehen."; +$Lang{Only_privileged_users_can_view_archive_information} = "Nur berechtigte Benutzer können Archiv Informationen einsehen."; +$Lang{Only_privileged_users_can_view_restore_information} = "Nur berechtigte Benutzer können Restore Informationen einsehen."; $Lang{Restore_number__num_for_host__does_not_exist} = "Restore Nummer \$num für Computer \${EscHTML(\$host)} existiert" . " nicht."; $Lang{Archive_number__num_for_host__does_not_exist} = "Archiv Nummer \$num für Computer \${EscHTML(\$host)} existiert" @@ -999,20 +1006,20 @@ $Lang{Status} = "Status"; $Lang{PC_Summary} = "Computer Übersicht"; $Lang{LOG_file} = "LOG Datei"; $Lang{LOG_files} = "LOG Dateien"; -$Lang{Old_LOGs} = "Alte LOGs"; -$Lang{Email_summary} = "Email Übersicht"; +$Lang{Old_LOGs} = "Alte LOG Dateien"; +$Lang{Email_summary} = "eMail Übersicht"; $Lang{Config_file} = "Config Datei"; $Lang{Hosts_file} = "Hosts Datei"; $Lang{Current_queues} = "Warteschlangen"; $Lang{Documentation} = "Dokumentation"; -#$Lang{Host_or_User_name} = "Computer oder User Name:"; +#$Lang{Host_or_User_name} = "Computer oder Benutzer Name:"; $Lang{Go} = "gehe zu"; $Lang{Hosts} = "Computer"; $Lang{Select_a_host} = "Computer auswählen..."; $Lang{There_have_been_no_archives} = "

Es existieren keine Archive

\n"; -$Lang{This_PC_has_never_been_backed_up} = "

Dieser Computer wurde nie gesichert!!

\n"; +$Lang{This_PC_has_never_been_backed_up} = "

Dieser Computer wurde nie gesichert!

\n"; $Lang{This_PC_is_used_by} = "
  • Dieser Computer wird betreut von \${UserLink(\$user)}"; $Lang{Extracting_only_Errors} = "(nur Fehler anzeigen)"; @@ -1021,7 +1028,7 @@ $Lang{Errors} = "Fehler"; # ------------ $Lang{Last_email_sent_to__was_at___subject} = <Letzte e-mail gesendet an \${UserLink(\$user)} am \$mailTime, Titel "\$subj". +
  • Letzte eMail gesendet an \${UserLink(\$user)} am \$mailTime, Titel "\$subj". EOF # ------------ $Lang{The_command_cmd_is_currently_running_for_started} = <Computer \$host ist in die User-Warteschlange eingereiht (Backup wird bald gestartet). +
  • Computer \$host ist in die Benutzer-Warteschlange eingereiht (Backup wird bald gestartet). EOF # --------- @@ -1088,7 +1095,7 @@ $Lang{checkAll} = <
  • EOF @@ -1112,8 +1119,8 @@ EOF $Lang{Home} = "Home"; $Lang{Browse} = "Datensicherungen anzeigen"; -$Lang{Last_bad_XferLOG} = "Letzte bad XferLOG"; -$Lang{Last_bad_XferLOG_errors_only} = "Letzte bad XferLOG (nur Fehler)"; +$Lang{Last_bad_XferLOG} = "Letztes fehlerhafte XferLOG"; +$Lang{Last_bad_XferLOG_errors_only} = "Letztes fehlerhafte XferLOG (nur Fehler)"; $Lang{This_display_is_merged_with_backup} = < Diese Liste ist mit Backup #\$numF verbunden. @@ -1131,7 +1138,7 @@ Klicken Sie auf die Restore Nummer (Restore#) f - + @@ -1172,7 +1179,7 @@ $Lang{off} = "aus"; $Lang{backupType_full} = "voll"; $Lang{backupType_incr} = "inkrementell"; -$Lang{backupType_partial} = "partiell"; +$Lang{backupType_partial} = "unvollständig"; $Lang{failed} = "fehler"; $Lang{success} = "erfolgreich"; @@ -1196,9 +1203,9 @@ $Lang{Reason_backup_failed} = "Backup Fehler"; $Lang{Reason_restore_failed} = "Restore Fehler"; $Lang{Reason_archive_failed} = "Archivierung Fehler"; $Lang{Reason_no_ping} = "nicht erreichbar"; -$Lang{Reason_backup_canceled_by_user} = "Abbruch durch User"; -$Lang{Reason_restore_canceled_by_user} = "Abbruch durch User"; -$Lang{Reason_archive_canceled_by_user} = "Archivierung abgebrochen durch User"; +$Lang{Reason_backup_canceled_by_user} = "Abbruch durch Benutzer"; +$Lang{Reason_restore_canceled_by_user} = "Abbruch durch Benutzer"; +$Lang{Reason_archive_canceled_by_user} = "Archivierung abgebrochen durch Benutzer"; # --------- # Email messages diff --git a/lib/BackupPC/Lang/en.pm b/lib/BackupPC/Lang/en.pm index eb629f1..1276dd0 100644 --- a/lib/BackupPC/Lang/en.pm +++ b/lib/BackupPC/Lang/en.pm @@ -59,10 +59,7 @@ EOF $Lang{H_BackupPC_Server_Status} = "BackupPC Server Status"; -$Lang{BackupPC_Server_Status}= < +$Lang{BackupPC_Server_Status_General_Info}= < @@ -82,6 +79,13 @@ $Lang{BackupPC_Server_Status}= < +EOF + +$Lang{BackupPC_Server_Status} = < +\$generalInfo \${h2("Currently Running Jobs")}

    @@ -901,7 +905,7 @@ $Lang{Archive___num_details_for__host} = "BackupPC: Archive #\$num details for \ $Lang{Archive___num_details_for__host2 } = < -

    Nummer \$Archives[\$i]{num}
    beauftragt von \$ArchiveReq{user}
    Auftrag Zeitpunkt \$reqTime
     alles auswählen - +
    Restore# Ergebnis Start Zeitpunkt Dauer/mins Dauer/min #Dateien Größe/MB #tar Fehler
    +
    diff --git a/lib/BackupPC/Lang/es.pm b/lib/BackupPC/Lang/es.pm index a595948..30dade2 100644 --- a/lib/BackupPC/Lang/es.pm +++ b/lib/BackupPC/Lang/es.pm @@ -6,37 +6,36 @@ # -------------------------------- -$Lang{Start_Archive} = "ENG Start Archive"; -$Lang{Stop_Dequeue_Archive} = "ENG Stop/Dequeue Archive"; +$Lang{Start_Archive} = "Comenzar archivado"; +$Lang{Stop_Dequeue_Archive} = "Parar/anular archivado"; $Lang{Start_Full_Backup} = "Comenzar copia de seguridad completa"; $Lang{Start_Incr_Backup} = "Comenzar copia de seguridad incremental"; $Lang{Stop_Dequeue_Backup} = "Parar/anular copia de seguridad"; $Lang{Restore} = "Restaurar"; -$Lang{Type_full} = "ENG full"; -$Lang{Type_incr} = "ENG incremental"; +$Lang{Type_full} = "completo"; +$Lang{Type_incr} = "incremental"; # ----- -$Lang{Only_privileged_users_can_view_admin_options} = "ENG Only privileged users can view admin options."; -$Lang{H_Admin_Options} = "ENG BackupPC Server: Admin Options"; -$Lang{Admin_Options} = "ENG Admin Options"; +$Lang{Only_privileged_users_can_view_admin_options} = "Sólo los superusuarios pueden ver las opciones de administración."; +$Lang{H_Admin_Options} = "Servidor BackupPC: Opciones de administración"; +$Lang{Admin_Options} = "Opciones de administración"; $Lang{Admin_Options_Page} = < -\${h2("Server Control")} +\${h2("Control del Servidor")}
    Number \$Archives[\$i]{num}
    Requested by \$ArchiveReq{user}
    Request time \$reqTime
    - -
    Reload the server configuration: + +
    Actualizar configuración del servidor:
    EOF @@ -47,11 +46,11 @@ $Lang{Unable_to_connect_to_BackupPC_server} = "Imposible conectar al servidor Ba "Quizá el servidor BackupPC no está activo o hay un " . " error de configuración. Por favor informe a su administrador de sistemas."; $Lang{Admin_Start_Server} = < -The BackupPC server at \$Conf{ServerHost} port \$Conf{ServerPort} -is not currently running (maybe you just stopped it, or haven't yet started it).
    -Do you want to start it? +El servidor BackupPC en \$Conf{ServerHost} port \$Conf{ServerPort} +no está en funcionamiento ahora (puede haberlo detenido o no haberlo arrancado aún).
    +¿Quiere inicializarlo? @@ -61,17 +60,14 @@ EOF $Lang{H_BackupPC_Server_Status} = "Estado del Servidor BackupPC"; -$Lang{BackupPC_Server_Status}= < +$Lang{BackupPC_Server_Status_General_Info}= <

  • El PID del servidor es \$Info{pid}, en el host \$Conf{ServerHost}, version \$Info{Version}, iniciado el \$serverStartTime.
  • Esta información de estado se ha generado el \$now. -
  • ENG The configuration was last loaded at \$configLoadTime +
  • La última configuración ha sido cargada a las \$configLoadTime
  • La cola de PC´s se activará de nuevo el \$nextWakeupTime.
  • Información adicional:
      @@ -84,6 +80,13 @@ $Lang{BackupPC_Server_Status}= <
    +EOF + +$Lang{BackupPC_Server_Status} = < +\$generalInfo \${h2("Trabajos en Ejecución")}

    @@ -116,7 +119,7 @@ EOF # -------------------------------- $Lang{BackupPC__Server_Summary} = "BackupPC: Resumen del Servidor"; -$Lang{BackupPC__Archive} = "ENG BackupPC: Archive"; +$Lang{BackupPC__Archive} = "BackupPC: Archivo"; $Lang{BackupPC_Summary}=< -There are \$hostCntGood hosts that have been backed up for a total size of \${fullSizeTot}GB +Hay \$hostCntGood hosts que tienen copia de seguridad con un tamaño total de \${fullSizeTot}GB

    @@ -216,8 +219,8 @@ There are \$hostCntGood hosts that have been backed up for a total size of \${fu EOF $Lang{BackupPC_Archive2} = < \$HostListStr @@ -237,14 +240,14 @@ About to archive the following hosts EOF $Lang{BackupPC_Archive2_location} = < - Archive Location/Device + + Ubicación de archivo/Dispositivo EOF $Lang{BackupPC_Archive2_compression} = < + Compression None
    @@ -255,15 +258,15 @@ ENG EOF $Lang{BackupPC_Archive2_parity} = < - Number of Parity Files + + Porcentaje de datos de paridad (0 = deshabilitado, 5 = normal) EOF $Lang{BackupPC_Archive2_split} = < - Split output into + + Dividir resultado en Megabytes EOF @@ -330,7 +333,7 @@ EOF # -------------------------------- $Lang{Only_privileged_users_can_view_queues_} = "Sólo los administradores pueden ver las colas."; # -------------------------------- -$Lang{Only_privileged_users_can_archive} = "ENG Only privileged users can Archive."; +$Lang{Only_privileged_users_can_archive} = "Sólo los administradores pueden archivar."; # -------------------------------- $Lang{BackupPC__Queue_Summary} = "BackupPC: Resumen de la Cola"; # -------------------------------- @@ -479,8 +482,8 @@ seleccionado ser EOF $Lang{Restore_Options_for__host_Option1_disabled} = <

    ¡Atención!: Dependiendo de que archivos/carpetas haya seleccionado, -este archivo puede ser muy grande. Podría tardar muchos minutos +este archivo puede ser muy grande. Podría tardar muchos minutos en crear y transferir el archivo. Además necesitará suficiente espacio el el disco local para almacenarlo.

    @@ -557,7 +560,7 @@ EOF # ------------------------------ -$Lang{Restore_Confirm_on__host} = "BackupPC: Restore Confirm on \$host"; +$Lang{Restore_Confirm_on__host} = "BackupPC: Confirme restauración en \$host"; $Lang{Are_you_sure} = < \$hiddenStr -Do you really want to do this? +¿Realmente quiere hacer esto? @@ -593,13 +596,13 @@ $Lang{Reply_from_server_was___reply} = < La respuesta del servidor fué: \$reply

    -ENG Go back to \$hostDest home page. +volver a \$hostDest home page. EOF $Lang{BackupPC_Archive_Reply_from_server} = < -Reply from server was: \$reply +La respuesta del servidor fué: \$reply EOF # ------------------------- @@ -712,14 +715,14 @@ EOF $Lang{Host__host_Archive_Summary} = "BackupPC: Host \$host Archive Summary"; $Lang{Host__host_Archive_Summary2} = < \$warnStr

      \$statusStr
    -\${h2("User Actions")} +\${h2("Acciones de usuario")}

    @@ -782,10 +785,10 @@ $Lang{Backup_browse_for__host} = < Está revisando la copia de seguridad Nº\$num, que comenzó hacia las \$backupTime (hace \$backupAge dias), \$filledBackup -
  • ENG Enter directory: +
  • Introduzca el directorio:
  • Haga click en uno de los directorios de abajo para revisar sus contenidos,
  • Haga click en un archivo para restaurarlo, -
  • ENG You can view the backup history of the current directory. +
  • Puede ver la copia de seguridad history del directorio actual.
  • @@ -821,32 +824,32 @@ This is now in the checkAll row EOF # ------------------------------ -$Lang{DirHistory_backup_for__host} = "(ENGLISH) BackupPC: Directory backup history for \$host"; +$Lang{DirHistory_backup_for__host} = "BackupPC: Histórico de copia de seguridad del directorio en \$host"; # # These two strings are used to build the links for directories and # file versions. Files are appended with a version number. # -$Lang{DirHistory_dirLink} = "ENG dir"; -$Lang{DirHistory_fileLink} = "ENG v"; +$Lang{DirHistory_dirLink} = "dir"; +$Lang{DirHistory_fileLink} = "v"; $Lang{DirHistory_for__host} = < -This display shows each unique version of files across all -the backups: +Esta pantalla muestra cada versión única de archivos de entre todas +las copias de seguridad:
      -
    • Click on a backup number to return to the backup browser, -
    • Click on a directory link (\$Lang->{DirHistory_dirLink}) to navigate - into that directory, -
    • Click on a file version link (\$Lang->{DirHistory_fileLink}0, - \$Lang->{DirHistory_fileLink}1, ...) to download that file, -
    • Files with the same contents between different backups have the same - version number, -
    • Files or directories not present in a particular backup have an - empty box. -
    • Files shown with the same version might have different attributes. - Select the backup number to see the file attributes. +
    • Haga click en un número de copia de seguridad para volver al explorador de copias de seguridad, +
    • Haga click en un vínculo de directorio (\$Lang->{DirHistory_dirLink}) para navegar + en ese directorio, +
    • Haga click en un vínculo de versión de archivo (\$Lang->{DirHistory_fileLink}0, + \$Lang->{DirHistory_fileLink}1, ...) para descargar ese archivo, +
    • Los archivos con diferentes contenidos entre distintas copias de seguridad tienen el mismo + número de versión, +
    • Los archivos o directorios que no existen en una copia concreta tienen una + celda vacía. +
    • Los archivos mostrados con la misma versión pueden tener diferentes atributos. + Seleccione el número de copia de seguridad para ver los atributos del archivo.
    \${h2("History of \${EscHTML(\$dirDisplay)}")} @@ -898,20 +901,20 @@ $Lang{Restore___num_details_for__host2} = < - - - - - - - - - EOF @@ -1117,7 +1120,7 @@ $Lang{fileHeader} = < ENG Select the backup you wish to view: +
  • Seleccione la copia de seguridad que desea ver: EOF $Lang{Restore_Summary} = < Click on the archive number for more details.
  • Number \$Archives[\$i]{num}
    Requested by \$ArchiveReq{user}
    Request time \$reqTime
    Result \$Archives[\$i]{result}
    Error Message \$Archives[\$i]{errorMsg}
    Start time \$startTime
    Duration \$duration min
    Xfer log file + + + + + + + + + @@ -920,7 +923,7 @@ ENG\${h1("Archive #\$num Details for \$host")} \${h1("Host list")}

    Número \$Archives[\$i]{num}
    Solicitado por \$ArchiveReq{user}
    Hora petición \$reqTime
    Resultado \$Archives[\$i]{result}
    Mensaje de error \$Archives[\$i]{errorMsg}
    Hora comienzo \$startTime
    Duración \$duration min
    Archivo registro Xfer View, Errors
    - + \$HostListStr
    HostBackup Number
    HostCopia de seguridad número
    EOF @@ -956,7 +959,7 @@ $Lang{Only_privileged_users_can_restore_backup_files} = "S $Lang{Bad_host_name} = "Nombre de host erróneo \${EscHTML(\$host)}"; $Lang{You_haven_t_selected_any_files__please_go_Back_to} = "No ha seleccionado nigún archivo; por favor, vuelva a" . " seleccione algunos archivos."; -$Lang{You_haven_t_selected_any_hosts} = "ENG You haven\'t selected any hosts; please go Back to" +$Lang{You_haven_t_selected_any_hosts} = "No ha seleccionado ningún host; por favor vuelva a" . " select some hosts."; $Lang{Nice_try__but_you_can_t_put} = "Buen intento, pero no puede usar \'..\' en los nombres de archivo"; $Lang{Host__doesn_t_exist} = "El Host \${EscHTML(\$In{hostDest})} no existe"; @@ -970,12 +973,12 @@ $Lang{Empty_host_name} = "Nombre de host vac $Lang{Unknown_host_or_user} = "Unknown host or user \${EscHTML(\$host)}"; $Lang{Only_privileged_users_can_view_information_about} = "Sólo los usuarios autorizados pueden ver información del" . " host \${EscHTML(\$host)}." ; -$Lang{Only_privileged_users_can_view_archive_information} = "ENG Only privileged users can view archive information."; +$Lang{Only_privileged_users_can_view_archive_information} = "Sólo los administradores pueden ver información de archivo."; $Lang{Only_privileged_users_can_view_restore_information} = "Sólo los usuarios autorizados pueden ver información de restauración."; $Lang{Restore_number__num_for_host__does_not_exist} = "El número de restauración \$num del host \${EscHTML(\$host)} " . " no existe."; -$Lang{Archive_number__num_for_host__does_not_exist} = "ENG Archive number \$num for host \${EscHTML(\$host)} does" - . " not exist."; +$Lang{Archive_number__num_for_host__does_not_exist} = "La copia de seguridad \$num del host \${EscHTML(\$host)} " + . " no existe."; $Lang{Can_t_find_IP_address_for} = "No puedo encontrar la dirección IP de \${EscHTML(\$host)}"; $Lang{host_is_a_DHCP_host} = <Host o usuario:"; $Lang{Go} = "Aceptar"; $Lang{Hosts} = "Hosts"; -$Lang{Select_a_host} = "ENGLISH Select a host..."; +$Lang{Select_a_host} = "Seleccione un host..."; -$Lang{There_have_been_no_archives} = "

    ENG There have been no archives

    \n"; +$Lang{There_have_been_no_archives} = "

    No ha habido archivos

    \n"; $Lang{This_PC_has_never_been_backed_up} = "

    !Nunca se ha hecho copia de seguridad de este PC!

    \n"; $Lang{This_PC_is_used_by} = "
  • This PC es utilizado por \${UserLink(\$user)}"; @@ -1100,9 +1103,9 @@ EOF $Lang{checkAllHosts} = <
  • - ENG Select all + Seleccionar todo - +
    - - + + \$ArchiveStr @@ -1178,7 +1181,7 @@ $Lang{off} = "inactivo"; $Lang{backupType_full} = "completo"; $Lang{backupType_incr} = "incremental"; -$Lang{backupType_partial} = "ENG partial"; +$Lang{backupType_partial} = "parcial"; $Lang{failed} = "fallido"; $Lang{success} = "éxito"; @@ -1196,15 +1199,15 @@ $Lang{Status_link_running} = "conexi $Lang{Reason_backup_done} = "copia de seguridad realizada"; $Lang{Reason_restore_done} = "restauración realizada"; -$Lang{Reason_archive_done} = "ENG archive done"; +$Lang{Reason_archive_done} = "archivado realizado"; $Lang{Reason_nothing_to_do} = "nada por hacer"; $Lang{Reason_backup_failed} = "copia de seguridad fallida"; $Lang{Reason_restore_failed} = "restauración fallida"; -$Lang{Reason_archive_failed} = "ENG archive failed"; +$Lang{Reason_archive_failed} = "ha fallado el archivado"; $Lang{Reason_no_ping} = "no hay ping"; $Lang{Reason_backup_canceled_by_user} = "copia cancelada por el usuario"; $Lang{Reason_restore_canceled_by_user} = "restauración cancelada por el usuario"; -$Lang{Reason_archive_canceled_by_user} = "ENG archive canceled by user"; +$Lang{Reason_archive_canceled_by_user} = "archivado cancelado por el usuario"; # --------- # Email messages @@ -1306,3 +1309,4 @@ $Lang{howLong_not_been_backed_up} = "no se le ha realizado una copia de segurida $Lang{howLong_not_been_backed_up_for_days_days} = "no se le ha realizado una copia de seguridad durante \$days días"; #end of lang_en.pm + diff --git a/lib/BackupPC/Lang/fr.pm b/lib/BackupPC/Lang/fr.pm index 279d32d..240c009 100644 --- a/lib/BackupPC/Lang/fr.pm +++ b/lib/BackupPC/Lang/fr.pm @@ -59,10 +59,7 @@ EOF $Lang{H_BackupPC_Server_Status} = "État du serveur BackupPC"; -$Lang{BackupPC_Server_Status}= < +$Lang{BackupPC_Server_Status_General_Info}= < @@ -82,6 +79,13 @@ $Lang{BackupPC_Server_Status}= < +EOF + +$Lang{BackupPC_Server_Status} = < +\$generalInfo \${h2("Travaux en cours d'exécution")}

    @@ -899,7 +903,7 @@ $Lang{Archive___num_details_for__host} = "BackupPC: D $Lang{Archive___num_details_for__host2 } = < -

    Archive# Result Start Date Resultado Hora comienzo Dur/mins
    +
    diff --git a/lib/BackupPC/Lang/it.pm b/lib/BackupPC/Lang/it.pm index b821a80..d662030 100644 --- a/lib/BackupPC/Lang/it.pm +++ b/lib/BackupPC/Lang/it.pm @@ -1,6 +1,6 @@ #!/bin/perl # -# $Id: it.pm,v 1.6 2004/04/10 06:52:47 cbarratt Exp $ +# $Id: it.pm,v 1.7 2004/05/21 02:11:35 cbarratt Exp $ # # Italian i18n file # @@ -64,10 +64,7 @@ EOF $Lang{H_BackupPC_Server_Status} = "Stato server BackupPC"; -$Lang{BackupPC_Server_Status}= < +$Lang{BackupPC_Server_Status_General_Info}= < @@ -89,6 +86,13 @@ $Lang{BackupPC_Server_Status}= < +EOF + +$Lang{BackupPC_Server_Status} = < +\$generalInfo \${h2("Processi attualmente in esecuzione")}

    @@ -262,7 +266,7 @@ EOF $Lang{BackupPC_Archive2_parity} = < -

    + EOF @@ -910,7 +914,7 @@ $Lang{Archive___num_details_for__host} = "BackupPC: Dettagli archivio n. \$num p $Lang{Archive___num_details_for__host2 } = < -
    Numéro \$Archives[\$i]{num}
    Demandé par \$ArchiveReq{user}
    Heure de demande \$reqTime
    ENG Percentage of Parity Data (0 = disable, 5 = typical)Percentuale di dati di parità (0 = disabiltata, 5 = valori tipici)
    +
    diff --git a/lib/BackupPC/Xfer/Rsync.pm b/lib/BackupPC/Xfer/Rsync.pm index 338ca56..d3358c9 100644 --- a/lib/BackupPC/Xfer/Rsync.pm +++ b/lib/BackupPC/Xfer/Rsync.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 2.1.0beta1, released 9 Apr 2004. +# Version 2.1.0beta2, released 9 May 2004. # # See http://backuppc.sourceforge.net. # @@ -55,7 +55,7 @@ BEGIN { # # Note: also update configure.pl when this version number is changed! # - if ( $File::RsyncP::VERSION < 0.50 ) { + if ( $File::RsyncP::VERSION < 0.51 ) { $RsyncLibOK = 0; $RsyncLibErr = "File::RsyncP module version too old: need 0.50"; } else { @@ -324,6 +324,7 @@ sub start $str .= "\n"; $t->{XferLOG}->write(\$str); }, + cacheCheckProb => $conf->{RsyncCsumCacheVerifyProb}, %$fioArgs, }), }); diff --git a/lib/BackupPC/Xfer/RsyncDigest.pm b/lib/BackupPC/Xfer/RsyncDigest.pm index be0b24b..07d5a10 100644 --- a/lib/BackupPC/Xfer/RsyncDigest.pm +++ b/lib/BackupPC/Xfer/RsyncDigest.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 2.1.0beta1, released 9 Apr 2004. +# Version 2.1.0beta2, released 9 May 2004. # # See http://backuppc.sourceforge.net. # @@ -38,9 +38,32 @@ package BackupPC::Xfer::RsyncDigest; use strict; +use BackupPC::FileZIO; use vars qw( $RsyncLibOK ); use Carp; +require Exporter; +use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS ); + +my $Log = \&logHandler; + +# +# Magic value for checksum seed. We only cache block and file digests +# when the checksum seed matches this value. +# +use constant RSYNC_CSUMSEED_CACHE => 32761; + +@ISA = qw(Exporter); + +@EXPORT = qw( ); + +@EXPORT_OK = qw( + RSYNC_CSUMSEED_CACHE + ); + +%EXPORT_TAGS = ( + 'all' => [ @EXPORT_OK ], +); BEGIN { eval "use File::RsyncP;"; @@ -72,25 +95,53 @@ sub blockSize return $blkSize; } +sub fileDigestIsCached +{ + my($class, $file) = @_; + my $data; + + open(my $fh, "<", $file) || return -1; + binmode($fh); + return -2 if ( sysread($fh, $data, 1) != 1 ); + close($fh); + return $data eq chr(0xd6) ? 1 : 0; +} + # # Compute and add rsync block and file digests to the given file. # +# Empty files don't get cached checksums. +# +# If verify is set then existing cached checksums are checked. +# +# Returns 0 on success. Returns 1 on good verify and 2 on bad verify. +# Returns a variety of negative values on error. +# sub digestAdd { - my($class, $file, $blockSize, $checksumSeed) = @_; + my($class, $file, $blockSize, $checksumSeed, $verify) = @_; + my $retValue = 0; + + # + # Don't cache checksums if the checksumSeed is not RSYNC_CSUMSEED_CACHE + # or if the file is empty. + # + return -100 if ( $checksumSeed != RSYNC_CSUMSEED_CACHE || !-s $file ); + if ( $blockSize == 0 ) { - print("bogus digestAdd($file, $blockSize, $checksumSeed)\n"); + &$Log("digestAdd: bad blockSize ($file, $blockSize, $checksumSeed)"); $blockSize = 2048; } my $nBlks = int(65536 * 16 / $blockSize) + 1; my($data, $blockDigest, $fileDigest); - return if ( !$RsyncLibOK ); + return -101 if ( !$RsyncLibOK ); my $digest = File::RsyncP::Digest->new; $digest->add(pack("V", $checksumSeed)) if ( $checksumSeed ); - return -1 if ( !defined(my $fh = BackupPC::FileZIO->open($file, 0, 1)) ); + return -102 if ( !defined(my $fh = BackupPC::FileZIO->open($file, 0, 1)) ); + while ( 1 ) { $fh->read(\$data, $nBlks * $blockSize); last if ( $data eq "" ); @@ -113,18 +164,56 @@ sub digestAdd # length($metaData), # $file, # $eofPosn); - open(my $fh2, "+<", $file) || return -2; + open(my $fh2, "+<", $file) || return -103; binmode($fh2); - return -3 if ( sysread($fh2, $data, 1) != 1 ); + return -104 if ( sysread($fh2, $data, 1) != 1 ); if ( $data ne chr(0x78) && $data ne chr(0xd6) ) { - printf("Unexpected first char 0x%x\n", ord($data)); - return -4; + &$Log(sprintf("digestAdd: $file has unexpected first char 0x%x", + ord($data))); + return -105; + } + return -106 if ( sysseek($fh2, $eofPosn, 0) != $eofPosn ); + if ( $verify ) { + my $data3; + + # + # Verify the cached checksums + # + return -107 if ( $data ne chr(0xd6) ); + return -108 if ( sysread($fh2, $data3, length($data2) + 1) < 0 ); + if ( $data2 eq $data3 ) { + return 1; + } + # + # Checksums don't agree - fall through so we rewrite the data + # + &$Log("digestAdd: $file verify failed; redoing checksums"); + return -109 if ( sysseek($fh2, $eofPosn, 0) != $eofPosn ); + $retValue = 2; } - return -5 if ( sysseek($fh2, $eofPosn, 0) != $eofPosn ); - return -6 if ( syswrite($fh2, $data2) != length($data2) ); - return -7 if ( !defined(sysseek($fh2, 0, 0)) ); - return -8 if ( syswrite($fh2, chr(0xd6)) != 1 ); + return -110 if ( syswrite($fh2, $data2) != length($data2) ); + if ( $verify ) { + # + # Make sure there is no extraneous data on the end of + # the file. Seek to the end and truncate if it doesn't + # match our expected length. + # + return -111 if ( !defined(sysseek($fh2, 0, 2)) ); + if ( tell($fh2) != $eofPosn + length($data2) ) { + if ( !truncate($fh2, $eofPosn + length($data2)) ) { + &$Log(sprintf("digestAdd: $file truncate from %d to %d failed", + tell($fh2), $eofPosn + length($data2))); + return -112; + } else { + &$Log(sprintf("digestAdd: $file truncated from %d to %d", + tell($fh2), $eofPosn + length($data2))); + } + } + } + return -113 if ( !defined(sysseek($fh2, 0, 0)) ); + return -114 if ( syswrite($fh2, chr(0xd6)) != 1 ); close($fh2); + return $retValue; } # @@ -132,6 +221,17 @@ sub digestAdd # if they exist and the block size and checksum seed match. Otherwise # we compute the checksums from the file contents. # +# The doCache flag can take three ranges: +# +# - doCache < 0: don't generate/use cached checksums +# - doCache == 0: don't generate, but do use cached checksums if available +# - doCache > 0: generate (if necessary) and use cached checksums +# +# Note: caching is only enabled when compression is on and the +# checksum seed is RSYNC_CSUMSEED_CACHE (32761). +# +# Returns 0 on success. Returns a variety of negative values on error. +# sub digestStart { my($class, $fileName, $fileSize, $blockSize, $defBlkSize, @@ -141,20 +241,23 @@ sub digestStart my $data; - my $fio = bless { + my $dg = bless { name => $fileName, needMD4 => $needMD4, digest => File::RsyncP::Digest->new, }, $class; - if ( $fileSize > 0 && $compress ) { + if ( $fileSize > 0 && $compress && $doCache >= 0 ) { open(my $fh, "<", $fileName) || return -2; binmode($fh); return -3 if ( read($fh, $data, 1) != 1 ); - if ( $data eq chr(0x78) && $doCache && $checksumSeed == 32761 ) { + my $ret; + + if ( $data eq chr(0x78) && $doCache > 0 + && $checksumSeed == RSYNC_CSUMSEED_CACHE ) { # - # 32761 is the magic number that rsync uses for checksumSeed - # with the --fixed-csum option. + # RSYNC_CSUMSEED_CACHE (32761) is the magic number that + # rsync uses for checksumSeed with the --fixed-csum option. # # We now add the cached checksum data to the file. There # is a possible race condition here since two BackupPC_dump @@ -164,48 +267,57 @@ sub digestStart # in which they write it doesn't matter. # close($fh); - $fio->digestAdd($fileName, - $blockSize - || BackupPC::Xfer::RsyncDigest->blockSize($fileSize, - $defBlkSize), - $checksumSeed); + $ret = $dg->digestAdd($fileName, + $blockSize + || BackupPC::Xfer::RsyncDigest->blockSize( + $fileSize, $defBlkSize), + $checksumSeed); + if ( $ret < 0 ) { + &$Log("digestAdd($fileName) failed ($ret)"); + } # # now re-open the file and re-read the first byte # - open($fh, "<", $fileName) || return -2; + open($fh, "<", $fileName) || return -4; binmode($fh); - return -3 if ( read($fh, $data, 1) != 1 ); + return -5 if ( read($fh, $data, 1) != 1 ); } - if ( $data eq chr(0xd6) ) { + if ( $ret >= 0 && $data eq chr(0xd6) ) { # # Looks like this file has cached checksums # Read the last 48 bytes: that's 2 file MD4s (32 bytes) # plus 4 words of meta data # - return -4 if ( !defined(seek($fh, -48, 2)) ); - return -5 if ( read($fh, $data, 48) != 48 ); - ($fio->{md4DigestOld}, - $fio->{md4Digest}, - $fio->{blockSize}, - $fio->{checksumSeed}, - $fio->{nBlocks}, - $fio->{magic}) = unpack("a16 a16 V V V V", $data); - if ( $fio->{magic} == 0x5fe3c289 - && $fio->{checksumSeed} == $checksumSeed - && ($blockSize == 0 || $fio->{blockSize} == $blockSize) ) { - $fio->{fh} = $fh; - $fio->{cached} = 1; + return -6 if ( !defined(seek($fh, -48, 2)) ); + return -7 if ( read($fh, $data, 48) != 48 ); + ($dg->{md4DigestOld}, + $dg->{md4Digest}, + $dg->{blockSize}, + $dg->{checksumSeed}, + $dg->{nBlocks}, + $dg->{magic}) = unpack("a16 a16 V V V V", $data); + if ( $dg->{magic} == 0x5fe3c289 + && $dg->{checksumSeed} == $checksumSeed + && ($blockSize == 0 || $dg->{blockSize} == $blockSize) ) { + $dg->{fh} = $fh; + $dg->{cached} = 1; + # + # position the file at the start of the rsync block checksums + # (4 (adler) + 16 (md4) bytes each) + # + return -8 + if ( !defined(seek($fh, -$dg->{nBlocks}*20 - 48, 2)) ); } else { + # + # cached checksums are not valid, so we close the + # file and treat it as uncached. + # + $dg->{cachedInvalid} = 1; close($fh); } - # - # position the file at the start of the rsync block checksums - # (4 (adler) + 16 (md4) bytes each) - # - return -6 if ( !defined(seek($fh, -$fio->{nBlocks}*20 - 48, 2)) ); } } - if ( !$fio->{cached} ) { + if ( !$dg->{cached} ) { # # This file doesn't have cached checksums, or the checksumSeed # or blocksize doesn't match. Open the file and prepare to @@ -214,70 +326,104 @@ sub digestStart $blockSize = BackupPC::Xfer::RsyncDigest->blockSize($fileSize, $defBlkSize) if ( $blockSize == 0 ); - $fio->{checksumSeed} = $checksumSeed; - $fio->{blockSize} = $blockSize; - $fio->{fh} = BackupPC::FileZIO->open($fileName, 0, $compress); - return -7 if ( !defined($fio->{fh}) ); + $dg->{checksumSeed} = $checksumSeed; + $dg->{blockSize} = $blockSize; + $dg->{fh} = BackupPC::FileZIO->open($fileName, 0, $compress); + return -9 if ( !defined($dg->{fh}) ); if ( $needMD4) { - $fio->{csumDigest} = File::RsyncP::Digest->new; - $fio->{csumDigest}->add(pack("V", $fio->{checksumSeed})); + $dg->{csumDigest} = File::RsyncP::Digest->new; + $dg->{csumDigest}->add(pack("V", $dg->{checksumSeed})); } } - return (undef, $fio, $fio->{blockSize}); + return (undef, $dg, $dg->{blockSize}); } sub digestGet { - my($fio, $num, $csumLen) = @_; + my($dg, $num, $csumLen, $noPad) = @_; my($fileData); - my $blockSize = $fio->{blockSize}; + my $blockSize = $dg->{blockSize}; - if ( $fio->{cached} ) { + if ( $dg->{cached} ) { my $thisNum = $num; - $thisNum = $fio->{nBlocks} if ( $thisNum > $fio->{nBlocks} ); - read($fio->{fh}, $fileData, 20 * $thisNum); - $fio->{nBlocks} -= $thisNum; - if ( $thisNum < $num ) { + $thisNum = $dg->{nBlocks} if ( $thisNum > $dg->{nBlocks} ); + read($dg->{fh}, $fileData, 20 * $thisNum); + $dg->{nBlocks} -= $thisNum; + if ( $thisNum < $num && !$noPad) { # # unexpected shortfall of data; pad with zero digest # $fileData .= pack("c", 0) x (20 * ($num - $thisNum)); } - return $fio->{digest}->blockDigestExtract($fileData, $csumLen); + return $dg->{digest}->blockDigestExtract($fileData, $csumLen); } else { - if ( $fio->{fh}->read(\$fileData, $blockSize * $num) <= 0 ) { + if ( $dg->{fh}->read(\$fileData, $blockSize * $num) <= 0 ) { # # unexpected shortfall of data; pad with zeros # - $fileData = pack("c", 0) x ($blockSize * $num); + $fileData = pack("c", 0) x ($blockSize * $num) if ( !$noPad ); } - $fio->{csumDigest}->add($fileData) if ( $fio->{needMD4} ); - return $fio->{digest}->blockDigest($fileData, $blockSize, - $csumLen, $fio->{checksumSeed}); + $dg->{csumDigest}->add($fileData) if ( $dg->{needMD4} ); + return $dg->{digest}->blockDigest($fileData, $blockSize, + $csumLen, $dg->{checksumSeed}); } } sub digestEnd { - my($fio) = @_; + my($dg, $skipMD4) = @_; my($fileData); - if ( $fio->{cached} ) { - close($fio->{fh}); - return $fio->{md4DigestOld} if ( $fio->{needMD4} ); + if ( $dg->{cached} ) { + close($dg->{fh}); + return $dg->{md4DigestOld} if ( $dg->{needMD4} ); } else { # # make sure we read the entire file for the file MD4 digest # - if ( $fio->{needMD4} ) { + if ( $dg->{needMD4} && !$skipMD4 ) { my $fileData; - while ( $fio->{fh}->read(\$fileData, 65536) > 0 ) { - $fio->{csumDigest}->add($fileData); + while ( $dg->{fh}->read(\$fileData, 65536) > 0 ) { + $dg->{csumDigest}->add($fileData); } } - $fio->{fh}->close(); - return $fio->{csumDigest}->digest if ( $fio->{needMD4} ); + $dg->{fh}->close(); + return $dg->{csumDigest}->digest if ( $dg->{needMD4} ); } } +sub isCached +{ + my($dg) = @_; + + return wantarray ? ($dg->{cached}, $dg->{cachedInvalid}) : $dg->{cached}; +} + +sub blockSizeCurr +{ + my($dg) = @_; + + return $dg->{blockSize}; +} + +# +# Default log handler +# +sub logHandler +{ + my($str) = @_; + + print(STDERR $str, "\n"); +} + +# +# Set log handler to a new subroutine. +# +sub logHandlerSet +{ + my($sub) = @_; + + $Log = $sub; +} + 1; diff --git a/lib/BackupPC/Xfer/RsyncFileIO.pm b/lib/BackupPC/Xfer/RsyncFileIO.pm index b028b65..4d2dcb8 100644 --- a/lib/BackupPC/Xfer/RsyncFileIO.pm +++ b/lib/BackupPC/Xfer/RsyncFileIO.pm @@ -12,7 +12,7 @@ # #======================================================================== # -# Version 2.1.0beta1, released 9 Apr 2004. +# Version 2.1.0beta2, released 9 May 2004. # # See http://backuppc.sourceforge.net. # @@ -24,7 +24,7 @@ use strict; use File::Path; use BackupPC::Attrib qw(:all); use BackupPC::View; -use BackupPC::Xfer::RsyncDigest; +use BackupPC::Xfer::RsyncDigest qw(:all); use BackupPC::PoolWrite; use constant S_IFMT => 0170000; # type of file @@ -97,6 +97,7 @@ sub logHandlerSet { my($fio, $sub) = @_; $fio->{logHandler} = $sub; + BackupPC::Xfer::RsyncDigest->logHandlerSet($sub); } # @@ -104,17 +105,55 @@ sub logHandlerSet # sub csumStart { - my($fio, $f, $needMD4, $defBlkSize) = @_; + my($fio, $f, $needMD4, $defBlkSize, $phase) = @_; $defBlkSize ||= $fio->{blockSize}; my $attr = $fio->attribGet($f); $fio->{file} = $f; $fio->csumEnd if ( defined($fio->{csum}) ); return -1 if ( $attr->{type} != BPC_FTYPE_FILE ); + # + # Rsync uses short checksums on the first phase. If the whole-file + # checksum fails, then the file is repeated with full checksums. + # So on phase 2 we verify the checksums if they are cached. + # + if ( ($phase > 0 || rand(1) < $fio->{cacheCheckProb}) + && $attr->{compress} + && $fio->{checksumSeed} == RSYNC_CSUMSEED_CACHE ) { + my($err, $d, $blkSize) = BackupPC::Xfer::RsyncDigest->digestStart( + $attr->{fullPath}, $attr->{size}, 0, + $defBlkSize, $fio->{checksumSeed}, + 0, $attr->{compress}, 0); + my($isCached, $isInvalid) = $d->isCached; + if ( $fio->{logLevel} >= 5 ) { + $fio->log("$attr->{fullPath} verify; cached = $isCached," + . " invalid = $isInvalid, phase = $phase"); + } + if ( $isCached || $isInvalid ) { + my $ret = BackupPC::Xfer::RsyncDigest->digestAdd( + $attr->{fullPath}, $blkSize, + $fio->{checksumSeed}, 1 # verify + ); + if ( $ret != 1 ) { + $fio->log("Bad cached digest for $attr->{fullPath} ($ret);" + . " fixed"); + $fio->{stats}{errorCnt}++; + } else { + $fio->log("$f->{name}: verified cached digest") + if ( $fio->{logLevel} >= 2 ); + } + } + $d->digestEnd; + } (my $err, $fio->{csum}, my $blkSize) = BackupPC::Xfer::RsyncDigest->digestStart($attr->{fullPath}, $attr->{size}, 0, $defBlkSize, $fio->{checksumSeed}, $needMD4, $attr->{compress}, 1); + if ( $fio->{logLevel} >= 5 ) { + my($isCached, $invalid) = $fio->{csum}->isCached; + $fio->log("$attr->{fullPath} cache = $isCached," + . " invalid = $invalid, phase = $phase"); + } if ( $err ) { $fio->log("Can't get rsync digests from $attr->{fullPath}" . " (err=$err, name=$f->{name})"); @@ -192,9 +231,9 @@ sub checksumSeed $fio->{checksumSeed} = $checksumSeed; $fio->log("Checksum caching enabled (checksumSeed = $checksumSeed)") - if ( $fio->{logLevel} >= 1 && $checksumSeed == 32761 ); + if ( $fio->{logLevel} >= 1 && $checksumSeed == RSYNC_CSUMSEED_CACHE ); $fio->log("Checksum seed is $checksumSeed") - if ( $fio->{logLevel} >= 2 && $checksumSeed != 32761 ); + if ( $fio->{logLevel} >= 2 && $checksumSeed != RSYNC_CSUMSEED_CACHE ); } sub dirs @@ -876,7 +915,7 @@ sub fileDeltaRxNext # sub fileDeltaRxDone { - my($fio, $md4) = @_; + my($fio, $md4, $phase) = @_; my $name = $1 if ( $fio->{rxFile}{name} =~ /(.*)/ ); my $ret; @@ -903,12 +942,17 @@ sub fileDeltaRxDone = BackupPC::Xfer::RsyncDigest->digestStart( $attr->{fullPath}, $attr->{size}, 0, 2048, $fio->{checksumSeed}, 1, - $attr->{compress}); + $attr->{compress}, 1); if ( $err ) { $fio->log("Can't open $attr->{fullPath} for MD4" . " check (err=$err, $name)"); $fio->{stats}{errorCnt}++; } else { + if ( $fio->{logLevel} >= 5 ) { + my($isCached, $invalid) = $csum->isCached; + $fio->log("MD4 $attr->{fullPath} cache = $isCached," + . " invalid = $invalid"); + } $newDigest = $csum->digestEnd; } $fio->{rxSize} = $attr->{size}; @@ -930,7 +974,13 @@ sub fileDeltaRxDone $fio->log("$name got digests $md4Str vs $newStr") } if ( $md4 ne $newDigest ) { - $fio->log("$name: fatal error: md4 doesn't match"); + if ( $phase > 0 ) { + $fio->log("$name: fatal error: md4 doesn't match on retry;" + . " file removed"); + } else { + $fio->log("$name: md4 doesn't match: will retry in phase 1;" + . " file removed"); + } $fio->{stats}{errorCnt}++; if ( defined($fio->{rxOutFd}) ) { $fio->{rxOutFd}->close; diff --git a/lib/BackupPC/Xfer/Smb.pm b/lib/BackupPC/Xfer/Smb.pm index ebdff99..6886397 100644 --- a/lib/BackupPC/Xfer/Smb.pm +++ b/lib/BackupPC/Xfer/Smb.pm @@ -304,6 +304,7 @@ sub readOutput || /^\s*restore directory \\/i || /^\s*Output is \/dev\/null/i || /^\s*Timezone is/i + || /^\s*tar_re_search set/i || /^\s*creating lame (up|low)case table/i ) { # ignore these messages diff --git a/makeDist b/makeDist index ebddca8..2ed1a08 100755 --- a/makeDist +++ b/makeDist @@ -42,8 +42,8 @@ use Getopt::Std; umask(0022); -my $Version = "2.1.0beta1"; -my $ReleaseDate = "9 Apr 2004"; +my $Version = "2.1.0beta2"; +my $ReleaseDate = "20 May 2004"; my $DistDir = "dist/BackupPC-$Version"; my @PerlSrc = qw( @@ -235,13 +235,13 @@ sub InstallFile # # fixup for perl 5.6.x # - if ( !/A NAME="item_%24Conf/i ) { + if ( !/A NAME="item_(%|_)24Conf/i ) { s/\$Conf{([^}]*)}/ defined($ConfName{$1}) ? "\L\E\$Conf{$1}<\/A>" : "\$Conf{$1}"/eg; } - s/<(A NAME="item_%24Conf%7B.*?%7D).*?">/\L<$1">/ig; + s/<(A NAME="item_(%|_)24Conf(%|_)7B(.*?)(%|_)7D).*?">/\L/ig; s/^
    /

    /; # # fixup for perl 5.8.x @@ -407,6 +407,7 @@ sub CheckLangUsage s/\$Lang{([^}]*)}/ my $var = $1; next if ( $var =~ m{^(Reason_|Status_|backupType_)} ); + next if ( $var eq "Documentation" ); if ( !defined($vars->{$var}) ) { print("Unexpected Lang var $var in $f\n"); $errors++; -- 2.20.1

    Number \$Archives[\$i]{num}
    Requested by \$ArchiveReq{user}
    Request time \$reqTime