- 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: fatal error: md4 doesn't match");
- $fio->{stats}{errorCnt}++;
- if ( defined($fio->{rxOutFd}) ) {
- $fio->{rxOutFd}->close;
- unlink($fio->{rxOutFile});
+
+ #
+ # Check the final md4 digest
+ #
+ if ( defined($md4) ) {
+ my $newDigest;
+ if ( !defined($fio->{rxDigest}) ) {
+ #
+ # File was exact match, but we still need to verify the
+ # MD4 checksum. Compute the md4 digest (or fetch the
+ # cached one.)
+ #
+ if ( defined(my $attr = $fio->{rxLocalAttr}) ) {
+ #
+ # block size doesn't matter: we're only going to
+ # fetch the md4 file digest, not the block digests.
+ #
+ my($err, $csum, $blkSize)
+ = BackupPC::Xfer::RsyncDigest->digestStart(
+ $attr->{fullPath}, $attr->{size},
+ 0, 2048, $fio->{checksumSeed}, 1,
+ $attr->{compress});
+ if ( $err ) {
+ $fio->log("Can't open $attr->{fullPath} for MD4"
+ . " check (err=$err, $name)");
+ $fio->{stats}{errorCnt}++;
+ } else {
+ $newDigest = $csum->digestEnd;
+ }
+ $fio->{rxSize} = $attr->{size};
+ } else {
+ #
+ # Empty file; just create an empty file digest
+ #
+ $fio->{rxDigest} = File::RsyncP::Digest->new;
+ $fio->{rxDigest}->add(pack("V", $fio->{checksumSeed}));
+ $newDigest = $fio->{rxDigest}->digest;
+ }
+ $fio->log("$name got exact match") if ( $fio->{logLevel} >= 5 );
+ } else {
+ $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: fatal error: md4 doesn't match");
+ $fio->{stats}{errorCnt}++;
+ if ( defined($fio->{rxOutFd}) ) {
+ $fio->{rxOutFd}->close;
+ unlink($fio->{rxOutFile});
+ }
+ delete($fio->{rxFile});
+ delete($fio->{rxOutFile});
+ return 1;