BackupPC Patch 3.3.1-1

BackupPC ist eine freie Disk-zu-Disk Backup-Suite mit einem webbasierten Frontend. Es ist kein spezieller Client notwendig, da der Server selbst unterschiedliche Protokolle unterstützt.
Antworten
Benutzeravatar
THE-AB
Administrator
Beiträge: 15
Registriert: So 10. Apr 2016, 15:40

BackupPC Patch 3.3.1-1

Beitrag von THE-AB » So 10. Apr 2016, 18:25

Nach vielen erfolglosen versuchen die Version 3.3.1 zu installieren oder Aktualisieren habe ich jetzt diesen Patch erstellt,

bei mir läuft BackupPC 24/7 und macht täglich erfolgreich backups von verschiedenen Client´s

zusätzlich beinhaltet dieser Patch 2 neue Dateien,
BackupPC_fixPoolMdsums
BackupPC_verifyPool

Download
BackupPC-patch3.3.1-1.zip
(332.74 KiB) 396-mal heruntergeladen
dieser Patch lässt sich auch in bereits konfigurierte installationen einspielen, dafür bei Punkt 3 weiter machen

Installation BackupPC (Debian Jessie)

1. als erstes wird ein System Update gemacht und anschliessend BackupPC über das debian Repository installiert

Code: Alles auswählen

apt-get update && apt-get dist-upgrade
apt-get install backuppc
2. nach erfolgreicher Installation wird das Passwort für den Webinterface Zugriff geändert

Code: Alles auswählen

htpasswd /etc/backuppc/htpasswd backuppc
3. jetzt wird BackupPC gestoppt

Code: Alles auswählen

/etc/init.d/backuppc stop
4. nun wird der Patch auf den Server kopiert, das Archiv beinhaltet die genaue Verzeichnissstruktur wie die Installation,
BackupPC ist in diesem fall in /usr/share/backuppc installiert, das Archiv beinhaltet einen Ordner usr der über den Ordner auf dem Server kopiert wird und somit die Dateien überschreibt die verändert wurden, anschliessend wird BackupPC gestartet

Code: Alles auswählen

/etc/init.d/backuppc start
backuppc-patch.JPG
backuppc-patch.JPG (131.13 KiB) 2785 mal betrachtet
BackupPC_fixPoolMdsums

Code: Alles auswählen

#!/usr/bin/perl
#============================================================= -*-perl-*-
#
# BackupPC_fixPoolMdsums: Rename/move pool files if mdsum path name invalid
#
# DESCRIPTION
#   See 'usage' for more detailed description of what it does
#   
# AUTHOR
#   Jeff Kosowsky
#
# COPYRIGHT
#   Copyright (C) 2011  Jeff Kosowsky
#
#   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.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#========================================================================
#
# Version 0.2, released January 2011 (BackupPC_fixPoolMdsums)
# Version 3.3.1-1, patched 8 Apr 2016.
#
#========================================================================

use strict;
use warnings;

use lib "/usr/share/BackupPC/lib";
use BackupPC::Lib;
use BackupPC::jLib 0.4.0;  # Requires version >= 0.4.0
use File::Glob ':glob';
use Getopt::Long qw(:config no_ignore_case bundling);

#Variables
my $bpc = BackupPC::Lib->new or die("BackupPC::Lib->new failed\n");
my $md5 = Digest::MD5->new;
my $MAXLINKS = $bpc->{Conf}{HardLinkMax};

#Option variables:
my $Force;
my $warndups;
my $outfile;
my $TopDir = my	$TopDir_def = $bpc->{TopDir};
my $verbose=0;
#$dryrun=0;  #Global variable defined in jLib.pm (do not use 'my')
$dryrun=1;  #Global variable defined in jLib.pm (do not use 'my')

usage() unless( 
	GetOptions( 
		"dryrun|d!"        => \$dryrun,
		"Force"          => \$Force,     #Override stuff...
		"outfile|o=s"      => \$outfile,
		"topdir|t=s"       => \$TopDir,    #Location of TopDir
		"verbose|v+"       => \$verbose,   #Verbosity (repeats allowed)
		"warndups|w"       => \$warndups,  #Warn if dup created in new chain
	)
	&& defined $outfile
	);

