X-Git-Url: http://git.rot13.org/?p=BackupPC.git;a=blobdiff_plain;f=lib%2FBackupPC%2FXfer%2FRsyncFileIO.pm;h=83b9db968f08f8d7b1c7f1a3994813141c6123cd;hp=ea72dce06bccee89d6d604eaf2a8c7e2ee1830a8;hb=f6fbcc3682d2bc9e7dfdc26e95bd5fcdb359496d;hpb=4cdaa6b8a9f5161ee2da4371d68cbbad41248ea0 diff --git a/lib/BackupPC/Xfer/RsyncFileIO.pm b/lib/BackupPC/Xfer/RsyncFileIO.pm index ea72dce..83b9db9 100644 --- a/lib/BackupPC/Xfer/RsyncFileIO.pm +++ b/lib/BackupPC/Xfer/RsyncFileIO.pm @@ -8,11 +8,11 @@ # Craig Barratt # # COPYRIGHT -# Copyright (C) 2002-2003 Craig Barratt +# Copyright (C) 2002-2007 Craig Barratt # #======================================================================== # -# Version 3.0.0beta0, released 11 Jul 2006. +# Version 3.2.0beta0, released 5 April 2009. # # See http://backuppc.sourceforge.net. # @@ -160,7 +160,14 @@ sub csumStart 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," @@ -169,7 +176,8 @@ sub csumStart 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);" @@ -185,18 +193,18 @@ sub csumStart (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; } @@ -321,14 +329,16 @@ sub viewCacheDir 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{(.*)/(.*)} ) { + if ( $fname =~ m{(.*)/(.*)}s ) { $shareM = $fio->{shareM}; $dir = $1; $fname = $2; @@ -386,15 +396,10 @@ sub attribGet 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 ); } @@ -437,7 +442,9 @@ sub attribSet my($fio, $f, $placeHolder) = @_; my($dir, $file); - if ( $f->{name} =~ m{(.*)/(.*)} ) { + return if ( $placeHolder && $fio->{phase} > 0 ); + + if ( $f->{name} =~ m{(.*)/(.*)}s ) { $file = $2; $dir = "$fio->{shareM}/" . $1; } elsif ( $f->{name} eq "." ) { @@ -448,10 +455,13 @@ sub attribSet $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/} ); @@ -460,17 +470,29 @@ sub attribSet $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}; @@ -491,11 +513,6 @@ sub attribWrite 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) @@ -506,6 +523,7 @@ sub attribWrite 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 @@ -517,7 +535,7 @@ sub attribWrite my $dir; my $share; - $dir = $1 if ( $d =~ m{.+?/(.*)} ); + $dir = $1 if ( $d =~ m{.+?/(.*)}s ); $fio->viewCacheDir(undef, $dir); ##print("attribWrite $d,$dir\n"); ##$Data::Dumper::Indent = 1; @@ -529,7 +547,7 @@ sub attribWrite if ( defined($fio->{viewCache}{$d}) ) { foreach my $f ( keys(%{$fio->{viewCache}{$d}}) ) { my $name = $f; - $name = "$1/$name" if ( $d =~ m{.*?/(.*)} ); + $name = "$1/$name" if ( $d =~ m{.*?/(.*)}s ); if ( defined(my $a = $fio->{attrib}{$d}->get($f)) ) { # # delete temporary attributes (skipped files) @@ -542,7 +560,7 @@ sub attribWrite }) 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}}, @@ -560,12 +578,12 @@ sub attribWrite } } } - if ( $fio->{attrib}{$d}->fileCount ) { + if ( $fio->{attrib}{$d}->fileCount || $fio->{phase} > 0 ) { my $data = $fio->{attrib}{$d}->writeData; my $dirM = $d; $dirM = $1 . "/" . $fio->{bpc}->fileNameMangle($2) - if ( $dirM =~ m{(.*?)/(.*)} ); + if ( $dirM =~ m{(.*?)/(.*)}s ); my $fileName = $fio->{attrib}{$d}->fileName("$fio->{outDir}$dirM"); $fio->log("attribWrite(dir=$d) -> $fileName") if ( $fio->{logLevel} >= 4 ); @@ -584,7 +602,10 @@ sub processClose 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; @@ -615,7 +636,7 @@ sub statsGet sub makePath { my($fio, $f) = @_; - my $name = $1 if ( $f->{name} =~ /(.*)/ ); + my $name = $1 if ( $f->{name} =~ /(.*)/s ); my $path; if ( $name eq "." ) { @@ -625,8 +646,8 @@ sub makePath } $fio->logFileAction("create", $f) if ( $fio->{logLevel} >= 1 ); $fio->log("makePath($path, 0777)") if ( $fio->{logLevel} >= 5 ); - $path = $1 if ( $path =~ /(.*)/ ); - File::Path::mkpath($path, 0, 0777) if ( !-d $path ); + $path = $1 if ( $path =~ /(.*)/s ); + 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}++; @@ -639,7 +660,7 @@ sub makePath sub makeSpecial { my($fio, $f) = @_; - my $name = $1 if ( $f->{name} =~ /(.*)/ ); + my $name = $1 if ( $f->{name} =~ /(.*)/s ); my $fNameM = $fio->{bpc}->fileNameMangle($name); my $path = $fio->{outDirSh} . $fNameM; my $attr = $fio->attribGet($f); @@ -912,7 +933,7 @@ sub fileDeltaRxNext # need to open an output file where we will build the # new version. # - $fio->{rxFile}{name} =~ /(.*)/; + $fio->{rxFile}{name} =~ /(.*)/s; my $rxOutFileRel = "$fio->{shareM}/" . $fio->{bpc}->fileNameMangle($1); my $rxOutFile = $fio->{outDir} . $rxOutFileRel; $fio->{rxOutFd} = BackupPC::PoolWrite->new($fio->{bpc}, @@ -1079,7 +1100,7 @@ sub fileDeltaRxNext sub fileDeltaRxDone { my($fio, $md4, $phase) = @_; - my $name = $1 if ( $fio->{rxFile}{name} =~ /(.*)/ ); + my $name = $1 if ( $fio->{rxFile}{name} =~ /(.*)/s ); my $ret; close($fio->{rxInFd}) if ( defined($fio->{rxInFd}) ); @@ -1106,7 +1127,8 @@ sub fileDeltaRxDone = 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)"); @@ -1142,11 +1164,11 @@ sub fileDeltaRxDone 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}); @@ -1358,7 +1380,7 @@ sub fileListEltSend if ( $fio->{clientCharset} ne "" ); $fList->encode($f); - $logName = "$fio->{xfer}{pathHdrDest}/$f->{name}"; + $logName = "$fio->{xfer}{pathHdrDest}/$logName"; $logName =~ s{//+}{/}g; $f->{name} = $logName; $fio->logFileAction("restore", $f) if ( $fio->{logLevel} >= 1 );