"Fossies" - the Fresh Open Source Software Archive  

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

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

BackupPC_migrateV3toV4  (BackupPC-4.3.2):BackupPC_migrateV3toV4  (BackupPC-4.4.0)
skipping to change at line 34 skipping to change at line 34
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
#======================================================================== #========================================================================
# #
# Version 4.3.2, released 17 Feb 2020. # Version 4.4.0, released 20 Jun 2020.
# #
# See http://backuppc.sourceforge.net. # See http://backuppc.sourceforge.net.
# #
#======================================================================== #========================================================================
use strict; use strict;
no utf8; no utf8;
use lib "__INSTALLDIR__/lib"; use lib "__INSTALLDIR__/lib";
use Getopt::Std; use Getopt::Std;
use File::Copy; use File::Copy;
use File::Path; use File::Path;
use Data::Dumper; use Data::Dumper;
use Digest::MD5; use Digest::MD5;
use Fcntl ':mode'; use Fcntl ':mode';
use BackupPC::Lib; use BackupPC::Lib;
use BackupPC::XS qw( :all ); use BackupPC::XS qw( :all );
use BackupPC::DirOps; use BackupPC::DirOps;
my $ErrorCnt = 0; my $ErrorCnt = 0;
my $FileCnt = 0; my $FileCnt = 0;
my($FileCntNext, $FileCntTotal, $FileCntPctTextLast, $FileCntIncr); my($FileCntNext, $FileCntTotal, $FileCntPctTextLast, $FileCntIncr);
die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) ); die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
my $TopDir = $bpc->TopDir(); my $TopDir = $bpc->TopDir();
my $BinDir = $bpc->BinDir(); my $BinDir = $bpc->BinDir();
my %Conf = $bpc->Conf(); my %Conf = $bpc->Conf();
my $Hosts = $bpc->HostInfoRead(); my $Hosts = $bpc->HostInfoRead();
my %opts; my %opts;
if ( !getopts("ampvh:n:", \%opts) || @ARGV >= 1 if ( !getopts("ampvh:n:", \%opts)
|| !(defined($opts{a}) xor defined($opts{h})) || @ARGV >= 1
|| (!defined($opts{h}) && defined($opts{n})) ) { || !(defined($opts{a}) xor defined($opts{h}))
|| (!defined($opts{h}) && defined($opts{n})) ) {
print STDERR <<EOF; print STDERR <<EOF;
usage: BackupPC_migrateV3toV4 -a [-m] [-p] [-v] usage: BackupPC_migrateV3toV4 -a [-m] [-p] [-v]
BackupPC_migrateV3toV4 -h host [-n V3backupNum] [-m] [-p] [-v] BackupPC_migrateV3toV4 -h host [-n V3backupNum] [-m] [-p] [-v]
Options: Options:
-a migrate all hosts and all backups -a migrate all hosts and all backups
-h host migrate just a specific host -h host migrate just a specific host
-n V3backupNum migrate specific host backup; does all V3 backups -n V3backupNum migrate specific host backup; does all V3 backups
for that host if not specified for that host if not specified
-m don't migrate anything; just print what would be done -m don't migrate anything; just print what would be done
-p don't print progress information -p don't print progress information
skipping to change at line 90 skipping to change at line 93
EOF EOF
exit(1); exit(1);
} }
# #
# Make sure BackupPC isn't running # Make sure BackupPC isn't running
# #
CheckIfServerRunning(); CheckIfServerRunning();
if ( defined($opts{h}) ) { if ( defined($opts{h}) ) {
if ( $opts{h} !~ /^([\w\.\s-]+)$/ if ( $opts{h} !~ /^([\w\.\s-]+)$/
|| $opts{h} =~ m{(^|/)\.\.(/|$)} || $opts{h} =~ m{(^|/)\.\.(/|$)}
|| !defined($Hosts->{$opts{h}}) ) { || !defined($Hosts->{$opts{h}}) ) {
print(STDERR "BackupPC_migrateV3toV4: bad host name '$opts{h}'\n"); print(STDERR "BackupPC_migrateV3toV4: bad host name '$opts{h}'\n");
exit(1); exit(1);
} }
if ( $opts{n} !~ /^\d*/ ) { if ( $opts{n} !~ /^\d*/ ) {
print(STDERR "BackupPC_migrateV3toV4: invalid backup number '$opts{n}'\n "); print(STDERR "BackupPC_migrateV3toV4: invalid backup number '$opts{n}'\n ");
exit(1); exit(1);
} }
} }
$bpc->ChildInit(); $bpc->ChildInit();
skipping to change at line 135 skipping to change at line 138
# Write new-style attrib files (<= 4.0.0beta3 uses old-style), which are 0-l ength # Write new-style attrib files (<= 4.0.0beta3 uses old-style), which are 0-l ength
# files with the digest encoded in the file name (eg: attrib_md5HexDigest). We # files with the digest encoded in the file name (eg: attrib_md5HexDigest). We
# can still read the old-style files, and we upgrade them as we go. # can still read the old-style files, and we upgrade them as we go.
# #
BackupPC::XS::Attrib::backwardCompat(0, 0); BackupPC::XS::Attrib::backwardCompat(0, 0);
my @Backups = $bpc->BackupInfoRead($Host); my @Backups = $bpc->BackupInfoRead($Host);
$Inode = 1; $Inode = 1;
my $bkupNum2LastInode = {}; my $bkupNum2LastInode = {};
my $foundBackup = 0; my $foundBackup = 0;
for ( my $i = 0 ; $i < @Backups ; $i++ ) { for ( my $i = 0 ; $i < @Backups ; $i++ ) {
$Inode = $Backups[$i]{inodeLast} + 1 if ( $Inode < $Backups[$i]{inodeLas t} ); $Inode = $Backups[$i]{inodeLast} + 1 if ( $Inode < $Backups[$i]{inodeLas t} );
$foundBackup = 1 if ( $opts{n} == $Backups[$i]{num} ); $foundBackup = 1 if ( $opts{n} == $Backups[$i]{num} );
} }
$Inode2MD5Digest = {}; $Inode2MD5Digest = {};
$BkupNum = undef; $BkupNum = undef;
if ( defined($opts{n}) && !$foundBackup ) { if ( defined($opts{n}) && !$foundBackup ) {
print("BackupPC_migrateV3toV4: backup $opts{n} for host $Host doesn't ex ist\n"); print("BackupPC_migrateV3toV4: backup $opts{n} for host $Host doesn't ex ist\n");
next; next;
} }
if ( -d "$TopDir/pc/$Host/new" ) {
print("BackupPC_migrateV3toV4: removing partial backup in $TopDir/pc/$Ho
st/new\n");
BackupPC::DirOps::RmTreeQuiet($bpc, "$TopDir/pc/$Host/new", -2);
}
unlink("$TopDir/pc/$Host/NewFileList") if ( -e "$TopDir/pc/$Host/NewFileList
" );
for ( my $i = 0 ; $i < @Backups ; $i++ ) { for ( my $i = 0 ; $i < @Backups ; $i++ ) {
next if ( (defined($opts{n}) && $opts{n} != $Backups[$i]{num}) ); next if ( (defined($opts{n}) && $opts{n} != $Backups[$i]{num}) );
if ( $Backups[$i]{version} >= 4 ) { if ( $Backups[$i]{version} >= 4 ) {
if ( defined($opts{n}) ) { if ( defined($opts{n}) ) {
print("BackupPC_migrateV3toV4: backup $Backups[$i]{num} for host $Host is version >= 4; skipping\n"); print("BackupPC_migrateV3toV4: backup $Backups[$i]{num} for host $Host is version >= 4; skipping\n");
} }
next; next;
} }
$BkupNum = $Backups[$i]{num}; $BkupNum = $Backups[$i]{num};
$Compress = $Backups[$i]{compress}; $Compress = $Backups[$i]{compress};
$SrcDir = "$TopDir/pc/$Host/$BkupNum"; $SrcDir = "$TopDir/pc/$Host/$BkupNum";
$DestDir = "$TopDir/pc/$Host/$BkupNum.v4"; $DestDir = "$TopDir/pc/$Host/$BkupNum.v4";
$FileCnt = 0; $FileCnt = 0;
$FileCntNext = 1; $FileCntNext = 1;
$FileCntTotal = $Backups[$i]{nFiles}; $FileCntTotal = $Backups[$i]{nFiles};
$FileCntIncr = int($FileCntTotal / 500); $FileCntIncr = int($FileCntTotal / 500);
$FileCntIncr = 2 if ( $FileCntIncr < 2 ); $FileCntIncr = 2 if ( $FileCntIncr < 2 );
# #
# #
# Migrate the V3 backup from $SrcDir to $DestDir # Migrate the V3 backup from $SrcDir to $DestDir
# #
if ( -d "$SrcDir/refCnt" ) { if ( -d "$SrcDir/refCnt" ) {
print("BackupPC_migrateV3toV4: backup $Backups[$i]{num} for host $Ho print(
st already has a refCnt directory; skipping this backup\n"); "BackupPC_migrateV3toV4: backup $Backups[$i]{num} for host $Host
already has a refCnt directory; skipping this backup\n"
);
next; next;
} }
print("BackupPC_migrateV3toV4: migrating host $Host backup #$BkupNum to print("BackupPC_migrateV3toV4: migrating host $Host backup #$BkupNum to
V4 (approx $FileCntTotal files)\n") if ( !$opts{p} ); V4 (approx $FileCntTotal files)\n")
if ( !$opts{p} );
next if ( $opts{m} ); next if ( $opts{m} );
if ( -d $DestDir ) { if ( -d $DestDir ) {
print("BackupPC_migrateV3toV4: removing temp target directory $DestD ir\n"); print("BackupPC_migrateV3toV4: removing temp target directory $DestD ir\n");
BackupPC::DirOps::RmTreeQuiet($bpc, $DestDir, -2); BackupPC::DirOps::RmTreeQuiet($bpc, $DestDir, -2);
if ( -d $DestDir ) { if ( -d $DestDir ) {
print("BackupPC_migrateV3toV4: failed to remove temp target dire print(
ctory $DestDir; skipping this backup\n"); "BackupPC_migrateV3toV4: failed to remove temp target direct
ory $DestDir; skipping this backup\n");
next; next;
} }
} }
createFsckFile($DestDir); createFsckFile($DestDir);
$bpc->flushXSLibMesgs(); $bpc->flushXSLibMesgs();
$DeltaInfo = BackupPC::XS::DeltaRefCnt::new($DestDir); $DeltaInfo = BackupPC::XS::DeltaRefCnt::new($DestDir);
if ( !chdir($SrcDir) ) { if ( !chdir($SrcDir) ) {
print("BackupPC_migrateV3toV4: cannot chdir to $SrcDir; skipping this print("BackupPC_migrateV3toV4: cannot chdir to $SrcDir; skipping thi
backup\n"); s backup\n");
next; next;
} }
update_v3_dir("attrib", "."); update_v3_dir("attrib", ".");
BackupPC::DirOps::find($bpc, {wanted => \&update_v3_dir}, ".", 1); BackupPC::DirOps::find($bpc, {wanted => \&update_v3_dir}, ".", 1);
$DeltaInfo->flush(); $DeltaInfo->flush();
$bpc->flushXSLibMesgs(); $bpc->flushXSLibMesgs();
printProgress(); printProgress();
if ( (my $errCnt = BackupPC::XS::Lib::logErrorCntGet()) > 0 ) { if ( (my $errCnt = BackupPC::XS::Lib::logErrorCntGet()) > 0 ) {
print("BackupPC_migrateV3toV4: got $errCnt errors from BackupPC::XS: :Lib::logErrorCntGet()\n"); print("BackupPC_migrateV3toV4: got $errCnt errors from BackupPC::XS: :Lib::logErrorCntGet()\n");
$ErrorCnt += $errCnt; $ErrorCnt += $errCnt;
} }
skipping to change at line 215 skipping to change at line 228
# move $DestDir to $SrcDir and then remove $SrcDir # move $DestDir to $SrcDir and then remove $SrcDir
# #
if ( -e "$SrcDir.old" ) { if ( -e "$SrcDir.old" ) {
if ( -d "$SrcDir.old" ) { if ( -d "$SrcDir.old" ) {
BackupPC::DirOps::RmTreeQuiet($bpc, "$SrcDir.old", -2); BackupPC::DirOps::RmTreeQuiet($bpc, "$SrcDir.old", -2);
} else { } else {
unlink("$SrcDir.old"); unlink("$SrcDir.old");
} }
} }
if ( !rename($SrcDir, "$SrcDir.old") ) { if ( !rename($SrcDir, "$SrcDir.old") ) {
print("BackupPC_migrateV3toV4: unable to rename $SrcDir to $SrcDir.o print(
ld; cleaning up by removing $DestDir\n"); "BackupPC_migrateV3toV4: unable to rename $SrcDir to $SrcDir.old
; cleaning up by removing $DestDir\n");
BackupPC::DirOps::RmTreeQuiet($bpc, $DestDir, -2); BackupPC::DirOps::RmTreeQuiet($bpc, $DestDir, -2);
$ErrorCnt++; $ErrorCnt++;
next; next;
} }
if ( !rename($DestDir, $SrcDir) ) { if ( !rename($DestDir, $SrcDir) ) {
$ErrorCnt++; $ErrorCnt++;
print("BackupPC_migrateV3toV4: unable to rename $DestDir to $SrcDir; print(
moving $SrcDir.old back to $SrcDir and removing $DestDir\n"); "BackupPC_migrateV3toV4: unable to rename $DestDir to $SrcDir; m
oving $SrcDir.old back to $SrcDir and removing $DestDir\n"
);
if ( !rename("$SrcDir.old", $SrcDir) ) { if ( !rename("$SrcDir.old", $SrcDir) ) {
print("BackupPC_migrateV3toV4: unable to rename $SrcDir.old back to $SrcDir\n"); print("BackupPC_migrateV3toV4: unable to rename $SrcDir.old back to $SrcDir\n");
$ErrorCnt++; $ErrorCnt++;
next; next;
} }
BackupPC::DirOps::RmTreeQuiet($bpc, $DestDir, -2); BackupPC::DirOps::RmTreeQuiet($bpc, $DestDir, -2);
} }
print("BackupPC_migrateV3toV4: converted backup in $SrcDir; removing $Sr cDir.old\n"); print("BackupPC_migrateV3toV4: converted backup in $SrcDir; removing $Sr cDir.old\n");
BackupPC::DirOps::RmTreeQuiet($bpc, "$SrcDir.old", -2); BackupPC::DirOps::RmTreeQuiet($bpc, "$SrcDir.old", -2);
} }
next if ( $opts{m} ); next if ( $opts{m} );
if ( system("$BinDir/BackupPC_refCountUpdate -h $Host -o 0") != 0 ) { if ( system("$BinDir/BackupPC_refCountUpdate -h $Host -o 0") != 0 ) {
print("BackupPC_migrateV3toV4: BackupPC_refCountUpdate exited with error s\n"); print("BackupPC_migrateV3toV4: BackupPC_refCountUpdate exited with error s\n");
$ErrorCnt++ $ErrorCnt++;
} }
# #
# Update last inode in each backup we updated # Update last inode in each backup we updated
# #
@Backups = $bpc->BackupInfoRead($Host); @Backups = $bpc->BackupInfoRead($Host);
my $updateBackups = 0; my $updateBackups = 0;
for ( my $i = 0 ; $i < @Backups ; $i++ ) { for ( my $i = 0 ; $i < @Backups ; $i++ ) {
next if ( !defined($bkupNum2LastInode->{$Backups[$i]{num}}) ); next if ( !defined($bkupNum2LastInode->{$Backups[$i]{num}}) );
$Backups[$i]{inodeLast} = $bkupNum2LastInode->{$Backups[$i]{num}}; $Backups[$i]{inodeLast} = $bkupNum2LastInode->{$Backups[$i]{num}};
print("Updating inodeLast for backup #$Backups[$i]{num} to $Backups[$i]{ inodeLast}\n"); print("Updating inodeLast for backup #$Backups[$i]{num} to $Backups[$i]{ inodeLast}\n");
skipping to change at line 261 skipping to change at line 277
} }
print("BackupPC_migrateV3toV4: got $ErrorCnt error" . ($ErrorCnt == 1 ? "\n" : " s\n")); print("BackupPC_migrateV3toV4: got $ErrorCnt error" . ($ErrorCnt == 1 ? "\n" : " s\n"));
exit($ErrorCnt ? 1 : 0); exit($ErrorCnt ? 1 : 0);
sub update_v3_dir sub update_v3_dir
{ {
my($name, $path) = @_; my($name, $path) = @_;
print("update_v3_dir name = $name, path = $path\n") if ( $LogLevel >= 6 ); print("update_v3_dir name = $name, path = $path\n") if ( $LogLevel >= 6 );
return if ( !-d $path ); return if ( !-d $path );
$name = "attrib"; $name = "attrib";
my $attrOld = BackupPC::XS::Attrib::new($Compress); my $attrOld = BackupPC::XS::Attrib::new($Compress);
my $attr = BackupPC::XS::Attrib::new($Compress); my $attr = BackupPC::XS::Attrib::new($Compress);
if ( -f "$path/attrib" && !$attrOld->read($path, $name) ) { if ( -f "$path/attrib" && !$attrOld->read($path, $name) ) {
print("BackupPC_migrateV3toV4: can't read attribute file $path/$name\n") ; print("BackupPC_migrateV3toV4: can't read attribute file $path/$name\n") ;
$ErrorCnt++; $ErrorCnt++;
} }
my $attrAll = {}; my $attrAll = {};
# #
# populate attrAll with the files in the directory # populate attrAll with the files in the directory
# #
my $dirEntries = BackupPC::DirOps::dirRead($bpc, $path); my $dirEntries = BackupPC::DirOps::dirRead($bpc, $path);
foreach my $e ( @$dirEntries ) { foreach my $e ( @$dirEntries ) {
my $file = $e->{name}; my $file = $e->{name};
next if ( $file !~ /^f/ ); next if ( $file !~ /^f/ );
my $fileUM = $bpc->fileNameUnmangle($file); my $fileUM = $bpc->fileNameUnmangle($file);
my $a = $attrOld->get($fileUM); my $a = $attrOld->get($fileUM);
if ( defined($a) ) { if ( defined($a) ) {
$attrAll->{$fileUM} = $a; $attrAll->{$fileUM} = $a;
next; next;
} }
# #
# We found a file that isn't in the attributes. Need to create an # We found a file that isn't in the attributes. Need to create an
# entry for it. # entry for it.
# #
my @s = stat("$path/$file"); my @s = stat("$path/$file");
my $size = 0; my $size = 0;
if ( S_ISREG($s[2]) ) { if ( S_ISREG($s[2]) ) {
if ( !$Compress ) { if ( !$Compress ) {
$size = $s[7]; $size = $s[7];
} else { } else {
# #
# Compute the correct size by reading the whole file # Compute the correct size by reading the whole file
# #
my $f = BackupPC::XS::FileZIO::open("$path/$file", 0, $Compress) ; my $f = BackupPC::XS::FileZIO::open("$path/$file", 0, $Compress) ;
if ( !defined($f) ) { if ( !defined($f) ) {
skipping to change at line 313 skipping to change at line 330
my($data); my($data);
while ( $f->read(\$data, 65636 * 8) > 0 ) { while ( $f->read(\$data, 65636 * 8) > 0 ) {
$size += length($data); $size += length($data);
} }
$f->close; $f->close;
} }
} }
} }
$attrAll->{$fileUM} = { $attrAll->{$fileUM} = {
name => $fileUM, name => $fileUM,
type => S_ISDIR($s[2]) ? BPC_FTYPE_DIR : BPC_FTYPE_FILE, type => S_ISDIR($s[2]) ? BPC_FTYPE_DIR : BPC_FTYPE_FILE,
mode => $s[2], mode => $s[2],
uid => $s[4], uid => $s[4],
gid => $s[5], gid => $s[5],
size => $size, size => $size,
mtime => $s[9], mtime => $s[9],
}; };
print("update_v3_dir: adding missing attributes for $path/$file (type $a print(
ttrAll->{$fileUM}{type}, size $size, ...)\n") "update_v3_dir: adding missing attributes for $path/$file (type $att
if ( $LogLevel >= 4 ); rAll->{$fileUM}{type}, size $size, ...)\n"
) if ( $LogLevel >= 4 );
} }
foreach my $fileUM ( keys(%$attrAll) ) { foreach my $fileUM ( keys(%$attrAll) ) {
my $a = $attrAll->{$fileUM}; my $a = $attrAll->{$fileUM};
my $copyFile = 0; my $copyFile = 0;
$FileCnt++ if ( $a->{type} != BPC_FTYPE_DIR ); $FileCnt++ if ( $a->{type} != BPC_FTYPE_DIR );
$a->{inode} = $Inode++; $a->{inode} = $Inode++;
$a->{nlinks} = 0; $a->{nlinks} = 0;
print("update_v3_dir($path): got file $a->{name}\n") if ( $LogLevel >= 6 ); print("update_v3_dir($path): got file $a->{name}\n") if ( $LogLevel >= 6 );
$copyFile = 1 if ( $a->{type} == BPC_FTYPE_FILE $copyFile = 1
|| $a->{type} == BPC_FTYPE_SYMLINK if ( $a->{type} == BPC_FTYPE_FILE
|| $a->{type} == BPC_FTYPE_HARDLINK || $a->{type} == BPC_FTYPE_SYMLINK
|| $a->{type} == BPC_FTYPE_CHARDEV || $a->{type} == BPC_FTYPE_HARDLINK
|| $a->{type} == BPC_FTYPE_BLOCKDEV ); || $a->{type} == BPC_FTYPE_CHARDEV
|| $a->{type} == BPC_FTYPE_BLOCKDEV );
# #
# If there isn't an associated file, or there is a digest already, then # If there isn't an associated file, or there is a digest already, then
# there nothing more to do # there nothing more to do
# #
if ( !$copyFile || length($a->{digest}) ) { if ( !$copyFile || length($a->{digest}) ) {
$attr->set($a->{name}, $a); $attr->set($a->{name}, $a);
next; next;
} }
# #
# Check if we've seen this file already based on the fullPath inode # Check if we've seen this file already based on the fullPath inode
# #
my $fullPath = "$path/" . $bpc->fileNameEltMangle($a->{name}); my $fullPath = "$path/" . $bpc->fileNameEltMangle($a->{name});
my @s = stat($fullPath); my @s = stat($fullPath);
if ( @s == 0 ) { if ( @s == 0 ) {
print("BackupPC_migrateV3toV4: unable to stat $fullPath\n"); print("BackupPC_migrateV3toV4: unable to stat $fullPath\n");
$ErrorCnt++; $ErrorCnt++;
next; next;
} }
my $inode = $s[1]; my $inode = $s[1];
if ( defined($Inode2MD5Digest->{$inode}) ) { if ( defined($Inode2MD5Digest->{$inode}) ) {
$a->{digest} = $Inode2MD5Digest->{$inode}; $a->{digest} = $Inode2MD5Digest->{$inode};
if ( $LogLevel >= 5 ) { if ( $LogLevel >= 5 ) {
my $digestStr = unpack("H*", $a->{digest}); my $digestStr = unpack("H*", $a->{digest});
print("$a->{name}: found inode $inode -> digest = $digestStr\n") if ( $LogLevel >= 4 ); print("$a->{name}: found inode $inode -> digest = $digestStr\n") if ( $LogLevel >= 4 );
} }
$attr->set($a->{name}, $a); $attr->set($a->{name}, $a);
next; next;
} }
# #
# Compute the V3 and V4 digests # Compute the V3 and V4 digests
# #
my $f = BackupPC::XS::FileZIO::open($fullPath, 0, $Compress); my $f = BackupPC::XS::FileZIO::open($fullPath, 0, $Compress);
my($size, $data, $data1MB, $fileSize, $found, @s, $thisRead); my($size, $data, $data1MB, $fileSize, $found, @s, $thisRead);
if ( !defined($f) ) { if ( !defined($f) ) {
print("BackupPC_migrateV3toV4: unable to open file $fullPath\n"); print("BackupPC_migrateV3toV4: unable to open file $fullPath\n");
$ErrorCnt++; $ErrorCnt++;
next; next;
} }
my $md5 = Digest::MD5->new(); my $md5 = Digest::MD5->new();
do { do {
$thisRead = $f->read(\$data, 1 << 20); $thisRead = $f->read(\$data, 1 << 20);
if ( $thisRead < 0 ) { if ( $thisRead < 0 ) {
print("BackupPC_migrateV3toV4: error reading file $fullPath (read print("BackupPC_migrateV3toV4: error reading file $fullPath (rea
returns $thisRead)\n"); d returns $thisRead)\n");
$ErrorCnt++; $ErrorCnt++;
$f->close(); $f->close();
next; next;
} elsif ( $thisRead > 0 ) { } elsif ( $thisRead > 0 ) {
$md5->add($data); $md5->add($data);
$fileSize += length($data); $fileSize += length($data);
$data1MB .= $data if ( length($data1MB) < (1 << 20) ); $data1MB .= $data if ( length($data1MB) < (1 << 20) );
} }
} while ( $thisRead > 0 ); } while ( $thisRead > 0 );
my $digest4 = $md5->digest();
my $digest3 = $bpc->Buffer2MD5_v3(Digest::MD5->new(), $fileSize, \$data1M my $digest4 = $md5->digest();
B); my $digest3 = $bpc->Buffer2MD5_v3(Digest::MD5->new(), $fileSize, \$data1
my $path3 = $bpc->MD52Path_v3($digest3, $Compress); MB);
my $path4 = $bpc->MD52Path($digest4, $Compress); my $path3 = $bpc->MD52Path_v3($digest3, $Compress);
my $i = -1; my $path4 = $bpc->MD52Path($digest4, $Compress);
my $i = -1;
print("$a->{name}: path3 = $path3, path4 = $path4\n") if ( $LogLevel >= 5
); print("$a->{name}: path3 = $path3, path4 = $path4\n") if ( $LogLevel >=
5 );
#
# see if it's already in the v4 pool #
# # see if it's already in the v4 pool
if ( $fileSize == 0 ) { #
$found = 1; if ( $fileSize == 0 ) {
print("$a->{name}: empty file in pool by default\n") if ( $LogLevel > $found = 1;
= 4 ); print("$a->{name}: empty file in pool by default\n") if ( $LogLevel
} elsif ( (@s = stat($path4)) && $s[1] == $inode ) { >= 4 );
$found = 1; } elsif ( (@s = stat($path4)) && $s[1] == $inode ) {
print("$a->{name}: already in pool4 $path4\n") if ( $LogLevel >= 4 ); $found = 1;
} elsif ( !-f $path4 ) { print("$a->{name}: already in pool4 $path4\n") if ( $LogLevel >= 4 )
# ;
# look in v3 pool for match } elsif ( !-f $path4 ) {
# #
while ( 1 ) { # look in v3 pool for match
my $testPath = $path3; #
$testPath .= "_$i" if ( $i >= 0 ); while ( 1 ) {
@s = stat($testPath); my $testPath = $path3;
last if ( !@s ); $testPath .= "_$i" if ( $i >= 0 );
if ( $s[1] != $inode ) { @s = stat($testPath);
$i++; last if ( !@s );
next; if ( $s[1] != $inode ) {
} $i++;
# next;
# Found it! }
# #
print("$a->{name}: found at $testPath; link/move to $path4\n") if # Found it!
( $LogLevel >= 4 ); #
$found = 1; print("$a->{name}: found at $testPath; link/move to $path4\n") i
my $dir4 = $path4; f ( $LogLevel >= 4 );
$dir4 =~ s{(.*)/.*}{$1}; $found = 1;
if ( !-d $dir4 ) { my $dir4 = $path4;
print("Creating directory $dir4\n") if ( $LogLevel >= 5 ); $dir4 =~ s{(.*)/.*}{$1};
eval { mkpath($dir4, 0, 0777) }; if ( !-d $dir4 ) {
if ( $@ ) { print("Creating directory $dir4\n") if ( $LogLevel >= 5 );
print("BackupPC_migrateV3toV4: can't mkpath $dir4\n"); eval { mkpath($dir4, 0, 0777) };
$ErrorCnt++; if ( $@ ) {
$found = 0; print("BackupPC_migrateV3toV4: can't mkpath $dir4\n");
} $ErrorCnt++;
} $found = 0;
if ( !link($testPath, $path4) ) { }
print("BackupPC_migrateV3toV4: can't link($testPath,$path4)\n }
"); if ( !link($testPath, $path4) ) {
$ErrorCnt++; print("BackupPC_migrateV3toV4: can't link($testPath,$path4)\
$found = 0; n");
} elsif ( unlink($testPath) != 1 ) { $ErrorCnt++;
print("BackupPC_migrateV3toV4: can't unlink($testPath)\n"); $found = 0;
$ErrorCnt++; } elsif ( unlink($testPath) != 1 ) {
$found = 0; print("BackupPC_migrateV3toV4: can't unlink($testPath)\n");
} $ErrorCnt++;
last; $found = 0;
} }
} last;
# }
# check one more time for the V4 pool in case someone else just moved it }
there #
# (in which case the link error above is actually not an error). # check one more time for the V4 pool in case someone else just moved it
# there
if ( !$found && (@s = stat($path4)) && $s[1] == $inode ) { # (in which case the link error above is actually not an error).
$found = 1; #
print("$a->{name}: rediscovered in pool4 $path4; prior link error is if ( !$found && (@s = stat($path4)) && $s[1] == $inode ) {
benign\n"); $found = 1;
$ErrorCnt-- if ( $ErrorCnt > 0 ); # reverse increment above print("$a->{name}: rediscovered in pool4 $path4; prior link error is
} benign\n");
$ErrorCnt-- if ( $ErrorCnt > 0 ); # reverse increment above
if ( $found ) { }
$f->close();
} else { if ( $found ) {
# $f->close();
# fall back on copying it to the new pool } else {
# #
$f->rewind(); # fall back on copying it to the new pool
my $pw = BackupPC::XS::PoolWrite::new($Compress); #
while ( $f->read(\$data, 1 << 20) > 0 ) { $f->rewind();
$pw->write(\$data); my $pw = BackupPC::XS::PoolWrite::new($Compress);
$size += length($data); while ( $f->read(\$data, 1 << 20) > 0 ) {
} $pw->write(\$data);
$f->close(); $size += length($data);
my($match, $poolSize, $errorCnt); }
($match, $digest4, $poolSize, $errorCnt) = $pw->close(); $f->close();
if ( $LogLevel >= 5 ) { my($match, $poolSize, $errorCnt);
my $digestStr = unpack("H*", $digest4); ($match, $digest4, $poolSize, $errorCnt) = $pw->close();
print("poolWrite->close $a->{name} returned match $match, digest if ( $LogLevel >= 5 ) {
$digestStr, poolSize $poolSize, errCnt $errorCnt\n") my $digestStr = unpack("H*", $digest4);
if ( $LogLevel >= 6 ); print(
} "poolWrite->close $a->{name} returned match $match, digest $
$ErrorCnt += $errorCnt; digestStr, poolSize $poolSize, errCnt $errorCnt\n"
} ) if ( $LogLevel >= 6 );
}
$ErrorCnt += $errorCnt;
}
$a->{digest} = $digest4; $a->{digest} = $digest4;
$attr->set($a->{name}, $a); $attr->set($a->{name}, $a);
$Inode2MD5Digest->{$inode} = $digest4; $Inode2MD5Digest->{$inode} = $digest4;
$DeltaInfo->update($Compress, $digest4, 1) if ( length($digest4) ); $DeltaInfo->update($Compress, $digest4, 1) if ( length($digest4) );
} }
eval { mkpath("$DestDir/$path", 0, 0777) }; eval { mkpath("$DestDir/$path", 0, 0777) };
if ( $@ ) { if ( $@ ) {
print("BackupPC_migrateV3toV4: can't mkpath $DestDir/$path\n"); print("BackupPC_migrateV3toV4: can't mkpath $DestDir/$path\n");
$ErrorCnt++; $ErrorCnt++;
} }
if ( !$attr->write("$DestDir/$path", $name, undef, $DeltaInfo) ) { if ( !$attr->write("$DestDir/$path", $name, undef, $DeltaInfo) ) {
print("BackupPC_migrateV3toV4: write to $DestDir/$path/$name failed\n"); print("BackupPC_migrateV3toV4: write to $DestDir/$path/$name failed\n");
$ErrorCnt++; $ErrorCnt++;
} }
printProgress() if ( $FileCnt >= $FileCntNext ); printProgress() if ( $FileCnt >= $FileCntNext );
$bpc->flushXSLibMesgs(); $bpc->flushXSLibMesgs();
} }
# #
# Create a needFsck file, so if we are killed and can't recover, we can # Create a needFsck file, so if we are killed and can't recover, we can
# make sure an fsck is run next time. # make sure an fsck is run next time.
# #
sub createFsckFile sub createFsckFile
 End of changes. 32 change blocks. 
180 lines changed or deleted 204 lines changed or added

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