#
#========================================================================
#
-# Version 1.6.0_CVS, released 10 Dec 2002.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
use strict;
use File::Path;
use BackupPC::Attrib qw(:all);
-use BackupPC::FileZIO;
+use BackupPC::View;
+use BackupPC::PoolWrite;
use BackupPC::PoolWrite;
use Data::Dumper;
digest => File::RsyncP::Digest->new,
checksumSeed => 0,
attrib => {},
+ logHandler => \&logHandler,
+ stats => {
+ errorCnt => 0,
+ TotalFileCnt => 0,
+ TotalFileSize => 0,
+ ExistFileCnt => 0,
+ ExistFileSize => 0,
+ ExistFileCompSize => 0,
+ },
%$options,
}, $class;
- $fio->{shareM} = $fio->{bpc}->fileNameEltMangle($fio->{xfer}{shareName});
+ $fio->{shareM} = $fio->{bpc}->fileNameEltMangle($fio->{share});
$fio->{outDir} = "$fio->{xfer}{outDir}/new/";
$fio->{outDirSh} = "$fio->{outDir}/$fio->{shareM}/";
- $fio->{view} = BackupPC::View->new($fio->{bpc}, $fio->{host},
+ $fio->{view} = BackupPC::View->new($fio->{bpc}, $fio->{client},
$fio->{backups});
- $fio->{full} = $fio->{xfer}{type} eq "full" ? 1 : 0;
+ $fio->{full} = $fio->{xfer}{type} eq "full" ? 1 : 0;
$fio->{newFilesFH} = $fio->{xfer}{newFilesFH};
- $fio->{lastBkupNum} = $fio->{xfer}{lastBkupNum};
return $fio;
}
return $fio->{blockSize};
}
+sub logHandlerSet
+{
+ my($fio, $sub) = @_;
+ $fio->{logHandler} = $sub;
+}
+
#
# Setup rsync checksum computation for the given file.
#
sub csumStart
{
- my($fio, $f) = @_;
- my $attr = $fio->attribGet($f);
+ my($fio, $f, $needMD4) = @_;
+ my $attr = $fio->attribGet($f);
$fio->{file} = $f;
$fio->csumEnd if ( defined($fio->{fh}) );
return if ( $attr->{type} != BPC_FTYPE_FILE );
if ( !defined($fio->{fh} = BackupPC::FileZIO->open($attr->{fullPath},
0,
$attr->{compress})) ) {
- $fio->log("Can't open $attr->{fullPath}");
+ $fio->log("Can't open $attr->{fullPath} (name=$f->{name})");
+ $fio->{stats}{errorCnt}++;
return -1;
}
+ if ( $needMD4) {
+ $fio->{csumDigest} = File::RsyncP::Digest->new;
+ $fio->{csumDigest}->add(pack("V", $fio->{checksumSeed}));
+ } else {
+ delete($fio->{csumDigest});
+ }
}
sub csumGet
return if ( !defined($fio->{fh}) );
if ( $fio->{fh}->read(\$fileData, $blockSize * $num) <= 0 ) {
- return $fio->csumEnd;
+ $fio->log("$fio->{file}{name}: csumGet is at EOF - zero padding");
+ $fio->{stats}{errorCnt}++;
+ $fileData = pack("c", 0) x ($blockSize * $num);
}
- #$fileData = substr($fileData, 0, $blockSize * $num - 2);
- $fio->log(sprintf("%s: getting csum ($num,$csumLen,%d,0x%x)\n",
+ $fio->{csumDigest}->add($fileData) if ( defined($fio->{csumDigest}) );
+ $fio->log(sprintf("%s: getting csum ($num,$csumLen,%d,0x%x)",
$fio->{file}{name},
length($fileData),
$fio->{checksumSeed}))
- if ( $fio->{logLevel} >= 10 );
- return $fio->{digest}->rsyncChecksum($fileData, $blockSize,
+ if ( $fio->{logLevel} >= 9 );
+ return $fio->{digest}->blockDigest($fileData, $blockSize,
$csumLen, $fio->{checksumSeed});
}
my($fio) = @_;
return if ( !defined($fio->{fh}) );
+ #
+ # make sure we read the entire file for the file MD4 digest
+ #
+ if ( defined($fio->{csumDigest}) ) {
+ my $fileData;
+ while ( $fio->{fh}->read(\$fileData, 65536) > 0 ) {
+ $fio->{csumDigest}->add($fileData);
+ }
+ }
$fio->{fh}->close();
delete($fio->{fh});
+ return $fio->{csumDigest}->digest if ( defined($fio->{csumDigest}) );
}
sub readStart
{
my($fio, $f) = @_;
- my $attr = $fio->attribGet($f);
+ my $attr = $fio->attribGet($f);
$fio->{file} = $f;
$fio->readEnd if ( defined($fio->{fh}) );
- if ( !defined(my $fh = BackupPC::FileZIO->open($attr->{fullPath},
+ if ( !defined($fio->{fh} = BackupPC::FileZIO->open($attr->{fullPath},
0,
$attr->{compress})) ) {
- $fio->log("Can't open $attr->{fullPath}");
+ $fio->log("Can't open $attr->{fullPath} (name=$f->{name})");
+ $fio->{stats}{errorCnt}++;
return;
}
+ $fio->log("$f->{name}: opened for read") if ( $fio->{logLevel} >= 4 );
}
sub read
{
my($fio, $num) = @_;
- my($fileData);
+ my $fileData;
$num ||= 32768;
return if ( !defined($fio->{fh}) );
if ( $fio->{fh}->read(\$fileData, $num) <= 0 ) {
return $fio->readEnd;
}
+ $fio->log(sprintf("read returns %d bytes", length($fileData)))
+ if ( $fio->{logLevel} >= 8 );
return \$fileData;
}
return if ( !defined($fio->{fh}) );
$fio->{fh}->close;
+ $fio->log("closing $fio->{file}{name})") if ( $fio->{logLevel} >= 8 );
delete($fio->{fh});
+ return;
}
sub checksumSeed
#$fio->log("viewCacheDir($share, $dir)");
if ( !defined($share) ) {
- $share = $fio->{xfer}{shareName};
+ $share = $fio->{share};
$shareM = $fio->{shareM};
} else {
$shareM = $fio->{bpc}->fileNameEltMangle($share);
# fetch new directory attributes
#
$fio->{viewCache}{$shareM}
- = $fio->{view}->dirAttrib($fio->{lastBkupNum}, $share, $dir);
+ = $fio->{view}->dirAttrib($fio->{viewNum}, $share, $dir);
}
sub attribGet
my($fio, $f) = @_;
my($dir, $fname, $share, $shareM);
- if ( $f->{name} =~ m{(.*)/(.*)} ) {
+ $fname = $f->{name};
+ $fname = "$fio->{xfer}{pathHdrSrc}/$fname"
+ if ( defined($fio->{xfer}{pathHdrSrc}) );
+ $fname =~ s{//+}{/}g;
+ if ( $fname =~ m{(.*)/(.*)} ) {
$shareM = $fio->{shareM};
$dir = $1;
$fname = $2;
- } elsif ( $f->{name} ne "." ) {
+ } elsif ( $fname ne "." ) {
$shareM = $fio->{shareM};
$dir = "";
- $fname = $f->{name};
} else {
$share = "";
$shareM = "";
$dir = "";
- $fname = $fio->{xfer}{shareName};
+ $fname = $fio->{share};
}
$fio->viewCacheDir($share, $dir);
$shareM .= "/$dir" if ( $dir ne "" );
$dir = "$fio->{shareM}/" . $1;
} elsif ( $f->{name} eq "." ) {
$dir = "";
- $file = $fio->{xfer}{shareName};
+ $file = $fio->{share};
} else {
$dir = $fio->{shareM};
$file = $f->{name};
my $poolWrite = BackupPC::PoolWrite->new($fio->{bpc}, $fileName,
length($data), $fio->{xfer}{compress});
$poolWrite->write(\$data);
- $fio->processClose($poolWrite, $fio->{attrib}{$d}->fileName($d),
+ $fio->processClose($poolWrite, $fio->{attrib}{$d}->fileName($dirM),
length($data), 0);
}
delete($fio->{attrib}{$d});
#
# Make a given directory. Returns non-zero on error.
#
-sub mkpath
+sub makePath
{
my($fio, $f) = @_;
my $name = $1 if ( $f->{name} =~ /(.*)/ );
$path = $fio->{outDirSh} . $fio->{bpc}->fileNameMangle($name);
}
$fio->logFileAction("create", $f) if ( $fio->{logLevel} >= 1 );
- $fio->log("mkpath($path, 0777)") if ( $fio->{logLevel} >= 5 );
+ $fio->log("makePath($path, 0777)") if ( $fio->{logLevel} >= 5 );
$path = $1 if ( $path =~ /(.*)/ );
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}++;
return -1;
}
#
# Make a special file. Returns non-zero on error.
#
-sub mkspecial
+sub makeSpecial
{
my($fio, $f) = @_;
my $name = $1 if ( $f->{name} =~ /(.*)/ );
my $str = "";
my $type = $fio->mode2type($f->{mode});
- $fio->log("mkspecial($path, $type, $f->{mode})")
+ $fio->log("makeSpecial($path, $type, $f->{mode})")
if ( $fio->{logLevel} >= 5 );
if ( $type == BPC_FTYPE_CHARDEV || $type == BPC_FTYPE_BLOCKDEV ) {
my($major, $minor, $fh, $fileData);
|| $attr->{type} != $fio->mode2type($f->{mode})
|| $attr->{mtime} != $f->{mtime}
|| $attr->{size} != $f->{size}
+ || $attr->{uid} != $f->{uid}
|| $attr->{gid} != $f->{gid}
|| $attr->{mode} != $f->{mode}
|| !defined($fh = BackupPC::FileZIO->open($attr->{fullPath}, 0,
}
#
-# Appends to list of log messages
+# Default log handler
+#
+sub logHandler
+{
+ my($str) = @_;
+
+ print(STDERR $str, "\n");
+}
+
+#
+# Handle one or more log messages
#
sub log
{
- my($fio, @msg) = @_;
+ my($fio, @logStr) = @_;
- $fio->{log} ||= [];
- push(@{$fio->{log}}, @msg);
+ foreach my $str ( @logStr ) {
+ next if ( $str eq "" );
+ $fio->{logHandler}($str);
+ }
}
#
}
#
-# Returns a list of log messages
+# Later we'll use this function to complete a prior unfinished dump.
+# We'll do an incremental on the part we have already, and then a
+# full or incremental against the rest.
#
-sub logMsg
+sub ignoreAttrOnFile
{
- my($fio) = @_;
- my $log = $fio->{log} || [];
-
- delete($fio->{log});
- return @$log;
+ return undef;
}
#
$fio->{rxRemainder} = $remainder; # size of the last block
$fio->{rxMatchBlk} = 0; # current start of match
$fio->{rxMatchNext} = 0; # current next block of match
- my $rxSize = ($cnt - 1) * $size + $remainder;
+ $fio->{rxSize} = 0; # size of received file
+ my $rxSize = $cnt > 0 ? ($cnt - 1) * $size + $remainder : 0;
if ( $fio->{rxFile}{size} != $rxSize ) {
$fio->{rxMatchBlk} = undef; # size different, so no file match
$fio->log("$fio->{rxFile}{name}: size doesn't match"
$rxOutFile, $fio->{rxFile}{size},
$fio->{xfer}{compress});
$fio->log("$fio->{rxFile}{name}: opening output file $rxOutFile")
- if ( $fio->{logLevel} >= 10 );
+ if ( $fio->{logLevel} >= 9 );
$fio->{rxOutFile} = $rxOutFile;
$fio->{rxOutFileRel} = $rxOutFileRel;
$fio->{rxDigest} = File::RsyncP::Digest->new;
0,
$attr->{compress})) ) {
$fio->log("Can't open $attr->{fullPath}");
+ $fio->{stats}{errorCnt}++;
return -1;
}
- if ( $attr->{size} < 10 * 1024 * 1024 ) {
+ if ( $attr->{size} < 16 * 1024 * 1024 ) {
#
- # Cache the entire old file if it is less than 10MB
+ # Cache the entire old file if it is less than 16MB
#
my $data;
$fio->{rxInData} = "";
- while ( $fh->read(\$data, 10 * 1024 * 1024) > 0 ) {
+ while ( $fh->read(\$data, 16 * 1024 * 1024) > 0 ) {
$fio->{rxInData} .= $data;
}
+ $fio->log("$attr->{fullPath}: cached all $attr->{size}"
+ . " bytes")
+ if ( $fio->{logLevel} >= 9 );
} else {
#
# Create and write a temporary output file
#
unlink("$fio->{outDirSh}RStmp")
if ( -f "$fio->{outDirSh}RStmp" );
- if ( open(F, ">+$fio->{outDirSh}RStmp") ) {
+ if ( open(F, "+>", "$fio->{outDirSh}RStmp") ) {
my $data;
+ my $byteCnt = 0;
while ( $fh->read(\$data, 1024 * 1024) > 0 ) {
if ( syswrite(F, $data) != length($data) ) {
$fio->log(sprintf("Can't write len=%d to %s",
length($data) , "$fio->{outDirSh}RStmp"));
$fh->close;
+ $fio->{stats}{errorCnt}++;
return -1;
}
+ $byteCnt += length($data);
}
$fio->{rxInFd} = *F;
$fio->{rxInName} = "$fio->{outDirSh}RStmp";
- seek($fio->{rxInFd}, 0, 0);
+ sysseek($fio->{rxInFd}, 0, 0);
+ $fio->log("$attr->{fullPath}: copied $byteCnt,"
+ . "$attr->{size} bytes to $fio->{rxInName}")
+ if ( $fio->{logLevel} >= 9 );
} else {
$fio->log("Unable to open $fio->{outDirSh}RStmp");
$fh->close;
+ $fio->{stats}{errorCnt}++;
return -1;
}
}
$fh->close;
} else {
- if ( open(F, $attr->{fullPath}) ) {
+ if ( open(F, "<", $attr->{fullPath}) ) {
$fio->{rxInFd} = *F;
$fio->{rxInName} = $attr->{fullPath};
} else {
$fio->log("Unable to open $attr->{fullPath}");
+ $fio->{stats}{errorCnt}++;
return -1;
}
}
my $lastBlk = $fio->{rxMatchNext} - 1;
$fio->log("$fio->{rxFile}{name}: writing blocks $fio->{rxMatchBlk}.."
. "$lastBlk")
- if ( $fio->{logLevel} >= 10 );
+ if ( $fio->{logLevel} >= 9 );
my $seekPosn = $fio->{rxMatchBlk} * $fio->{rxBlkSize};
- if ( defined($fio->{rxInFd}) && !seek($fio->{rxInFd}, $seekPosn, 0) ) {
- $fio->log("Unable to seek $attr->{fullPath} to $seekPosn");
+ if ( defined($fio->{rxInFd})
+ && !sysseek($fio->{rxInFd}, $seekPosn, 0) ) {
+ $fio->log("Unable to seek $attr->{rxInName} to $seekPosn");
+ $fio->{stats}{errorCnt}++;
return -1;
}
my $cnt = $fio->{rxMatchNext} - $fio->{rxMatchBlk};
}
if ( defined($fio->{rxInData}) ) {
$data = substr($fio->{rxInData}, $seekPosn, $len);
+ $seekPosn += $len;
} else {
- if ( sysread($fio->{rxInFd}, $data, $len) != $len ) {
- $fio->log("Unable to read $len bytes from"
- . " $fio->{rxInName} "
- . "($i,$thisCnt,$fio->{rxBlkCnt})");
+ my $got = sysread($fio->{rxInFd}, $data, $len);
+ if ( $got != $len ) {
+ my $inFileSize = -s $fio->{rxInName};
+ $fio->log("Unable to read $len bytes from $fio->{rxInName}"
+ . " got=$got, seekPosn=$seekPosn"
+ . " ($i,$thisCnt,$fio->{rxBlkCnt},$inFileSize"
+ . ",$attr->{size})");
+ $fio->{stats}{errorCnt}++;
return -1;
}
+ $seekPosn += $len;
}
$fio->{rxOutFd}->write(\$data);
$fio->{rxDigest}->add($data);
+ $fio->{rxSize} += length($data);
}
$fio->{rxMatchBlk} = undef;
}
#
my $len = length($newData);
$fio->log("$fio->{rxFile}{name}: writing $len bytes new data")
- if ( $fio->{logLevel} >= 10 );
+ if ( $fio->{logLevel} >= 9 );
$fio->{rxOutFd}->write(\$newData);
$fio->{rxDigest}->add($newData);
+ $fio->{rxSize} += length($newData);
}
}
$fio->{rxDigest} = File::RsyncP::Digest->new;
$fio->{rxDigest}->add(pack("V", $fio->{checksumSeed}));
my $attr = $fio->{rxLocalAttr};
- if ( defined($attr) && defined(my $fh = BackupPC::FileZIO->open(
+ if ( defined($attr) ) {
+ if ( defined(my $fh = BackupPC::FileZIO->open(
$attr->{fullPath},
0,
$attr->{compress})) ) {
- my $data;
- while ( $fh->read(\$data, 4 * 65536) > 0 ) {
- $fio->{rxDigest}->add($data);
+ my $data;
+ while ( $fh->read(\$data, 4 * 65536) > 0 ) {
+ $fio->{rxDigest}->add($data);
+ $fio->{rxSize} += length($data);
+ }
+ $fh->close;
+ } else {
+ $fio->log("Can't open $attr->{fullPath} for MD4 check ($name)");
+ $fio->{stats}{errorCnt}++;
}
- $fh->close;
- } else {
- # error
}
$fio->log("$name got exact match")
if ( $fio->{logLevel} >= 5 );
}
close($fio->{rxInFd}) if ( defined($fio->{rxInFd}) );
unlink("$fio->{outDirSh}RStmp") if ( -f "$fio->{outDirSh}RStmp" );
- my $newDigest = $fio->{rxDigest}->rsyncDigest;
+ my $newDigest = $fio->{rxDigest}->digest;
if ( $fio->{logLevel} >= 3 ) {
my $md4Str = unpack("H*", $md4);
my $newStr = unpack("H*", $newDigest);
$fio->log("$name got digests $md4Str vs $newStr")
}
if ( $md4 ne $newDigest ) {
- $fio->log("$name md4 doesn't match")
- if ( $fio->{logLevel} >= 1 );
+ $fio->log("$name: fatal error: md4 doesn't match");
+ $fio->{stats}{errorCnt}++;
if ( defined($fio->{rxOutFd}) ) {
$fio->{rxOutFd}->close;
unlink($fio->{rxOutFile});
# One special case is an empty file: if the file size is
# zero we need to open the output file to create it.
#
- if ( $fio->{rxFile}{size} == 0 ) {
+ if ( $fio->{rxSize} == 0 ) {
my $rxOutFileRel = "$fio->{shareM}/"
. $fio->{bpc}->fileNameMangle($name);
my $rxOutFile = $fio->{outDir} . $rxOutFileRel;
$fio->{rxOutFd} = BackupPC::PoolWrite->new($fio->{bpc},
- $rxOutFile, $fio->{rxFile}{size},
+ $rxOutFile, $fio->{rxSize},
$fio->{xfer}{compress});
}
if ( !defined($fio->{rxOutFd}) ) {
. $fio->{bpc}->fileNameMangle($name);
if ( !link($attr->{fullPath}, $rxOutFile) ) {
$fio->log("Unable to link $attr->{fullPath} to $rxOutFile");
+ $fio->{stats}{errorCnt}++;
return -1;
}
#
# Cumulate the stats
#
$fio->{stats}{TotalFileCnt}++;
- $fio->{stats}{TotalFileSize} += $fio->{rxFile}{size};
+ $fio->{stats}{TotalFileSize} += $fio->{rxSize};
$fio->{stats}{ExistFileCnt}++;
- $fio->{stats}{ExistFileSize} += $fio->{rxFile}{size};
+ $fio->{stats}{ExistFileSize} += $fio->{rxSize};
$fio->{stats}{ExistFileCompSize} += -s $rxOutFile;
- return;
+ $fio->{rxFile}{size} = $fio->{rxSize};
+ return $fio->attribSet($fio->{rxFile});
}
}
if ( defined($fio->{rxOutFd}) ) {
my $exist = $fio->processClose($fio->{rxOutFd},
$fio->{rxOutFileRel},
- $fio->{rxFile}{size}, 1);
+ $fio->{rxSize}, 1);
$fio->logFileAction($exist ? "pool" : "create", $fio->{rxFile})
if ( $fio->{logLevel} >= 1 );
+ $fio->{rxFile}{size} = $fio->{rxSize};
+ return $fio->attribSet($fio->{rxFile});
}
delete($fio->{rxDigest});
delete($fio->{rxInData});
return;
}
+#
+# Callback function for BackupPC::View->find. Note the order of the
+# first two arguments.
+#
sub fileListEltSend
{
- my($fio, $name, $fList, $outputFunc) = @_;
- my @s = stat($name);
-
- (my $n = $name) =~ s/^\Q$fio->{localDir}/$fio->{remoteDir}/;
- $fList->encode({
- fname => $n,
- dev => $s[0],
- inode => $s[1],
- mode => $s[2],
- uid => $s[4],
- gid => $s[5],
- rdev => $s[6],
- mtime => $s[9],
- });
+ my($a, $fio, $fList, $outputFunc) = @_;
+ my $name = $a->{relPath};
+ my $n = $name;
+ my $type = $fio->mode2type($a->{mode});
+ my $extraAttribs = {};
+
+ $n =~ s/^\Q$fio->{xfer}{pathHdrSrc}//;
+ $fio->log("Sending $name (remote=$n)") if ( $fio->{logLevel} >= 4 );
+ if ( $type == BPC_FTYPE_CHARDEV
+ || $type == BPC_FTYPE_BLOCKDEV
+ || $type == BPC_FTYPE_SYMLINK ) {
+ my $fh = BackupPC::FileZIO->open($a->{fullPath}, 0, $a->{compress});
+ my($str, $rdSize);
+ if ( defined($fh) ) {
+ $rdSize = $fh->read(\$str, $a->{size} + 1024);
+ if ( $type == BPC_FTYPE_SYMLINK ) {
+ #
+ # Reconstruct symbolic link
+ #
+ $extraAttribs = { link => $str };
+ if ( $rdSize != $a->{size} ) {
+ # ERROR
+ $fio->log("$name: can't read exactly $a->{size} bytes");
+ $fio->{stats}{errorCnt}++;
+ }
+ } elsif ( $str =~ /(\d*),(\d*)/ ) {
+ #
+ # Reconstruct char or block special major/minor device num
+ #
+ # Note: char/block devices have $a->{size} = 0, so we
+ # can't do an error check on $rdSize.
+ #
+ $extraAttribs = { rdev => $1 * 256 + $2 };
+ } else {
+ $fio->log("$name: unexpected special file contents $str");
+ $fio->{stats}{errorCnt}++;
+ }
+ $fh->close;
+ } else {
+ # ERROR
+ $fio->log("$name: can't open");
+ $fio->{stats}{errorCnt}++;
+ }
+ }
+ my $f = {
+ name => $n,
+ #dev => 0, # later, when we support hardlinks
+ #inode => 0, # later, when we support hardlinks
+ mode => $a->{mode},
+ uid => $a->{uid},
+ gid => $a->{gid},
+ mtime => $a->{mtime},
+ size => $a->{size},
+ %$extraAttribs,
+ };
+ $fList->encode($f);
+ $f->{name} = "$fio->{xfer}{pathHdrDest}/$f->{name}";
+ $f->{name} =~ s{//+}{/}g;
+ $fio->logFileAction("restore", $f) if ( $fio->{logLevel} >= 1 );
&$outputFunc($fList->encodeData);
+ #
+ # Cumulate stats
+ #
+ if ( $type != BPC_FTYPE_DIR ) {
+ $fio->{stats}{TotalFileCnt}++;
+ $fio->{stats}{TotalFileSize} += $a->{size};
+ }
}
sub fileListSend
{
my($fio, $flist, $outputFunc) = @_;
- $fio->log("fileListSend not implemented!!");
- $fio->{view}->find($fio->{lastBkupNum}, $fio->{xfer}{shareName},
- $fio->{restoreFiles}, 1, \&fileListEltSend,
- $flist, $outputFunc);
+ #
+ # Populate the file list with the files requested by the user.
+ # Since some might be directories so we call BackupPC::View::find.
+ #
+ $fio->log("fileListSend: sending file list: "
+ . join(" ", @{$fio->{fileList}})) if ( $fio->{logLevel} >= 4 );
+ foreach my $name ( @{$fio->{fileList}} ) {
+ $fio->{view}->find($fio->{xfer}{bkupSrcNum},
+ $fio->{xfer}{bkupSrcShare},
+ $name, 1,
+ \&fileListEltSend, $fio, $flist, $outputFunc);
+ }
}
sub finish
#
# Flush the attributes if this is the child
#
- $fio->attribWrite(undef)
+ $fio->attribWrite(undef);
}
-
-sub is_tainted
-{
- return ! eval {
- join('',@_), kill 0;
- 1;
- };
-}
+#sub is_tainted
+#{
+# return ! eval {
+# join('',@_), kill 0;
+# 1;
+# };
+#}
1;