# Craig Barratt <cbarratt@users.sourceforge.net>
#
# COPYRIGHT
-# Copyright (C) 2002-2003 Craig Barratt
+# Copyright (C) 2002-2009 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.
+#
+# 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.0.0beta2, released 11 Nov 2006.
+# Version 3.2.0, released 31 Jul 2010.
#
# See http://backuppc.sourceforge.net.
#
my($err, $d, $blkSize) = BackupPC::Xfer::RsyncDigest->digestStart(
$attr->{fullPath}, $attr->{size}, 0,
$defBlkSize, $fio->{checksumSeed},
- 0, $attr->{compress}, 0);
+ 0, $attr->{compress}, 0,
+ $fio->{protocol_version});
+ if ( $err ) {
+ $fio->log("Can't get rsync digests from $attr->{fullPath}"
+ . " (err=$err, name=$f->{name})");
+ $fio->{stats}{errorCnt}++;
+ return -1;
+ }
my($isCached, $isInvalid) = $d->isCached;
if ( $fio->{logLevel} >= 5 ) {
$fio->log("$attr->{fullPath} verify; cached = $isCached,"
if ( $isCached || $isInvalid ) {
my $ret = BackupPC::Xfer::RsyncDigest->digestAdd(
$attr->{fullPath}, $blkSize,
- $fio->{checksumSeed}, 1 # verify
+ $fio->{checksumSeed}, 1, # verify
+ $fio->{protocol_version}
);
if ( $ret != 1 ) {
$fio->log("Bad cached digest for $attr->{fullPath} ($ret);"
(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");
- }
+ $needMD4, $attr->{compress}, 1, $fio->{protocol_version});
if ( $err ) {
$fio->log("Can't get rsync digests from $attr->{fullPath}"
. " (err=$err, name=$f->{name})");
$fio->{stats}{errorCnt}++;
return -1;
}
+ if ( $fio->{logLevel} >= 5 ) {
+ my($isCached, $invalid) = $fio->{csum}->isCached;
+ $fio->log("$attr->{fullPath} cache = $isCached,"
+ . " invalid = $invalid, phase = $phase");
+ }
return $blkSize;
}
sub attribGetWhere
{
- my($fio, $f, $noCache) = @_;
- my($dir, $fname, $share, $shareM, $partial, $attr);
+ my($fio, $f, $noCache, $fname) = @_;
+ my($dir, $share, $shareM, $partial, $attr);
- $fname = $f->{name};
- $fname = "$fio->{xfer}{pathHdrSrc}/$fname"
+ if ( !defined($fname) ) {
+ $fname = $f->{name};
+ $fname = "$fio->{xfer}{pathHdrSrc}/$fname"
if ( defined($fio->{xfer}{pathHdrSrc}) );
+ }
$fname =~ s{//+}{/}g;
if ( $fname =~ m{(.*)/(.*)}s ) {
$shareM = $fio->{shareM};
return $attr;
}
$target = "/$target" if ( $target !~ /^\// );
- $fio->log("$attr->{fullPath}: redirecting to $target (will trim "
- . "$fio->{xfer}{pathHdrSrc})") if ( $fio->{logLevel} >= 4 );
- $target =~ s/^\Q$fio->{xfer}{pathHdrSrc}//;
+ $fio->log("$attr->{fullPath}: redirecting to $target")
+ if ( $fio->{logLevel} >= 4 );
$target =~ s{^/+}{};
- #
- # Note: overwrites name to point to real file
- #
- $f->{name} = $target;
- ($attr) = $fio->attribGetWhere($f, 1);
+ ($attr) = $fio->attribGetWhere($f, 1, $target);
$fio->log(" ... now got $attr->{fullPath}")
if ( $fio->{logLevel} >= 4 );
}
my($fio, $f, $placeHolder) = @_;
my($dir, $file);
+ return if ( $placeHolder && $fio->{phase} > 0 );
+
if ( $f->{name} =~ m{(.*)/(.*)}s ) {
$file = $2;
$dir = "$fio->{shareM}/" . $1;
$file = $f->{name};
}
- if ( !defined($fio->{attribLastDir}) || $fio->{attribLastDir} ne $dir ) {
+ if ( $dir ne ""
+ && (!defined($fio->{attribLastDir}) || $fio->{attribLastDir} ne $dir) ) {
#
# Flush any directories that don't match the first part
- # of the new directory
+ # of the new directory. Don't flush the top-level directory
+ # (ie: $dir eq "") since the "." might get sorted in the middle
+ # of other top-level directories or files.
#
foreach my $d ( keys(%{$fio->{attrib}}) ) {
next if ( $d eq "" || "$dir/" =~ m{^\Q$d/} );
$fio->{attribLastDir} = $dir;
}
if ( !exists($fio->{attrib}{$dir}) ) {
+ $fio->log("attribSet: dir=$dir not found") if ( $fio->{logLevel} >= 4 );
$fio->{attrib}{$dir} = BackupPC::Attrib->new({
compress => $fio->{xfer}{compress},
});
- my $path = $fio->{outDir} . $dir;
- if ( -f $fio->{attrib}{$dir}->fileName($path)
- && !$fio->{attrib}{$dir}->read($path) ) {
- $fio->log(sprintf("Unable to read attribute file %s",
+ my $dirM = $dir;
+ $dirM = $1 . "/" . $fio->{bpc}->fileNameMangle($2)
+ if ( $dirM =~ m{(.*?)/(.*)}s );
+ my $path = $fio->{outDir} . $dirM;
+ if ( -f $fio->{attrib}{$dir}->fileName($path) ) {
+ if ( !$fio->{attrib}{$dir}->read($path) ) {
+ $fio->log(sprintf("Unable to read attribute file %s",
$fio->{attrib}{$dir}->fileName($path)));
+ } else {
+ $fio->log(sprintf("attribRead file %s",
+ $fio->{attrib}{$dir}->fileName($path)))
+ if ( $fio->{logLevel} >= 4 );
+ }
}
+ } else {
+ $fio->log("attribSet: dir=$dir exists") if ( $fio->{logLevel} >= 4 );
}
- $fio->log("attribSet(dir=$dir, file=$file)") if ( $fio->{logLevel} >= 4 );
+ $fio->log("attribSet(dir=$dir, file=$file, size=$f->{size}, placeholder=$placeHolder)")
+ if ( $fio->{logLevel} >= 4 );
my $mode = $f->{mode};
my($fio, $d) = @_;
my($poolWrite);
- #
- # Don't write attributes on 2nd phase - they're already
- # taken care of during the first phase.
- #
- return if ( $fio->{phase} > 0 );
if ( !defined($d) ) {
#
# flush all entries (in reverse order)
return;
}
return if ( !defined($fio->{attrib}{$d}) );
+
#
# Set deleted files in the attributes. Any file in the view
# that doesn't have attributes is flagged as deleted for
}) if ( $fio->{logLevel} >= 2
&& $a->{type} == BPC_FTYPE_FILE );
}
- } elsif ( !$fio->{full} ) {
+ } elsif ( $fio->{phase} == 0 && !$fio->{full} ) {
##print("Delete file $f\n");
$fio->logFileAction("delete", {
%{$fio->{viewCache}{$d}{$f}},
}
}
}
- if ( $fio->{attrib}{$d}->fileCount ) {
+ if ( $fio->{attrib}{$d}->fileCount || $fio->{phase} > 0 ) {
my $data = $fio->{attrib}{$d}->writeData;
my $dirM = $d;
my($exists, $digest, $outSize, $errs) = $poolWrite->close;
$fileName =~ s{^/+}{};
- $fio->log(@$errs) if ( defined($errs) && @$errs );
+ if ( defined($errs) && @$errs ) {
+ $fio->log(@$errs);
+ $fio->{stats}{errorCnt} += @$errs;
+ }
if ( $doStats ) {
$fio->{stats}{TotalFileCnt}++;
$fio->{stats}{TotalFileSize} += $origSize;
$fio->logFileAction("create", $f) if ( $fio->{logLevel} >= 1 );
$fio->log("makePath($path, 0777)") if ( $fio->{logLevel} >= 5 );
$path = $1 if ( $path =~ /(.*)/s );
- File::Path::mkpath($path, 0, 0777) if ( !-d $path );
+ eval { File::Path::mkpath($path, 0, 0777) } if ( !-d $path );
return $fio->attribSet($f) if ( -d $path );
$fio->log("Can't create directory $path");
$fio->{stats}{errorCnt}++;
= BackupPC::Xfer::RsyncDigest->digestStart(
$attr->{fullPath}, $attr->{size},
0, 2048, $fio->{checksumSeed}, 1,
- $attr->{compress}, 1);
+ $attr->{compress}, 1,
+ $fio->{protocol_version});
if ( $err ) {
$fio->log("Can't open $attr->{fullPath} for MD4"
. " check (err=$err, $name)");
if ( $phase > 0 ) {
$fio->log("$name: fatal error: md4 doesn't match on retry;"
. " file removed");
+ $fio->{stats}{errorCnt}++;
} 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;
unlink($fio->{rxOutFile});