* Modified bin/BackupPC_dump to fix the case of a single partial
authorcbarratt <cbarratt>
Sat, 17 Jan 2009 19:26:46 +0000 (19:26 +0000)
committercbarratt <cbarratt>
Sat, 17 Jan 2009 19:26:46 +0000 (19:26 +0000)
   backup followed by a successful incremental resulting in a full
   backup of level 1, rather than level 0.  Reported by Jeff
   Kosowsky.

 * Fixed BackupPC::PoolWrite to always create the parent directory.
   This fixed a case with rsync/rsyncd where a file like "-i" in the
   top-level directory sorts before ".", which meant the directory
   creation is after the file creation.  Also PoolWrite errors now
   increment xferError count.  Reported by Jeff Kosowsky.

 * BackupPC now gives a more useful error message if BackupPC_nightly
   takes more than 24 hours (ie: when the next one is meant to
   start).  Reported by Tony Schreiner.

12 files changed:
ChangeLog
bin/BackupPC
bin/BackupPC_dump
conf/config.pl
configure.pl
lib/BackupPC/Attrib.pm
lib/BackupPC/CGI/Restore.pm
lib/BackupPC/Lib.pm
lib/BackupPC/PoolWrite.pm
lib/BackupPC/Storage/Text.pm
lib/BackupPC/Xfer/Rsync.pm
lib/BackupPC/Xfer/RsyncFileIO.pm

index 3fca576..c114378 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
   charset to utf-8.  Also changed bin/BackupPC_sendEmail to not send
   any per-client email if $Conf{BackupsDisable} is set.
 
+* Modified bin/BackupPC_dump to fix the case of a single partial
+  backup followed by a successful incremental resulting in a full
+  backup of level 1, rather than level 0.  Reported by Jeff
+  Kosowsky.
+
+* Fixed BackupPC::PoolWrite to always create the parent directory.
+  This fixed a case with rsync/rsyncd where a file like "-i" in the
+  top-level directory sorts before ".", which meant the directory
+  creation is after the file creation.  Also PoolWrite errors now
+  increment xferError count.  Reported by Jeff Kosowsky.
+
+* BackupPC now gives a more useful error message if BackupPC_nightly
+  takes more than 24 hours (ie: when the next one is meant to
+  start).  Reported by Tony Schreiner.
+
 * Added server message for queuing a single host based on patch
   submitted by Joe Digilio.
 