#############################################################################
if($TopDir ne $TopDir_def) {
	#NOTE: if we are not using the TopDir in the config file, then we
	# need to manually override the settings of BackupPC::Lib->new
	# which *doesn't* allow you to set TopDir (even though it seems so
	# from the function definition, it gets overwritten later when the
	# config file is read)
	$TopDir =~ s|//*|/|g; #Remove any lurking double slashes
	$TopDir =~ s|/*$||g; #Remove trailing slash
	$bpc->{TopDir} = $TopDir;
	$bpc->{Conf}{TopDir} = $TopDir;

	$bpc->{storage}->setPaths({TopDir => $TopDir});
	$bpc->{PoolDir}  = "$bpc->{TopDir}/pool";
	$bpc->{CPoolDir} = "$bpc->{TopDir}/cpool";
}

%Conf   = $bpc->Conf(); #Global variable defined in jLib.pm (do not use 'my')
#############################################################################
my $compress = $Conf{CompressLevel};
my $pool = $compress > 0 ? "cpool" : "pool";
my $compare = $compress > 0 ? \&zcompare2 : \&jcompare;
my $file2md5 = $compress > 0 ? \&zFile2MD5 : \&File2MD5;

my ($OUT);
die "ERROR: '$outfile' already exists!\n" if -e $outfile;
open($OUT, '>', "$outfile") or
	die "ERROR: Can't open '$outfile' for writing!($!)\n";

chdir $TopDir;

if(!$Force && 
   (my @partialbackups = glob("pc/*/NewFileList{,.[0-9]*}"))) {
	die("ERROR: Pool conflicts will occur if NewFileList present (--Force overrides):\n          " . 
		join('\n          ', @partialbackups) . "\n");
}

system("$bpc->{InstallDir}/bin/BackupPC_serverMesg status jobs >/dev/null 2>&1");
unless(($? >>8) == 1) {
	die "Dangerous to run when BackupPC is running!!!\n"
		if $TopDir eq $TopDir_def;
	warn "WARNING: May be dangerous to run when BackupPC is running!!!\n"; 
    #Warn but don't die if *appear* to be in different TopDir
}

my $totalfiles = 0;
my $md5errors = 0;
my $fixed = 0;
my $badpoolentry = 0;
my $chaindups = 0;
my $norename = 0;
my $renumbererr = 0;

scan_pool($pool);

#Note: Total = total pool files scanned
#     NotFixed = NoRename (i.e. rename fails - shouldn't happen...)
#     ChainDups (only calcualted if --warndups set)
#     RenumberErrs = Errors renumbering old chain after move (shouldn't happen...)
printf("Total=%d Md5PathErrors=%d [Fixed=%d, NotFixed=%d]%s\n",
	   $totalfiles, $md5errors, $fixed, ($md5errors-$fixed), 
	   ($dryrun ? " DRY-RUN" : ""));
printf("BadPoolEntries=%d RenumberErrs=%d\n", $badpoolentry, $renumbererr);
printf("ChainDups=%d\n", $chaindups) if $warndups;
print "\n";
exit;

