Release for 3.2.0. Changes since 3.2.0beta1:
[BackupPC.git] / lib / BackupPC / Xfer / Tar.pm
index bc4f787..24df54b 100644 (file)
@@ -11,7 +11,7 @@
 #   Craig Barratt  <cbarratt@users.sourceforge.net>
 #
 # COPYRIGHT
-#   Copyright (C) 2001-2003  Craig Barratt
+#   Copyright (C) 2001-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
@@ -29,7 +29,7 @@
 #
 #========================================================================
 #
-# Version 2.1.0, released 20 Jun 2004.
+# Version 3.2.0, released 31 Jul 2010.
 #
 # See http://backuppc.sourceforge.net.
 #
 package BackupPC::Xfer::Tar;
 
 use strict;
-
-sub new
-{
-    my($class, $bpc, $args) = @_;
-
-    $args ||= {};
-    my $t = bless {
-        bpc       => $bpc,
-        conf      => { $bpc->Conf },
-        host      => "",
-        hostIP    => "",
-        shareName => "",
-        pipeRH    => undef,
-        pipeWH    => undef,
-        badFiles  => [],
-        %$args,
-    }, $class;
-
-    return $t;
-}
-
-sub args
-{
-    my($t, $args) = @_;
-
-    foreach my $arg ( keys(%$args) ) {
-       $t->{$arg} = $args->{$arg};
-    }
-}
+use Encode qw/from_to encode/;
+use base qw(BackupPC::Xfer::Protocol);
 
 sub useTar
 {
@@ -100,13 +73,18 @@ sub start
         if ( defined($conf->{BackupFilesExclude}{$t->{shareName}}) ) {
             foreach my $file ( @{$conf->{BackupFilesExclude}{$t->{shareName}}} )
             {
-               $file = ".$file" if ( $file =~ /^\// );
+                $file = "./$2" if ( $file =~ m{^(\./+|/+)(.*)}s );
+                $file = encode($conf->{ClientCharset}, $file)
+                            if ( $conf->{ClientCharset} ne "" );
                 push(@fileList, "--exclude=$file");
             }
         }
         if ( defined($conf->{BackupFilesOnly}{$t->{shareName}}) ) {
             foreach my $file ( @{$conf->{BackupFilesOnly}{$t->{shareName}}} ) {
-               $file = ".$file" if ( $file =~ /^\// );
+                $file = $2 if ( $file =~ m{^(\./+|/+)(.*)}s );
+               $file = "./$file";
+                $file = encode($conf->{ClientCharset}, $file)
+                            if ( $conf->{ClientCharset} ne "" );
                 push(@fileList, $file);
             }
         } else {
@@ -122,9 +100,10 @@ sub start
            $args = $conf->{TarFullArgs};
             $logMsg = "full backup started for directory $t->{shareName}";
         } else {
-            $incrDate = $bpc->timeStamp($t->{lastFull} - 3600, 1);
+            $incrDate = $bpc->timeStamp($t->{incrBaseTime} - 3600, 1);
            $args = $conf->{TarIncrArgs};
-            $logMsg = "incr backup started back to $incrDate for directory"
+            $logMsg = "incr backup started back to $incrDate"
+                    . " (backup #$t->{incrBaseBkupNum}) for directory"
                     . " $t->{shareName}";
         }
        push(@$tarClientCmd, split(/ +/, $args));
@@ -142,6 +121,8 @@ sub start
         tarPath   => $conf->{TarClientPath},
         sshPath   => $conf->{SshPath},
     };
+    from_to($args->{shareName}, "utf8", $conf->{ClientCharset})
+                            if ( $conf->{ClientCharset} ne "" );
     $tarClientCmd = $bpc->cmdVarSubstitute($tarClientCmd, $args);
     if ( !defined($t->{xferPid} = open(TAR, "-|")) ) {
         $t->{_errStr} = "Can't fork to run tar";
@@ -183,6 +164,8 @@ sub start
         return;
     }
     my $str = "Running: " . $bpc->execCmd2ShellCmd(@$tarClientCmd) . "\n";
+    from_to($str, $conf->{ClientCharset}, "utf8")
+                            if ( $conf->{ClientCharset} ne "" );
     $t->{XferLOG}->write(\"Running: @$tarClientCmd\n");
     alarm($conf->{ClientTimeout});
     $t->{_errStr} = undef;
@@ -198,7 +181,12 @@ sub readOutput
         my $mesg;
         if ( sysread($t->{pipeTar}, $mesg, 8192) <= 0 ) {
             vec($$FDreadRef, fileno($t->{pipeTar}), 1) = 0;
-           if ( !close($t->{pipeTar}) ) {
+            if ( !close($t->{pipeTar}) && $? != 256 ) {
+                #
+                # Tar 1.16 uses exit status 1 (256) when some files
+                # changed during archive creation.  We allow this
+                # as a benign error and consider the archive ok
+                #
                $t->{tarOut} .= "Tar exited with error $? ($!) status\n";
                $t->{xferOK} = 0 if ( !$t->{tarBadExitOk} );
            }
@@ -206,23 +194,31 @@ sub readOutput
             $t->{tarOut} .= $mesg;
         }
     }
+    my $logFileThres = $t->{type} eq "restore" ? 1 : 2;
     while ( $t->{tarOut} =~ /(.*?)[\n\r]+(.*)/s ) {
         $_ = $1;
         $t->{tarOut} = $2;
+        from_to($_, $conf->{ClientCharset}, "utf8")
+                            if ( $conf->{ClientCharset} ne "" );
         #
         # refresh our inactivity alarm
         #
         alarm($conf->{ClientTimeout}) if ( !$t->{abort} );
         $t->{lastOutputLine} = $_ if ( !/^$/ );
-        if ( /^Total bytes written: / ) {
+        if ( /^Total bytes (written|read): / ) {
             $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 1 );
             $t->{xferOK} = 1;
         } elsif ( /^\./ ) {
-            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 2 );
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= $logFileThres );
             $t->{fileCnt}++;
         } else {
-            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
-            $t->{xferErrCnt}++;
+            #
+            # Ignore annoying log message on incremental for tar 1.15.x
+            #
+            if ( !/: file is unchanged; not dumped$/ && !/: socket ignored$/ ) {
+                $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
+                $t->{xferErrCnt}++;
+            }
            #
            # If tar encounters a minor error, it will exit with a non-zero
            # status.  We still consider that ok.  Remember if tar prints
@@ -246,18 +242,6 @@ sub readOutput
     return 1;
 }
 
-sub abort
-{
-    my($t, $reason) = @_;
-    my @xferPid = $t->xferPid;
-
-    $t->{abort} = 1;
-    $t->{abortReason} = $reason;
-    if ( @xferPid ) {
-       kill($t->{bpc}->sigName2num("INT"), @xferPid);
-    }
-}
-
 sub setSelectMask
 {
     my($t, $FDreadRef) = @_;
@@ -265,53 +249,4 @@ sub setSelectMask
     vec($$FDreadRef, fileno($t->{pipeTar}), 1) = 1;
 }
 
-sub errStr
-{
-    my($t) = @_;
-
-    return $t->{_errStr};
-}
-
-sub xferPid
-{
-    my($t) = @_;
-
-    return ($t->{xferPid});
-}
-
-sub logMsg
-{
-    my($t, $msg) = @_;
-
-    push(@{$t->{_logMsg}}, $msg);
-}
-
-sub logMsgGet
-{
-    my($t) = @_;
-
-    return shift(@{$t->{_logMsg}});
-}
-
-#
-# Returns a hash ref giving various status information about
-# the transfer.
-#
-sub getStats
-{
-    my($t) = @_;
-
-    return { map { $_ => $t->{$_} }
-            qw(byteCnt fileCnt xferErrCnt xferBadShareCnt xferBadFileCnt
-               xferOK hostAbort hostError lastOutputLine)
-    };
-}
-
-sub getBadFiles
-{
-    my($t) = @_;
-
-    return @{$t->{badFiles}};
-}
-
 1;