index f3df54a..2edf36d 100755 (executable)
@@ -409,7 +409,6 @@ sub Main_TryToRun_nightly
        $CmdQueueOn{$bpc->trashJob} = 1;
     }
     if ( $RunNightlyWhenIdle == 1 ) {
-
         #
         # Queue multiple nightly jobs based on the configuration
         #
@@ -477,7 +476,6 @@ sub Main_TryToRun_nightly
             $start = $start0 + int(($end - $start0)
                                  * ($i + 1) / $Conf{MaxBackupPCNightlyJobs});
             push(@$cmd, $start - 1);
-
             my $job = $bpc->adminJob($i);
             unshift(@CmdQueue, {
                     host    => $job,
@@ -868,7 +866,12 @@ sub Main_Check_Timeout
         # Remember to run the nightly script when the next CmdQueue
         # job is done.
         #
-        $RunNightlyWhenIdle = 1;
+        if ( $RunNightlyWhenIdle == 2 ) {
+            print(LOG $bpc->timeStamp, "BackupPC_nightly is still running after 24 hours!!"
+                                     . "  You should adjust the config settings; Skipping this run\n");
+        } else {
+            $RunNightlyWhenIdle = 1;
+        }
     }
     #
     # Write out the current status and then queue all the PCs
index 0971f9e..288ee85 100755 (executable)
@@ -413,7 +413,7 @@ for ( my $i = 0 ; $i < @Backups ; $i++ ) {
 #
 # Decide whether we do nothing, or a full or incremental backup.
 #
-if ( @Backups == 0
+if ( $lastFullTime == 0
         || $opts{f}
         || (!$opts{i} && (time - $lastFullTime > $Conf{FullPeriod} * 24*3600
             && time - $lastIncrTime > $Conf{IncrPeriod} * 24*3600)) ) {
index c7e17bb..feed6bf 100644 (file)
@@ -2058,7 +2058,7 @@ $Conf{CgiHeaders} = '<meta http-equiv="pragma" content="no-cache">';
 # used by configure.pl when you upgrade BackupPC.
 #
 # Example:
-#     $Conf{CgiImageDir} = '/usr/local/apache/htdocs/BackupPC';
+#     $Conf{CgiImageDir} = '/var/www/htdocs/BackupPC';
 #
 $Conf{CgiImageDir} = '';
 
index 4b97fa7..a879807 100755 (executable)
@@ -472,12 +472,12 @@ if ( $Conf{CgiDir} ne "" ) {
 
     print <<EOF;
 
-BackupPC's CGI script needs to display various GIF images that
-should be stored where Apache can serve them.  They should be
-placed somewhere under Apache's DocumentRoot.  BackupPC also
-needs to know the URL to access these images.  Example:
+BackupPC's CGI script needs to display various PNG/GIF images that
+should be stored where Apache can serve them.  They should be placed
+somewhere under Apache's DocumentRoot.  BackupPC also needs to know
+the URL to access these images.  Example:
 
-    Apache image directory:  /usr/local/apache/htdocs/BackupPC
+    Apache image directory:  /var/www/htdocs/BackupPC
     URL for image directory: /BackupPC
 
 The URL for the image directory should start with a slash.
@@ -1235,7 +1235,7 @@ specified for a batch new install.
 
 Example:
 
-    --html-dir /usr/local/apache/htdocs/BackupPC
+    --html-dir /var/www/htdocs/BackupPC
 
 =item B<--html-dir-url URL>
 
index e19d85c..fc245d7 100644 (file)
@@ -304,7 +304,13 @@ sub write
     my($data) = $a->writeData;
 
     $file = $a->fileName($dir, $file);
-    mkpath($dir, 0, 0777) if ( !-d $dir );
+    if ( !-d $dir ) {
+        eval { mkpath($dir, 0, 0777) };
+        if ( $@ ) {
+            $a->{_errStr} = "Can't create directory $dir";
+            return;
+        }
+    }
     my $fd = BackupPC::FileZIO->open($file, 1, $a->{compress});
     if ( !$fd ) {
        $a->{_errStr} = "Can't open/write to $file";
index 6b8755c..1892a95 100644 (file)
@@ -28,7 +28,7 @@
 #
 #========================================================================
 #
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -337,7 +337,7 @@ EOF
                          [  \%restoreReq],
                          [qw(*RestoreReq)]);
         $dump->Indent(1);
-        mkpath("$TopDir/pc/$hostDest", 0, 0777)
+        eval { mkpath("$TopDir/pc/$hostDest", 0, 0777) }
                                     if ( !-d "$TopDir/pc/$hostDest" );
        my $openPath = "$TopDir/pc/$hostDest/$reqFileName";
         if ( open(REQ, ">", $openPath) ) {
index e5cb98a..7e63431 100644 (file)
@@ -624,7 +624,15 @@ sub RmTreeDefer
     my($i, $f);
 
     return if ( !-e $file );
-    mkpath($trashDir, 0, 0777) if ( !-d $trashDir );
+    if ( !-d $trashDir ) {
+        eval { mkpath($trashDir, 0, 0777) };
+        if ( $@ ) {
+            #
+            # There's no good place to send this error - use stderr
+            #
+            print(STDERR "RmTreeDefer: can't create directory $trashDir");
+        }
+    }
     for ( $i = 0 ; $i < 1000 ; $i++ ) {
         $f = sprintf("%s/%d_%d_%d", $trashDir, time, $$, $i);
         next if ( -e $f );
@@ -903,7 +911,10 @@ sub MakeFileLink
         } elsif ( $newFile && -f $name && (stat($name))[3] == 1 ) {
             my($newDir);
             ($newDir = $rawFile) =~ s{(.*)/.*}{$1};
-            mkpath($newDir, 0, 0777) if ( !-d $newDir );
+            if ( !-d $newDir ) {
+                eval { mkpath($newDir, 0, 0777) };
+                return -5 if ( $@ );
+            }
             return -4 if ( !link($name, $rawFile) );
             return 2;
         } else {
index 415c67f..3934827 100644 (file)
@@ -56,7 +56,7 @@
 #
 #========================================================================
 #
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -95,6 +95,12 @@ sub new
     # Always unlink any current file in case it is already linked
     #
     unlink($fileName) if ( -f $fileName );
+    if ( $fileName =~ m{(.*)/.+} && !-d $1 ) {
+        eval { mkpath($1, 0, 0777) };
+        if ( $@ ) {
+            push(@{$self->{errors}}, "Unable to create directory $1 for $self->{fileName}");
+        }
+    }
     return $self;
 }
 
@@ -135,7 +141,7 @@ sub write
         if ( !defined($a->{base} = $a->{bpc}->MD52Path($a->{digest},
                                                        $a->{compress})) ) {
             push(@{$a->{errors}}, "Unable to get path from '$a->{digest}'"
-                                . " for $a->{fileName}\n");
+                                . " for $a->{fileName}");
         } else {
             while ( @{$a->{files}} < $MaxFiles ) {
                 my $fh;
@@ -176,7 +182,7 @@ sub write
                                               1, $a->{compress});
             if ( !defined($a->{fhOut}) ) {
                 push(@{$a->{errors}}, "Unable to open $a->{fileName}"
-                                    . " for writing\n");
+                                    . " for writing");
             }
         }
     }
@@ -220,7 +226,7 @@ sub write
                 if ( !$a->{files}[$i]->{fh}->rewind() ) {
                     push(@{$a->{errors}},
                             "Unable to rewind $a->{files}[$i]->{name}"
-                          . " for compare\n");
+                          . " for compare");
                 }
                 $match = $a->filePartialCompare($a->{files}[$i]->{fh}, $fh,
                                           $a->{nWrite}, $dataLen, \$a->{data});
@@ -249,12 +255,12 @@ sub write
                     if ( !defined($a->{fhOut}) ) {
                         push(@{$a->{errors}},
                                 "Unable to open $a->{fileName}"
-                              . " for writing\n");
+                              . " for writing");
                     } else {
                         if ( !$a->{files}[$i]->{fh}->rewind() ) {
                             push(@{$a->{errors}}, 
                                      "Unable to rewind"
-                                   . " $a->{files}[$i]->{name} for copy\n");
+                                   . " $a->{files}[$i]->{name} for copy");
                         }
                         $a->filePartialCopy($a->{files}[$i]->{fh}, $a->{fhOut},
                                         $a->{nWrite});
@@ -273,7 +279,7 @@ sub write
         my $n = $a->{fhOut}->write(\$a->{data});
         if ( $n != $dataLen ) {
             push(@{$a->{errors}}, "Unable to write $dataLen bytes to"
-                                . " $a->{fileName} (got $n)\n");
+                                . " $a->{fileName} (got $n)");
         }
     }
     $a->{nWrite} += $dataLen;