#######################################################################
#Run through the pool looking for misnamed md5sum paths
sub scan_pool
{
	my ($fpool) = @_;
	my ($dh, @fstat);

	return unless glob("$fpool/[0-9a-f]"); #No entries in pool
	my @hexlist = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
	my ($idir, $jdir, $kdir);
	foreach my $i (@hexlist) {
		print STDERR "\n**$fpool/$i: " if $verbose >=2;
		$idir = $fpool . "/" . $i . "/";
		foreach my $j (@hexlist) {
			print STDERR "$j " if $verbose >=2;
			$jdir = $idir . $j . "/";
			foreach my $k (@hexlist) {
				$kdir = $jdir . $k . "/";
				unless(opendir($dh, $kdir)) {
					warn "Can't open pool directory: $kdir\n" if $verbose>=4;
					next;
				}
				#Sort directory entries so that chains are ordered lowest to
                #highest - This preserves sequential order between source and 
                #target chains PLUS ensures that we fill holes corretly and
				#most efficiently
				my @entries = sort {poolname2number($a) cmp poolname2number($b)}
				                    (readdir ($dh));
				close($dh);
				warn "POOLDIR: $kdir (" . ($#entries-1) ." files)\n"
					if $verbose >=3;

				my $chainholes = 0;
				my $chainstart;
				my $lastdigest='';
				foreach (@entries) {
					next if /^\.\.?$/;     # skip dot files (. and ..)

					$totalfiles++;
					my $origfile = ${kdir} . $_;
					unless(m|^([0-9a-f]+)(_[0-9]+)?|) {
						warn "ERROR: '$origfile' is not a valid pool entry\n";
						$badpoolentry++;
						next;
					}
					my $origdigest = $1;
					my $newdigest = $file2md5->($bpc, $md5, $origfile, -1, $compress);
					if($newdigest eq "-1") {
						$badpoolentry++;
						warn "ERROR: Can't calculate md5sum name for: $origfile\n";
						next;
					}
					if($newdigest ne $origdigest) { #MD5sum Path is WRONG
						$md5errors++;
						if($origdigest ne $lastdigest) { #New chain
							#So go back and renumber last chain to remove holes
							if($chainholes > 0) {
								renumber_pool_chain($chainstart, $chainholes)>0
									or $renumbererr++;
							}
							$lastdigest=$origdigest; #Reset to new chain base
							$chainholes = 0;
							$chainstart = $origfile; #lowest element of chain
							#since we are sorting directory in chain order
						}
						if(rename_entry($origfile, $newdigest)>0) {$chainholes++}
					}
				}
				#Check in case any holes unfixed at end of directory scan
				if($chainholes > 0) {
					renumber_pool_chain($chainstart, $chainholes) >0
						or $renumbererr++;
				}
			}
		}
	}
	print STDERR "\n" if $verbose >=2;
}

#Rename/move pool chain entry $source to first open position
#in $digest chain if permitted. Renumber source chain as
#needed after the move
sub rename_entry
{
	my ($source, $digest) = @_;

	my $dups = '';
	my @dups = ();

	my $poolpath = $bpc->MD52Path($digest,$compress);
	my $poolbase_ = $poolpath . "_";
	for(my $i=0; -f $poolpath; $i++) { # Iterate through pool chain with same md5sum to find
		                    # first free entry
		if($warndups && (stat(_))[3] < $MAXLINKS &&
		   ! $compare->($source,$poolpath)) { #Matches existing pool entry
			push(@dups,$i);
		}
		$poolpath = $poolbase_ . $i;
	}
	$poolpath =~ m|^$TopDir/?((.*)/.*)|;
	my $target = $1; #Path relative to TopDir
	my $dir = $2; #Relative to TopDir
#	print "$source $target [$md5errors/$totalfiles]$dups\n";

	if(@dups) {
		$dups = " CHAINDUPS(" . join(',', @dups) . ")";
		warn "WARN: $dups: $source->$target\n" if $verbose >=1;
		$chaindups++;
	}

	if((!-d $dir && !jmkpath($dir, 0, 0750)) || #Directory creation error
	   !jrename($source,$poolpath)) { #Rename error
		warn "ERROR: Can't rename: $source->$target\n" if $verbose >=1;
		print $OUT "$source $target NO_RENAME$dups\n";
		$norename++;
		return -1;
		}

	#Fixed without errors
	print $OUT "$source $target FIXED$dups\n";
	$fixed++;
	return 1;
}

sub usage
{
    print STDERR <<EOF;

usage: $0 [options] --outfile|-o <outfile>  
  Options:
   --dryrun|-d         Dry-run 
                       Negate with: --nodryrun
   --Force             Force - MAY BE DANGEROUS!
   --topdir|-t         Location of TopDir. [Default = $TopDir_def]
                       Note you may want to change from default for example
                       if you are working on a shadow copy.
   --verbose|-v        Verbose (repeat for more verbosity)
   --warndups|-w       Warn if renamed pool entry is a pool duplicate

  DESCRIPTION:
    Find and fix md5sum pool name errors in pool and cpool

  DETAILS:
    Recurses through pool and cpool trees to test if the md5sum name of each
    pool file is correct relative to the file data. If not, the program attempts
    to rename (i.e. move) it to its proper md5sum name.

	If there already are pool files with the new name, then move it to
    the end of the target chain. After removing, renumber the source
    chain (if needed) to fill in holes left by the move. Note that the relative
    ordering of each chain is preserved.

    If the contents of the file match the contents of any of the files in the
    target chain, note the duplicate suffix numbers.

    If the --warndups|-w flag is set then check to see if the renamed pool 
	entry duplicates an existing pool entry (with <MAX LINKS). This may be
    slow if you have a lot of chains since to check for duplicates you need
    to compare files
    Note: it is not generally an error to have two pool entries in the same
    chain with the same data (in fact, it occurs intentionally when you exceed 
    MAX LINKS), it just may waste some space. My routine BackupPC_fixLinks.pl 
    can correct just such duplicates later if that is an issue.

    In any case, if all your misnumbering was consistent you won\'t have this
    situation anyway.

	<outfile> records all the changes made plus appends a status code:

	FIXED = pool file moved/renamed and original chain renumbered if needed.
    NO_RENAME = Signals error in renaming/moving the pool file. The mdsum name
                was thus not corrected.
	DUPS(n1,n2,n3) = Signals duplicates in the target chain and lists the
                     suffixes (-1 = no suffix)

	The following errors are tabulated but shouldn\'t occur:
    BadPoolEntries = Files in pool with name not of form [0-9a-f]+(_[0-9]+)?
                     or that can\'t be read to compute the MD5 path digest
    RenumberErrors = Failures to renumber original chain to fill hole 
                      after renaming
    
EOF
exit(1)
}
BackupPC_verifyPool

Code: Alles auswählen

#!/usr/bin/perl
#============================================================= -*-perl-*-
#
# BackupPC_verifyPool: Verify pool integrity
#
# DESCRIPTION
#
#   BackupPC_verifyPool tries to verify the integrity of the pool files,
#   based on their file names, which are supposed to correspond to MD5
#   digests calculated from the (uncompressed) length and parts of their
#   (again uncompressed) contents.
#   Needs to be run as backuppc user for access to the pool files and
#   meta data.
#
#   Usage: BackupPC_verifyPool [-v] [-p] [-u] [-r range] [-s]
#
#   Options:
#
#     -v        Show what is going on. Without this flag, only errors found
#               are displayed, which might be very boring. Use '-p' for a
#               bit of entertainment without causing your tty to scroll so
#               much.
#     -p        Show more terse progress output.
#     -u        Check the pool (uncompressed files), not the cpool
#               (uncompressed files).
#     -r range  Specify the pool range to check (see below). 'range'
#               can be a Perl expression like '0 .. 255' or '0, 10, 30 .. 40'.
#               Only safe characters allowed [\da-fA-F,.\s].
#     -s        Show summary.
#
#   The pool range was chosen as in BackupPC_nightly as means to divide
#   the possibly lengthy operation of verifying the pool into smaller
#   steps. The full pool goes from 0 to 255, that's all you really need to
#   know. For more information, see BackupPC_nightly from the BackupPC
#   distribution.
#
# AUTHOR
#   Holger Parplies  <wopp at parplies.de>
#
# VERSION
#   $Id$
#
# COPYRIGHT
#   Copyright (C) 2007  Holger Parplies
#
#   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.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#========================================================================
#
# Version 3.3.1-1, patched 8 Apr 2016.
#
#========================================================================


use strict;
use lib '/usr/share/backuppc/lib'; # Debian; change to fit your needs
use BackupPC::Lib;
use BackupPC::FileZIO;
use Getopt::Std;
use File::Find;

# $ENV {PATH} = '/bin:/usr/bin';
# chdir '.';

my %opts = (
	    v => 0,		# verbose output
	    p => 0,		# terse progress output
	    u => 0,		# pool (1) or cpool (0)
	    r => '0 .. 255',	# range
	    s => 0,		# show summary
	   );

unless (getopts ('vpur:s', \%opts)) {
    die <<EOM;
Usage: $0 [-v] [-p] [-u] [-r range] [-s]

Options: -v         Verbose output of files being checked and result
	 -p         Terse output of what is happening (counter)
	 -u         Check uncompressed pool (pool instead of cpool)
	 -r range   Check subset of pool (default whole pool = 0 .. 255).
	            Use any valid Perl expression containing only numbers
		    (octal or hexadecimal is ok), dots, commas and whitespace
		    here.
         -s         Show summary.
EOM
}

# unbuffered output
$| = 1;

# some variables
my $bpc = new BackupPC::Lib	# BackupPC object
    or die "Can't create BackupPC object!\n";
my $pooldir = $bpc -> {TopDir} . '/' . ($opts {u} ? 'pool' : 'cpool') . '/';
				# Pool directory to check
my @range;			# Pool range to check
my $mismatch_count = 0;		# number of invalid files
my $file_count = 0;		# running file count for progress output
my $md5;			# handle of MD5 object

# # untaint range specification; NOTE THAT THIS IS NOT SECURE!
# $opts {r} = $1
#   if $opts {r} =~ /^(.*)$/;

# check range specification
die "Range specification '$opts{r}' contains insecure characters!\n"
  if $opts {r} !~ /^[0-9a-fA-Fx.,\s]*$/;
eval "\@range = ($opts{r});";
if ($@) {
  die "Range specification '$opts{r}' is invalid: $@\n";
} elsif (not defined @range or @range == 0) {
  die "Range specification '$opts{r}' is empty. Nothing to do.\n";
} elsif (grep { $_ < 0 or $_ > 255 } @range) {
  die "Range specification '$opts{r}' contains values outside (0 .. 255)\n";
}

# iterate over the specified part of the pool
$md5 = new Digest::MD5
  or die "Can't create MD5 object: $!\n";
foreach my $i (@range) {
  my $dir = sprintf '%s/%1x/%1x', $pooldir, int ($i / 16), $i % 16;
  find (\&validate_pool_dir, $dir)
    if -d $dir;
}

# Summary
if ($opts {s}) {
  printf "%d files in %d directories checked, %d had wrong digests.\n",
    $file_count, @range * 16, $mismatch_count;
} elsif ($mismatch_count > 0) {
  print "ERROR: $mismatch_count files in ", $opts {u} ? 'pool' : 'cpool',
    ", range ($opts{r}), seem to be corrupt!\n";
}

# Return code
exit $mismatch_count > 0 ? 1 : 0;

# actual verification process
sub validate_pool_dir {
  my ($name_md5) = ($_ =~ /^([0-9a-fA-F]{32})/);
  my $content_md5;

  return			# ignore directories
    if -d $File::Find::name;

  $file_count ++;
  if ($opts {p} and not $opts {v}) {
    if (/^([0-9a-fA-F])([0-9a-fA-F])/) {
      print "[$1$2 $file_count]\r";
    } else {
      print "[   $file_count]\r";
    }
  }

  # since we are only reading the file, we can treat the 'compLevel' parameter
  # of BackupPC::FileZIO::open as a boolean
  my $fh = BackupPC::FileZIO -> open ($File::Find::name, 0, ! $opts {u});
  if (defined $fh) {
    my $buf;
    my $bytes = $fh -> read (\$buf, 1024 * 1024 + 100);
    if ($bytes > 1024 * 1024) {
      # read complete file for determining length. Keep first 1MB in $buf,
      # put total length into $bytes, read in 100KB chunks for lower mem usage
      my $buf2;
      my $new = 1;
      while ($new > 0) {
	$new = $fh -> read (\$buf2, 102400);
	$bytes += $new;
      }
    }
    $content_md5 = $bpc -> Buffer2MD5 ($md5, $bytes, \$buf);
    if ($content_md5 ne $name_md5) {
      # print ">$content_md5< != >$name_md5<\n";
      printf "[%5d] %-36.36s != %-32.32s\n", $file_count, $_, $content_md5;
    } elsif ($opts {v}) {
      printf "[%5d] %-36.36s (%10d) ok\n", $file_count, $_, $bytes;
    }
  } else {
    # open failed, count as mismatch
    print "$_: BackupPC::FileZIO::open failed!\n";
    $mismatch_count ++;
  }
}

Code: Alles auswählen

#========================================================================
#
# ChangeLog - change log for BackupPC.
#
# DESCRIPTION
#   Revision history for BackupPC, detailing significant changes between
#   versions, most recent first.
#
# AUTHOR
#   Craig Barratt  <cbarratt@users.sourceforge.net>
#
#========================================================================
#
# Version 3.3.1, released 11 Jan 2015.
#
# See http://backuppc.sourceforge.net.
#
#========================================================================

#------------------------------------------------------------------------ 
# Version 3.3.1-1, 08 Apr 2016
#------------------------------------------------------------------------ 

* Custom Changes

* patch from debian jessie backuppc (3.3.0-2) unstable with
  Version 3.3.1, released 11 Jan 2015. to 3.3.1-1 Custom

#------------------------------------------------------------------------ 
# Version 3.3.1, 11 Jan 2015 
#------------------------------------------------------------------------ 

* Added more helpful text (instead of "New Key") for BackupFilesOnly and BackupFilesExclude in the CGI editor.

* Removed deprecated defined(@Backups) from lib/BackupPC/CGI/Browse.pm; patch from Alexander Moisseev.

* Updated Spanish language file lib/BackupPC/Lang/es.pm from Luis Bustamante.

Antworten