# Craig Barratt <cbarratt@users.sourceforge.net>
#
# COPYRIGHT
-# Copyright (C) 2004 Craig Barratt
+# Copyright (C) 2004-2009 Craig Barratt
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
#
#========================================================================
#
-# Version 2.1.0, released 20 Jun 2004.
+# Version 3.2.0beta0, released 5 April 2009.
#
# See http://backuppc.sourceforge.net.
#
close(BK_INFO);
}
close(LOCK);
+ #
+ # Default the version field. Prior to 3.0.0 the xferMethod
+ # field is empty, so we use that to figure out the version.
+ #
+ for ( my $i = 0 ; $i < @Backups ; $i++ ) {
+ next if ( $Backups[$i]{version} ne "" );
+ if ( $Backups[$i]{xferMethod} eq "" ) {
+ $Backups[$i]{version} = "2.1.2";
+ } else {
+ $Backups[$i]{version} = "3.0.0";
+ }
+ }
return @Backups;
}
#
# Write the file
#
- return $s->TextFileWrite("$s->{TopDir}/pc/$host", "backups", $contents);
+ return $s->TextFileWrite("$s->{TopDir}/pc/$host/backups", $contents);
}
sub RestoreInfoRead
#
# Write the file
#
- return $s->TextFileWrite("$s->{TopDir}/pc/$host", "restores", $contents);
+ return $s->TextFileWrite("$s->{TopDir}/pc/$host/restores", $contents);
}
sub ArchiveInfoRead
#
# Write the file
#
- return $s->TextFileWrite("$s->{TopDir}/pc/$host", "archives", $contents);
+ return $s->TextFileWrite("$s->{TopDir}/pc/$host/archives", $contents);
}
#
#
sub TextFileWrite
{
- my($s, $dir, $file, $contents) = @_;
+ my($s, $file, $contents) = @_;
local(*FD, *LOCK);
my($fileOk);
- mkpath($dir, 0, 0775) if ( !-d $dir );
- if ( open(FD, ">", "$dir/$file.new") ) {
+ (my $dir = $file) =~ s{(.+)/(.+)}{$1};
+
+ 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;
close(FD);
#
# verify the file
#
- if ( open(FD, "<", "$dir/$file.new") ) {
+ if ( open(FD, "<", "$file.new") ) {
binmode(FD);
if ( join("", <FD>) ne $contents ) {
- return "TextFileWrite: Failed to verify $dir/$file.new";
+ return "TextFileWrite: Failed to verify $file.new";
} else {
$fileOk = 1;
}
$lock = 1;
flock(LOCK, LOCK_EX);
}
- if ( -s "$dir/$file" ) {
- unlink("$dir/$file.old") if ( -f "$dir/$file.old" );
- rename("$dir/$file", "$dir/$file.old") if ( -f "$dir/$file" );
+ if ( -s "$file" ) {
+ unlink("$file.old") if ( -f "$file.old" );
+ rename("$file", "$file.old") if ( -f "$file" );
} else {
- unlink("$dir/$file") if ( -f "$dir/$file" );
+ unlink("$file") if ( -f "$file" );
}
- rename("$dir/$file.new", "$dir/$file") if ( -f "$dir/$file.new" );
+ rename("$file.new", "$file") if ( -f "$file.new" );
close(LOCK) if ( $lock );
} else {
- return "TextFileWrite: Failed to write $dir/$file.new";
+ return "TextFileWrite: Failed to write $file.new";
}
return;
}
+sub ConfigPath
+{
+ my($s, $host) = @_;
+
+ return "$s->{ConfDir}/config.pl" if ( !defined($host) );
+ if ( $s->{useFHS} ) {
+ return "$s->{ConfDir}/pc/$host.pl";
+ } else {
+ return "$s->{TopDir}/pc/$host/config.pl"
+ if ( -f "$s->{TopDir}/pc/$host/config.pl" );
+ return "$s->{ConfDir}/$host.pl"
+ if ( $host ne "config" && -f "$s->{ConfDir}/$host.pl" );
+ return "$s->{ConfDir}/pc/$host.pl";
+ }
+}
+
sub ConfigDataRead
{
my($s, $host) = @_;
# TODO: add lock
#
my $conf = {};
+ my $configPath = $s->ConfigPath($host);
- if ( defined($host) ) {
- push(@configs, "$s->{TopDir}/conf/$host.pl")
- if ( $host ne "config" && -f "$s->{TopDir}/conf/$host.pl" );
- push(@configs, "$s->{TopDir}/pc/$host/config.pl")
- if ( -f "$s->{TopDir}/pc/$host/config.pl" );
- } else {
- push(@configs, "$s->{TopDir}/conf/config.pl");
- }
+ push(@configs, $configPath) if ( -f $configPath );
foreach $config ( @configs ) {
%Conf = ();
if ( !defined($ret = do $config) && ($! || $@) ) {
}
%$conf = ( %$conf, %Conf );
}
+
#
# Promote BackupFilesOnly and BackupFilesExclude to hashes
#
$conf->{$param} = { "*" => $conf->{$param} };
}
+ #
+ # Handle backward compatibility with defunct BlackoutHourBegin,
+ # BlackoutHourEnd, and BlackoutWeekDays parameters.
+ #
+ if ( defined($conf->{BlackoutHourBegin}) ) {
+ push(@{$conf->{BlackoutPeriods}},
+ {
+ hourBegin => $conf->{BlackoutHourBegin},
+ hourEnd => $conf->{BlackoutHourEnd},
+ weekDays => $conf->{BlackoutWeekDays},
+ }
+ );
+ delete($conf->{BlackoutHourBegin});
+ delete($conf->{BlackoutHourEnd});
+ delete($conf->{BlackoutWeekDays});
+ }
+
return (undef, $conf);
}
{
my($s, $host, $newConf) = @_;
- my($confDir) = $host eq "" ? "$s->{TopDir}/conf"
- : "$s->{TopDir}/pc/$host";
+ my $configPath = $s->ConfigPath($host);
- my($err, $contents) = $s->ConfigFileMerge("$confDir/config.pl", $newConf);
+ my($err, $contents) = $s->ConfigFileMerge("$configPath", $newConf);
if ( defined($err) ) {
return $err;
} else {
#
# Write the file
#
- return $s->TextFileWrite($confDir, "config.pl", $contents);
+ return $s->TextFileWrite($configPath, $contents);
}
}
{
my($s, $inFile, $newConf) = @_;
local(*C);
- my($contents, $out);
- my $comment = 1;
- my $skipVar = 0;
- my $endLine = undef;
+ my($contents, $skipExpr, $fakeVar);
my $done = {};
if ( -f $inFile ) {
binmode(C);
while ( <C> ) {
- if ( $comment && /^\s*#/ ) {
- $out .= $_;
- } elsif ( /^\s*\$Conf\{([^}]*)\}\s*=/ ) {
+ if ( /^\s*\$Conf\{([^}]*)\}\s*=(.*)/ ) {
my $var = $1;
- if ( exists($newConf->{$var}) ) {
- $contents .= $out;
+ $skipExpr = "\$fakeVar = $2\n";
+ if ( exists($newConf->{$var}) ) {
my $d = Data::Dumper->new([$newConf->{$var}], [*value]);
$d->Indent(1);
$d->Terse(1);
$contents .= "\$Conf{$var} = " . $value;
$done->{$var} = 1;
}
- $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<(.*);/ );
- $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<'(.*)';/ );
- $out = "";
- $skipVar = 1;
- } elsif ( $skipVar ) {
- if ( !defined($endLine) && (/^\s*[\r\n]*$/ || /^\s*#/) ) {
- $skipVar = 0;
- $comment = 1;
- $out .= $_;
- }
- if ( defined($endLine) && /^\Q$endLine\E[\n\r]*$/ ) {
- $endLine = undef;
- $skipVar = 0;
- $comment = 1;
- }
+ } elsif ( defined($skipExpr) ) {
+ $skipExpr .= $_;
} else {
- $out .= $_;
+ $contents .= $_;
+ }
+ if ( defined($skipExpr)
+ && ($skipExpr =~ /^\$fakeVar = *<</
+ || $skipExpr =~ /;[\n\r]*$/) ) {
+ #
+ # if we have a complete expression, then we are done
+ # skipping text from the original config file.
+ #
+ $skipExpr = $1 if ( $skipExpr =~ /(.*)/s );
+ eval($skipExpr);
+ $skipExpr = undef if ( $@ eq "" );
}
}
close(C);
- $contents .= $out;
}
#
sub ConfigMTime
{
my($s) = @_;
- return (stat("$s->{TopDir}/conf/config.pl"))[9];
+ return (stat($s->ConfigPath()))[9];
}
#
-# Returns information from the host file in $s->{TopDir}/conf/hosts.
+# Returns information from the host file in $s->{ConfDir}/hosts.
# With no argument a ref to a hash of hosts is returned. Each
# hash contains fields as specified in the hosts file. With an
# argument a ref to a single hash is returned with information
my(%hosts, @hdr, @fld);
local(*HOST_INFO, *LOCK);
- flock(LOCK, LOCK_EX) if open(LOCK, "$s->{TopDir}/pc/$host/LOCK");
- if ( !open(HOST_INFO, "$s->{TopDir}/conf/hosts") ) {
- print(STDERR "Can't open $s->{TopDir}/conf/hosts\n");
+ flock(LOCK, LOCK_EX) if open(LOCK, "$s->{ConfDir}/LOCK");
+ if ( !open(HOST_INFO, "$s->{ConfDir}/hosts") ) {
+ print(STDERR "Can't open $s->{ConfDir}/hosts\n");
close(LOCK);
return {};
}
if ( @hdr ) {
if ( defined($host) ) {
next if ( lc($fld[0]) ne lc($host) );
- @{$hosts{$fld[0]}}{@hdr} = @fld;
+ @{$hosts{lc($fld[0])}}{@hdr} = @fld;
close(HOST_INFO);
close(LOCK);
return \%hosts;
} else {
- @{$hosts{$fld[0]}}{@hdr} = @fld;
+ @{$hosts{lc($fld[0])}}{@hdr} = @fld;
}
} else {
@hdr = @fld;
}
#
-# Writes new hosts information to the hosts file in $s->{TopDir}/conf/hosts.
+# Writes new hosts information to the hosts file in $s->{ConfDir}/hosts.
# With no argument a ref to a hash of hosts is returned. Each
# hash contains fields as specified in the hosts file. With an
# argument a ref to a single hash is returned with information
my($gotHdr, @fld, $hostText, $contents);
local(*HOST_INFO);
- if ( !open(HOST_INFO, "$s->{TopDir}/conf/hosts") ) {
- return "Can't open $s->{TopDir}/conf/hosts";
+ if ( !open(HOST_INFO, "$s->{ConfDir}/hosts") ) {
+ return "Can't open $s->{ConfDir}/hosts";
}
foreach my $host ( keys(%$hosts) ) {
my $name = "$hosts->{$host}{host}";
#
# Write and verify the new host file
#
- return $s->TextFileWrite("$s->{TopDir}/conf", "hosts", $contents);
+ return $s->TextFileWrite("$s->{ConfDir}/hosts", $contents);
}
#
sub HostsMTime
{
my($s) = @_;
- return (stat("$s->{TopDir}/conf/hosts"))[9];
+ return (stat("$s->{ConfDir}/hosts"))[9];
}
1;