* Failed dumps now cleanup correctly, deleting in-progress file
authorcbarratt <cbarratt>
Mon, 15 Mar 2004 03:12:42 +0000 (03:12 +0000)
committercbarratt <cbarratt>
Mon, 15 Mar 2004 03:12:42 +0000 (03:12 +0000)
   and correctly saving attribs.

 * Updates to de.pm from Manfred.

 * Minor updates to other lang files.

 * Support for multiple blackouts added.

 * Moved lib/BackupPC/RsyncDigest.pm to lib/BackupPC/Xfer/RsyncDigest.pm

 * Patches to configure.pl and makeDist from gfk.

24 files changed:
bin/BackupPC
bin/BackupPC_archive
bin/BackupPC_dump
bin/BackupPC_link
bin/BackupPC_restore
bin/BackupPC_tarExtract
conf/config.pl
configure.pl
lib/BackupPC/CGI/HostInfo.pm
lib/BackupPC/Lang/de.pm
lib/BackupPC/Lang/en.pm
lib/BackupPC/Lang/es.pm
lib/BackupPC/Lang/fr.pm
lib/BackupPC/Lang/it.pm
lib/BackupPC/Lib.pm
lib/BackupPC/PoolWrite.pm
lib/BackupPC/RsyncDigest.pm [deleted file]
lib/BackupPC/Xfer/Archive.pm
lib/BackupPC/Xfer/Rsync.pm
lib/BackupPC/Xfer/RsyncDigest.pm [new file with mode: 0644]
lib/BackupPC/Xfer/RsyncFileIO.pm
lib/BackupPC/Xfer/Smb.pm
lib/BackupPC/Xfer/Tar.pm
makeDist

index 61276e2..ba6cde9 100755 (executable)
@@ -47,7 +47,7 @@
 #
 #========================================================================
 #
-# Version 2.1.0_CVS, released 8 Feb 2004.
+# Version 2.1.0_CVS, released 13 Mar 2004.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -772,7 +772,7 @@ sub Main_Check_Job_Messages
                     if ( defined($Jobs{$newHost}) ) {
                         print(LOG $bpc->timeStamp,
                                 "Backup on $newHost is already running\n");
-                        kill(2, $Jobs{$host}{pid});
+                        kill($bpc->sigName2num("INT"), $Jobs{$host}{pid});
                         $nbytes = 0;
                         last;
                     }
@@ -835,6 +835,13 @@ sub Main_Check_Job_Messages
                 delete($Status{$host}{error});
                 delete($Status{$host}{errorTime});
                 $Status{$host}{endTime}   = time;
+            } elsif ( $mesg =~ /^backups disabled/ ) {
+                print(LOG $bpc->timeStamp,
+                           "Ignoring old backup error on $host\n");
+                $Status{$host}{reason}    = "Reason_backup_done";
+                delete($Status{$host}{error});
+                delete($Status{$host}{errorTime});
+                $Status{$host}{endTime}   = time;
             } elsif ( $mesg =~ /^restore complete/ ) {
                 print(LOG $bpc->timeStamp, "Finished restore on $host\n");
                 $Status{$host}{reason}    = "Reason_restore_done";
@@ -873,25 +880,46 @@ sub Main_Check_Job_Messages
                }
             } elsif ( $mesg =~ /^dump failed: (.*)/ ) {
                 $Status{$host}{state}     = "Status_idle";
-                $Status{$host}{reason}    = "Reason_backup_failed";
-                $Status{$host}{error}     = $1;
-                $Status{$host}{errorTime} = time;
-                $Status{$host}{endTime}   = time;
-                print(LOG $bpc->timeStamp, "Backup failed on $host ($1)\n");
+               $Status{$host}{error}     = $1;
+               $Status{$host}{errorTime} = time;
+               $Status{$host}{endTime}   = time;
+               if ( $Status{$host}{reason}
+                       eq "Reason_backup_canceled_by_user" ) {
+                   print(LOG $bpc->timeStamp,
+                           "Backup canceled on $host ($1)\n");
+               } else {
+                   $Status{$host}{reason} = "Reason_backup_failed";
+                   print(LOG $bpc->timeStamp,
+                           "Backup failed on $host ($1)\n");
+               }
             } elsif ( $mesg =~ /^restore failed: (.*)/ ) {
                 $Status{$host}{state}     = "Status_idle";
-                $Status{$host}{reason}    = "Reason_restore_failed";
                 $Status{$host}{error}     = $1;
                 $Status{$host}{errorTime} = time;
                 $Status{$host}{endTime}   = time;
-                print(LOG $bpc->timeStamp, "Restore failed on $host ($1)\n");
+               if ( $Status{$host}{reason}
+                        eq "Reason_restore_canceled_by_user" ) {
+                   print(LOG $bpc->timeStamp,
+                           "Restore canceled on $host ($1)\n");
+               } else {
+                   $Status{$host}{reason} = "Reason_restore_failed";
+                   print(LOG $bpc->timeStamp,
+                           "Restore failed on $host ($1)\n");
+               }
             } elsif ( $mesg =~ /^archive failed: (.*)/ ) {
                 $Status{$host}{state}     = "Status_idle";
-                $Status{$host}{reason}    = "Reason_archive_failed";
                 $Status{$host}{error}     = $1;
                 $Status{$host}{errorTime} = time;
                 $Status{$host}{endTime}   = time;
-                print(LOG $bpc->timeStamp, "Archive failed on $host ($1)\n");
+               if ( $Status{$host}{reason}
+                        eq "Reason_archive_canceled_by_user" ) {
+                   print(LOG $bpc->timeStamp,
+                           "Archive canceled on $host ($1)\n");
+               } else {
+                   $Status{$host}{reason} = "Reason_archive_failed";
+                   print(LOG $bpc->timeStamp,
+                           "Archive failed on $host ($1)\n");
+               }
             } elsif ( $mesg =~ /^log\s+(.*)/ ) {
                 print(LOG $bpc->timeStamp, "$1\n");
             } elsif ( $mesg =~ /^BackupPC_stats = (.*)/ ) {
@@ -1043,7 +1071,7 @@ sub Main_Check_Client_Messages
                     print(LOG $bpc->timeStamp,
                                "Stopping current $Jobs{$host}{type} of $host,"
                              . " request by $user (backoff=$backoff)\n");
-                    kill(2, $Jobs{$host}{pid});
+                    kill($bpc->sigName2num("INT"), $Jobs{$host}{pid});
                    #
                    # Don't close the pipe now; wait until the child
                    # really exits later.  Otherwise close() will
@@ -1066,7 +1094,7 @@ sub Main_Check_Client_Messages
                    }
                     $Status{$host}{activeJob} = 0;
                     $Status{$host}{startTime} = time;