@@ -322,7 +328,7 @@ sub write
              || !defined($fh = BackupPC::FileZIO->open($fileName, 0,
                                                 $a->{compress})) ) {
                push(@{$a->{errors}}, "Can't rename $a->{fileName} -> $fileName"
-                                   . " or open during size fixup\n");
+                                   . " or open during size fixup");
            }
            #print("Using temporary name $fileName\n");
        } elsif ( defined($a->{files}) && defined($a->{files}[0]) ) {
@@ -347,7 +353,7 @@ sub write
                if ( $n != $thisRead ) {
                    push(@{$a->{errors}},
                                "Unable to read $thisRead bytes during resize"
-                              . " from temp $fileName (got $n)\n");
+                              . " from temp $fileName (got $n)");
                    last;
                }
                $poolWrite->write(\$data);
@@ -371,7 +377,7 @@ sub write
         local(*OUT);
         if ( !open(OUT, ">", $a->{fileName}) ) {
             push(@{$a->{errors}}, "Can't open $a->{fileName} for empty"
-                                . " output\n");
+                                . " output");
         } else {
             close(OUT);
         }
@@ -394,7 +400,7 @@ sub write
     } else {
         if ( @{$a->{files}} == 0 ) {
             push(@{$a->{errors}}, "Botch, no matches on $a->{fileName}"
-                                . " ($a->{digest})\n");
+                                . " ($a->{digest})");
         } elsif ( @{$a->{files}} > 1 ) {
            #
            # This is no longer a real error because $Conf{HardLinkMax}
@@ -429,7 +435,7 @@ sub write
             if ( !$a->{files}[$i]->{fh}->rewind() ) {
                 push(@{$a->{errors}}, 
                          "Unable to rewind $a->{files}[$i]->{name}"
-                       . " for copy after link fail\n");
+                       . " for copy after link fail");
                 next;
             }
             $a->{fhOut} = BackupPC::FileZIO->open($a->{fileName},
@@ -437,7 +443,7 @@ sub write
             if ( !defined($a->{fhOut}) ) {
                 push(@{$a->{errors}},
                         "Unable to open $a->{fileName}"
-                      . " for writing after link fail\n");
+                      . " for writing after link fail");
             } else {
                 $a->filePartialCopy($a->{files}[$i]->{fh}, $a->{fhOut},
                                     $a->{nWrite});
@@ -501,14 +507,14 @@ sub filePartialCopy
         if ( $n != $thisRead ) {
             push(@{$a->{errors}},
                         "Unable to read $thisRead bytes from "
-                       . $fhIn->name . " (got $n)\n");
+                       . $fhIn->name . " (got $n)");
             return;
         }
         $n = $fhOut->write(\$data, $thisRead);
         if ( $n != $thisRead ) {
             push(@{$a->{errors}},
                         "Unable to write $thisRead bytes to "
-                       . $fhOut->name . " (got $n)\n");
+                       . $fhOut->name . " (got $n)");
             return;
         }
         $nRead += $thisRead;
