charset to utf-8. Also changed bin/BackupPC_sendEmail to not send
any per-client email if $Conf{BackupsDisable} is set.
+* Modified bin/BackupPC_dump to fix the case of a single partial
+ backup followed by a successful incremental resulting in a full
+ backup of level 1, rather than level 0. Reported by Jeff
+ Kosowsky.
+
+* Fixed BackupPC::PoolWrite to always create the parent directory.
+ This fixed a case with rsync/rsyncd where a file like "-i" in the
+ top-level directory sorts before ".", which meant the directory
+ creation is after the file creation. Also PoolWrite errors now
+ increment xferError count. Reported by Jeff Kosowsky.
+
+* BackupPC now gives a more useful error message if BackupPC_nightly
+ takes more than 24 hours (ie: when the next one is meant to
+ start). Reported by Tony Schreiner.
+
* Added server message for queuing a single host based on patch
submitted by Joe Digilio.
$CmdQueueOn{$bpc->trashJob} = 1;
}
if ( $RunNightlyWhenIdle == 1 ) {
-
#
# Queue multiple nightly jobs based on the configuration
#
$start = $start0 + int(($end - $start0)
* ($i + 1) / $Conf{MaxBackupPCNightlyJobs});
push(@$cmd, $start - 1);
-
my $job = $bpc->adminJob($i);
unshift(@CmdQueue, {
host => $job,
# Remember to run the nightly script when the next CmdQueue
# job is done.
#
- $RunNightlyWhenIdle = 1;
+ if ( $RunNightlyWhenIdle == 2 ) {
+ print(LOG $bpc->timeStamp, "BackupPC_nightly is still running after 24 hours!!"
+ . " You should adjust the config settings; Skipping this run\n");
+ } else {
+ $RunNightlyWhenIdle = 1;
+ }
}
#
# Write out the current status and then queue all the PCs
#
# Decide whether we do nothing, or a full or incremental backup.
#
-if ( @Backups == 0
+if ( $lastFullTime == 0
|| $opts{f}
|| (!$opts{i} && (time - $lastFullTime > $Conf{FullPeriod} * 24*3600
&& time - $lastIncrTime > $Conf{IncrPeriod} * 24*3600)) ) {
# used by configure.pl when you upgrade BackupPC.
#
# Example:
-# $Conf{CgiImageDir} = '/usr/local/apache/htdocs/BackupPC';
+# $Conf{CgiImageDir} = '/var/www/htdocs/BackupPC';
#
$Conf{CgiImageDir} = '';
print <<EOF;
-BackupPC's CGI script needs to display various GIF images that
-should be stored where Apache can serve them. They should be
-placed somewhere under Apache's DocumentRoot. BackupPC also
-needs to know the URL to access these images. Example:
+BackupPC's CGI script needs to display various PNG/GIF images that
+should be stored where Apache can serve them. They should be placed
+somewhere under Apache's DocumentRoot. BackupPC also needs to know
+the URL to access these images. Example:
- Apache image directory: /usr/local/apache/htdocs/BackupPC
+ Apache image directory: /var/www/htdocs/BackupPC
URL for image directory: /BackupPC
The URL for the image directory should start with a slash.
Example:
- --html-dir /usr/local/apache/htdocs/BackupPC
+ --html-dir /var/www/htdocs/BackupPC
=item B<--html-dir-url URL>
my($data) = $a->writeData;
$file = $a->fileName($dir, $file);
- mkpath($dir, 0, 0777) if ( !-d $dir );
+ if ( !-d $dir ) {
+ eval { mkpath($dir, 0, 0777) };
+ if ( $@ ) {
+ $a->{_errStr} = "Can't create directory $dir";
+ return;
+ }
+ }
my $fd = BackupPC::FileZIO->open($file, 1, $a->{compress});
if ( !$fd ) {
$a->{_errStr} = "Can't open/write to $file";
#
#========================================================================
#
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
#
# See http://backuppc.sourceforge.net.
#
[ \%restoreReq],
[qw(*RestoreReq)]);
$dump->Indent(1);
- mkpath("$TopDir/pc/$hostDest", 0, 0777)
+ eval { mkpath("$TopDir/pc/$hostDest", 0, 0777) }
if ( !-d "$TopDir/pc/$hostDest" );
my $openPath = "$TopDir/pc/$hostDest/$reqFileName";
if ( open(REQ, ">", $openPath) ) {
my($i, $f);
return if ( !-e $file );
- mkpath($trashDir, 0, 0777) if ( !-d $trashDir );
+ if ( !-d $trashDir ) {
+ eval { mkpath($trashDir, 0, 0777) };
+ if ( $@ ) {
+ #
+ # There's no good place to send this error - use stderr
+ #
+ print(STDERR "RmTreeDefer: can't create directory $trashDir");
+ }
+ }
for ( $i = 0 ; $i < 1000 ; $i++ ) {
$f = sprintf("%s/%d_%d_%d", $trashDir, time, $$, $i);
next if ( -e $f );
} elsif ( $newFile && -f $name && (stat($name))[3] == 1 ) {
my($newDir);
($newDir = $rawFile) =~ s{(.*)/.*}{$1};
- mkpath($newDir, 0, 0777) if ( !-d $newDir );
+ if ( !-d $newDir ) {
+ eval { mkpath($newDir, 0, 0777) };
+ return -5 if ( $@ );
+ }
return -4 if ( !link($name, $rawFile) );
return 2;
} else {
#
#========================================================================
#
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
#
# See http://backuppc.sourceforge.net.
#
# Always unlink any current file in case it is already linked
#
unlink($fileName) if ( -f $fileName );
+ if ( $fileName =~ m{(.*)/.+} && !-d $1 ) {
+ eval { mkpath($1, 0, 0777) };
+ if ( $@ ) {
+ push(@{$self->{errors}}, "Unable to create directory $1 for $self->{fileName}");
+ }
+ }
return $self;
}
if ( !defined($a->{base} = $a->{bpc}->MD52Path($a->{digest},
$a->{compress})) ) {
push(@{$a->{errors}}, "Unable to get path from '$a->{digest}'"
- . " for $a->{fileName}\n");
+ . " for $a->{fileName}");
} else {
while ( @{$a->{files}} < $MaxFiles ) {
my $fh;
1, $a->{compress});
if ( !defined($a->{fhOut}) ) {
push(@{$a->{errors}}, "Unable to open $a->{fileName}"
- . " for writing\n");
+ . " for writing");
}
}
}
if ( !$a->{files}[$i]->{fh}->rewind() ) {
push(@{$a->{errors}},
"Unable to rewind $a->{files}[$i]->{name}"
- . " for compare\n");
+ . " for compare");
}
$match = $a->filePartialCompare($a->{files}[$i]->{fh}, $fh,
$a->{nWrite}, $dataLen, \$a->{data});
if ( !defined($a->{fhOut}) ) {
push(@{$a->{errors}},
"Unable to open $a->{fileName}"
- . " for writing\n");
+ . " for writing");
} else {
if ( !$a->{files}[$i]->{fh}->rewind() ) {
push(@{$a->{errors}},
"Unable to rewind"
- . " $a->{files}[$i]->{name} for copy\n");
+ . " $a->{files}[$i]->{name} for copy");
}
$a->filePartialCopy($a->{files}[$i]->{fh}, $a->{fhOut},
$a->{nWrite});
my $n = $a->{fhOut}->write(\$a->{data});
if ( $n != $dataLen ) {
push(@{$a->{errors}}, "Unable to write $dataLen bytes to"
- . " $a->{fileName} (got $n)\n");
+ . " $a->{fileName} (got $n)");
}
}
$a->{nWrite} += $dataLen;
|| !defined($fh = BackupPC::FileZIO->open($fileName, 0,
$a->{compress})) ) {
push(@{$a->{errors}}, "Can't rename $a->{fileName} -> $fileName"
- . " or open during size fixup\n");
+ . " or open during size fixup");
}
#print("Using temporary name $fileName\n");
} elsif ( defined($a->{files}) && defined($a->{files}[0]) ) {
if ( $n != $thisRead ) {
push(@{$a->{errors}},
"Unable to read $thisRead bytes during resize"
- . " from temp $fileName (got $n)\n");
+ . " from temp $fileName (got $n)");
last;
}
$poolWrite->write(\$data);
local(*OUT);
if ( !open(OUT, ">", $a->{fileName}) ) {
push(@{$a->{errors}}, "Can't open $a->{fileName} for empty"
- . " output\n");
+ . " output");
} else {
close(OUT);
}
} else {
if ( @{$a->{files}} == 0 ) {
push(@{$a->{errors}}, "Botch, no matches on $a->{fileName}"
- . " ($a->{digest})\n");
+ . " ($a->{digest})");
} elsif ( @{$a->{files}} > 1 ) {
#
# This is no longer a real error because $Conf{HardLinkMax}
if ( !$a->{files}[$i]->{fh}->rewind() ) {
push(@{$a->{errors}},
"Unable to rewind $a->{files}[$i]->{name}"
- . " for copy after link fail\n");
+ . " for copy after link fail");
next;
}
$a->{fhOut} = BackupPC::FileZIO->open($a->{fileName},
if ( !defined($a->{fhOut}) ) {
push(@{$a->{errors}},
"Unable to open $a->{fileName}"
- . " for writing after link fail\n");
+ . " for writing after link fail");
} else {
$a->filePartialCopy($a->{files}[$i]->{fh}, $a->{fhOut},
$a->{nWrite});
if ( $n != $thisRead ) {
push(@{$a->{errors}},
"Unable to read $thisRead bytes from "
- . $fhIn->name . " (got $n)\n");
+ . $fhIn->name . " (got $n)");
return;
}
$n = $fhOut->write(\$data, $thisRead);
if ( $n != $thisRead ) {
push(@{$a->{errors}},
"Unable to write $thisRead bytes to "
- . $fhOut->name . " (got $n)\n");
+ . $fhOut->name . " (got $n)");
return;
}
$nRead += $thisRead;
$n = $fh0->read(\$data0, $thisRead);
if ( $n != $thisRead ) {
push(@{$a->{errors}}, "Unable to read $thisRead bytes from "
- . $fh0->name . " (got $n)\n");
+ . $fh0->name . " (got $n)");
return;
}
$n = $fh1->read(\$data1, $thisRead);
#
#========================================================================
#
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
#
# See http://backuppc.sourceforge.net.
#
(my $dir = $file) =~ s{(.+)/(.+)}{$1};
- mkpath($dir, 0, 0775) if ( !-d $dir );
+ if ( !-d $dir ) {
+ eval { mkpath($dir, 0, 0775) };
+ return "TextFileWrite: can't create directory $dir" if ( $@ );
+ }
if ( open(FD, ">", "$file.new") ) {
binmode(FD);
print FD $contents;
#
#========================================================================
#
-# Version 3.1.0, released 25 Nov 2007.
+# Version 3.2.0, released 31 Dec 2008.
#
# See http://backuppc.sourceforge.net.
#
$t->{hostError} = $err;
return;
}
+
+ #
+ # This is a hack. To avoid wide chars we encode the arguments
+ # to utf8 byte streams, then to the client's local charset.
+ # The second conversion should really go in File::RsyncP, since
+ # it shouldn't be applied to in-line include/exclude arguments.
+ #
+ for ( my $i = 0 ; $i < @{$rs->{rsyncArgs}} ; $i++ ) {
+ $rs->{rsyncArgs}[$i] = encode('utf8', $rs->{rsyncArgs}[$i]);
+ from_to($rs->{rsyncArgs}[$i], 'utf8', $conf->{ClientCharset})
+ if ( $conf->{ClientCharset} ne "" );
+ }
+
+ my $str = "RsyncArgsBefore: " . join(" ", @{$rs->{rsyncArgs}}) . "\n";
+ $t->{XferLOG}->write(\$str);
+
$rs->serverStart($remoteSend, $remoteDirDaemon);
+
+ my $str = "RsyncArgsAfter: " . join(" ", @{$rs->{rsyncArgs}}) . "\n";
+ $t->{XferLOG}->write(\$str);
}
my $shareNameSlash = $t->{shareNameSlash};
from_to($shareNameSlash, "utf8", $conf->{ClientCharset})
my($exists, $digest, $outSize, $errs) = $poolWrite->close;
$fileName =~ s{^/+}{};
- $fio->log(@$errs) if ( defined($errs) && @$errs );
+ if ( defined($errs) && @$errs ) {
+ $fio->log(@$errs);
+ $fio->{stats}{errorCnt} += @$errs;
+ }
if ( $doStats ) {
$fio->{stats}{TotalFileCnt}++;
$fio->{stats}{TotalFileSize} += $origSize;
$fio->logFileAction("create", $f) if ( $fio->{logLevel} >= 1 );
$fio->log("makePath($path, 0777)") if ( $fio->{logLevel} >= 5 );
$path = $1 if ( $path =~ /(.*)/s );
- File::Path::mkpath($path, 0, 0777) if ( !-d $path );
+ eval { File::Path::mkpath($path, 0, 0777) } if ( !-d $path );
return $fio->attribSet($f) if ( -d $path );
$fio->log("Can't create directory $path");
$fio->{stats}{errorCnt}++;