-                    $reply = "ok: $Jobs{$host}{type} of $host cancelled";
+                    $reply = "ok: $Jobs{$host}{type} of $host canceled";
                 } elsif ( $BgQueueOn{$host} || $UserQueueOn{$host} ) {
                     print(LOG $bpc->timeStamp,
                                "Stopping pending backup of $host,"
@@ -1074,7 +1102,7 @@ sub Main_Check_Client_Messages
                     @BgQueue = grep($_->{host} ne $host, @BgQueue);
                     @UserQueue = grep($_->{host} ne $host, @UserQueue);
                     $BgQueueOn{$host} = $UserQueueOn{$host} = 0;
-                    $reply = "ok: pending backup of $host cancelled";
+                    $reply = "ok: pending backup of $host canceled";
                 } else {
                     print(LOG $bpc->timeStamp,
                                "Nothing to do for stop backup of $host,"
@@ -1484,7 +1512,7 @@ sub catch_signal
     if ( $SigName ) {
         $SigName = shift;
         foreach my $host ( keys(%Jobs) ) {
-            kill(2, $Jobs{$host}{pid});
+            kill($bpc->sigName2num("INT"), $Jobs{$host}{pid});
         }
         #
         # In case we are inside the exit handler, reopen the log file
@@ -1604,11 +1632,11 @@ sub ServerShutdown
     print(LOG $bpc->timeStamp, "$mesg\n");
     if ( keys(%Jobs) ) {
         foreach my $host ( keys(%Jobs) ) {
-            kill(2, $Jobs{$host}{pid});
+            kill($bpc->sigName2num("INT"), $Jobs{$host}{pid});
         }
         sleep(1);
         foreach my $host ( keys(%Jobs) ) {
-            kill(9, $Jobs{$host}{pid});
+            kill($bpc->sigName2num("KILL"), $Jobs{$host}{pid});
         }
         %Jobs = ();
     }
index c61e5cf..ebdc103 100644 (file)
@@ -244,9 +244,9 @@ sub ArchiveCleanup
        # kill off the tranfer program, first nicely then forcefully
        #
        if ( @xferPid ) {
-           kill(2, @xferPid);
+           kill($bpc->sigName2num("INT"), @xferPid);
            sleep(1);
-           kill(9, @xferPid);
+           kill($bpc->sigName2num("KILL"), @xferPid);
        }
     }
 
index dbc2ee0..733ceae 100755 (executable)
@@ -70,7 +70,7 @@
 #
 #========================================================================
 #
-# Version 2.1.0_CVS, released 8 Feb 2004.
+# Version 2.1.0_CVS, released 13 Mar 2004.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -86,6 +86,7 @@ use BackupPC::Xfer::Tar;
 use BackupPC::Xfer::Rsync;
 use Socket;
 use File::Path;
+use File::Find;
 use Getopt::Std;
 
 ###########################################################################
@@ -98,6 +99,8 @@ my $BinDir = $bpc->BinDir();
 my %Conf   = $bpc->Conf();
 my $NeedPostCmd;
 my $Hosts;
+my $SigName;
+my $Abort;
 
 $bpc->ChildInit();
 
@@ -203,6 +206,8 @@ if ( $opts{e} ) {
 # For archive hosts we don't bother any further
 #
 if ($Conf{XferMethod} eq "archive" ) {
+    print(STDERR "Exiting because the XferMethod is set to archive\n")
+                if ( $opts{v} );
     exit(0);
 }
 
@@ -274,6 +279,15 @@ my $partialNum;
 
 if ( $Conf{FullPeriod} == -1 && !$opts{f} && !$opts{i}
         || $Conf{FullPeriod} == -2 ) {
+    print(STDERR "Exiting because backups are disabled with"
+               . "\$Conf{FullPeriod} = $Conf{FullPeriod}\n") if ( $opts{v} );
+    #
+    # Tell BackupPC to ignore old failed backups on hosts that
+    # have backups disabled.
+    #
+    print("backups disabled\n")
+               if ( $StatusHost{reason} ne "Reason_backup_done"
+                    && time - $StatusHost{startTime} > 2 * 24 * 3600 );
     NothingToDo($needLink);
 }
 
@@ -301,6 +315,10 @@ if ( !$opts{i} && !$opts{f} && $Conf{BlackoutGoodCnt} >= 0
         # Allow blackout to span midnight (specified by BlackoutHourBegin
         # being greater than BlackoutHourEnd)
         #
+        next if ( ref($p->{weekDays}) ne "ARRAY" 
+                    || !defined($p->{hourBegin})
+                    || !defined($p->{hourEnd})
+                );
         if ( $p->{hourBegin} > $p->{hourEnd} ) {
             $blackout = $p->{hourBegin} <= $currHours
                           || $currHours <= $p->{hourEnd};
@@ -423,10 +441,41 @@ if ( !defined($XferLOG) ) {
     print("dump failed: unable to open/create $Dir/XferLOG$fileExt\n");
     exit(1);
 }
+
+#
+# Ignore the partial dump in the case of an incremental.
+# A partial is a partial full.
+#
+if ( $type ne "full" ) {
+    $partialNum = undef;
+    $partialIdx = -1;
+}
+
+#
+# If this is a partial, copy the old XferLOG file
+#
+if ( $partialNum ) {
+    my($compress, $fileName);
+    if ( -f "$Dir/XferLOG.$partialNum.z" ) {
+       $fileName = "$Dir/XferLOG.$partialNum.z";
+       $compress = 1;
+    } elsif ( -f "$Dir/XferLOG.$partialNum" ) {
+       $fileName = "$Dir/XferLOG.$partialNum";
+       $compress = 0;
+    }
+    if ( my $oldLOG = BackupPC::FileZIO->open($fileName, 0, $compress) ) {
+       my $data;
+       while ( $oldLOG->read(\$data, 65536) > 0 ) {
+           $XferLOG->write(\$data);
+       }
+       $oldLOG->close;
+    }
+}
+
 $XferLOG->writeTeeStderr(1) if ( $opts{v} );
 unlink("$Dir/NewFileList") if ( -f "$Dir/NewFileList" );
-my $startTime = time();
 
+my $startTime     = time();
 my $tarErrs       = 0;
 my $nFilesExist   = 0;
 my $sizeExist     = 0;
@@ -576,6 +625,7 @@ for my $shareName ( @$ShareNames ) {
        backups     => \@Backups,
        compress    => $Conf{CompressLevel},
        XferMethod  => $Conf{XferMethod},
+       logLevel    => $Conf{XferLogLevel},
        pidHandler  => \&pidHandler,
         partialNum  => $partialNum,
     });
@@ -588,14 +638,14 @@ for my $shareName ( @$ShareNames ) {
         # kill off the tar process, first nicely then forcefully
         #
        if ( $tarPid > 0 ) {
-           kill(2, $tarPid);
+           kill($bpc->sigName2num("INT"), $tarPid);
            sleep(1);
-           kill(9, $tarPid);
+           kill($bpc->sigName2num("KILL"), $tarPid);
        }
        if ( @xferPid ) {
-           kill(2, @xferPid);
+           kill($bpc->sigName2num("INT"), @xferPid);
            sleep(1);
-           kill(9, @xferPid);
+           kill($bpc->sigName2num("KILL"), @xferPid);
        }
        UserCommandRun("DumpPostUserCmd") if ( $NeedPostCmd );
         exit(1);
@@ -642,7 +692,14 @@ for my $shareName ( @$ShareNames ) {
                while ( $tarOut =~ /(.*?)[\n\r]+(.*)/s ) {
                    $_ = $1;
                    $tarOut = $2;
-                   $XferLOG->write(\"tarExtract: $_\n");
+                    if ( /^  / ) {
+                        $XferLOG->write(\"$_\n");
+                    } else {
+                        $XferLOG->write(\"tarExtract: $_\n");
+                    }
+                    if ( /^BackupPC_tarExtact aborting \((.*)\)/ ) {
+                        $stat{hostError} = $1;
+                    }
                    if ( /^Done: (\d+) errors, (\d+) filesExist, (\d+) sizeExist, (\d+) sizeExistComp, (\d+) filesTotal, (\d+) sizeTotal/ ) {
                        $tarErrs       += $1;
                        $nFilesExist   += $2;
@@ -709,17 +766,17 @@ for my $shareName ( @$ShareNames ) {
         # kill off the tranfer program, first nicely then forcefully
         #
        if ( @xferPid ) {
-           kill(2, @xferPid);
+           kill($bpc->sigName2num("INT"), @xferPid);
            sleep(1);
-           kill(9, @xferPid);
+           kill($bpc->sigName2num("KILL"), @xferPid);
        }
         #
         # kill off the tar process, first nicely then forcefully
         #
        if ( $tarPid > 0 ) {
-           kill(2, $tarPid);
+           kill($bpc->sigName2num("INT"), $tarPid);
            sleep(1);
-           kill(9, $tarPid);
+           kill($bpc->sigName2num("KILL"), $tarPid);
        }
         #
         # don't do any more shares on this host
@@ -737,6 +794,8 @@ if ( $type eq "full" && $stat{hostError} eq ""
     $stat{xferOK} = 0;
 }
 
+$stat{xferOK} = 0 if ( $Abort );
+
 #
 # Do one last check to make sure it is still the machine we expect.
 #
@@ -746,7 +805,6 @@ if ( $stat{xferOK} && (my $errMsg = CorrectHostCheck($hostIP, $host)) ) {
 }
 
 UserCommandRun("DumpPostUserCmd") if ( $NeedPostCmd );
-$XferLOG->close();
 close($newFilesFH) if ( defined($newFilesFH) );
 
 my $endTime = time();
@@ -755,25 +813,31 @@ my $endTime = time();
 # If the dump failed, clean up
 #
 if ( !$stat{xferOK} ) {
-    #
-    # wait a short while and see if the system is still alive
-    #
     $stat{hostError} = $stat{lastOutputLine} if ( $stat{hostError} eq "" );
     if ( $stat{hostError} ) {
         print(LOG $bpc->timeStamp,
                   "Got fatal error during xfer ($stat{hostError})\n");
+       $XferLOG->write(\"Got fatal error during xfer ($stat{hostError})\n");
     }
-    sleep(10);
-    if ( $bpc->CheckHostAlive($hostIP) < 0 ) {
-        $stat{hostAbort} = 1;
-    }
-    if ( $stat{hostAbort} ) {
-        $stat{hostError} = "lost network connection during backup";
+    if ( !$Abort ) {
+       #
+       # wait a short while and see if the system is still alive
+       #
+       sleep(5);
+       if ( $bpc->CheckHostAlive($hostIP) < 0 ) {
+           $stat{hostAbort} = 1;
+       }
+       if ( $stat{hostAbort} ) {
+           $stat{hostError} = "lost network connection during backup";
+       }
+       print(LOG $bpc->timeStamp, "Backup aborted ($stat{hostError})\n");
+       $XferLOG->write(\"Backup aborted ($stat{hostError})\n");
+    } else {
+       $XferLOG->write(\"Backup aborted by user signal\n");
     }
-    print(LOG $bpc->timeStamp, "Dump aborted ($stat{hostError})\n");
 
     #
-    # This exits.
+    # Close the log file and call BackupFailCleanup, which exits.
     #
     BackupFailCleanup();
 }
@@ -807,50 +871,147 @@ sub NothingToDo
 
 sub catch_signal
 {
-    my $signame = shift;
+    my $sigName = shift;
 
     #
-    # Children quit quietly on ALRM
+    # The first time we receive a signal we try to gracefully
+    # abort the backup.  This allows us to keep a partial dump
+    # with the in-progress file deleted and attribute caches
+    # flushed to disk etc.
     #
-    exit(1) if ( $Pid != $$ && $signame eq "ALRM" );
+    if ( !length($SigName) ) {
+       my $reason;
+       if ( $sigName eq "INT" ) {
+           $reason = "aborted by user (signal=$sigName)";
+       } else {
+           $reason = "aborted by signal=$sigName";
+       }
+       if ( $Pid == $$ ) {
+           #
+           # Parent logs a message
+           #
+           print(LOG $bpc->timeStamp,
+                   "Aborting backup up after signal $sigName\n");
+
+           #
+           # Tell xfer to abort
+           #
+           $xfer->abort($reason);
+
+           #
+           # Send ALRMs to BackupPC_tarExtract if we are using it
+           #
+           if ( $tarPid > 0 ) {
+               kill($bpc->sigName2num("ARLM"), $tarPid);
+           }
+
+           #
+           # Schedule a 20 second timer in case the clean
+           # abort doesn't complete
+           #
+           alarm(20);
+       } else {
+           #
+           # Children ignore anything other than ALRM and INT
+           #
+           if ( $sigName ne "ALRM" && $sigName ne "INT" ) {
+               return;
+           }
+
+           #
+           # The child also tells xfer to abort
+           #
+           $xfer->abort($reason);
+
+           #
+           # Schedule a 15 second timer in case the clean
+           # abort doesn't complete
+           #
+           alarm(15);
+       }
+       $SigName = $sigName;
+       $Abort = 1;
+       return;
+    }
+
+    #
+    # This is a second signal: time to clean up.
+    #
+    if ( $Pid != $$ && ($sigName eq "ALRM" || $sigName eq "INT") ) {
+       #
+       # Children quit quietly on ALRM or INT
+       #
+       exit(1)
+    }
 
     #
     # Ignore other signals in children
     #
     return if ( $Pid != $$ );
 
-    print(LOG $bpc->timeStamp, "cleaning up after signal $signame\n");
-    $SIG{$signame} = 'IGNORE';
+    $SIG{$sigName} = 'IGNORE';
     UserCommandRun("DumpPostUserCmd") if ( $NeedPostCmd );
-    $XferLOG->write(\"exiting after signal $signame\n");
-    $XferLOG->close();
+    $XferLOG->write(\"exiting after signal $sigName\n");
     if ( @xferPid ) {
-        kill(2, @xferPid);
+        kill($bpc->sigName2num("INT"), @xferPid);
        sleep(1);
-       kill(9, @xferPid);
+       kill($bpc->sigName2num("KILL"), @xferPid);
     }
     if ( $tarPid > 0 ) {
-        kill(2, $tarPid);
+        kill($bpc->sigName2num("INT"), $tarPid);
        sleep(1);
-       kill(9, $tarPid);
+       kill($bpc->sigName2num("KILL"), $tarPid);
     }
-    if ( $signame eq "INT" ) {
-        $stat{hostError} = "aborted by user (signal=$signame)";
+    if ( $sigName eq "INT" ) {
+        $stat{hostError} = "aborted by user (signal=$sigName)";
     } else {
-        $stat{hostError} = "received signal=$signame";
+        $stat{hostError} = "received signal=$sigName";
     }
     BackupFailCleanup();
 }
 
+sub CheckForNewFiles
+{
+    if ( -f _ && $File::Find::name !~ /\/fattrib$/ ) {
+        $nFilesTotal++;
+    } elsif ( -d _ ) {
+       #
+       # No need to check entire tree
+       #
+        $File::Find::prune = 1 if ( $nFilesTotal );
+    }
+}
+
 sub BackupFailCleanup
 {
     my $fileExt = $Conf{CompressLevel} > 0 ? ".z" : "";
+    my $keepPartial = 0;
+
+    #
+    # We keep this backup if it is a full and we actually backed
+    # up some files.
+    #
+    if ( $type eq "full" ) {
+       if ( $nFilesTotal == 0 && $xfer->getStats->{fileCnt} == 0 ) {
+           #
+           # Xfer didn't report any files, but check in the new
+           # directory just in case.
+           #
+           find(\&CheckForNewFiles, "$Dir/new");
+           $keepPartial = 1 if ( $nFilesTotal );
+       } else {
+           #
+           # Xfer reported some files
+           #
+           $keepPartial = 1;
+       }
+    }
 
-    if ( $type ne "full" ) {
-#            || ($nFilesTotal == 0 && $xfer->getStats->{fileCnt} == 0) ) {
+    if ( !$keepPartial ) {
         #
         # No point in saving this dump; get rid of eveything.
         #
+        $XferLOG->close();
         unlink("$Dir/timeStamp.level0")    if ( -f "$Dir/timeStamp.level0" );
         unlink("$Dir/SmbLOG.bad")          if ( -f "$Dir/SmbLOG.bad" );
         unlink("$Dir/SmbLOG.bad$fileExt")  if ( -f "$Dir/SmbLOG.bad$fileExt" );
@@ -860,6 +1021,7 @@ sub BackupFailCleanup
         rename("$Dir/XferLOG$fileExt", "$Dir/XferLOG.bad$fileExt");
         $bpc->RmTreeDefer("$TopDir/trash", "$Dir/new") if ( -d "$Dir/new" );
         print("dump failed: $stat{hostError}\n");
+        $XferLOG->close();
         print("link $clientURI\n") if ( $needLink );
         exit(1);
     }
@@ -1063,15 +1225,12 @@ sub BackupSave
         $num = $Backups[$i]{num} if ( $num < $Backups[$i]{num} );
     }
     $num++;
-    $bpc->RmTreeDefer("$TopDir/trash", "$Dir/$num")
-                                if ( -d "$Dir/$num" );
+    $bpc->RmTreeDefer("$TopDir/trash", "$Dir/$num") if ( -d "$Dir/$num" );
     if ( !rename("$Dir/new", "$Dir/$num") ) {
-        print(LOG $bpc->timeStamp,
-                  "Rename $Dir/new -> $Dir/$num failed\n");
+        print(LOG $bpc->timeStamp, "Rename $Dir/new -> $Dir/$num failed\n");
         $stat{xferOK} = 0;
     }
-    rename("$Dir/XferLOG$fileExt", "$Dir/XferLOG.$num$fileExt");
-    rename("$Dir/NewFileList", "$Dir/NewFileList.$num");
+    $needLink = 1 if ( -f "$Dir/NewFileList" );
 
     #
     # Add the new backup information to the backup file
@@ -1122,22 +1281,27 @@ sub BackupSave
            next if ( !-f "$Dir/$Backups[$j]{num}/$file" );
            if ( !link("$Dir/$Backups[$j]{num}/$file",
                                "$Dir/$num/$shareM/$fileM") ) {
-               print(LOG $bpc->timeStamp,
-                         "Unable to link $num/$shareM/$fileM to"
-                       . " $Backups[$j]{num}/$file\n");
+               my $str = \"Unable to link $num/$f->{share}/$f->{file} to"
+                         . " $Backups[$j]{num}/$f->{share}/$f->{file}\n";
+               $XferLOG->write(\$str);
            } else {
-               print(LOG $bpc->timeStamp,
-                         "Bad file $num/$shareM/$fileM replaced by link to"
-                       . " $Backups[$j]{num}/$file\n");
+               my $str = "Bad file $num/$f->{share}/$f->{file} replaced"
+                        . " by link to"
+                        . " $Backups[$j]{num}/$f->{share}/$f->{file}\n";
+               $XferLOG->write(\$str);
            }
            last;
        }
        if ( $j < 0 ) {
-           print(LOG $bpc->timeStamp,
-                     "Removed bad file $num/$shareM/$fileM (no older"
-                   . " copy to link to)\n");
+           my $str = "Removed bad file $num/$f->{share}/$f->{file}"
+                    . " (no older copy to link to)\n";
+           $XferLOG->write(\$str);
        }
     }
+    $XferLOG->close();
+    rename("$Dir/XferLOG$fileExt", "$Dir/XferLOG.$num$fileExt");
+    rename("$Dir/NewFileList", "$Dir/NewFileList.$num");
+
     return $num;
 }
 
index 98bada9..b86b7e4 100755 (executable)
@@ -128,7 +128,7 @@ while ( 1 ) {
     #
     my $noFill = 1;
     my $fillFromNum;
-    if ( $Backups[$num]{type} eq "full" ) {
+    if ( $Backups[$num]{type} ne "incr" ) {
         $noFill = 0
     } elsif ( $Conf{IncrFill} ) {
         my $i;
index 9ebd8c4..a17fbcc 100755 (executable)
@@ -264,6 +264,7 @@ my $xferArgs = {
     pipeWH       => *WH,
     XferLOG      => $RestoreLOG,
     XferMethod   => $Conf{XferMethod},
+    logLevel     => $Conf{XferLogLevel},
     bkupSrcHost  => $RestoreReq{hostSrc},
     bkupSrcShare => $RestoreReq{shareSrc},
     bkupSrcNum   => $RestoreReq{num},
@@ -493,17 +494,17 @@ sub RestoreCleanup
        # kill off the tranfer program, first nicely then forcefully
        #
        if ( @xferPid ) {
-           kill(2, @xferPid);
+           kill($bpc->sigName2num("INT"), @xferPid);
            sleep(1);
-           kill(9, @xferPid);
+           kill($bpc->sigName2num("KILL"), @xferPid);
        }
        #
        # kill off the tar process, first nicely then forcefully
        #
        if ( $tarPid > 0 ) {
-           kill(2, $tarPid);
+           kill($bpc->sigName2num("INT"), $tarPid);
            sleep(1);
-           kill(9, $tarPid);
+           kill($bpc->sigName2num("KILL"), $tarPid);
        }
     }
 
index 9a2872b..cb2d54a 100755 (executable)
@@ -42,20 +42,22 @@ use BackupPC::FileZIO;
 use BackupPC::PoolWrite;
 use File::Path;
 
+use constant S_IFMT       => 0170000;   # type of file
+
 die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
 my $TopDir = $bpc->TopDir();
 my $BinDir = $bpc->BinDir();
 my %Conf   = $bpc->Conf();
 
 if ( @ARGV != 3 ) {
-    print("usage: $0 <host> <shareName> <compressLevel>\n");
+    print("usage: $0 <client> <shareName> <compressLevel>\n");
     exit(1);
 }
 if ( $ARGV[0] !~ /^([\w\.\s-]+)$/ ) {
-    print("$0: bad host name '$ARGV[0]'\n");
+    print("$0: bad client name '$ARGV[0]'\n");
     exit(1);
 }
-my $host = $1;
+my $client = $1;
 if ( $ARGV[1] !~ /^([\w\s\.\/\$-]+)$/ ) {
     print("$0: bad share name '$ARGV[1]'\n");
     exit(1);
@@ -67,6 +69,28 @@ if ( $ARGV[2] !~ /^(\d+)$/ ) {
     exit(1);
 }
 my $Compress = $1;
+my $Abort = 0;
+my $AbortReason;
+
+#
+# Re-read config file, so we can include the PC-specific config
+#
+if ( defined(my $error = $bpc->ConfigRead($client)) ) {
+    print("BackupPC_tarExtract: Can't read PC's config file: $error\n");
+    exit(1);
+}
+%Conf = $bpc->Conf();
+
+#
+# Catch various signals
+#
+$SIG{INT}  = \&catch_signal;
+$SIG{ALRM} = \&catch_signal;
+$SIG{TERM} = \&catch_signal;
+$SIG{PIPE} = \&catch_signal;
+$SIG{STOP} = \&catch_signal;
+$SIG{TSTP} = \&catch_signal;
+$SIG{TTIN} = \&catch_signal;
 
 #
 # This constant and the line of code below that uses it is borrowed
@@ -83,7 +107,7 @@ my $tar_header_length = 512;
 my $BufSize  = 1048576;     # 1MB or 2^20
 my $MaxFiles = 20;
 my $Errors   = 0;
-my $OutDir   = "$TopDir/pc/$host/new";
+my $OutDir   = "$TopDir/pc/$client/new";
 my %Attrib   = ();
 
 my $ExistFileCnt      = 0;
@@ -99,12 +123,15 @@ sub TarRead
 
     $data = "\0" x $totBytes;
     while ( $numBytes < $totBytes ) {
+       return if ( $Abort );
         $newBytes = sysread($fh,
                         substr($data, $numBytes, $totBytes - $numBytes),
                         $totBytes - $numBytes);
         if ( $newBytes <= 0 ) {
-            print(STDERR "Unexpected end of tar archive (tot = $totBytes,"
+            print("Unexpected end of tar archive (tot = $totBytes,"
                    . " num = $numBytes, posn = " . sysseek($fh, 0, 1) . ")\n");
+            $Abort = 1;
+            $AbortReason = "Unexpected end of tar archive";
             $Errors++;
             return;
         }
@@ -140,7 +167,8 @@ sub TarReadFileInfo
 
     while ( 1 ) {
         $head = TarReadHeader($fh);
-        return if ( $head eq "" || $head eq "\0" x $tar_header_length );
+        return if ( $Abort || $head eq ""
+                          || $head eq "\0" x $tar_header_length );
         ($name,                # string
             $mode,     # octal number
             $uid,      # octal number
@@ -198,7 +226,7 @@ sub TarReadFileInfo
         $prefix   = "";
         substr ($head, 148, 8) = "        ";
         if (unpack ("%16C*", $head) != $chksum) {
-           print(STDERR "$name: checksum error at "
+           print("$name: checksum error at "
                         . sysseek($fh, 0, 1) , "\n");
            $Errors++;
         }
@@ -215,6 +243,8 @@ sub TarReadFileInfo
             TarFlush($fh, $size);
             next;
         }
+        printf("Got file '%s', mode 0%o, size %g, type %d\n",
+                $name, $mode, $size, $type) if ( $Conf{XferLogLevel} >= 3 );
         $name     = $longName if ( defined($longName) );
         $linkname = $longLink if ( defined($longLink) );
         $name     =~ s{^\./+}{};
@@ -262,7 +292,7 @@ sub TarReadFile
        $Attrib{$dir} = BackupPC::Attrib->new({ compress => $Compress });
        if ( -f $Attrib{$dir}->fileName("$OutDir/$dir")
                     && !$Attrib{$dir}->read("$OutDir/$dir") ) {
-            printf(STDERR "Unable to read attribute file %s\n",
+            printf("Unable to read attribute file %s\n",
                                 $Attrib{$dir}->fileName("$OutDir/$dir"));
             $Errors++;
        }
@@ -271,6 +301,7 @@ sub TarReadFile
         #
         # Directory
         #
+        logFileAction("create", $f) if ( $Conf{XferLogLevel} >= 1 );
         mkpath("$OutDir/$ShareName/$f->{mangleName}", 0, 0777)
                             if ( !-d "$OutDir/$ShareName/$f->{mangleName}" );
     } elsif ( $f->{type} == BPC_FTYPE_FILE ) {
@@ -287,14 +318,24 @@ sub TarReadFile
                                 ? $f->{size} - $nRead : $BufSize;
             my $data = TarRead($fh, $thisRead);
             if ( $data eq "" ) {
-                print(STDERR "Unexpected end of tar archive during read\n");
-                $Errors++;
+               if ( !$Abort ) {
+                   print("Unexpected end of tar archive during read\n");
+                    $AbortReason = "Unexpected end of tar archive";
+                   $Errors++;
+               }
+               $poolWrite->abort;
+                $Abort = 1;
+               unlink("$OutDir/$ShareName/$f->{mangleName}");
+               print("Removing partial file $f->{name}\n");
                 return;
             }
             $poolWrite->write(\$data);
             $nRead += $thisRead;
         }
-        processClose($poolWrite, "$ShareName/$f->{mangleName}", $f->{size});
+        my $exist = processClose($poolWrite, "$ShareName/$f->{mangleName}",
+                                 $f->{size});
+       logFileAction($exist ? "pool" : "create", $f)
+                                 if ( $Conf{XferLogLevel} >= 1 );
         TarFlush($fh, $f->{size});
     } elsif ( $f->{type} == BPC_FTYPE_HARDLINK ) {
         #
@@ -310,7 +351,10 @@ sub TarReadFile
                                          "$OutDir/$ShareName/$f->{mangleName}",
                                          $f->{size}, $Compress);
         $poolWrite->write(\$f->{linkname});
-        processClose($poolWrite, "$ShareName/$f->{mangleName}", $f->{size});
+        my $exist = processClose($poolWrite, "$ShareName/$f->{mangleName}",
+                                 $f->{size});
+       logFileAction($exist ? "pool" : "create", $f)
+                                 if ( $Conf{XferLogLevel} >= 1 );
     } elsif ( $f->{type} == BPC_FTYPE_SYMLINK ) {
         #
         # Symbolic link: write the value of the link to a plain file,
@@ -324,7 +368,10 @@ sub TarReadFile
                                          "$OutDir/$ShareName/$f->{mangleName}",
                                          $f->{size}, $Compress);
         $poolWrite->write(\$f->{linkname});
-        processClose($poolWrite, "$ShareName/$f->{mangleName}", $f->{size});
+        my $exist = processClose($poolWrite, "$ShareName/$f->{mangleName}",
+                                 $f->{size});
+       logFileAction($exist ? "pool" : "create", $f)
+                                 if ( $Conf{XferLogLevel} >= 1 );
     } elsif ( $f->{type} == BPC_FTYPE_CHARDEV
            || $f->{type} == BPC_FTYPE_BLOCKDEV
            || $f->{type} == BPC_FTYPE_FIFO ) {
@@ -345,7 +392,10 @@ sub TarReadFile
                                          length($data), $Compress);
         $poolWrite->write(\$data);
         $f->{size} = length($data);
-        processClose($poolWrite, "$ShareName/$f->{mangleName}", length($data));
+        my $exist = processClose($poolWrite, "$ShareName/$f->{mangleName}",
+                                 length($data));
+       logFileAction($exist ? "pool" : "create", $f)
+                                 if ( $Conf{XferLogLevel} >= 1 );
     } else {
         print("Got unknown type $f->{type} for $f->{name}\n");
        $Errors++;
@@ -384,7 +434,7 @@ sub processClose
     my($exists, $digest, $outSize, $errs) = $poolWrite->close;
 
     if ( @$errs ) {
-        print(STDERR join("", @$errs));
+        print(join("", @$errs));
         $Errors += @$errs;
     }
     $TotalFileCnt++;
@@ -396,15 +446,63 @@ sub processClose
     } elsif ( $outSize > 0 ) {
         print(NEW_FILES "$digest $origSize $fileName\n");
     }
+    return $exists && $origSize > 0;
+}
+
+#
+# Generate a log file message for a completed file
+#
+sub logFileAction
+{
+    my($action, $f) = @_;
+    my $owner = "$f->{uid}/$f->{gid}";
+    my $name = $f->{name};
+    $name = "." if ( $name eq "" );
+    my $type  = (("", "p", "c", "", "d", "", "b", "", "", "", "l", "", "s"))
+                   [($f->{mode} & S_IFMT) >> 12];
+    $type = "h" if ( $f->{type} == BPC_FTYPE_HARDLINK );
+
+    printf("  %-6s %1s%4o %9s %11.0f %s\n",
+                               $action,
+                               $type,
+                               $f->{mode} & 07777,
+                               $owner,
+                               $f->{size},
+                               $name);
+}
+
+sub catch_signal
+{
+    my $sigName = shift;
+
+    #
+    # The first time we receive a signal we try to gracefully
+    # abort the backup.  This allows us to keep a partial dump
+    # with the in-progress file deleted and attribute caches
+    # flushed to disk etc.
+    #
+    print("BackupPC_tarExtract: got signal $sigName\n");
+    if ( !$Abort ) {
+       $Abort++;
+       $AbortReason = "received signal $sigName";
+       return;
+    }
+
+    #
+    # This is a second signal: time to clean up.
+    #
+    print("BackupPC_tarExtract: quitting on second signal $sigName\n");
+    close(NEW_FILES);
+    exit(1)
 }
 
 mkpath("$OutDir/$ShareName", 0, 0777);
-open(NEW_FILES, ">>", "$TopDir/pc/$host/NewFileList")
-                 || die("can't open $TopDir/pc/$host/NewFileList");
+open(NEW_FILES, ">>", "$TopDir/pc/$client/NewFileList")
+                 || die("can't open $TopDir/pc/$client/NewFileList");
 binmode(NEW_FILES);
 binmode(STDIN);
-1 while ( TarReadFile(*STDIN) );
-1 while ( sysread(STDIN, my $discard, 1024) );
+1 while ( !$Abort && TarReadFile(*STDIN) );
+1 while ( !$Abort && sysread(STDIN, my $discard, 1024) );
 
 #
 # Flush out remaining attributes.
@@ -414,6 +512,10 @@ foreach my $d ( keys(%Attrib) ) {
 }
 close(NEW_FILES);
 
+if ( $Abort ) {
+    print("BackupPC_tarExtact aborting ($AbortReason)\n");
+}
+
 #
 # Report results to BackupPC_dump
 #
index 714f1d7..ff5090e 100644 (file)
@@ -688,6 +688,13 @@ $Conf{BackupZeroFilesIsFatal} = 1;
 #
 $Conf{XferMethod} = 'smb';
 
+#
+# Level of verbosity in Xfer log files.  0 means be quiet, 1 will give
+# will give one line per file, 2 will also show skipped files on
+# incrementals, higher values give more output.
+#
+$Conf{XferLogLevel} = 1;
+
 #
 # Full path for smbclient. Security caution: normal users should not
 # allowed to write to this file or directory.
@@ -981,15 +988,6 @@ $Conf{RsyncRestoreArgs} = [
            #
 ];
 
-#
-# Amount of verbosity in Rsync Xfer log files.  0 means be quiet,
-# 1 will give will give one line per file, 2 will also show skipped
-# files on incrementals, higher values give more output.  10 will
-# include byte dumps of all data read/written, which will make the
-# log files huge.
-#
-$Conf{RsyncLogLevel} = 1;
-
 #
 # Archive Destination
 #
index fe04994..a48ffc6 100755 (executable)
@@ -15,7 +15,7 @@
 #   Craig Barratt <cbarratt@users.sourceforge.net>
 #
 # COPYRIGHT
-#   Copyright (C) 2001-2003  Craig Barratt
+#   Copyright (C) 2001-2004  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
@@ -432,6 +432,7 @@ foreach my $lib ( qw(
        BackupPC/Xfer/Tar.pm
         BackupPC/Xfer/Smb.pm
        BackupPC/Xfer/Rsync.pm
+       BackupPC/Xfer/RsyncDigest.pm
         BackupPC/Xfer/RsyncFileIO.pm
        BackupPC/Zip/FileMember.pm
         BackupPC/Lang/en.pm
@@ -549,6 +550,11 @@ if ( defined($Conf{BlackoutHourBegin}) ) {
     delete($Conf{BlackoutWeekDays});
 }
 
+#
+# $Conf{RsyncLogLevel} has been replaced by $Conf{XferLogLevel}
+#
+$Conf{XferLogLevel} = $Conf{RsyncLogLevel};
+
 #
 # IncrFill should now be off
 #
index cf58ad7..ae3a5db 100644 (file)
@@ -287,16 +287,50 @@ EOF
         $statusStr .= eval("qq{$Lang->{priorStr_to_host_have_succeeded_StatusHostaliveCnt_consecutive_times}}");
 
         if ( $StatusHost{aliveCnt} >= $Conf{BlackoutGoodCnt}
-                && $Conf{BlackoutGoodCnt} >= 0 && $Conf{BlackoutHourBegin} >= 0
-                && $Conf{BlackoutHourEnd} >= 0 ) {
+                && $Conf{BlackoutGoodCnt} >= 0 ) {
+            #
+            # Handle backward compatibility with original separate scalar
+            # blackout parameters.
+            #
+            if ( defined($Conf{BlackoutHourBegin}) ) {
+                push(@{$Conf{BlackoutPeriods}},
+                     {
+                         hourBegin => $Conf{BlackoutHourBegin},
+                         hourEnd   => $Conf{BlackoutHourEnd},
+                         weekDays  => $Conf{BlackoutWeekDays},
+                     }
+                );
+            }
+
+            #
+            # TODO: this string needs i18n.  Also, comma-separated
+            # list with "and" for the last element might not translate
+            # correctly.
+            #
             my(@days) = qw(Sun Mon Tue Wed Thu Fri Sat);
-            my($days) = join(", ", @days[@{$Conf{BlackoutWeekDays}}]);
-            my($t0) = sprintf("%d:%02d", $Conf{BlackoutHourBegin},
-                            60 * ($Conf{BlackoutHourBegin}
-                                     - int($Conf{BlackoutHourBegin})));
-            my($t1) = sprintf("%d:%02d", $Conf{BlackoutHourEnd},
-                            60 * ($Conf{BlackoutHourEnd}
-                                     - int($Conf{BlackoutHourEnd})));
+            my $blackoutStr;
+            my $periodCnt = 0;
+            foreach my $p ( @{$Conf{BlackoutPeriods}} ) {
+                next if ( ref($p->{weekDays}) ne "ARRAY"
+                            || !defined($p->{hourBegin})
+                            || !defined($p->{hourEnd})
+                        );
+                my $days = join(", ", @days[@{$p->{weekDays}}]);
+                my $t0   = sprintf("%d:%02d", $p->{hourBegin},
+                              60 * ($p->{hourBegin} - int($p->{hourBegin})));
+                my $t1   = sprintf("%d:%02d", $p->{hourEnd},
+                              60 * ($p->{hourEnd} - int($p->{hourEnd})));
+                if ( $periodCnt ) {
+                    $blackoutStr .= ", ";
+                    if ( $periodCnt == @{$Conf{BlackoutPeriods}} - 1 ) {
+                        $blackoutStr .= eval("qq{$Lang->{and}}");
+                        $blackoutStr .= " ";
+                    }
+                }
+                $blackoutStr
+                        .= eval("qq{$Lang->{__time0_to__time1_on__days}}");
+                $periodCnt++;
+            }
             $statusStr .= eval("qq{$Lang->{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___}}");
         }
     }
index 7b546a9..c119f42 100644 (file)
@@ -1,5 +1,6 @@
 #!/bin/perl
 #
+# by Manfred Herrmann (11.03.2004 for V2.1.0beta0)
 # by Manfred Herrmann (V1.1) (some typo errors + 3 new strings)
 # CVS-> Revision ???
 #
 
 # --------------------------------
 
-$Lang{Start_Archive} = "ENG Start Archive";
-$Lang{Stop_Dequeue_Archive} = "ENG Stop/Dequeue Archive";
+$Lang{Start_Archive} = "Archivierung starten";
+$Lang{Stop_Dequeue_Archive} = "Archivierung stoppen";
 $Lang{Start_Full_Backup} = "Starte Backup vollständig";
 $Lang{Start_Incr_Backup} = "Starte Backup incrementell";
 $Lang{Stop_Dequeue_Backup} = "Stoppen/Aussetzen Backup";
 $Lang{Restore} = "Wiederherstellung";
 
-$Lang{Type_full} = "ENG full";
-$Lang{Type_incr} = "ENG incremental";
+$Lang{Type_full} = "voll";
+$Lang{Type_incr} = "inkrementell";
 
 # -----
 
-$Lang{Only_privileged_users_can_view_admin_options} = "ENG Only privileged users can view admin options.";
-$Lang{H_Admin_Options} = "ENG BackupPC Server: Admin Options";
-$Lang{Admin_Options} = "ENG Admin Options";
+$Lang{Only_privileged_users_can_view_admin_options} = "Nur privilegierte Nutzer können Admin Optionen einsehen.";
+$Lang{H_Admin_Options} = "BackupPC Server: Admin Optionen";
+$Lang{Admin_Options} = "Admin Optionen";
 $Lang{Admin_Options_Page} = <<EOF;
-ENG
 \${h1(qq{$Lang{Admin_Options}})}
 <br>
-\${h1("Server Control")}
+\${h1("Server Steuerung")}
 <form action="\$MyURL" method="get">
 <table>
-  <tr><td>Stop the server:<td><input type="submit" name="action" value="Stop">
-  <tr><td>Reload the server configuration:<td><input type="submit" name="action" value="Reload">
+  <tr><td>Server stoppen:<td><input type="submit" name="action" value="Stop">
+  <tr><td>Server Konfiguration neu laden:<td><input type="submit" name="action" value="Reload">
 </table>
 </form>
-\${h1("Server Configuration")}
+\${h1("Server Konfiguration")}
 <ul>
-  <li><i>Other options can go here... e.g.,</i>
-  <li>Edit server configuration
+  <li><i>Andere Optionen sind hier möglich ... z.B.,</i>
+  <li>Server Konfiguration editieren
 </ul>
 EOF
 $Lang{Unable_to_connect_to_BackupPC_server} = "Kann keine Verbindung zu BackupPC server herstellen",
@@ -48,11 +48,11 @@ $Lang{Unable_to_connect_to_BackupPC_server} = "Kann keine Verbindung zu BackupPC
             "Möglicherweise ist der BackupPC server Prozess nicht gestartet oder es besteht ein"
           . " Konfigurationsfehler.  Bitte teilen Sie diese Fehlermeldung dem Systemadministrator mit.";
 $Lang{Admin_Start_Server} = <<EOF;
-ENG\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
+\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
 <form action="\$MyURL" method="get">
-The BackupPC server at <tt>\$Conf{ServerHost}</tt> port <tt>\$Conf{ServerPort}</tt>
-is not currently running (maybe you just stopped it, or haven't yet started it).<br>
-Do you want to start it?
+Der BackupPC Server auf <tt>\$Conf{ServerHost}</tt> port <tt>\$Conf{ServerPort}</tt>
+ist momentan nicht aktiv (möglicherweise wurde er gestoppt, oder noch nicht gestartet).<br>
+Möchten Sie den Server starten?
 <input type="hidden" name="action" value="startServer">
 <input type="submit" value="Start Server" name="ignore">
 </form>
@@ -72,7 +72,7 @@ $Lang{BackupPC_Server_Status}= <<EOF;
 <li> Die Server Prozess ID (PID) ist \$Info{pid},  auf Computer \$Conf{ServerHost},
      Version \$Info{Version}, gestartet am \$serverStartTime.
 <li> Dieser Status wurde am \$now generiert.
-<li> ENG The configuration was last loaded at \$configLoadTime.
+<li> Die Konfiguration wurde neu geladen am \$configLoadTime.
 <li> Computer werden am \$nextWakeupTime auf neue Aufträge geprüft.
 <li> Weitere Informationen:
     <ul>
@@ -118,7 +118,7 @@ EOF
 
 # --------------------------------
 $Lang{BackupPC__Server_Summary} = "BackupServer: Übersicht";
-$Lang{BackupPC__Archive} = "ENG BackupPC: Archive";
+$Lang{BackupPC__Archive} = "BackupPC: Archivierung";
 $Lang{BackupPC_Summary}=<<EOF;
 
 \${h1(qq{$Lang{BackupPC__Server_Summary}})}
@@ -170,7 +170,7 @@ Es gibt \$hostCntNone Computer ohne Backups !!!.
 EOF
 
 $Lang{BackupPC_Archive} = <<EOF;
-ENG\${h1(qq{$Lang{BackupPC__Archive}})}
+\${h1(qq{$Lang{BackupPC__Archive}})}
 <script language="javascript" type="text/javascript">
 <!--
 
@@ -197,8 +197,7 @@ ENG\${h1(qq{$Lang{BackupPC__Archive}})}
 
 //-->
 </script>
-
-There are \$hostCntGood hosts that have been backed up for a total size of \${fullSizeTot}GB
+Es gibt \$hostCntGood Computer die gesichert wurden, mit insgesamt \${fullSizeTot}GB
 <p>
 <form name="form1" method="post" action="\$MyURL">
 <input type="hidden" name="fcbMax" value="\$checkBoxCnt">
@@ -206,9 +205,9 @@ There are \$hostCntGood hosts that have been backed up for a total size of \${fu
 <input type="hidden" name="host" value="\${EscHTML(\$archHost)}">
 <input type="hidden" name="action" value="Archive">
 <table class="tableStnd" border cellpadding="3" cellspacing="1">
-<tr class="tableheader"><td align=center> Host</td>
+<tr class="tableheader"><td align=center>Computer</td>
     <td align="center"> User </td>
-    <td align="center"> Backup Size </td>
+    <td align="center"> Backup Größe </td>
 \$strGood
 \$checkAllHosts
 </table>
@@ -218,8 +217,8 @@ There are \$hostCntGood hosts that have been backed up for a total size of \${fu
 EOF
 
 $Lang{BackupPC_Archive2} = <<EOF;
-ENG\${h1(qq{$Lang{BackupPC__Archive}})}
-About to archive the following hosts
+\${h1(qq{$Lang{BackupPC__Archive}})}
+Archivierung der folgenden Computer
 <ul>
 \$HostListStr
 </ul>
@@ -232,22 +231,22 @@ About to archive the following hosts
 <table class="tableStnd" border cellspacing="1" cellpadding="3">
 \$paramStr
 <tr>
-    <td colspan=2><input type="submit" value="Start the Archive" name=""></td>
+    <td colspan=2><input type="submit" value="Archivierung starten" name=""></td>
 </tr>
 </form>
 </table>
 EOF
 
 $Lang{BackupPC_Archive2_location} = <<EOF;
-ENG<tr>
-    <td>Archive Location/Device</td>
+<tr>
+    <td>Archivierung Ort/Gerät</td>
     <td><input type="text" value="\$ArchiveDest" name="archive_device"></td>
 </tr>
 EOF
 
 $Lang{BackupPC_Archive2_compression} = <<EOF;
-ENG<tr>
-    <td>Compression</td>
+<tr>
+    <td>Kompression</td>
     <td>
     <input type="radio" value="0" name="compression" \$ArchiveCompNone>None<br>
     <input type="radio" value="1" name="compression" \$ArchiveCompGzip>gzip<br>
@@ -257,15 +256,15 @@ ENG<tr>
 EOF
 
 $Lang{BackupPC_Archive2_parity} = <<EOF;
-ENG<tr>
-    <td>Number of Parity Files</td>
+<tr>
+    <td>Anzahl Parität-Dateien</td>
     <td><input type="numeric" value="\$ArchivePar" name="par"></td>
 </tr>
 EOF
 
 $Lang{BackupPC_Archive2_split} = <<EOF;
-ENG<tr>
-    <td>Split output into</td>
+<tr>
+    <td>Aufteilen in</td>
     <td><input type="numeric" value="\$ArchiveSplit" name="splitsize">Megabytes</td>
 </tr>
 EOF
@@ -331,7 +330,7 @@ EOF
 # --------------------------------
 $Lang{Only_privileged_users_can_view_queues_} = "Nur berechtigte User können die Warteschlangen einsehen.";
 # --------------------------------
-$Lang{Only_privileged_users_can_archive} = "ENG Only privileged users can Archive.";
+$Lang{Only_privileged_users_can_archive} = "Nur berechtigte Personen könnnen archivieren.";
 # --------------------------------
 $Lang{BackupPC__Queue_Summary} = "BackupServer: Warteschlangen Übersicht";
 # --------------------------------
@@ -465,7 +464,7 @@ Wiederherstellung korrekt ist)
                 window.open(URL,'','width=500,height=400');
          }
          </script>
-         <a href="javascript:myOpen('\$MyURL?action=findShares&host='+document.direct.hostDest.options.value)">Search for available shares (NOT IMPLEMENTED)</a></td>
+         <a href="javascript:myOpen('\$MyURL?action=findShares&host='+document.direct.hostDest.options.value)">Suche nach verfügbaren Freigaben (NICHT IMPLEMENTIERT)</a></td>
 </tr><tr>
     <td>Restore auf Freigabe</td>
     <td><input type="text" size="40" value="\${EscHTML(\$share)}"
@@ -481,8 +480,8 @@ Wiederherstellung korrekt ist)
 EOF
 
 $Lang{Restore_Options_for__host_Option1_disabled} = <<EOF;
-ENG Direct restore has been disabled for host \${EscHTML(\$hostDest)}.
-Please select one of the other restore options.
+Direkte Wiederherstellung ist deaktiviert für Computer: \${EscHTML(\$hostDest)}.
+Bitte wählen Sie eine andere Wiederherstellungsoption.
 EOF
 
 # ------------------------------
@@ -522,10 +521,9 @@ $Lang{Option_2__Download_Zip_archive2} = <<EOF;
 <p>
 \${h2("Möglichkeit 2: Download als Zip Archiv Datei")}
 <p>
-Archive::Zip is not installed so you will not be able to download a
-zip archive.
-Please ask your system adminstrator to install Archive::Zip from
-<a href="http://www.cpan.org">www.cpan.org</a>.
+Archive::Zip ist nicht installiert. Der Download als Zip Archiv Datei ist daher nicht möglich.
+Bitte lassen Sie bei Bedarf von Ihrem Administrator die Perl-Erweiterung Archive::Zip von 
+<a href="http://www.cpan.org">www.cpan.org</a> installieren.
 </p>
 EOF
 
@@ -599,9 +597,9 @@ Zur
 EOF
 
 $Lang{BackupPC_Archive_Reply_from_server} = <<EOF;
-ENG\${h1(\$str)}
+\${h1(\$str)}
 <p>
-Reply from server was: \$reply
+Die Antwort vom Server war: \$reply
 EOF
 
 # -------------------------
@@ -712,14 +710,14 @@ EOF
 
 $Lang{Host__host_Archive_Summary} = "BackupPC: Host \$host Archive Summary";
 $Lang{Host__host_Archive_Summary2} = <<EOF;
-ENG\${h1("Host \$host Archive Summary")}
+\${h1("Host \$host Archiv Übersicht")}
 <p>
 \$warnStr
 <ul>
 \$statusStr
 </ul>
 
-\${h2("User Actions")}
+\${h2("User Aktionen")}
 <p>
 <form action="\$MyURL" method="get">
 <input type="hidden" name="archivehost" value="\$host">
@@ -782,10 +780,10 @@ $Lang{Backup_browse_for__host} = <<EOF;
 <li> Sie browsen das Backup #\$num, erstellt am \$backupTime
         (vor \$backupAge Tagen),
 \$filledBackup
-<li> ENG Enter directory: <input type="text" name="dir" size="50" maxlength="4096" value="\${EscHTML(\$dir)}"> <input type="submit" value="\$Lang->{Go}" name="Submit">
+<li> Verzeichnis eingeben: <input type="text" name="dir" size="50" maxlength="4096" value="\${EscHTML(\$dir)}"> <input type="submit" value="\$Lang->{Go}" name="Submit">
 <li> Klicken Sie auf ein Verzeichnis um dieses zu durchsuchen,
 <li> Klicken Sie auf eine Datei um diese per download wiederherzustellen,
-<li> ENG You can view the backup <a href="\$MyURL?action=dirHistory&host=\${EscURI(\$host)}&share=\$shareURI&dir=\$pathURI">history</a> of the current directory.
+<li> Einsehen der Backup <a href="\$MyURL?action=dirHistory&host=\${EscURI(\$host)}&share=\$shareURI&dir=\$pathURI">Historie</a> des aktuellen Verzeichnisses.
 </ul>
 </form>
 
@@ -821,40 +819,35 @@ This is now in the checkAll row
 EOF
 
 # ------------------------------
-$Lang{DirHistory_backup_for__host} = "(ENGLISH) BackupPC: Directory backup history for \$host";
+$Lang{DirHistory_backup_for__host} = "BackupPC: Verzeichnis Historie für \$host";
 
 #
 # These two strings are used to build the links for directories and
 # file versions.  Files are appended with a version number.
 #
-$Lang{DirHistory_dirLink}  = "ENG dir";
-$Lang{DirHistory_fileLink} = "ENG v";
+$Lang{DirHistory_dirLink}  = "Verzeichnis";
+$Lang{DirHistory_fileLink} = "V";
 
 $Lang{DirHistory_for__host} = <<EOF;
-ENG\${h1("Directory backup history for \$host")}
+\${h1("Verzeichnis Sicherungs-Historie für \$host")}
 <p>
-This display shows each unique version of files across all
-the backups:
+Diese Ansicht zeigt alle unterschiedlichen Versionen der Dateien in den Datensicherungen:
 <ul>
-<li> Click on a backup number to return to the backup browser,
-<li> Click on a directory link (\$Lang->{DirHistory_dirLink}) to navigate
-     into that directory,
-<li> Click on a file version link (\$Lang->{DirHistory_fileLink}0,
-     \$Lang->{DirHistory_fileLink}1, ...) to download that file,
-<li> Files with the same contents between different backups have the same
-     version number,
-<li> Files or directories not present in a particular backup have an
-     empty box.
-<li> Files shown with the same version might have different attributes.
-     Select the backup number to see the file attributes.
+<li> Klicken Sie eine Datensicherungs Nummer für die Datensicherungs Übersicht,
+<li> Wählen Sie hier einen Verzeichnis Namen: (\$Lang->{DirHistory_dirLink}) um Verzeichnisse anzuzeigen,
+<li> Klicken Sie auf eine Datei Version (\$Lang->{DirHistory_fileLink}0,
+     \$Lang->{DirHistory_fileLink}1, ...) für einen Download der Datei,
+<li> Dateien mit dem gleichen Inhalt in verschiedenen Datensicherungen haben die gleiche Versionsnummer,
+<li> Dateien oder Verzeichnisse, die in einer Datensicherung nicht vorhanden sind, haben dort keinen Eintrag.
+<li> Dateien mit der gleichen Version können unterschiedliche Attribute haben. Wählen Sie die Datensicherungsnummer um die Attribute anzuzeigen.
 </ul>
 
-\${h2("History of \${EscHTML(\$dirDisplay)}")}
+\${h2("Historie von \${EscHTML(\$dirDisplay)}")}
 
 <br>
 <table cellspacing="2" cellpadding="3">
-<tr class="fviewheader"><td>Backup number</td>\$backupNumStr</tr>
-<tr class="fviewheader"><td>Backup time</td>\$backupTimeStr</tr>
+<tr class="fviewheader"><td>Datensicherung Nummer</td>\$backupNumStr</tr>
+<tr class="fviewheader"><td>Sicherung Zeitpunkt</td>\$backupTimeStr</tr>
 \$fileStr
 </table>
 EOF
@@ -898,29 +891,29 @@ $Lang{Restore___num_details_for__host2 } = <<EOF;
 EOF
 
 # ------------------------------
-$Lang{Archive___num_details_for__host} = "ENG BackupPC: Archive #\$num details for \$host";
+$Lang{Archive___num_details_for__host} = "BackupPC: Archiv #\$num Details für \$host";
 
 $Lang{Archive___num_details_for__host2 } = <<EOF;
-ENG\${h1("Archive #\$num Details for \$host")}
+\${h1("Archiv #\$num Details für \$host")}
 <p>
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="50%">
-<tr><td class="tableheader"> Number </td><td class="border"> \$Archives[\$i]{num} </td></tr>
-<tr><td class="tableheader"> Requested by </td><td class="border"> \$ArchiveReq{user} </td></tr>
-<tr><td class="tableheader"> Request time </td><td class="border"> \$reqTime </td></tr>
-<tr><td class="tableheader"> Result </td><td class="border"> \$Archives[\$i]{result} </td></tr>
-<tr><td class="tableheader"> Error Message </td><td class="border"> \$Archives[\$i]{errorMsg} </td></tr>
-<tr><td class="tableheader"> Start time </td><td class="border"> \$startTime </td></tr>
-<tr><td class="tableheader"> Duration </td><td class="border"> \$duration min </td></tr>
-<tr><td class="tableheader"> Xfer log file </td><td class="border">
-<a href="\$MyURL?action=view&type=ArchiveLOG&num=\$Archives[\$i]{num}&host=\$host">View</a>,
-<a href="\$MyURL?action=view&type=ArchiveErr&num=\$Archives[\$i]{num}&host=\$host">Errors</a>
+<tr><td class="tableheader"> Nummer </td><td class="border"> \$Archives[\$i]{num} </td></tr>
+<tr><td class="tableheader"> beauftragt von </td><td class="border"> \$ArchiveReq{user} </td></tr>
+<tr><td class="tableheader"> Auftrag Zeitpunkt</td><td class="border"> \$reqTime </td></tr>
+<tr><td class="tableheader"> Ergebnis </td><td class="border"> \$Archives[\$i]{result} </td></tr>
+<tr><td class="tableheader"> Fehlermeldung </td><td class="border"> \$Archives[\$i]{errorMsg} </td></tr>
+<tr><td class="tableheader"> Start Zeitpunkt </td><td class="border"> \$startTime </td></tr>
+<tr><td class="tableheader"> Dauer </td><td class="border"> \$duration min </td></tr>
+<tr><td class="tableheader"> Xfer LOG Datei </td><td class="border">
+<a href="\$MyURL?action=view&type=ArchiveLOG&num=\$Archives[\$i]{num}&host=\$host">Anzeigen</a>,
+<a href="\$MyURL?action=view&type=ArchiveErr&num=\$Archives[\$i]{num}&host=\$host">Fehler</a>
 </tr></tr>
 </table>
 <p>
-\${h1("Host list")}
+\${h1("Computer Liste")}
 <p>
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
-<tr class="tableheader"><td>Host</td><td>Backup Number</td></tr>
+<tr class="tableheader"><td>Host</td><td>Datensicherung Nummer</td></tr>
 \$HostListStr
 </table>
 EOF
@@ -956,8 +949,7 @@ $Lang{Only_privileged_users_can_restore_backup_files} = "Nur berechtigte User k
 $Lang{Bad_host_name} = "Falscher Computer Name \${EscHTML(\$host)}";
 $Lang{You_haven_t_selected_any_files__please_go_Back_to} = "Sie haben keine Dateien selektiert; bitte gehen Sie zurück um"
                 . " Dateien zu selektieren.";
-$Lang{You_haven_t_selected_any_hosts} = "ENG You haven\'t selected any hosts; please go Back to"
-                . " select some hosts.";
+$Lang{You_haven_t_selected_any_hosts} = "Sie haben keinen Computer gewählt, bitte zurückgehen um einen auszuwählen.";
 $Lang{Nice_try__but_you_can_t_put} = "Sie dürfen \'..\' nicht in Dateinamen verwenden";
 $Lang{Host__doesn_t_exist} = "Computer \${EscHTML(\$In{hostDest})} existiert nicht";
 $Lang{You_don_t_have_permission_to_restore_onto_host} = "Sie haben keine Berechtigung zum Restore auf Computer"
@@ -970,12 +962,12 @@ $Lang{Empty_host_name} = "leerer Computer Name";
 $Lang{Unknown_host_or_user} = "Unbekannter Computer oder User \${EscHTML(\$host)}";
 $Lang{Only_privileged_users_can_view_information_about} = "Nur berechtigte User können Informationen sehen über"
                 . " Computer \${EscHTML(\$host)}." ;
-$Lang{Only_privileged_users_can_view_archive_information} = "ENG Only privileged users can view archive information.";
+$Lang{Only_privileged_users_can_view_archive_information} = "Nur berechtigte User können Archiv Informationen einsehen.";
 $Lang{Only_privileged_users_can_view_restore_information} = "Nur berechtigte User können Restore Informationen einsehen.";
 $Lang{Restore_number__num_for_host__does_not_exist} = "Restore Nummer \$num für Computer \${EscHTML(\$host)} existiert"
                . " nicht.";
-$Lang{Archive_number__num_for_host__does_not_exist} = "ENG Archive number \$num for host \${EscHTML(\$host)} does"
-                . " not exist.";
+$Lang{Archive_number__num_for_host__does_not_exist} = "Archiv Nummer \$num für Computer \${EscHTML(\$host)} existiert"
+                . " nicht.";
 $Lang{Can_t_find_IP_address_for} = "Kann IP-Adresse für \${EscHTML(\$host)} nicht finden";
 $Lang{host_is_a_DHCP_host} = <<EOF;
 \$host ist ein DHCP Computer und ich kenne seine IP-Adresse nicht.  Ich prüfte den
@@ -995,7 +987,7 @@ $Lang{Backup_requested_on__host_by__User} = "Backup angefordert f
 $Lang{Backup_stopped_dequeued_on__host_by__User} = "Backup gestoppt/gelöscht für \$host durch \$User";
 $Lang{Restore_requested_to_host__hostDest__backup___num} = "Restore beauftragt nach Computer \$hostDest, von Backup #\$num,"
             . " durch User \$User von Client \$ENV{REMOTE_ADDR}";
-$Lang{Archive_requested} = "ENG Archive requested by \$User from \$ENV{REMOTE_ADDR}";
+$Lang{Archive_requested} = "Archivierung beauftragt durch \$User von \$ENV{REMOTE_ADDR}";
 
 # -------------------------------------------------
 # ------- Stuff that was forgotten ----------------
@@ -1004,7 +996,7 @@ $Lang{Archive_requested} = "ENG Archive requested by \$User from \$ENV{REMOTE_AD
 $Lang{Status} = "Status";
 $Lang{PC_Summary} = "Computer Übersicht";
 $Lang{LOG_file} = "LOG Datei";
-$Lang{LOG_files} = "ENG LOG files";
+$Lang{LOG_files} = "LOG Dateien";
 $Lang{Old_LOGs} = "Alte LOGs";
 $Lang{Email_summary} = "Email Übersicht";
 $Lang{Config_file} = "Config Datei";
@@ -1017,7 +1009,7 @@ $Lang{Go} = "gehe zu";
 $Lang{Hosts} = "Computer";
 $Lang{Select_a_host} = "ENGLISH Select a host...";
 
-$Lang{There_have_been_no_archives} = "<h2> ENG There have been no archives </h2>\n";
+$Lang{There_have_been_no_archives} = "<h2> Es existieren keine Archive </h2>\n";
 $Lang{This_PC_has_never_been_backed_up} = "<h2> Dieser Computer wurde nie gesichert!! </h2>\n";
 $Lang{This_PC_is_used_by} = "<li>Dieser Computer wird betreut von \${UserLink(\$user)}";
 
@@ -1075,10 +1067,12 @@ EOF
 
 $Lang{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___} = <<EOF;
 <li>Da Computer \$host mindestens \$Conf{BlackoutGoodCnt}
-mal fortlaufend erreichbar war, wird er in der Zeit von \$t0 bis \$t1 am \$days nicht gesichert. (Die Sicherung
+mal fortlaufend erreichbar war, wird er in der Zeit von \$blackoutStr nicht gesichert. (Die Sicherung
 erfolgt automatisch außerhalb der konfigurierten Betriebszeit)
 EOF
 
+$Lang{__time0_to__time1_on__days} = "\$t0 bis \$t1 am \$days";
+
 $Lang{Backups_are_deferred_for_hours_hours_change_this_number} = <<EOF;
 <li>Backups sind für die nächsten \$hours Stunden deaktiviert.
 (<a href=\"\$MyURL?action=\${EscURI(\$Lang->{Stop_Dequeue_Archive})}&host=\$host\">diese Zeit ändern</a>).
@@ -1098,9 +1092,9 @@ EOF
 
 $Lang{checkAllHosts} = <<EOF;
 <tr><td class="fviewborder">
-<input type="checkbox" name="allFiles" onClick="return checkAll('allFiles');">&nbsp;ENG Select all
+<input type="checkbox" name="allFiles" onClick="return checkAll('allFiles');">&nbsp;alle auswählen
 </td><td colspan="2" align="center" class="fviewborder">
-<input type="submit" name="Submit" value="ENG Archive selected hosts">
+<input type="submit" name="Submit" value="Gewählte Computer archivieren">
 </td></tr>
 EOF
 
@@ -1115,7 +1109,7 @@ $Lang{fileHeader} = <<EOF;
 EOF
 
 $Lang{Home} = "Home";
-$Lang{Browse} = "ENG Browse backups";
+$Lang{Browse} = "Datensicherungen anzeigen";
 $Lang{Last_bad_XferLOG} = "Letzte bad XferLOG";
 $Lang{Last_bad_XferLOG_errors_only} = "Letzte bad XferLOG (nur&nbsp;Fehler)";
 
@@ -1124,7 +1118,7 @@ $Lang{This_display_is_merged_with_backup} = <<EOF;
 EOF
 
 $Lang{Visit_this_directory_in_backup} = <<EOF;
-<li> ENG Dieses Verzeichnis in Backup <select onChange="window.location=this.value">\$otherDirs </select> browsen.
+<li> Wählen Sie die anzuzeigende Datensicherung: <select onChange="window.location=this.value">\$otherDirs </select>
 EOF
 
 $Lang{Restore_Summary} = <<EOF;
@@ -1147,14 +1141,14 @@ Klicken Sie auf die Restore Nummer (Restore#) f
 EOF
 
 $Lang{Archive_Summary} = <<EOF;
-ENG\${h2("Archive Summary")}
+\${h2("Archiv Übersicht")}
 <p>
-Click on the archive number for more details.
+Klicken Sie auf die Archiv Nummer um die Details anzuzeigen.
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
-<tr class="tableheader"><td align="center"> Archive# </td>
-    <td align="center"> Result </td>
-    <td align="right"> Start Date</td>
-    <td align="right"> Dur/mins</td>
+<tr class="tableheader"><td align="center"> Archiv# </td>
+    <td align="center"> Ergebnis </td>
+    <td align="right"> Start Zeitpunkt</td>
+    <td align="right"> Dauer/min.</td>
 </tr>
 \$ArchiveStr
 </table>
@@ -1175,8 +1169,8 @@ EOF
 $Lang{off} = "aus";
 
 $Lang{backupType_full}    = "voll";
-$Lang{backupType_incr}    = "incr";
-$Lang{backupType_partial} = "ENG partial";
+$Lang{backupType_incr}    = "inkrementell";
+$Lang{backupType_partial} = "partiell";
 
 $Lang{failed} = "fehler";
 $Lang{success} = "erfolgreich";
@@ -1194,15 +1188,15 @@ $Lang{Status_link_running} = "Link l
 
 $Lang{Reason_backup_done} = "Backup durchgeführt";
 $Lang{Reason_restore_done} = "Restore durchgeführt";
-$Lang{Reason_archive_done}   = "ENG archive done";
+$Lang{Reason_archive_done} = "Archivierung durchgeführt";
 $Lang{Reason_nothing_to_do} = "kein Auftrag";
 $Lang{Reason_backup_failed} = "Backup Fehler";
 $Lang{Reason_restore_failed} = "Restore Fehler";
-$Lang{Reason_archive_failed} = "ENG archive failed";
+$Lang{Reason_archive_failed} = "Archivierung Fehler";
 $Lang{Reason_no_ping} = "nicht erreichbar";
 $Lang{Reason_backup_canceled_by_user} = "Abbruch durch User";
 $Lang{Reason_restore_canceled_by_user} = "Abbruch durch User";
-$Lang{Reason_archive_canceled_by_user} = "ENG archive canceled by user";
+$Lang{Reason_archive_canceled_by_user} = "Archivierung abgebrochen durch User";
 
 # ---------
 # Email messages
index 78e1e73..dea65b8 100644 (file)
@@ -1072,9 +1072,11 @@ EOF
 
 $Lang{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___} = <<EOF;
 <li>Because \$host has been on the network at least \$Conf{BlackoutGoodCnt}
-consecutive times, it will not be backed up from \$t0 to \$t1 on \$days.
+consecutive times, it will not be backed up from \$blackoutStr.
 EOF
 
+$Lang{__time0_to__time1_on__days} = "\$t0 to \$t1 on \$days";
+
 $Lang{Backups_are_deferred_for_hours_hours_change_this_number} = <<EOF;
 <li>Backups are deferred for \$hours hours
 (<a href=\"\$MyURL?action=\${EscURI(\$Lang->{Stop_Dequeue_Archive})}&host=\$host\">change this number</a>).
index e96b331..1d8e591 100644 (file)
@@ -1074,9 +1074,11 @@ EOF
 
 $Lang{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___} = <<EOF;
 <li>Dado que \$host ha estado en la red al menos \$Conf{BlackoutGoodCnt}
-veces consecutivas, no se le realizará copia de seguridad desde \$t0 hasta \$t1 en \$days.
+veces consecutivas, no se le realizará copia de seguridad desde \$blackoutStr.
 EOF
 
+$Lang{__time0_to__time1_on__days} = "\$t0 hasta \$t1 en \$days";
+
 $Lang{Backups_are_deferred_for_hours_hours_change_this_number} = <<EOF;
 <li>Las copias de seguridad se retrasarán durante \$hours hours
 (<a href=\"\$MyURL?action=\${EscURI(\$Lang->{Stop_Dequeue_Archive})}&host=\$host\">Cambie este número</a>).
index 8d32c24..37829dc 100644 (file)
@@ -1070,9 +1070,11 @@ EOF
 
 $Lang{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___} = <<EOF;
 <li>Du fait que \$host a été présent sur le réseau au moins \$Conf{BlackoutGoodCnt}
-fois consécutives, il ne sera pas sauvegardé de \$t0 à \$t1 pendant \$days.
+fois consécutives, il ne sera pas sauvegardé de \$blackoutStr.
 EOF
 
+$Lang{__time0_to__time1_on__days} = "\$t0 à \$t1 pendant \$days";
+
 $Lang{Backups_are_deferred_for_hours_hours_change_this_number} = <<EOF;
 <li>Les sauvegardes sont reportées pour \$hours heures
 (<a href=\"\$MyURL?action=\${EscURI(\$Lang->{Stop_Dequeue_Archive})}&host=\$host\">changer ce nombre</a>).
index 76e6e54..de5b11b 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 #
-# $Id: it.pm,v 1.2 2004/03/13 20:57:05 gfk Exp $
+# $Id: it.pm,v 1.3 2004/03/15 03:12:43 cbarratt Exp $
 #
 # Italian i18n file
 #
@@ -119,13 +119,13 @@ EOF
 
 # --------------------------------
 $Lang{BackupPC__Server_Summary} = "BackupPC: prospetto server";
-+$Lang{BackupPC__Archive} = "BackupPC: Archive";
-+$Lang{BackupPC_Summary} = <<EOF;
+$Lang{BackupPC__Archive} = "BackupPC: Archive";
+$Lang{BackupPC_Summary} = <<EOF;
 
 \${h1(qq{$Lang{BackupPC__Server_Summary}})}
 <p>
 Questo rapporto di stato &egrave; stato generato il \$now.
-<p>
+</p>
 
 \${h2("Host con backup buoni")}
 <p>
@@ -136,15 +136,16 @@ Ci sono \$hostCntGood host sottoposti a backup per un totale di:
 <li> \$incrTot backup incrementali per una dimensione totale di \${incrSizeTot}GB
      (prima del processo di pooling e compressione).
 </ul>
-<table border>
-<tr><td> Host </td>
+</p>
+<table class="tableStnd" border cellpadding="3" cellspacing="1">
+<tr class="tableheader"><td> Host </td>
     <td align="center"> Utente </td>
     <td align="center"> Completi </td>
-    <td align="center"> Et&agrave; completi<br>(giorni) </td>
-    <td align="center"> Dimensione completi<br>(GB) </td>
-    <td align="center"> Velocit&agrave<br>(MB/s) </td>
+    <td align="center"> Et&agrave; completi (giorni) </td>
+    <td align="center"> Dimensione completi (GB) </td>
+    <td align="center"> Velocit&agrave (MB/s) </td>
     <td align="center"> Incrementali </td>
-    <td align="center"> Et&agrave; incrementali<br>(giorni) </td>
+    <td align="center"> Et&agrave; incrementali (giorni) </td>
     <td align="center"> Stato </td>
     <td align="center"> Ultimo tentativo </td></tr>
 \$strGood
@@ -158,11 +159,11 @@ Ci sono \$hostCntNone host senza alcun backup.
 <tr class="tableheader"><td> Host </td>
     <td align="center"> Utente </td>
     <td align="center"> Completi </td>
-    <td align="center"> Et&agrave; completi<br>(giorni) </td>
-    <td align="center"> Dimensione completi<br>(GB) </td>
-    <td align="center"> Velocit&agrave<br>(MB/s) </td>
+    <td align="center"> Et&agrave; completi (giorni) </td>
+    <td align="center"> Dimensione completi (GB) </td>
+    <td align="center"> Velocit&agrave (MB/s) </td>
     <td align="center"> Incrementali </td>
-    <td align="center"> Et&agrave; incrementali<br>(giorni) </td>
+    <td align="center"> Et&agrave; incrementali (giorni) </td>
     <td align="center"> Stato </td>
     <td align="center"> Ultimo tentativo </td></tr>
 \$strNone
@@ -209,7 +210,7 @@ totale di \${fullSizeTot}GB
 <table class="tableStnd" border cellpadding="3" cellspacing="1">
 <tr class="tableheader"><td align=center> Host</td>
     <td align="center"> Utente </td>
-    <td align="center"> Dimensione<br>backup </td>
+    <td align="center"> Dimensione backup </td>
 \$strGood
 \$checkAllHosts
 </table>
@@ -355,6 +356,7 @@ Sono state accodate le seguenti richieste degli utenti:
 \${h2("Prospetto code in background")}
 <p>
 Sono attualmente in coda le seguenti richieste di background:
+</p>
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
 <tr class="tableheader"><td> Host </td>
     <td> Data richiesta </td>
@@ -365,6 +367,7 @@ Sono attualmente in coda le seguenti richieste di background:
 \${h2("Prospetto coda comandi")}
 <p>
 Sono attualmente in coda le seguenti richieste di comandi:
+</p>
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
 <tr class="tableheader"><td> Host </td>
     <td> Data richiesta </td>
@@ -444,7 +447,6 @@ su \$host.
 </p><p>
 <b>Attenzione:</b> ogni file esistente che corrisponde ai file selezionati
 sar&agrave; sovrascritto!
-
 </p>
 <form action="\$MyURL" method="post" name="direct">
 <input type="hidden" name="host" value="\${EscHTML(\$host)}">
@@ -465,13 +467,13 @@ sar&agrave; sovrascritto!
                window.open(URL,'','width=500,height=400');
         }
         </script>
-        <a href="javascript:myOpen('\$MyURL?action=findShares&host='+document.d irect.hostDest.options.value)">Search for available shares (NOT IMPLEMENTED)</a></td>
+        <a href="javascript:myOpen('\$MyURL?action=findShares&host='+document.direct.hostDest.options.value)">Search for available shares (NOT IMPLEMENTED)</a></td>
 </tr><tr>
     <td>Ripristino dei file sulla condivisione</td>
     <td><input type="text" size="40" value="\${EscHTML(\$share)}"
         name="shareDest"></td>
 </tr><tr>
-    <td>Ripristino dei file al di sotto della directory<br>
+    <td>Ripristino dei file al di sotto della directory
         (relativa alla condivisione)</td>
     <td valign="top"><input type="text" size="40" maxlength="256"
        value="\${EscHTML(\$pathHdr)}" name="pathHdr"></td>
@@ -488,6 +490,7 @@ EOF
   
 # ------------------------------
 $Lang{Option_2__Download_Zip_archive} = <<EOF;
+<p>
 \${h2("Opzione 2: scaricamento archivio zip")}
 <p>
 &Egrave; possibile scaricare un archivio zip contenente tutti i
@@ -525,7 +528,7 @@ $Lang{Option_2__Download_Zip_archive2} = <<EOF;
 Archive::Zip non &egrave; installato e non &egrave; quindi possibile
 scaricare un archivio zip.
 Contattare l\'amministratore di sistemaper installare Archive::Zip da
-a href="http://www.cpan.org">www.cpan.org</a>.
+<a href="http://www.cpan.org">www.cpan.org</a>.
 </p>
 EOF
 
@@ -595,7 +598,7 @@ $Lang{Reply_from_server_was___reply} = <<EOF;
 <p>
 La risposta del server &grave; stata: \$reply
 <p>
-Ritorna alla <a href="\$MyURL?host=\$host">homepage di \$hostDest</a>.
+Ritorna alla <a href="\$MyURL?host=\$hostDest">homepage di \$hostDest</a>.
 EOF
 
 $Lang{BackupPC_Archive_Reply_from_server} = <<EOF;
@@ -615,6 +618,7 @@ $Lang{Host__host_Backup_Summary2} = <<EOF;
 <ul>
 \$statusStr
 </ul>
+</p>
 \${h2("Azioni utente")}
 <p>
 <form action="\$MyURL" method="get">
@@ -628,12 +632,12 @@ $Lang{Host__host_Backup_Summary2} = <<EOF;
 Cliccare sul numero di bakcup per sfogliare e ripristinare i file di backup.
 </p>
 <table class="tableStnd" border cellspacing="1" cellpadding="3">
-<tr class="tableheader"><td align="center"> Numero<br>backup </td>
+<tr class="tableheader"><td align="center"> Numero backup </td>
     <td align="center"> Tipo </td>
     <td align="center"> Completo </td>
     <td align="center"> Data avvio </td>
-    <td align="center"> Durata<br>(minuti) </td>
-    <td align="center"> Et&agrave;<br>(giorni) </td>
+    <td align="center"> Durata (minuti) </td>
+    <td align="center"> Et&agrave; (giorni) </td>
     <td align="center"> Percorso backup server </td>
 </tr>
 \$str
@@ -646,13 +650,13 @@ Cliccare sul numero di bakcup per sfogliare e ripristinare i file di backup.
 \${h2("Prospetto errori trasferimento")}
 <br><br>
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
-<tr class="tableheader"><td align="center"> Numero<br>backup </td>
+<tr class="tableheader"><td align="center"> Numero backup </td>
     <td align="center"> Tipo </td>
     <td align="center"> Vedere </td>
-    <td align="center"> Numero errori<br>trasferimento </td>
-    <td align="center"> Numero file<br>con problemi </td>
-    <td align="center"> Numero condivisioni<br>con problemi </td>
-    <td align="center"> Numero<br>errori tar </td>
+    <td align="center"> Numero errori trasferimento </td>
+    <td align="center"> Numero file con problemi </td>
+    <td align="center"> Numero condivisioni con problemi </td>
+    <td align="center"> Numero errori tar </td>
 </tr>
 \$errStr
 </table>
@@ -664,6 +668,7 @@ I file esistenti sono quelli gi&agrave; presenti nel pool; i file nuovi sono
 quelli aggiunti al pool.
 I file vuoti e gli errori SMB non sono conteggiati nei contatori di
 riutilizzo e file nuovi.
+</p>
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
 <tr class="tableheader"><td colspan="2" bgcolor="#ffffff"></td>
     <td align="center" colspan="3"> Totali </td>
@@ -671,15 +676,15 @@ riutilizzo e file nuovi.
     <td align="center" colspan="2"> File nuovi </td>
 </tr>
 <tr class="tableheader">
-    <td align="center"> Numero<br>backup </td>
+    <td align="center"> Numero backup </td>
     <td align="center"> Tipo </td>
-    <td align="center"> Numero<br>file </td>
-    <td align="center"> Dimensione<br>(MB) </td>
-    <td align="center"> Velocit&agrave<br>(MB/s) </td>
-    <td align="center"> Numero<br>file </td>
-    <td align="center"> Dimensione<br>(MB) </td>
-    <td align="center"> Numero<br>file </td>
-    <td align="center"> Dimensione<br>(MB) </td>
+    <td align="center"> Numero file </td>
+    <td align="center"> Dimensione (MB) </td>
+    <td align="center"> Velocit&agrave (MB/s) </td>
+    <td align="center"> Numero file </td>
+    <td align="center"> Dimensione (MB) </td>
+    <td align="center"> Numero file </td>
+    <td align="center"> Dimensione (MB) </td>
 </tr>
 \$sizeStr
 </table>
@@ -695,15 +700,15 @@ nuovi.
     <td align="center" colspan="3"> File esistenti </td>
     <td align="center" colspan="3"> File nuovi </td>
 </tr>
-<tr class="tableheader"><td align="center"> Numero<br>backup </td>
+<tr class="tableheader"><td align="center"> Numero backup </td>
     <td align="center"> Tipo </td>
-    <td align="center"> Livello<br>compressione </td>
-    <td align="center"> Dimensione<br>(MB) </td>
-    <td align="center"> Compresso<br>(MB) </td>
-    <td align="center"> Tasso<br>compressione </td>
-    <td align="center"> Dimensione<br>(MB) </td>
-    <td align="center"> Compresso<br>(MB) </td>
-    <td align="center"> Tasso<br>compressione </td>
+    <td align="center"> Livello compressione </td>
+    <td align="center"> Dimensione (MB) </td>
+    <td align="center"> Compresso (MB) </td>
+    <td align="center"> Tasso compressione </td>
+    <td align="center"> Dimensione (MB) </td>
+    <td align="center"> Compresso (MB) </td>
+    <td align="center"> Tasso compressione </td>
 </tr>
 \$compStr
 </table>
@@ -799,16 +804,13 @@ $Lang{Backup_browse_for__host} = <<EOF;
 <br>
 <table width="100%">
 <tr><td valign="top">
-    <!--Navigate here:-->
     <br><table align="center" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff">
     \$dirStr
     </table>
 </td><td width="3%">
 </td><td valign="top">
     <br>
-        <table border="0" width="100%" align="left" cellpadding="3" cellspacing
-  ="1">
-        <table border="0" width="100%" align="left" cellpadding="2" cellspacing="1">
+        <table border="0" width="100%" align="left" cellpadding="3" cellspacing="1">
         \$fileHeader
         \$topCheckAll
         \$fileStr
@@ -820,7 +822,6 @@ $Lang{Backup_browse_for__host} = <<EOF;
 This is now in the checkAll row
 <input type="submit" name="Submit" value="Ripristina file selezionati">
 -->
-</td></tr></table>
 </form>
 EOF
 
@@ -870,24 +871,24 @@ $Lang{Restore___num_details_for__host2 } = <<EOF;
 \${h1("Dettagli ripristino numero \$num per \$host")}
 <p>
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="50%">
-<tr><td class="tableheader"> Numero </td><td> \$Restores[\$i]{num} </td></tr>
-<tr><td class="tableheader"> Richiesto da </td><td> \$RestoreReq{user} </td></tr>
-<tr><td class="tableheader"> Data richiesta </td><td> \$reqTime </td></tr>
-<tr><td class="tableheader"> Risultato </td><td> \$Restores[\$i]{result} </td></tr>
-<tr><td class="tableheader"> Messaggio d\'errore </td><td> \$Restores[\$i]{errorMsg} </td></tr>
-<tr><td class="tableheader"> Host sorgente </td><td> \$RestoreReq{hostSrc} </td></tr>
-<tr><td class="tableheader"> Numero backup<br>sorgente </td><td> \$RestoreReq{num} </td></tr>
-<tr><td class="tableheader"> Condivisione<br>sorgente </td><td> \$RestoreReq{shareSrc} </td></tr>
-<tr><td class="tableheader"> Host destinazione </td><td> \$RestoreReq{hostDest} </td></tr>
-<tr><td class="tableheader"> Condivisione<br>destinazione </td><td> \$RestoreReq{shareDest} </td></tr>
-<tr><td class="tableheader"> Data avvio </td><td> \$startTime </td></tr>
-<tr><td class="tableheader"> Durata </td><td> \$duration min </td></tr>
-<tr><td class="tableheader"> Numero file </td><td> \$Restores[\$i]{nFiles} </td></tr>
-<tr><td class="tableheader"> Dimensione totale </td><td> \${MB}MB </td></tr>
-<tr><td class="tableheader"> Tasso<br>trasferimento </td><td> \$MBperSecMB/s </td></tr>
-<tr><td class="tableheader"> Errori<br>creazione tar </td><td> \$Restores[\$i]{tarCreateErrs} </td></tr>
-<tr><td class="tableheader"> Errori<br>trasferimento </td><td> \$Restores[\$i]{xferErrs} </td></tr>
-<tr><td class="tableheader"> File log<br>trasferimento </td><td>
+<tr><td class="tableheader"> Numero </td><td class="border"> \$Restores[\$i]{num} </td></tr>
+<tr><td class="tableheader"> Richiesto da </td><td class="border"> \$RestoreReq{user} </td></tr>
+<tr><td class="tableheader"> Data richiesta </td><td class="border"> \$reqTime </td></tr>
+<tr><td class="tableheader"> Risultato </td><td class="border"> \$Restores[\$i]{result} </td></tr>
+<tr><td class="tableheader"> Messaggio d\'errore </td><td class="border"> \$Restores[\$i]{errorMsg} </td></tr>
+<tr><td class="tableheader"> Host sorgente </td><td class="border"> \$RestoreReq{hostSrc} </td></tr>
+<tr><td class="tableheader"> Numero backup sorgente </td><td class="border"> \$RestoreReq{num} </td></tr>
+<tr><td class="tableheader"> Condivisione sorgente </td><td class="border"> \$RestoreReq{shareSrc} </td></tr>
+<tr><td class="tableheader"> Host destinazione </td><td class="border"> \$RestoreReq{hostDest} </td></tr>
+<tr><td class="tableheader"> Condivisione destinazione </td><td class="border"> \$RestoreReq{shareDest} </td></tr>
+<tr><td class="tableheader"> Data avvio </td><td class="border"> \$startTime </td></tr>
+<tr><td class="tableheader"> Durata </td><td class="border"> \$duration min </td></tr>
+<tr><td class="tableheader"> Numero file </td><td class="border"> \$Restores[\$i]{nFiles} </td></tr>
+<tr><td class="tableheader"> Dimensione totale </td><td class="border"> \${MB}MB </td></tr>
+<tr><td class="tableheader"> Tasso trasferimento </td><td class="border"> \$MBperSecMB/s </td></tr>
+<tr><td class="tableheader"> Errori creazione tar </td><td class="border"> \$Restores[\$i]{tarCreateErrs} </td></tr>
+<tr><td class="tableheader"> Errori trasferimento </td><td class="border"> \$Restores[\$i]{xferErrs} </td></tr>
+<tr><td class="tableheader"> File log trasferimento </td><td class="border">
 <a href="\$MyURL?action=view&type=RestoreLOG&num=\$Restores[\$i]{num}&host=\$host">Vedi</a>,
 <a href="\$MyURL?action=view&type=RestoreErr&num=\$Restores[\$i]{num}&host=\$host">Errori</a>
 </tr></tr>
@@ -1082,9 +1083,11 @@ EOF
 
 $Lang{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___} = <<EOF;
 <li>Poich&eacute; \$host &egrave; rimasto in rete per almeno \$Conf{BlackoutGoodCnt}
-volte consecutive, il backup non sar&agrave; effettuato dalle \$t0 alle \$t1 di \$days.
+volte consecutive, il backup non sar&agrave; effettuato dalle \$blackoutStr.
 EOF
 
+$Lang{__time0_to__time1_on__days} = "\$t0 alle \$t1 di \$days";
+
 $Lang{Backups_are_deferred_for_hours_hours_change_this_number} = <<EOF;
 <li>I backup sono stati posticipati per \$hours ore
 (<a href=\"\$MyURL?action=\${EscURI(\$Lang->{Stop_Dequeue_Archive})}&host=\$host\">modifica questo numero</a>).
@@ -1138,14 +1141,14 @@ $Lang{Restore_Summary} = <<EOF;
 <p>
 Fare clic sul numero del ripristino per maggiori dettagli.
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
-<tr class="tableheader"><td align="center"> Numero<br>ripristino </td>
+<tr class="tableheader"><td align="center"> Numero ripristino </td>
     <td align="center"> Risultato </td>
     <td align="right"> Data avvio</td>
-    <td align="right"> Durata<br>(minuti)</td>
-    <td align="right"> Numero<br>file </td>
-    <td align="right"> Dimensione<br>(MB) </td>
-    <td align="right"> Numero<br>errori tar </td>
-    <td align="right"> Numero errori<br>trasferimento </td>
+    <td align="right"> Durata (minuti)</td>
+    <td align="right"> Numero file </td>
+    <td align="right"> Dimensione (MB) </td>
+    <td align="right"> Numero errori tar </td>
+    <td align="right"> Numero errori trasferimento </td>
 </tr>
 \$restoreStr
 </table>
@@ -1157,10 +1160,10 @@ $Lang{Archive_Summary} = <<EOF;
 <p>
 Fare clic sul numero di archivio per maggiori dettagli.
 <table class="tableStnd" border cellspacing="1" cellpadding="3" width="80%">
-<tr class="tableheader"><td align="center"> Numero<br>archivio</td>
+<tr class="tableheader"><td align="center"> Numero archivio</td>
     <td align="center"> Risultato </td>
-    <td align="right"> Data<br>avvio</td>
-    <td align="right"> Durata<br>minuti</td>
+    <td align="right"> Data avvio</td>
+    <td align="right"> Durata minuti</td>
 </tr>
 \$ArchiveStr
 </table>
@@ -1200,6 +1203,7 @@ $Lang{Status_link_running} = "collegamenti in esecuzione";
 
 $Lang{Reason_backup_done}    = "backup eseguito";
 $Lang{Reason_restore_done}   = "restore eseguito";
+$Lang{Reason_archive_done}   = "archivio eseguito";
 $Lang{Reason_nothing_to_do}  = "nulla da fare";
 $Lang{Reason_backup_failed}  = "backup fallito";
 $Lang{Reason_restore_failed} = "restore fallito";
index edd50dc..39f9680 100644 (file)
@@ -48,6 +48,7 @@ use File::Compare;
 use Socket;
 use Cwd;
 use Digest::MD5;
+use Config;
 
 sub new
 {
@@ -92,7 +93,7 @@ sub new
     if ( !$noUserCheck
            && $bpc->{Conf}{BackupPCUserVerify}
            && $> != (my $uid = (getpwnam($bpc->{Conf}{BackupPCUser}))[2]) ) {
-       print("Wrong user: my userid is $>, instead of $uid"
+       print(STDERR "Wrong user: my userid is $>, instead of $uid"
            . " ($bpc->{Conf}{BackupPCUser})\n");
        return;
     }
@@ -154,6 +155,20 @@ sub verbose
     return $bpc->{verbose};
 }
 
+sub sigName2num
+{
+    my($bpc, $sig) = @_;
+
+    if ( !defined($bpc->{SigName2Num}) ) {
+       my $i = 0;
+       foreach my $name ( split(' ', $Config{sig_name}) ) {
+           $bpc->{SigName2Num}{$name} = $i;
+           $i++;
+       }
+    }
+    return $bpc->{SigName2Num}{$sig};
+}
+
 #
 # Generate an ISO 8601 format timeStamp (but without the "T").
 # See http://www.w3.org/TR/NOTE-datetime and
@@ -434,7 +449,7 @@ sub RmTreeQuiet
     if ( defined($roots) && length($roots) ) {
       $roots = [$roots] unless ref $roots;
     } else {
-      print "RmTreeQuiet: No root path(s) specified\n";
+      print(STDERR "RmTreeQuiet: No root path(s) specified\n");
     }
     chdir($pwd);
     foreach $root (@{$roots}) {
@@ -448,7 +463,7 @@ sub RmTreeQuiet
        if ( !unlink($root) ) {
             if ( -d $root ) {
                 my $d = DirHandle->new($root)
-                  or print "Can't read $pwd/$root: $!";
+                  or print(STDERR "Can't read $pwd/$root: $!");
                 @files = $d->read;
                 $d->close;
                 @files = grep $_!~/^\.{1,2}$/, @files;
@@ -1154,7 +1169,7 @@ sub cmdSystemOrEval
            # force list-form of exec(), ie: no shell even for 1 arg
            #
            exec { $cmd->[0] } @$cmd;
-            print("Exec of @$cmd failed\n");
+            print(STDERR "Exec of @$cmd failed\n");
             exit(1);
        }
        #
index d77b7af..01d89a7 100644 (file)
@@ -115,7 +115,7 @@ sub write
     # file list if the file changes between the file list sending
     # and the file sending).  Here we only catch the case where
     # we haven't computed the digest (ie: we have written no more
-    # than $BufSize.  We catch the big file case below.
+    # than $BufSize).  We catch the big file case below.
     #
     if ( !defined($dataRef) && !defined($a->{digest})
                && $a->{fileSize} != length($a->{data}) ) {
@@ -270,9 +270,6 @@ sub write
     # We are at EOF, so finish up
     #
     $a->{eof} = 1;
-    foreach my $f ( @{$a->{files}} ) {
-        $f->{fh}->close();
-    }
 
     #
     # Make sure the fileSize was correct.  See above for comments about
@@ -291,27 +288,37 @@ sub write
 
        my($fh, $fileName);
        $a->{fileSize} = $a->{nWrite};
-       if ( $a->{fileName} =~ /(.*)\// ) {
-           $fileName = $1;
-       } else {
-           $fileName = ".";
-       }
 
-       #
-       # Find a unique target temporary file name
-       #
-       my $i = 0;
-       while ( -f "$fileName/t$$.$i" ) {
-           $i++;
+       if ( defined($a->{fhOut}) ) {
+           if ( $a->{fileName} =~ /(.*)\// ) {
+               $fileName = $1;
+           } else {
+               $fileName = ".";
+           }
+           #
+           # Find a unique target temporary file name
+           #
+           my $i = 0;
+           while ( -f "$fileName/t$$.$i" ) {
+               $i++;
+           }
+           $fileName = "$fileName/t$$.$i";
+           $a->{fhOut}->close();
+           if ( !rename($a->{fileName}, $fileName)
+             || !defined($fh = BackupPC::FileZIO->open($fileName, 0,
+                                                $a->{compress})) ) {
+               push(@{$a->{errors}}, "Can't rename $a->{fileName} -> $fileName"
+                                   . " or open during size fixup\n");
+           }
+       } elsif ( defined($a->{files}) && defined($a->{files}[0]) ) {
+           #
+           # We haven't written anything yet, so just use the
+           # compare file to copy from.
+           #
+           $fh = $a->{files}[0]->{fh};
+           $fh->rewind;
        }
-       $fileName = "$fileName/t$$.$i";
-        $a->{fhOut}->close();
-       if ( !rename($a->{fileName}, $fileName)
-         || !defined($fh = BackupPC::FileZIO->open($fileName, 0,
-                                            $a->{compress})) ) {
-            push(@{$a->{errors}}, "Can't rename $a->{fileName} -> $fileName"
-                               . " or open during size fixup\n");
-       } else {
+       if ( defined($fh) ) {
            my $poolWrite = BackupPC::PoolWrite->new($a->{bpc}, $a->{fileName},
                                        $a->{fileSize}, $a->{compress});
            my $nRead = 0;
@@ -331,7 +338,7 @@ sub write
                $nRead += $thisRead;
            }
            $fh->close;
-           unlink($fileName);
+           unlink($fileName) if ( defined($fileName) );
            if ( @{$a->{errors}} ) {
                $poolWrite->close;
                return (0, $a->{digest}, -s $a->{fileName}, $a->{errors});
@@ -341,6 +348,13 @@ sub write
        }
     }
 
+    #
+    # Close the compare files
+    #
+    foreach my $f ( @{$a->{files}} ) {
+        $f->{fh}->close();
+    }
+
     if ( $a->{fileSize} == 0 ) {
         #
         # Simply create an empty file
@@ -394,6 +408,23 @@ sub close
     return $a->write(undef);
 }
 
+#
+# Abort a pool write
+#
+sub abort
+{
+    my($a) = @_;
+
+    if ( defined($a->{fhOut}) ) {
+       $a->{fhOut}->close();
+       unlink($a->{fileName});
+    }
+    foreach my $f ( @{$a->{files}} ) {
+        $f->{fh}->close();
+    }
+    $a->{files} = [];
+}
+
 #
 # Copy $nBytes from files $fhIn to $fhOut.
 #
diff --git a/lib/BackupPC/RsyncDigest.pm b/lib/BackupPC/RsyncDigest.pm
deleted file mode 100644 (file)
index 3dd0896..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# BackupPC::RsyncDigest package
-#
-# DESCRIPTION
-#
-#   This library defines a BackupPC::RsyncDigest class for computing
-#   and caching rsync checksums.
-#
-# AUTHOR
-#   Craig Barratt  <cbarratt@users.sourceforge.net>
-#
-# COPYRIGHT
-#   Copyright (C) 2001-2003  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
-#   the Free Software Foundation; either version 2 of the License, or
-#   (at your option) any later version.
-#
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License
-#   along with this program; if not, write to the Free Software
-#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
-#========================================================================
-#
-# Version 2.1.0_CVS, released 3 Jul 2003.
-#
-# See http://backuppc.sourceforge.net.
-#
-#========================================================================
-
-package BackupPC::RsyncDigest;
-
-use strict;
-
-use vars qw( $RsyncLibOK );
-use Carp;
-
-BEGIN {
-    eval "use File::RsyncP;";
-    if ( $@ ) {
-        #
-        # File::RsyncP doesn't exist.  Define some dummy constant
-        # subs so that the code below doesn't barf.
-        #
-        $RsyncLibOK = 0;
-    } else {
-        $RsyncLibOK = 1;
-    }
-};
-
-#
-# Return the rsync block size based on the file size.
-# We also make sure the block size plus 4 (ie: cheeksumSeed)
-# is not a multiple of 64 - otherwise the cached checksums
-# will not be the same for protocol versions <= 26 and > 26.
-#
-sub blockSize
-{
-    my($class, $fileSize, $defaultBlkSize) = @_;
-
-    my $blkSize = int($fileSize / 10000);
-    $blkSize = $defaultBlkSize if ( $blkSize < $defaultBlkSize );
-    $blkSize = 16384 if ( $blkSize > 16384 );
-    $blkSize += 4 if ( (($blkSize + 4) % 64) == 0 );
-    return $blkSize;
-}
-
-#
-# Compute and add rsync block and file digests to the given file.
-#
-sub digestAdd
-{
-    my($class, $file, $blockSize, $checksumSeed) = @_;
-    if ( $blockSize == 0 ) {
-       print("bogus digestAdd($file, $blockSize, $checksumSeed)\n");
-       $blockSize = 2048;
-    }
-    my $nBlks = int(65536 * 16 / $blockSize) + 1;
-    my($data, $blockDigest, $fileDigest);
-
-    return if ( !$RsyncLibOK );
-
-    my $digest = File::RsyncP::Digest->new;
-    $digest->add(pack("V", $checksumSeed)) if ( $checksumSeed );
-
-    return -1 if ( !defined(my $fh = BackupPC::FileZIO->open($file, 0, 1)) );
-    while ( 1 ) {
-        $fh->read(\$data, $nBlks * $blockSize);
-        last if ( $data eq "" );
-        $blockDigest .= $digest->blockDigest($data, $blockSize, 16,
-                                             $checksumSeed);
-        $digest->add($data);
-    }
-    $fileDigest = $digest->digest2;
-    my $eofPosn = tell($fh->{fh});
-    $fh->close;
-    my $rsyncData = $blockDigest . $fileDigest;
-    my $metaData  = pack("VVVV", $blockSize,
-                                 $checksumSeed,
-                                 length($blockDigest) / 20,
-                                 0x5fe3c289,                # magic number
-                        );
-    my $data2 = chr(0xb3) . $rsyncData . $metaData;
-#    printf("appending %d+%d bytes to %s at offset %d\n",
-#                                            length($rsyncData),
-#                                            length($metaData),
-#                                            $file,
-#                                            $eofPosn);
-    open(my $fh2, "+<", $file) || return -2;
-    binmode($fh2);
-    return -3 if ( sysread($fh2, $data, 1) != 1 );
-    if ( $data ne chr(0x78) && $data ne chr(0xd6) ) {
-        printf("Unexpected first char 0x%x\n", ord($data));
-        return -4;
-    }
-    return -5 if ( sysseek($fh2, $eofPosn, 0) != $eofPosn );
-    return -6 if ( syswrite($fh2, $data2) != length($data2) );
-    return -7 if ( !defined(sysseek($fh2, 0, 0)) );
-    return -8 if ( syswrite($fh2, chr(0xd6)) != 1 );
-    close($fh2);
-}
-
-#
-# Return rsync checksums for the given file.  We read the cached checksums
-# if they exist and the block size and checksum seed match.  Otherwise
-# we compute the checksums from the file contents.
-#
-sub digestStart
-{
-    my($class, $fileName, $fileSize, $blockSize, $defBlkSize,
-       $checksumSeed, $needMD4, $compress, $doCache) = @_;
-
-    return -1 if ( !$RsyncLibOK );
-
-    my $data;
-
-    my $fio = bless {
-        name     => $fileName,
-        needMD4  => $needMD4,
-        digest   => File::RsyncP::Digest->new,
-    }, $class;
-
-    if ( $fileSize > 0 && $compress ) {
-        open(my $fh, "<", $fileName) || return -2;
-        binmode($fh);
-        return -3 if ( read($fh, $data, 1) != 1 );
-        if ( $data eq chr(0x78) && $doCache && $checksumSeed == 32761 ) {
-            #
-            # 32761 is the magic number that rsync uses for checksumSeed
-            # with the --fixed-csum option.
-            #
-            # We now add the cached checksum data to the file.  There
-            # is a possible race condition here since two BackupPC_dump
-            # processes might call this function at the same time
-            # on the same file.  But this should be ok since both
-            # processes will write the same data, and the order
-            # in which they write it doesn't matter.
-            #
-            close($fh);
-            $fio->digestAdd($fileName,
-                    $blockSize
-                       || BackupPC::RsyncDigest->blockSize($fileSize,
-                                                           $defBlkSize),
-                    $checksumSeed);
-            #
-            # now re-open the file and re-read the first byte
-            #
-            open($fh, "<", $fileName) || return -2;
-            binmode($fh);
-            return -3 if ( read($fh, $data, 1) != 1 );
-        }
-        if ( $data eq chr(0xd6) ) {
-            #
-            # Looks like this file has cached checksums
-            # Read the last 48 bytes: that's 2 file MD4s (32 bytes)
-            # plus 4 words of meta data
-            #
-            return -4 if ( !defined(seek($fh, -48, 2)) ); 
-            return -5 if ( read($fh, $data, 48) != 48 );
-            ($fio->{md4DigestOld},
-             $fio->{md4Digest},
-             $fio->{blockSize},
-             $fio->{checksumSeed},
-             $fio->{nBlocks},
-             $fio->{magic}) = unpack("a16 a16 V V V V", $data);
-            if ( $fio->{magic} == 0x5fe3c289
-                    && $fio->{checksumSeed} == $checksumSeed
-                    && ($blockSize == 0 || $fio->{blockSize} == $blockSize) ) {
-                $fio->{fh}     = $fh;
-                $fio->{cached} = 1;
-            } else {
-                close($fh);
-            }
-            #
-            # position the file at the start of the rsync block checksums
-            # (4 (adler) + 16 (md4) bytes each)
-            #
-            return -6 if ( !defined(seek($fh, -$fio->{nBlocks}*20 - 48, 2)) );
-        }
-    }
-    if ( !$fio->{cached} ) {
-        #
-        # This file doesn't have cached checksums, or the checksumSeed
-        # or blocksize doesn't match.  Open the file and prepare to
-        # compute the checksums.
-        #
-        $blockSize = BackupPC::RsyncDigest->blockSize($fileSize, $defBlkSize)
-                                        if ( $blockSize == 0 );
-        $fio->{checksumSeed} = $checksumSeed;
-        $fio->{blockSize}    = $blockSize;
-        $fio->{fh} = BackupPC::FileZIO->open($fileName, 0, $compress);
-        return -7 if ( !defined($fio->{fh}) );
-        if ( $needMD4) {
-            $fio->{csumDigest} = File::RsyncP::Digest->new;
-            $fio->{csumDigest}->add(pack("V", $fio->{checksumSeed}));
-        }
-    }
-    return (undef, $fio, $fio->{blockSize});
-}
-
-sub digestGet
-{
-    my($fio, $num, $csumLen) = @_;
-    my($fileData);
-    my $blockSize = $fio->{blockSize};
-
-    if ( $fio->{cached} ) {
-        my $thisNum = $num;
-        $thisNum = $fio->{nBlocks} if ( $thisNum > $fio->{nBlocks} );
-        read($fio->{fh}, $fileData, 20 * $thisNum);
-        $fio->{nBlocks} -= $thisNum;
-        if ( $thisNum < $num ) {
-            #
-            # unexpected shortfall of data; pad with zero digest
-            #
-            $fileData .= pack("c", 0) x (20 * ($num - $thisNum));
-        }
-        return $fio->{digest}->blockDigestExtract($fileData, $csumLen);
-    } else {
-        if ( $fio->{fh}->read(\$fileData, $blockSize * $num) <= 0 ) {
-            #
-            # unexpected shortfall of data; pad with zeros
-            #
-            $fileData = pack("c", 0) x ($blockSize * $num);
-        }
-        $fio->{csumDigest}->add($fileData) if ( $fio->{needMD4} );
-        return $fio->{digest}->blockDigest($fileData, $blockSize,
-                                           $csumLen, $fio->{checksumSeed});
-    }
-}
-
-sub digestEnd
-{
-    my($fio) = @_;
-    my($fileData);
-
-    if ( $fio->{cached} ) {
-        close($fio->{fh});
-        return $fio->{md4DigestOld} if ( $fio->{needMD4} );
-    } else {
-        #
-        # make sure we read the entire file for the file MD4 digest
-        #
-        if ( $fio->{needMD4} ) {
-            my $fileData;
-            while ( $fio->{fh}->read(\$fileData, 65536) > 0 ) {
-                $fio->{csumDigest}->add($fileData);
-            }
-        }
-        $fio->{fh}->close();
-        return $fio->{csumDigest}->digest if ( $fio->{needMD4} );
-    }
-}
-
-1;
index 841f016..613ae45 100644 (file)
@@ -137,6 +137,10 @@ sub errStr
     return $t->{_errStr};
 }
 
+sub abort
+{
+}
+
 sub xferPid
 {
     my($t) = @_;
index e8b605a..d629cd3 100644 (file)
@@ -278,7 +278,7 @@ sub start
     #
     $t->{rsyncClientCmd} = $rsyncClientCmd;
     $t->{rs} = File::RsyncP->new({
-       logLevel     => $conf->{RsyncLogLevel},
+       logLevel     => $t->{logLevel} || $conf->{RsyncLogLevel},
        rsyncCmd     => sub {
                            $bpc->verbose(0);
                            $bpc->cmdExecOrEval($rsyncClientCmd, $args);
@@ -287,11 +287,25 @@ sub start
        rsyncArgs    => $rsyncArgs,
        timeout      => $conf->{ClientTimeout},
        doPartial    => defined($t->{partialNum}) ? 1 : undef,
-       logHandler   => sub {
-                           my($str) = @_;
-                           $str .= "\n";
-                           $t->{XferLOG}->write(\$str);
-                       },
+       logHandler   =>
+                sub {
+                    my($str) = @_;
+                    $str .= "\n";
+                    $t->{XferLOG}->write(\$str);
+                    if ( $str =~ /^Remote\[1\]: read errors mapping "(.*)"/ ) {
+                        #
+                        # Files with read errors (eg: region locked files
+                        # on WinXX) are filled with 0 by rsync.  Remember
+                        # them and delete them later.
+                        #
+                        my $badFile = $1;
+                        $badFile =~ s/^\/+//;
+                        push(@{$t->{badFiles}}, {
+                                share => $t->{shareName},
+                                file  => $badFile
+                            });
+                    }
+                },
        pidHandler   => sub {
                            $t->{pidHandler}(@_);
                        },
@@ -300,7 +314,8 @@ sub start
                            bpc        => $t->{bpc},
                            conf       => $t->{conf},
                            backups    => $t->{backups},
-                           logLevel   => $conf->{RsyncLogLevel},
+                           logLevel   => $t->{logLevel}
+                                              || $conf->{RsyncLogLevel},
                            logHandler => sub {
                                              my($str) = @_;
                                              $str .= "\n";
@@ -427,6 +442,15 @@ sub run
     }
 }
 
+sub abort
+{
+    my($t, $reason) = @_;
+    my $rs = $t->{rs};
+
+    $rs->abort($reason);
+    return 1;
+}
+
 sub setSelectMask
 {
     my($t, $FDreadRef) = @_;
diff --git a/lib/BackupPC/Xfer/RsyncDigest.pm b/lib/BackupPC/Xfer/RsyncDigest.pm
new file mode 100644 (file)
index 0000000..def46a0
--- /dev/null
@@ -0,0 +1,283 @@
+#============================================================= -*-perl-*-
+#
+# BackupPC::Xfer::RsyncDigest package
+#
+# DESCRIPTION
+#
+#   This library defines a BackupPC::Xfer::RsyncDigest class for computing
+#   and caching rsync checksums.
+#
+# AUTHOR
+#   Craig Barratt  <cbarratt@users.sourceforge.net>
+#
+# COPYRIGHT
+#   Copyright (C) 2001-2003  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
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#========================================================================
+#
+# Version 2.1.0_CVS, released 3 Jul 2003.
+#
+# See http://backuppc.sourceforge.net.
+#
+#========================================================================
+
+package BackupPC::Xfer::RsyncDigest;
+
+use strict;
+
+use vars qw( $RsyncLibOK );
+use Carp;
+
+BEGIN {
+    eval "use File::RsyncP;";
+    if ( $@ ) {
+        #
+        # File::RsyncP doesn't exist.  Define some dummy constant
+        # subs so that the code below doesn't barf.
+        #
+        $RsyncLibOK = 0;
+    } else {
+        $RsyncLibOK = 1;
+    }
+};
+
+#
+# Return the rsync block size based on the file size.
+# We also make sure the block size plus 4 (ie: cheeksumSeed)
+# is not a multiple of 64 - otherwise the cached checksums
+# will not be the same for protocol versions <= 26 and > 26.
+#
+sub blockSize
+{
+    my($class, $fileSize, $defaultBlkSize) = @_;
+
+    my $blkSize = int($fileSize / 10000);
+    $blkSize = $defaultBlkSize if ( $blkSize < $defaultBlkSize );
+    $blkSize = 16384 if ( $blkSize > 16384 );
+    $blkSize += 4 if ( (($blkSize + 4) % 64) == 0 );
+    return $blkSize;
+}
+
+#
+# Compute and add rsync block and file digests to the given file.
+#
+sub digestAdd
+{
+    my($class, $file, $blockSize, $checksumSeed) = @_;
+    if ( $blockSize == 0 ) {
+       print("bogus digestAdd($file, $blockSize, $checksumSeed)\n");
+       $blockSize = 2048;
+    }
+    my $nBlks = int(65536 * 16 / $blockSize) + 1;
+    my($data, $blockDigest, $fileDigest);
+
+    return if ( !$RsyncLibOK );
+
+    my $digest = File::RsyncP::Digest->new;
+    $digest->add(pack("V", $checksumSeed)) if ( $checksumSeed );
+
+    return -1 if ( !defined(my $fh = BackupPC::FileZIO->open($file, 0, 1)) );
+    while ( 1 ) {
+        $fh->read(\$data, $nBlks * $blockSize);
+        last if ( $data eq "" );
+        $blockDigest .= $digest->blockDigest($data, $blockSize, 16,
+                                             $checksumSeed);
+        $digest->add($data);
+    }
+    $fileDigest = $digest->digest2;
+    my $eofPosn = tell($fh->{fh});
+    $fh->close;
+    my $rsyncData = $blockDigest . $fileDigest;
+    my $metaData  = pack("VVVV", $blockSize,
+                                 $checksumSeed,
+                                 length($blockDigest) / 20,
+                                 0x5fe3c289,                # magic number
+                        );
+    my $data2 = chr(0xb3) . $rsyncData . $metaData;
+#    printf("appending %d+%d bytes to %s at offset %d\n",
+#                                            length($rsyncData),
+#                                            length($metaData),
+#                                            $file,
+#                                            $eofPosn);
+    open(my $fh2, "+<", $file) || return -2;
+    binmode($fh2);
+    return -3 if ( sysread($fh2, $data, 1) != 1 );
+    if ( $data ne chr(0x78) && $data ne chr(0xd6) ) {
+        printf("Unexpected first char 0x%x\n", ord($data));
+        return -4;
+    }
+    return -5 if ( sysseek($fh2, $eofPosn, 0) != $eofPosn );
+    return -6 if ( syswrite($fh2, $data2) != length($data2) );
+    return -7 if ( !defined(sysseek($fh2, 0, 0)) );
+    return -8 if ( syswrite($fh2, chr(0xd6)) != 1 );
+    close($fh2);
+}
+
+#
+# Return rsync checksums for the given file.  We read the cached checksums
+# if they exist and the block size and checksum seed match.  Otherwise
+# we compute the checksums from the file contents.
+#
+sub digestStart
+{
+    my($class, $fileName, $fileSize, $blockSize, $defBlkSize,
+       $checksumSeed, $needMD4, $compress, $doCache) = @_;
+
+    return -1 if ( !$RsyncLibOK );
+
+    my $data;
+
+    my $fio = bless {
+        name     => $fileName,
+        needMD4  => $needMD4,
+        digest   => File::RsyncP::Digest->new,
+    }, $class;
+
+    if ( $fileSize > 0 && $compress ) {
+        open(my $fh, "<", $fileName) || return -2;
+        binmode($fh);
+        return -3 if ( read($fh, $data, 1) != 1 );
+        if ( $data eq chr(0x78) && $doCache && $checksumSeed == 32761 ) {
+            #
+            # 32761 is the magic number that rsync uses for checksumSeed
+            # with the --fixed-csum option.
+            #
+            # We now add the cached checksum data to the file.  There
+            # is a possible race condition here since two BackupPC_dump
+            # processes might call this function at the same time
+            # on the same file.  But this should be ok since both
+            # processes will write the same data, and the order
+            # in which they write it doesn't matter.
+            #
+            close($fh);
+            $fio->digestAdd($fileName,
+                    $blockSize
+                       || BackupPC::Xfer::RsyncDigest->blockSize($fileSize,
+                                                           $defBlkSize),
+                    $checksumSeed);
+            #
+            # now re-open the file and re-read the first byte
+            #
+            open($fh, "<", $fileName) || return -2;
+            binmode($fh);
+            return -3 if ( read($fh, $data, 1) != 1 );
+        }
+        if ( $data eq chr(0xd6) ) {
+            #
+            # Looks like this file has cached checksums
+            # Read the last 48 bytes: that's 2 file MD4s (32 bytes)
+            # plus 4 words of meta data
+            #
+            return -4 if ( !defined(seek($fh, -48, 2)) ); 
+            return -5 if ( read($fh, $data, 48) != 48 );
+            ($fio->{md4DigestOld},
+             $fio->{md4Digest},
+             $fio->{blockSize},
+             $fio->{checksumSeed},
+             $fio->{nBlocks},
+             $fio->{magic}) = unpack("a16 a16 V V V V", $data);
+            if ( $fio->{magic} == 0x5fe3c289
+                    && $fio->{checksumSeed} == $checksumSeed
+                    && ($blockSize == 0 || $fio->{blockSize} == $blockSize) ) {
+                $fio->{fh}     = $fh;
+                $fio->{cached} = 1;
+            } else {
+                close($fh);
+            }
+            #
+            # position the file at the start of the rsync block checksums
+            # (4 (adler) + 16 (md4) bytes each)
+            #
+            return -6 if ( !defined(seek($fh, -$fio->{nBlocks}*20 - 48, 2)) );
+        }
+    }
+    if ( !$fio->{cached} ) {
+        #
+        # This file doesn't have cached checksums, or the checksumSeed
+        # or blocksize doesn't match.  Open the file and prepare to
+        # compute the checksums.
+        #
+        $blockSize
+           = BackupPC::Xfer::RsyncDigest->blockSize($fileSize, $defBlkSize)
+                                   if ( $blockSize == 0 );
+        $fio->{checksumSeed} = $checksumSeed;
+        $fio->{blockSize}    = $blockSize;
+        $fio->{fh} = BackupPC::FileZIO->open($fileName, 0, $compress);
+        return -7 if ( !defined($fio->{fh}) );
+        if ( $needMD4) {
+            $fio->{csumDigest} = File::RsyncP::Digest->new;
+            $fio->{csumDigest}->add(pack("V", $fio->{checksumSeed}));
+        }
+    }
+    return (undef, $fio, $fio->{blockSize});
+}
+
+sub digestGet
+{
+    my($fio, $num, $csumLen) = @_;
+    my($fileData);
+    my $blockSize = $fio->{blockSize};
+
+    if ( $fio->{cached} ) {
+        my $thisNum = $num;
+        $thisNum = $fio->{nBlocks} if ( $thisNum > $fio->{nBlocks} );
+        read($fio->{fh}, $fileData, 20 * $thisNum);
+        $fio->{nBlocks} -= $thisNum;
+        if ( $thisNum < $num ) {
+            #
+            # unexpected shortfall of data; pad with zero digest
+            #
+            $fileData .= pack("c", 0) x (20 * ($num - $thisNum));
+        }
+        return $fio->{digest}->blockDigestExtract($fileData, $csumLen);
+    } else {
+        if ( $fio->{fh}->read(\$fileData, $blockSize * $num) <= 0 ) {
+            #
+            # unexpected shortfall of data; pad with zeros
+            #
+            $fileData = pack("c", 0) x ($blockSize * $num);
+        }
+        $fio->{csumDigest}->add($fileData) if ( $fio->{needMD4} );
+        return $fio->{digest}->blockDigest($fileData, $blockSize,
+                                           $csumLen, $fio->{checksumSeed});
+    }
+}
+
+sub digestEnd
+{
+    my($fio) = @_;
+    my($fileData);
+
+    if ( $fio->{cached} ) {
+        close($fio->{fh});
+        return $fio->{md4DigestOld} if ( $fio->{needMD4} );
+    } else {
+        #
+        # make sure we read the entire file for the file MD4 digest
+        #
+        if ( $fio->{needMD4} ) {
+            my $fileData;
+            while ( $fio->{fh}->read(\$fileData, 65536) > 0 ) {
+                $fio->{csumDigest}->add($fileData);
+            }
+        }
+        $fio->{fh}->close();
+        return $fio->{csumDigest}->digest if ( $fio->{needMD4} );
+    }
+}
+
+1;
index db43a5d..3a0e826 100644 (file)
@@ -12,7 +12,7 @@
 #
 #========================================================================
 #
-# Version 2.1.0_CVS, released 8 Feb 2004.
+# Version 2.1.0_CVS, released 13 Mar 2004.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -24,9 +24,8 @@ use strict;
 use File::Path;
 use BackupPC::Attrib qw(:all);
 use BackupPC::View;
-use BackupPC::RsyncDigest;
+use BackupPC::Xfer::RsyncDigest;
 use BackupPC::PoolWrite;
-use Data::Dumper;
 
 use constant S_IFMT       => 0170000;  # type of file
 use constant S_IFDIR      => 0040000;  # directory
@@ -112,9 +111,9 @@ sub csumStart
     $fio->csumEnd if ( defined($fio->{csum}) );
     return -1 if ( $attr->{type} != BPC_FTYPE_FILE );
     (my $err, $fio->{csum}, my $blkSize)
-         = BackupPC::RsyncDigest->digestStart($attr->{fullPath}, $attr->{size},
-                         0, $defBlkSize, $fio->{checksumSeed}, $needMD4,
-                         $attr->{compress}, 1);
+         = BackupPC::Xfer::RsyncDigest->digestStart($attr->{fullPath},
+                        $attr->{size}, 0, $defBlkSize, $fio->{checksumSeed},
+                        $needMD4, $attr->{compress}, 1);
     if ( $err ) {
         $fio->log("Can't get rsync digests from $attr->{fullPath}"
                 . " (err=$err, name=$f->{name})");
@@ -878,6 +877,7 @@ sub fileDeltaRxDone
 {
     my($fio, $md4) = @_;
     my $name = $1 if ( $fio->{rxFile}{name} =~ /(.*)/ );
+    my $ret;
 
     close($fio->{rxInFd})  if ( defined($fio->{rxInFd}) );
     unlink("$fio->{outDirSh}RStmp") if  ( -f "$fio->{outDirSh}RStmp" );
@@ -899,7 +899,7 @@ sub fileDeltaRxDone
                 # fetch the md4 file digest, not the block digests.
                 #
                 my($err, $csum, $blkSize)
-                         = BackupPC::RsyncDigest->digestStart(
+                         = BackupPC::Xfer::RsyncDigest->digestStart(
                                  $attr->{fullPath}, $attr->{size},
                                  0, 2048, $fio->{checksumSeed}, 1,
                                  $attr->{compress});
@@ -935,6 +935,8 @@ sub fileDeltaRxDone
                 $fio->{rxOutFd}->close;
                 unlink($fio->{rxOutFile});
             }
+            delete($fio->{rxFile});
+           delete($fio->{rxOutFile});
             return 1;
         }
     }
@@ -976,32 +978,34 @@ sub fileDeltaRxDone
             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->{rxSize};
-           $fio->{stats}{ExistFileCnt}++;
-           $fio->{stats}{ExistFileSize} += $fio->{rxSize};
-           $fio->{stats}{ExistFileCompSize} += -s $rxOutFile;
-           $fio->{rxFile}{size} = $fio->{rxSize};
-           return $fio->attribSet($fio->{rxFile});
+               $ret = -1;
+            } else {
+               #
+               # Cumulate the stats
+               #
+               $fio->{stats}{TotalFileCnt}++;
+               $fio->{stats}{TotalFileSize} += $fio->{rxSize};
+               $fio->{stats}{ExistFileCnt}++;
+               $fio->{stats}{ExistFileSize} += $fio->{rxSize};
+               $fio->{stats}{ExistFileCompSize} += -s $rxOutFile;
+               $fio->{rxFile}{size} = $fio->{rxSize};
+               $ret = $fio->attribSet($fio->{rxFile});
+           }
         }
-    }
-    if ( defined($fio->{rxOutFd}) ) {
+    } else {
        my $exist = $fio->processClose($fio->{rxOutFd},
                                       $fio->{rxOutFileRel},
                                       $fio->{rxSize}, 1);
        $fio->logFileAction($exist ? "pool" : "create", $fio->{rxFile})
                            if ( $fio->{logLevel} >= 1 );
        $fio->{rxFile}{size} = $fio->{rxSize};
-       return $fio->attribSet($fio->{rxFile});
+       $ret = $fio->attribSet($fio->{rxFile});
     }
     delete($fio->{rxDigest});
     delete($fio->{rxInData});
-    return;
+    delete($fio->{rxFile});
+    delete($fio->{rxOutFile});
+    return $ret;
 }
 
 #
@@ -1101,10 +1105,22 @@ sub finish
 {
     my($fio, $isChild) = @_;
 
+    #
+    # If we are aborting early, remove the last file since
+    # it was not complete
+    #
+    if ( $isChild && defined($fio->{rxFile}) ) {
+       unlink("$fio->{outDirSh}RStmp") if  ( -f "$fio->{outDirSh}RStmp" );
+       if ( defined($fio->{rxFile}) ) {
+           unlink($fio->{rxOutFile});
+           $fio->log("finish: removing in-process file $fio->{rxFile}{name}");
+       }
+    }
+
     #
     # Flush the attributes if this is the child
     #
-    $fio->attribWrite(undef);
+    $fio->attribWrite(undef) if ( $isChild );
 }
 
 #sub is_tainted
index 7cee1ef..3d6dd52 100644 (file)
@@ -29,7 +29,7 @@
 #
 #========================================================================
 #
-# Version 2.1.0_CVS, released 8 Feb 2004.
+# Version 2.1.0_CVS, released 13 Mar 2004.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -231,12 +231,14 @@ sub readOutput
        # ignore the log file time stamps from smbclient introduced
        # in version 3.0.0 - don't even write them to the log file.
        #
-       next if ( m{^\[\d+/\d+/\d+ +\d+:\d+:\d+.*\] +(client/cli|lib/util_unistr).*\(\d+\)} );
-        $t->{XferLOG}->write(\"$_\n");
+       if ( m{^\[\d+/\d+/\d+ +\d+:\d+:\d+.*\] +(client/cli|lib/util_unistr).*\(\d+\)} ) {
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 5 );
+            next;
+        }
         #
         # refresh our inactivity alarm
         #
-        alarm($conf->{ClientTimeout});
+        alarm($conf->{ClientTimeout}) if ( !$t->{abort} );
         $t->{lastOutputLine} = $_ if ( !/^$/ );
         #
         # This section is highly dependent on the version of smbclient.
@@ -250,15 +252,20 @@ sub readOutput
             $fileName =~ s/^\/*//;
             $t->{byteCnt} += $sambaFileSize;
             $t->{fileCnt}++;
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 2 );
         } elsif ( /restore tar file (.*) of size (\d+) bytes/ ) {
             $t->{byteCnt} += $2;
             $t->{fileCnt}++;
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 1 );
         } elsif ( /^\s*tar: dumped \d+ files/ ) {
             $t->{xferOK} = 1;
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
         } elsif ( /^\s*tar: restored \d+ files/ ) {
             $t->{xferOK} = 1;
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
         } elsif ( /^\s*read_socket_with_timeout: timeout read. /i ) {
             $t->{hostAbort} = 1;
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
         } elsif ( /^code 0 listing /
                     || /^\s*code 0 opening /
                     || /^\s*abandoning restore/i
@@ -272,6 +279,7 @@ sub readOutput
                $t->{XferLOG}->write(\"This backup will fail because: $_\n");
                $t->{hostError} = $_;
            }
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
         } elsif ( /^\s*NT_STATUS_ACCESS_DENIED listing (.*)/
               || /^\s*ERRDOS - ERRnoaccess \(Access denied\.\) listing (.*)/ ) {
            my $badDir = $1;
@@ -283,6 +291,9 @@ sub readOutput
                $t->{XferLOG}->write(\"This backup will fail because: $_\n");
                $t->{hostError} ||= $_;
            }
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
+        } elsif ( /^\s*directory \\/i ) {
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 2 );
         } elsif ( /smb: \\>/
                 || /^\s*added interface/i
                 || /^\s*tarmode is now/i
@@ -290,13 +301,13 @@ sub readOutput
                 || /^\s*Domain=/i
                 || /^\([\d\.]* kb\/s\) \(average [\d\.]* kb\/s\)$/i
                 || /^\s*Getting files newer than/i
-                || /^\s*directory \\/i
                || /^\s*restore directory \\/i
                 || /^\s*Output is \/dev\/null/i
                 || /^\s*Timezone is/i
                 || /^\s*creating lame (up|low)case table/i
            ) {
             # ignore these messages
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 1 );
         } else {
             $t->{xferErrCnt}++;
             $t->{xferBadShareCnt}++ if ( /^ERRDOS - ERRbadshare/ );
@@ -329,11 +340,20 @@ sub readOutput
                        file  => $badFile
                    });
             }
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 1 );
         }
     }
     return 1;
 }
 
+sub abort
+{
+    my($t, $reason) = @_;
+
+    $t->{abort} = 1;
+    $t->{abortReason} = $reason;
+}
+
 sub setSelectMask
 {
     my($t, $FDreadRef) = @_;
index 576b5ae..8c05492 100644 (file)
@@ -222,17 +222,19 @@ sub readOutput
     while ( $t->{tarOut} =~ /(.*?)[\n\r]+(.*)/s ) {
         $_ = $1;
         $t->{tarOut} = $2;
-        $t->{XferLOG}->write(\"$_\n");
         #
         # refresh our inactivity alarm
         #
-        alarm($conf->{ClientTimeout});
+        alarm($conf->{ClientTimeout}) if ( !$t->{abort} );
         $t->{lastOutputLine} = $_ if ( !/^$/ );
         if ( /^Total bytes written: / ) {
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 1 );
             $t->{xferOK} = 1;
         } elsif ( /^\./ ) {
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 2 );
             $t->{fileCnt}++;
         } else {
+            $t->{XferLOG}->write(\"$_\n") if ( $t->{logLevel} >= 0 );
             $t->{xferErrCnt}++;
            #
            # If tar encounters a minor error, it will exit with a non-zero
@@ -241,11 +243,34 @@ sub readOutput
            #
            $t->{tarBadExitOk} = 1
                    if ( $t->{xferOK} && /Error exit delayed from previous / );
+            #
+            # Also remember files that had read errors
+            #
+            if ( /: \.\/(.*): Read error at byte / ) {
+                my $badFile = $1;
+                push(@{$t->{badFiles}}, {
+                        share => $t->{shareName},
+                        file  => $badFile
+                    });
+            }
+
        }
     }
     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) = @_;
index 7492a03..0a54477 100755 (executable)
--- a/makeDist
+++ b/makeDist
@@ -16,7 +16,7 @@
 #   Craig Barratt <cbarratt@users.sourceforge.net>
 #
 # COPYRIGHT
-#   Copyright (C) 2001-2003  Craig Barratt
+#   Copyright (C) 2001-2004  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
@@ -43,7 +43,7 @@ use Getopt::Std;
 umask(0022);
 
 my $Version     = "2.1.0_CVS";
-my $ReleaseDate = "8 Feb 2004";
+my $ReleaseDate = "13 Mar 2004";
 my $DistDir     = "dist/BackupPC-$Version";
 
 my @PerlSrc = qw(
@@ -96,6 +96,7 @@ my @PerlSrc = qw(
     lib/BackupPC/Xfer/Smb.pm
     lib/BackupPC/Xfer/Tar.pm
     lib/BackupPC/Xfer/Rsync.pm
+    lib/BackupPC/Xfer/RsyncDigest.pm
     lib/BackupPC/Xfer/RsyncFileIO.pm
     lib/BackupPC/Zip/FileMember.pm
     cgi-bin/BackupPC_Admin
@@ -130,6 +131,7 @@ $ConfVars->{CgiImageDir}  = 2;
 $ConfVars->{BlackoutHourBegin} = 2;
 $ConfVars->{BlackoutHourEnd}   = 2;
 $ConfVars->{BlackoutWeekDays}  = 2;
+$ConfVars->{RsyncLogLevel}     = 2;
 
 foreach my $file ( @PerlSrc ) {
     $errCnt += CheckConfigParams($file, $ConfVars, 1);