-#!/bin/perl
+#!/usr/bin/env perl
#============================================================= -*-perl-*-
#
# configure.pl: Configuration and installation program for BackupPC
# Craig Barratt <cbarratt@users.sourceforge.net>
#
# COPYRIGHT
-# Copyright (C) 2001-2006 Craig Barratt
+# Copyright (C) 2001-2010 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 3.0.0alpha, released 23 Jan 2006
+# Version 3.1.0beta0, released 3 Sep 2007.
#
# See http://backuppc.sourceforge.net.
#
no utf8;
use vars qw(%Conf %OrigConf);
use lib "./lib";
+use Encode;
+
+my $EncodeVersion = eval($Encode::VERSION);
+if ( $EncodeVersion < 1.99 ) {
+ print("Error: you need to upgrade perl's Encode package.\n"
+ . "I found $EncodeVersion and BackupPC needs >= 1.99\n"
+ . "Please go to www.cpan.org or use the cpan command.\n");
+ exit(1);
+}
my @Packages = qw(File::Path File::Spec File::Copy DirHandle Digest::MD5
Data::Dumper Getopt::Std Getopt::Long Pod::Usage
if ( $pkg =~ /BackupPC/ ) {
die <<EOF;
-BackupPC cannot find the package $pkg, which is included in the
+Error loading $pkg: $@
+BackupPC cannot load the package $pkg, which is included in the
BackupPC distribution. This probably means you did not cd to the
unpacked BackupPC distribution before running configure.pl, eg:
"cgi-dir=s",
"compress-level=i",
"config-path=s",
+ "config-override=s%",
+ "config-dir=s",
"data-dir=s",
"dest-dir=s",
"fhs!",
"html-dir=s",
"html-dir-url=s",
"install-dir=s",
+ "log-dir=s",
"man",
"set-perms!",
"uid-ignore!",
pod2usage(-exitstatus => 0, -verbose => 2) if $opts{man};
my $DestDir = $opts{"dest-dir"};
+$DestDir = "" if ( $DestDir eq "/" );
if ( !$opts{"uid-ignore"} && $< != 0 ) {
print <<EOF;
# /var/log/BackupPC Pid, status and email info (was $TopDir/log)
#
-print <<EOF if ( !$opts{fhs} || !-f "/etc/BackupPC/config.pl" );
-
-Is this a new installation or upgrade for BackupPC? If this is
-an upgrade please tell me the full path of the existing BackupPC
-configuration file (eg: /etc/BackupPC/config.pl). Otherwise, just
-hit return.
-
-EOF
-
#
# Check if this is an upgrade, in which case read the existing
# config file to get all the defaults.
#
my $ConfigPath = "";
+my $ConfigFileOK = 1;
while ( 1 ) {
- if ( -f "/etc/BackupPC/config.pl" ) {
+ if ( $ConfigFileOK && -f "/etc/BackupPC/config.pl" ) {
$ConfigPath = "/etc/BackupPC/config.pl";
$opts{fhs} = 1 if ( !defined($opts{fhs}) );
+ print <<EOF;
+
+Found /etc/BackupPC/config.pl, so this is an upgrade of an
+existing BackupPC installation. We will verify some existing
+information, but you will probably not need to make any
+changes - just hit ENTER to each question.
+EOF
} else {
+ print <<EOF;
+
+Is this a new installation or upgrade for BackupPC? If this is
+an upgrade please tell me the full path of the existing BackupPC
+configuration file (eg: /etc/BackupPC/config.pl). Otherwise, just
+hit return.
+
+EOF
$ConfigPath = prompt("--> Full path to existing main config.pl",
$ConfigPath,
"config-path");
print("Need to specify a valid --config-path for upgrade\n");
exit(1);
}
+ $ConfigFileOK = 0;
}
$opts{fhs} = 1 if ( !defined($opts{fhs}) && $ConfigPath eq "" );
$opts{fhs} = 0 if ( !defined($opts{fhs}) );
# Create defaults for FHS setup
#
if ( $opts{fhs} ) {
- $Conf{TopDir} ||= "/data/BackupPC";
- $Conf{ConfDir} ||= "/etc/BackupPC";
- $Conf{InstallDir} ||= "/usr/local/BackupPC";
- $Conf{LogDir} ||= "/var/log/BackupPC";
+ $Conf{TopDir} ||= $opts{"data-dir"} || "/data/BackupPC";
+ $Conf{ConfDir} ||= $opts{"config-dir"} || "/etc/BackupPC";
+ $Conf{InstallDir} ||= $opts{"install-dir"} || "/usr/local/BackupPC";
+ $Conf{LogDir} ||= $opts{"log-dir"} || "/var/log/BackupPC";
+} else {
+ $Conf{TopDir} ||= $opts{"data-dir"} || "/data/BackupPC";
+ $Conf{ConfDir} ||= $opts{"config-dir"} || "$Conf{TopDir}/conf";
+ $Conf{InstallDir} ||= $opts{"install-dir"} || "/usr/local/BackupPC";
+ $Conf{LogDir} ||= $opts{"log-dir"} || "$Conf{TopDir}/log";
}
#
foreach my $prog ( sort(keys(%Programs)) ) {
my $path;
foreach my $subProg ( split(/\//, $prog) ) {
- $path = FindProgram("$ENV{PATH}:/bin:/usr/bin:/sbin:/usr/sbin",
+ $path = FindProgram("$ENV{PATH}:/usr/bin:/bin:/sbin:/usr/sbin",
$subProg) if ( !length($path) );
}
$Conf{$Programs{$prog}} = $path if ( !length($Conf{$Programs{$prog}}) );
}
}
-my $Perl56 = system($Conf{PerlPath}
- . q{ -e 'exit($^V && $^V ge v5.6.0 ? 1 : 0);'});
+my $Perl58 = system($Conf{PerlPath}
+ . q{ -e 'exit($^V && $^V ge v5.8.0 ? 1 : 0);'});
-if ( !$Perl56 ) {
+if ( !$Perl58 ) {
print <<EOF;
-BackupPC needs perl version 5.6.0 or later. $Conf{PerlPath} appears
+BackupPC needs perl version 5.8.0 or later. $Conf{PerlPath} appears
to be an older version. Please upgrade to a newer version of perl
and re-run this configure script.
directory (these directories will be setup shortly).
The primary group for this user should also be chosen carefully.
-By default the install directories will have group write permission.
-The data directories and files will have group read permission but
-no other permission.
+The data directories and files will have group read permission,
+so group members can access backup files.
EOF
my($name, $passwd, $Uid, $Gid);
EOF
exit(1) if ( $opts{batch} );
+ } else {
+ last;
}
}
print <<EOF;
-Please specify a data directory for BackupPC. This is where the
-all the PC backup data is stored. This file system needs to be
-big enough to accommodate all the PCs you expect to backup (eg:
-at least several GB per machine).
+Please specify a data directory for BackupPC. This is where all the
+PC backup data is stored. This file system needs to be big enough to
+accommodate all the PCs you expect to backup (eg: at least several GB
+per machine).
EOF
package installed (see www.cpan.org). Compression will provide around a
40% reduction in pool size, at the expense of cpu time. You can leave
compression off and run BackupPC without compression, in which case you
-should leave the compression level at 0 (which means off). You could
-install Compress::Zlib and turn compression on later, but read the
-documentation first about how to do this. Or the better choice is
-to quit, install Compress::Zlib, and re-run configure.pl.
+should leave the compression level at 0 (which means off). Or the better
+choice is to quit, install Compress::Zlib, and re-run configure.pl.
EOF
} elsif ( $Conf{CompressLevel} ) {
print <<EOF;
BackupPC now supports pool file compression. Since you are upgrading
-BackupPC you probably have existing uncompressed backups. You have
-several choices if you want to turn on compression. You can run
-the script BackupPC_compressPool to convert everything to compressed
-form. Or you can simply turn on compression, so that new backups
-will be compressed. This will increase the pool storage requirement,
-since both uncompressed and compressed copies of files will be stored.
-But eventually the old uncompressed backups will expire, recovering
-the pool storage. Please see the documentation for more details.
+BackupPC you probably have existing uncompressed backups. You could
+turn on compression, so that new backups will be compressed. This
+will increase the pool storage requirement, since both uncompressed
+and compressed copies of files will be stored. But eventually the old
+uncompressed backups will expire, recovering the pool storage. Please
+see the documentation for more details.
If you are not sure what to do, leave the Compression Level at 0,
which disables compression. You can always read the documentation
Compress::Zlib module (see www.cpan.org). For now, leave
the compression level set at 0 to disable compression. If you
want you can install Compress::Zlib and turn compression on.
-Please see the documentation for more details about converting
-old backups to compressed form.
EOF
}
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 somewher 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.
lib/BackupPC/Storage
lib/BackupPC/Xfer
lib/BackupPC/Zip
+ lib/Net/FTP
) ) {
next if ( -d "$DestDir$Conf{InstallDir}/$dir" );
- mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0775);
+ mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0755);
if ( !-d "$DestDir$Conf{InstallDir}/$dir"
|| !my_chown($Uid, $Gid, "$DestDir$Conf{InstallDir}/$dir") ) {
die("Failed to create or chown $DestDir$Conf{InstallDir}/$dir\n");
# Create CGI image directory
#
foreach my $dir ( ($Conf{CgiImageDir}) ) {
- next if ( $dir eq "" || -d $dir );
- mkpath("$DestDir$dir", 0, 0775);
+ next if ( $dir eq "" || -d "$DestDir$dir" );
+ mkpath("$DestDir$dir", 0, 0755);
if ( !-d "$DestDir$dir" || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
die("Failed to create or chown $DestDir$dir");
} else {
"$Conf{ConfDir}",
"$Conf{LogDir}",
) ) {
- mkpath("$DestDir/$dir", 0, 0750) if ( !-d "$DestDir/$dir" );
- if ( !-d "$DestDir/$dir"
- || !my_chown($Uid, $Gid, "$DestDir/$dir") ) {
- die("Failed to create or chown $DestDir/$dir\n");
+ mkpath("$DestDir$dir", 0, 0750) if ( !-d "$DestDir$dir" );
+ if ( !-d "$DestDir$dir"
+ || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
+ die("Failed to create or chown $DestDir$dir\n");
} else {
- print("Created $DestDir/$dir\n");
+ print("Created $DestDir$dir\n");
}
}
}
InstallFile("conf/BackupPC_stnd.css",
"$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", 0444, 0);
+ InstallFile("conf/BackupPC_stnd_orig.css",
+ "$DestDir$Conf{CgiImageDir}/BackupPC_stnd_orig.css", 0444, 0);
+ InstallFile("conf/sorttable.js",
+ "$DestDir$Conf{CgiImageDir}/sorttable.js", 0444, 0);
}
printf("Making init.d scripts\n");
foreach my $init ( qw(gentoo-backuppc gentoo-backuppc.conf linux-backuppc
- solaris-backuppc debian-backuppc suse-backuppc
- slackware-backuppc ) ) {
+ solaris-backuppc debian-backuppc freebsd-backuppc
+ freebsd-backuppc2 suse-backuppc slackware-backuppc ) ) {
InstallFile("init.d/src/$init", "init.d/$init", 0444);
}
+printf("Making Apache configuration file for suid-perl\n");
+InstallFile("httpd/src/BackupPC.conf", "httpd/BackupPC.conf", 0644);
+
printf("Installing docs in $DestDir$Conf{InstallDir}/doc\n");
foreach my $doc ( qw(BackupPC.pod BackupPC.html) ) {
InstallFile("doc/$doc", "$DestDir$Conf{InstallDir}/doc/$doc", 0444);
# parameters and deleting ones that are no longer needed.
#
my $dest = "$DestDir$Conf{ConfDir}/config.pl";
-my ($newConf, $newVars) = ConfigParse("conf/config.pl");
+my ($distConf, $distVars) = ConfigParse("conf/config.pl");
my ($oldConf, $oldVars);
+my ($newConf, $newVars) = ($distConf, $distVars);
if ( -f $dest ) {
($oldConf, $oldVars) = ConfigParse($dest);
- $newConf = ConfigMerge($oldConf, $oldVars, $newConf, $newVars);
+ ($newConf, $newVars) = ConfigMerge($oldConf, $oldVars, $distConf, $distVars);
}
-$Conf{EMailFromUserName} ||= $Conf{BackupPCUser};
-$Conf{EMailAdminUserName} ||= $Conf{BackupPCUser};
#
-# Update various config parameters
+# Update various config parameters. The old config is in Conf{}
+# and the new config is an array in text form in $newConf->[].
#
+$Conf{EMailFromUserName} ||= $Conf{BackupPCUser};
+$Conf{EMailAdminUserName} ||= $Conf{BackupPCUser};
#
# Guess $Conf{CgiURL}
#
$Conf{IncrFill} = 0;
+#
+# Empty $Conf{ParPath} if it isn't a valid executable
+# (pre-3.0.0 configure.pl incorrectly set it to a
+# hardcoded value).
+#
+$Conf{ParPath} = '' if ( $Conf{ParPath} ne '' && !-x $Conf{ParPath} );
+
#
# Figure out sensible arguments for the ping command
#
delete($Conf{SmbClientTimeout});
}
+#
+# Replace --devices with -D in RsyncArgs and RsyncRestoreArgs
+#
+foreach my $param ( qw(RsyncArgs RsyncRestoreArgs) ) {
+ next if ( !defined($newVars->{$param}) );
+ $newConf->[$newVars->{$param}]{text} =~ s/--devices/-D/g;
+}
+
+#
+# Merge any new user-editable parameters into CgiUserConfigEdit
+# by copying the old settings forward.
+#
+if ( defined($Conf{CgiUserConfigEdit}) ) {
+ #
+ # This is a real hack. The config file merging is done in text
+ # form without actually instantiating the new conf structure.
+ # So we need to extract the new hash of settings, update it,
+ # and merge the text. Ugh...
+ #
+ my $new;
+ my $str = $distConf->[$distVars->{CgiUserConfigEdit}]{text};
+
+ $str =~ s/^\s*\$Conf\{.*?\}\s*=\s*/\$new = /m;
+ eval($str);
+ foreach my $p ( keys(%$new) ) {
+ $new->{$p} = $Conf{CgiUserConfigEdit}{$p}
+ if ( defined($Conf{CgiUserConfigEdit}{$p}) );
+ }
+ $Conf{CgiUserConfigEdit} = $new;
+ my $d = Data::Dumper->new([$new], [*value]);
+ $d->Indent(1);
+ $d->Terse(1);
+ my $value = $d->Dump;
+ $value =~ s/(.*)\n/$1;\n/s;
+ $newConf->[$newVars->{CgiUserConfigEdit}]{text}
+ =~ s/(\s*\$Conf\{.*?\}\s*=\s*).*/$1$value/s;
+}
+
+#
+# Apply any command-line configuration parameter settings
+#
+foreach my $param ( keys(%{$opts{"config-override"}}) ) {
+ my $val = eval { $opts{"config-override"}{$param} };
+ if ( @$ ) {
+ printf("Can't eval --config-override setting %s=%s\n",
+ $param, $opts{"config-override"}{$param});
+ exit(1);
+ }
+ if ( !defined($newVars->{$param}) ) {
+ printf("Unkown config parameter %s in --config-override\n", $param);
+ exit(1);
+ }
+ $newConf->[$newVars->{$param}]{text} = $opts{"config-override"}{$param};
+}
+
+#
+# Now backup and write the config file
+#
my $confCopy = "$dest.pre-__VERSION__";
if ( -f $dest && !-f $confCopy ) {
#
will need to do:
- Browse through the config file, $Conf{ConfDir}/config.pl,
- and make sure all the settings are correct. In particular, you
- will need to set the smb share password and user name, backup
- policies and check the email message headers and bodies.
+ and make sure all the settings are correct. In particular,
+ you will need to set \$Conf{CgiAdminUsers} so you have
+ administration privileges in the CGI interface.
- Edit the list of hosts to backup in $Conf{ConfDir}/hosts.
- Verify that the CGI script BackupPC_Admin runs correctly. You might
need to change the permissions or group ownership of BackupPC_Admin.
+ If this is an upgrade and you are using mod_perl, you will need
+ to restart Apache. Otherwise it will have stale code.
- BackupPC should be ready to start. Don't forget to run it
as user $Conf{BackupPCUser}! The installation also contains an
}
eval "use File::RsyncP;";
-if ( !$@ && $File::RsyncP::VERSION < 0.52 ) {
+if ( !$@ && $File::RsyncP::VERSION < 0.68 ) {
print("\nWarning: you need to upgrade File::RsyncP;"
- . " I found $File::RsyncP::VERSION and BackupPC needs 0.52\n");
+ . " I found $File::RsyncP::VERSION and BackupPC needs 0.68\n");
}
exit(0);
if ( $prog =~ /Lib.pm/ );
s/__BACKUPPCUSER__/$Conf{BackupPCUser}/g;
s/__CGIDIR__/$Conf{CgiDir}/g;
+ s/__IMAGEDIR__/$Conf{CgiImageDir}/g;
+ s/__IMAGEDIRURL__/$Conf{CgiImageDirURL}/g;
if ( $first && /^#.*bin\/perl/ ) {
#
# Fill in correct path to perl (no taint for >= 2.0.1).
{
my($old, $oldVars, $new, $newVars) = @_;
my $posn = 0;
- my $res;
+ my($res, $resVars);
#
# Find which config parameters are not needed any longer
push(@$res, $new);
}
}
- return $res;
+ for ( my $i = 0 ; $i < @$res ; $i++ ) {
+ $resVars->{$res->[$i]{var}} = $i;
+ }
+ return ($res, $resVars);
}
sub my_chown
Set the configuration compression level to N. Default is 3
if Compress::Zlib is installed.
+=item B<--config-dir CONFIG_DIR>
+
+Configuration directory for new installations. Defaults
+to /etc/BackupPC with FHS. Automatically extracted
+from --config-path for existing installations.
+
=item B<--config-path CONFIG_PATH>
Path to the existing config.pl configuration file for BackupPC.
Use locations specified by the Filesystem Hierarchy Standard
for installing BackupPC. This is enabled by default for new
-installatios. To use the pre-3.0 installation locations,
+installations. To use the pre-3.0 installation locations,
specify --no-fhs.
=item B<--help|?>
Example:
- --html-dir /usr/local/apache/htdocs/BackupPC
+ --html-dir /var/www/htdocs/BackupPC
=item B<--html-dir-url URL>
--install-dir /usr/local/BackupPC
+=item B<--log-dir LOG_DIR>
+
+Log directory. Defaults to /var/log/BackupPC with FHS.
+
=item B<--man>
Prints the manual page and exits.
=head1 COPYRIGHT
-Copyright (C) 2001-2004 Craig Barratt.
+Copyright (C) 2001-2010 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