@@ -531,7 +537,7 @@ sub filePartialCompare
         $n = $fh0->read(\$data0, $thisRead);
         if ( $n != $thisRead ) {
             push(@{$a->{errors}}, "Unable to read $thisRead bytes from "
-                                 . $fh0->name . " (got $n)\n");
+                                 . $fh0->name . " (got $n)");
             return;
         }
         $n = $fh1->read(\$data1, $thisRead);
index 5c60cf6..09140fe 100644 (file)
@@ -30,7 +30,7 @@
 #
 #========================================================================
 #
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -214,7 +214,10 @@ sub TextFileWrite
 
     (my $dir = $file) =~ s{(.+)/(.+)}{$1};
 
-    mkpath($dir, 0, 0775) if ( !-d $dir );
+    if ( !-d $dir ) {
+        eval { mkpath($dir, 0, 0775) };
+        return "TextFileWrite: can't create directory $dir" if ( $@ );
+    }
     if ( open(FD, ">", "$file.new") ) {
        binmode(FD);
         print FD $contents;
index ff24cd5..f92e667 100644 (file)
@@ -29,7 +29,7 @@
 #
 #========================================================================
 #
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -376,7 +376,26 @@ sub run
            $t->{hostError} = $err;
            return;
        }
+        
+        #
+        # This is a hack.  To avoid wide chars we encode the arguments
+        # to utf8 byte streams, then to the client's local charset.
+        # The second conversion should really go in File::RsyncP, since
+        # it shouldn't be applied to in-line include/exclude arguments.
+        #
+        for ( my $i = 0 ; $i < @{$rs->{rsyncArgs}} ; $i++ ) {
+            $rs->{rsyncArgs}[$i] = encode('utf8', $rs->{rsyncArgs}[$i]);
+            from_to($rs->{rsyncArgs}[$i], 'utf8', $conf->{ClientCharset})
+                                    if ( $conf->{ClientCharset} ne "" );
+        }
+    
+       my $str = "RsyncArgsBefore: " . join(" ", @{$rs->{rsyncArgs}}) . "\n";
+        $t->{XferLOG}->write(\$str);
+
        $rs->serverStart($remoteSend, $remoteDirDaemon);
+
+       my $str = "RsyncArgsAfter: " . join(" ", @{$rs->{rsyncArgs}}) . "\n";
+        $t->{XferLOG}->write(\$str);
     }
     my $shareNameSlash = $t->{shareNameSlash};
     from_to($shareNameSlash, "utf8", $conf->{ClientCharset})
index 16f5fbb..bf52653 100644 (file)
@@ -602,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;
@@ -644,7 +647,7 @@ sub makePath
     $fio->logFileAction("create", $f) if ( $fio->{logLevel} >= 1 );
     $fio->log("makePath($path, 0777)") if ( $fio->{logLevel} >= 5 );
     $path = $1 if ( $path =~ /(.*)/s );
-    File::Path::mkpath($path, 0, 0777) if ( !-d $path );
+    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}++;