* checkin with 3.2.0beta0 release header
[BackupPC.git] / lib / BackupPC / FileZIO.pm
index 48554b8..0f4cd4d 100644 (file)
@@ -11,7 +11,7 @@
 #   Craig Barratt  <cbarratt@users.sourceforge.net>
 #
 # COPYRIGHT
-#   Copyright (C) 2001  Craig Barratt
+#   Copyright (C) 2001-2007  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
@@ -29,7 +29,7 @@
 #
 #========================================================================
 #
-# Version 2.0.0beta1, released 30 Mar 2003.
+# Version 3.2.0beta0, released 5 April 2009.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -43,6 +43,7 @@ use vars qw( $CompZlibOK );
 use Carp;
 use File::Path;
 use File::Copy;
+use Encode;
 
 #
 # For compressed files we have a to careful about running out of memory
@@ -99,9 +100,10 @@ sub open
         } else {
             open(FH, "<", $fileName) || return;
         }
+       binmode(FH);
         $fh = *FH;
     }
-    $compLevel = 0 if ( !$CompZlibOK );
+    $compLevel  = 0 if ( !$CompZlibOK );
     my $self = bless {
         fh           => $fh,
         name         => $fileName,
@@ -114,6 +116,7 @@ sub open
             $self->{deflate} = $self->myDeflateInit;
         } else {
             $self->{inflate} = $self->myInflateInit;
+            $self->{inflateStart} = 1;
         }
     }
     return $self;
@@ -124,6 +127,16 @@ sub compOk
     return $CompZlibOK;
 }
 
+#
+# Request utf8 strings with readLine interface
+#
+sub utf8
+{
+    my($self, $mode) = @_;
+
+    $self->{utf8} = $mode;
+}
+
 sub myDeflateInit
 {
     my $self = shift;
@@ -156,11 +169,42 @@ sub read
             return $n if ( $n < 0 );
             $self->{eof} = 1 if ( $n == 0 );
         }
+        if ( $self->{inflateStart} && $self->{dataIn} ne "" ) {
+            my $chr = substr($self->{dataIn}, 0, 1);
+
+            $self->{inflateStart} = 0;
+            if ( $chr eq chr(0xd6) || $chr eq chr(0xd7) ) {
+                #
+                # Flag 0xd6 or 0xd7 means this is a compressed file with
+                # appended md4 block checksums for rsync.  Change
+                # the first byte back to 0x78 and proceed.
+                #
+                ##print("Got 0xd6/0xd7 block: normal\n");
+                substr($self->{dataIn}, 0, 1) = chr(0x78);
+            } elsif ( $chr eq chr(0xb3) ) {
+                #
+                # Flag 0xb3 means this is the start of the rsync
+                # block checksums, so consider this as EOF for
+                # the compressed file.  Also seek the file so
+                # it is positioned at the 0xb3.
+                #
+                sysseek($self->{fh}, -length($self->{dataIn}), 1);
+                $self->{eof} = 1;
+                $self->{dataIn} = "";
+                ##print("Got 0xb3 block: considering eof\n");
+                last;
+            } else {
+                #
+                # normal case: nothing to do
+                #
+            }
+        }
         my($data, $err) = $self->{inflate}->inflate($self->{dataIn});
         $self->{dataOut} .= $data;
         if ( $err == Z_STREAM_END ) {
             #print("R");
             $self->{inflate} = $self->myInflateInit;
+            $self->{inflateStart} = 1;
         } elsif ( $err != Z_OK ) {
             $$dataRef = "";
             return -1;
@@ -187,11 +231,13 @@ sub readLine
     my($self) = @_;
     my $str;
 
-    while ( defined($self->{readLineBuf}) && !@{$self->{readLineBuf}} ) {
+    $self->{readLineBuf} = [] if ( !defined($self->{readLineBuf}) );
+    while ( !@{$self->{readLineBuf}} ) {
         $self->read(\$str, $CompMaxRead);
         if ( $str eq "" ) {
             $str = $self->{readLineFrag};
             $self->{readLineFrag} = "";
+            $str = decode_utf8($str) if ( $self->{utf8} );
             return $str;
         }
         @{$self->{readLineBuf}} = split(/\n/, $self->{readLineFrag} . $str);
@@ -201,7 +247,13 @@ sub readLine
             $self->{readLineFrag} = "";
         }
     }
-    return shift(@{$self->{readLineBuf}}) . "\n";
+    $str = shift(@{$self->{readLineBuf}}) . "\n";
+    if ( $self->{utf8} ) {
+        my $strUtf8 = decode_utf8($str, 0);
+        $strUtf8 = $str if ( length($strUtf8) == 0 );
+        return $strUtf8;
+    }
+    return $str;
 }
 
 sub rewind
@@ -214,6 +266,7 @@ sub rewind
     $self->{dataIn}  = '';
     $self->{eof}     = 0;
     $self->{inflate} = $self->myInflateInit;
+    $self->{inflateStart} = 1;
     return sysseek($self->{fh}, 0, 0);
 }
 
@@ -246,7 +299,7 @@ sub write
     my $n = length($$dataRef);
 
     return if ( !$self->{write} );
-    print($$dataRef) if ( $self->{writeTeeStdout} );
+    print(STDERR $$dataRef) if ( $self->{writeTeeStderr} );
     return 0 if ( $n == 0 );
     if ( !$self->{compress} ) {
         #
@@ -304,12 +357,12 @@ sub name
     return $self->{name};
 }
 
-sub writeTeeStdout
+sub writeTeeStderr
 {
     my($self, $param) = @_;
 
-    $self->{writeTeeStdout} = $param if ( defined($param) );
-    return $self->{writeTeeStdout};
+    $self->{writeTeeStderr} = $param if ( defined($param) );
+    return $self->{writeTeeStderr};
 }
 
 sub close
@@ -353,6 +406,7 @@ sub compressCopy
         my $fh = BackupPC::FileZIO->open($destFileZ, 1, $compress);
         my $data;
         if ( defined($fh) && open(LOG, "<", $srcFile) ) {
+           binmode(LOG);
             while ( sysread(LOG, $data, 65536) > 0 ) {
                 $fh->write(\$data);
             }