From a7e968ce327855f2ba2624ca8517069a936c9b5b Mon Sep 17 00:00:00 2001
From: cbarratt
Date: Sat, 2 Aug 2003 08:01:41 +0000
Subject: [PATCH] * Major changes from Ryan Kucera to add style sheets to the
CGI interface, allowing easy customization. Added new icons and BackupPC
logo. Numerous navigation improvements.
* Major addition of Archive feature from Josh Marshall. Special
clients can be configured to be archive targets (eg: tape drives,
CD-R). Any subset of the backup clients can be selected and tar
archives are created, optionally compressed and split and written
to the output device. Logs are maintained and are browsable.
* Addition of administration options from Paul Lukins. Initial
page allows server to be started/stopped/reloaded.
---
ChangeLog | 13 +
bin/BackupPC | 125 +++++++--
bin/BackupPC_archive | 375 +++++++++++++++++++++++++
bin/BackupPC_archivecd | 51 ++++
bin/BackupPC_archivetape | 45 +++
bin/BackupPC_dump | 24 +-
cgi-bin/BackupPC_Admin | 10 +
conf/config.pl | 309 +++++++++++++++++++-
configure.pl | 23 +-
doc-src/BackupPC.pod | 49 +++-
images/icon-dir.gif | Bin 0 -> 426 bytes
images/icon-file.gif | Bin 0 -> 395 bytes
images/icon-symlink.gif | Bin 0 -> 458 bytes
images/logo.gif | Bin 0 -> 1394 bytes
init.d/src/linux-backuppc | 2 +-
lib/BackupPC/CGI/AdminOptions.pm | 52 ++++
lib/BackupPC/CGI/Archive.pm | 235 ++++++++++++++++
lib/BackupPC/CGI/ArchiveInfo.pm | 87 ++++++
lib/BackupPC/CGI/Browse.pm | 71 +++--
lib/BackupPC/CGI/DirHistory.pm | 20 +-
lib/BackupPC/CGI/EmailSummary.pm | 4 +-
lib/BackupPC/CGI/GeneralInfo.pm | 34 +--
lib/BackupPC/CGI/HostInfo.pm | 175 +++++++-----
lib/BackupPC/CGI/LOGlist.pm | 4 +-
lib/BackupPC/CGI/Lib.pm | 246 +++++++++-------
lib/BackupPC/CGI/Queue.pm | 6 +-
lib/BackupPC/CGI/ReloadServer.pm | 51 ++++
lib/BackupPC/CGI/Restore.pm | 20 +-
lib/BackupPC/CGI/RestoreInfo.pm | 5 +-
lib/BackupPC/CGI/StartServer.pm | 63 +++++
lib/BackupPC/CGI/StartStopBackup.pm | 14 +-
lib/BackupPC/CGI/StopServer.pm | 56 ++++
lib/BackupPC/CGI/Summary.pm | 42 +--
lib/BackupPC/CGI/View.pm | 35 ++-
lib/BackupPC/Config.pm | 12 -
lib/BackupPC/Lang/en.pm | 421 +++++++++++++++++++++-------
lib/BackupPC/Lib.pm | 48 ++++
makeDist | 19 +-
38 files changed, 2289 insertions(+), 457 deletions(-)
create mode 100644 bin/BackupPC_archive
create mode 100644 bin/BackupPC_archivecd
create mode 100644 bin/BackupPC_archivetape
create mode 100644 images/icon-dir.gif
create mode 100644 images/icon-file.gif
create mode 100644 images/icon-symlink.gif
create mode 100644 images/logo.gif
create mode 100644 lib/BackupPC/CGI/AdminOptions.pm
create mode 100644 lib/BackupPC/CGI/Archive.pm
create mode 100644 lib/BackupPC/CGI/ArchiveInfo.pm
create mode 100644 lib/BackupPC/CGI/ReloadServer.pm
create mode 100644 lib/BackupPC/CGI/StartServer.pm
create mode 100644 lib/BackupPC/CGI/StopServer.pm
diff --git a/ChangeLog b/ChangeLog
index de07eca..5b4a846 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -21,6 +21,19 @@
# Version __VERSION__, __RELEASEDATE__
#------------------------------------------------------------------------
+* Major changes from Ryan Kucera to add style sheets to the CGI
+ interface, allowing easy customization. Added new icons and
+ BackupPC logo. Numerous navigation improvements.
+
+* Major addition of Archive feature from Josh Marshall. Special
+ clients can be configured to be archive targets (eg: tape drives,
+ CD-R). Any subset of the backup clients can be selected and tar
+ archives are created, optionally compressed and split and written
+ to the output device. Logs are maintained and are browsable.
+
+* Addition of administration options from Paul Lukins. Initial
+ page allows server to be started/stopped/reloaded.
+
* Split BackupPC_Admin into a set of modules, one for each major action.
Each action is now a seperate module in lib/BackupPC/CGI.
diff --git a/bin/BackupPC b/bin/BackupPC
index 027bbf2..3f1fa2b 100755
--- a/bin/BackupPC
+++ b/bin/BackupPC
@@ -300,6 +300,7 @@ sub Main_Initialize
$Info{ConfigModTime} = $bpc->ConfigMTime();
$Info{pid} = $$;
$Info{startTime} = time;
+ $Info{ConfigLTime} = time;
$Info{Version} = $bpc->{Version};
#
@@ -477,7 +478,7 @@ sub Main_TryToRun_Bg_or_User_Queue
next;
}
push(@args, $req->{doFull} ? "-f" : "-i")
- if ( !$req->{restore} );
+ if (( !$req->{restore} ) && ( !$req->{archive} ));
$UserQueueOn{$req->{host}} = 0;
} elsif ( $nJobs < $Conf{MaxBackups}
&& (@CmdQueue + $nJobs)
@@ -538,6 +539,10 @@ sub Main_TryToRun_Bg_or_User_Queue
$progName = "BackupPC_restore";
$type = "restore";
push(@args, $req->{hostIP}, $req->{host}, $req->{reqFileName});
+ } elsif ( $req->{archive} ) {
+ $progName = "BackupPC_archive";
+ $type = "archive";
+ push(@args, $req->{user}, $req->{host}, $req->{reqFileName});
} else {
$progName = "BackupPC_dump";
$type = "backup";
@@ -597,13 +602,7 @@ sub Main_Select
= localtime(time);
my($currHours) = $hour + $min / 60 + $sec / 3600;
if ( $bpc->ConfigMTime() != $Info{ConfigModTime} ) {
- my($mesg) = $bpc->ConfigRead()
- || "Re-read config file because mtime changed";
- print(LOG $bpc->timeStamp, "$mesg\n");
- %Conf = $bpc->Conf();
- $Info{ConfigModTime} = $bpc->ConfigMTime();
- umask($Conf{UmaskMode});
- ServerSocketInit();
+ ServerReload("Re-read config file because mtime changed");
}
my $delta = -1;
foreach my $t ( @{$Conf{WakeupSchedule} || [0..23]} ) {
@@ -651,30 +650,9 @@ sub Main_Process_Signal
# Process signals
#
if ( $SigName eq "HUP" ) {
- my($mesg) = $bpc->ConfigRead()
- || "Re-read config file because of a SIG_HUP";
- print(LOG $bpc->timeStamp, "$mesg\n");
- $Info{ConfigModTime} = $bpc->ConfigMTime();
- %Conf = $bpc->Conf();
- umask($Conf{UmaskMode});
- ServerSocketInit();
- HostsUpdate(0);
- $NextWakeup = 0;
+ ServerReload("Re-read config file because of a SIG_HUP");
} elsif ( $SigName ) {
- print(LOG $bpc->timeStamp, "Got signal $SigName... cleaning up\n");
- if ( keys(%Jobs) ) {
- foreach my $host ( keys(%Jobs) ) {
- kill(2, $Jobs{$host}{pid});
- }
- sleep(1);
- foreach my $host ( keys(%Jobs) ) {
- kill(9, $Jobs{$host}{pid});
- }
- %Jobs = ();
- }
- StatusWrite();
- unlink("$TopDir/log/BackupPC.pid");
- exit(1);
+ ServerShutdown("Got signal $SigName... cleaning up");
}
$SigName = "";
}
@@ -1055,6 +1033,9 @@ sub Main_Check_Client_Messages
if ( $Jobs{$host}{type} eq "restore" ) {
$Status{$host}{reason}
= "Reason_restore_canceled_by_user";
+ } elsif ( $Jobs{$host}{type} eq "archive" ) {
+ $Status{$host}{reason}
+ = "Reason_archive_canceled_by_user";
} else {
$Status{$host}{reason}
= "Reason_backup_canceled_by_user";
@@ -1126,6 +1107,36 @@ sub Main_Check_Client_Messages
$UserQueueOn{$hostIP} = 1;
$reply = "ok: requested backup of $host";
}
+ } elsif ( $cmd =~ /^archive (\S+)\s+(\S+)\s+(\S+)/ ) {
+ my $user = $1;
+ my $archivehost = $2;
+ my $reqFileName = $3;
+ $host = $bpc->uriUnesc($archivehost);
+ if ( !defined($Status{$host}) ) {
+ print(LOG $bpc->timeStamp,
+ "User $user requested archive of unknown archive host"
+ . " $host");
+ $reply = "archive error: unknown archive host $host";
+ } else {
+ print(LOG $bpc->timeStamp,
+ "User $user requested archive on $host"
+ . " ($host)\n");
+ if ( defined($Jobs{$host}) ) {
+ $reply = "Archive currently running on $host, please try later";
+ } else {
+ unshift(@UserQueue, {
+ host => $host,
+ hostIP => $user,
+ reqFileName => $reqFileName,
+ reqTime => time,
+ dhcp => 0,
+ archive => 1,
+ userReq => 1,
+ });
+ $UserQueueOn{$host} = 1;
+ $reply = "ok: requested archive on $host";
+ }
+ }
} elsif ( $cmd =~ /^restore (\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ ) {
my $hostIP = $1;
$host = $2;
@@ -1211,6 +1222,15 @@ sub Main_Check_Client_Messages
QueueLink($host);
} elsif ( $cmd =~ /^log\s+(.*)/ ) {
print(LOG $bpc->timeStamp, "$1\n");
+ } elsif ( $cmd =~ /^server\s+(\w+)/ ) {
+ my($type) = $1;
+ if ( $type eq 'reload' ) {
+ ServerReload("Reloading server configuration...");
+ } elsif ( $type eq 'shutdown' ) {
+ $reply = "Shutting down...\n";
+ syswrite($Clients{$client}{fh}, $reply, length($reply));
+ ServerShutdown("Server shutting down...");
+ }
} elsif ( $cmd =~ /^quit/ || $cmd =~ /^exit/ ) {
$nbytes = 0;
last;
@@ -1530,3 +1550,46 @@ sub ServerSocketInit
$ServerInetPort = $Conf{ServerPort};
}
}
+
+#
+# Reload the server. Used by Main_Process_Signal when $SigName eq "HUP"
+# or when the command "server reload" is received.
+#
+sub ServerReload
+{
+ my($mesg) = @_;
+ $mesg = $bpc->ConfigRead() || $mesg;
+ print(LOG $bpc->timeStamp, "$mesg\n");
+ $Info{ConfigModTime} = $bpc->ConfigMTime();
+ %Conf = $bpc->Conf();
+ umask($Conf{UmaskMode});
+ ServerSocketInit();
+ HostsUpdate(0);
+ $NextWakeup = 0;
+ $Info{ConfigLTime} = time;
+}
+
+#
+# Gracefully shutdown the server. Used by Main_Process_Signal when
+# $SigName ne "" && $SigName ne "HUP" or when the command
+# "server shutdown" is received.
+#
+sub ServerShutdown
+{
+ my($mesg) = @_;
+ print(LOG $bpc->timeStamp, "$mesg\n");
+ if ( keys(%Jobs) ) {
+ foreach my $host ( keys(%Jobs) ) {
+ kill(2, $Jobs{$host}{pid});
+ }
+ sleep(1);
+ foreach my $host ( keys(%Jobs) ) {
+ kill(9, $Jobs{$host}{pid});
+ }
+ %Jobs = ();
+ }
+ StatusWrite();
+ unlink("$TopDir/log/BackupPC.pid");
+ exit(1);
+}
+
diff --git a/bin/BackupPC_archive b/bin/BackupPC_archive
new file mode 100644
index 0000000..3a3bea4
--- /dev/null
+++ b/bin/BackupPC_archive
@@ -0,0 +1,375 @@
+#!/bin/perl -T
+#============================================================= -*-perl-*-
+#
+# BackupPC_archive: Archive files for an archive client.
+#
+# DESCRIPTION
+#
+# Usage: BackupPC_archive
+#
+# AUTHOR
+# Craig Barratt
+#
+# 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.
+#
+#========================================================================
+
+use strict;
+no utf8;
+use lib "/usr/local/BackupPC/lib";
+use BackupPC::Lib;
+use BackupPC::FileZIO;
+use BackupPC::Xfer::Archive;
+
+use vars qw( %ArchiveReq );
+
+###########################################################################
+# Initialize
+###########################################################################
+
+die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
+my $TopDir = $bpc->TopDir();
+my $BinDir = $bpc->BinDir();
+my %Conf = $bpc->Conf();
+my $NeedPostCmd;
+
+my($user, $host, $client, $reqFileName, %stat);
+
+$bpc->ChildInit();
+
+if ( @ARGV != 3 ) {
+ print("usage: $0 \n");
+ exit(1);
+}
+$user = $1 if ( $ARGV[0] =~ /(.+)/ );
+$client = $1 if ( $ARGV[1] =~ /(.+)/ );
+if ( $ARGV[2] !~ /^([\w.]+)$/ ) {
+ print("$0: bad reqFileName (arg #3): $ARGV[2]\n");
+ exit(1);
+}
+$reqFileName = $1;
+
+my $startTime = time();
+
+#my $Hosts = $bpc->HostInfoRead($client);
+
+my $Dir = "$TopDir/pc/$client";
+my @xferPid = ();
+
+#
+# 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;
+my $Pid = $$;
+
+mkpath($Dir, 0, 0777) if ( !-d $Dir );
+if ( !-f "$Dir/LOCK" ) {
+ open(LOCK, ">", "$Dir/LOCK") && close(LOCK);
+}
+open(LOG, ">>", "$Dir/LOG");
+select(LOG); $| = 1; select(STDOUT);
+
+
+#
+# Read the request file
+#
+
+if ( !(my $ret = do "$Dir/$reqFileName") ) {
+ my $err;
+ if ( $@ ) {
+ $err = "couldn't parse $Dir/$reqFileName: $@";
+ } elsif ( !defined($ret) ) {
+ $err = "couldn't do $Dir/$reqFileName: $!";
+ } else {
+ $err = "couldn't run $Dir/$reqFileName";
+ }
+ $stat{hostError} = $err;
+ exit(ArchiveCleanup($client));
+}
+#
+# Re-read config file, so we can include the PC-specific config
+#
+if ( defined(my $error = $bpc->ConfigRead($client)) ) {
+ $stat{hostError} = "Can't read PC's config file: $error";
+ exit(ArchiveCleanup($client));
+}
+%Conf = $bpc->Conf();
+
+#
+# Make sure we eventually timeout if there is no activity from
+# the data transport program.
+#
+alarm($Conf{ClientTimeout});
+
+#
+# See if the host name is aliased
+#
+if ( $Conf{ClientNameAlias} ne "" ) {
+ $host = $Conf{ClientNameAlias};
+} else {
+ $host = $client;
+}
+
+#
+# Setup file extension for compression and open ArchiveLOG output file
+#
+$Conf{CompressLevel} = 0 if ( !BackupPC::FileZIO->compOk );
+my $fileExt = $Conf{CompressLevel} > 0 ? ".z" : "";
+my $ArchiveLOG = BackupPC::FileZIO->open("$Dir/ArchiveLOG$fileExt", 1,
+ $Conf{CompressLevel});
+my($logMsg, $xfer);
+
+$stat{xferOK} = 1;
+$stat{hostAbort} = undef;
+$stat{hostError} = $stat{lastOutputLine} = undef;
+local(*RH, *WH);
+
+#
+# Run an optional pre-archive command
+#
+UserCommandRun("ArchivePreUserCmd");
+$NeedPostCmd = 1;
+
+$xfer = BackupPC::Xfer::Archive->new($bpc);
+
+#
+# Run the transport program
+#
+
+my $xferArgs = {
+ client => $client,
+ host => $host,
+ user => $ArchiveReq{user},
+ type => "archive",
+ XferLOG => $ArchiveLOG,
+ XferMethod => $Conf{XferMethod},
+ pathHdrSrc => $ArchiveReq{pathHdrSrc},
+ pathHdrDest => $ArchiveReq{pathHdrDest},
+ HostList => \@{$ArchiveReq{HostList}},
+ BackupList => \@{$ArchiveReq{BackupList}},
+ archiveloc => $ArchiveReq{archiveloc},
+ parfile => $ArchiveReq{parfile},
+ compression => $ArchiveReq{compression},
+ compext => $ArchiveReq{compext},
+ splitsize => $ArchiveReq{splitsize},
+ pidHandler => \&pidHandler,
+};
+
+$xfer->args($xferArgs);
+
+if ( !defined($logMsg = $xfer->start()) ) {
+ UserCommandRun("ArchivePostUserCmd") if ( $NeedPostCmd );
+ $stat{hostError} = "xfer start failed: ", $xfer->errStr;
+ exit(ArchiveCleanup($client));
+}
+
+print(LOG $bpc->timeStamp, "Starting archive\n");
+$xfer->run();
+alarm(0);
+
+exit(ArchiveCleanup($client));
+
+###########################################################################
+# Subroutines
+###########################################################################
+
+sub catch_signal
+{
+ my $signame = shift;
+
+ #
+ # Children quit quietly on ALRM
+ #
+ exit(1) if ( $Pid != $$ && $signame eq "ALRM" );
+
+ #
+ # Ignore signals in children
+ #
+ return if ( $Pid != $$ );
+
+ #
+ # Note: needs to be tested for each kind of XferMethod
+ #
+ print(LOG $bpc->timeStamp, "cleaning up after signal $signame\n");
+ $SIG{$signame} = 'IGNORE';
+ $ArchiveLOG->write(\"exiting after signal $signame\n");
+ $stat{xferOK} = 0;
+ if ( $signame eq "INT" ) {
+ $stat{hostError} = "aborted by user (signal=$signame)";
+ } else {
+ $stat{hostError} = "aborted by signal=$signame";
+ }
+ exit(ArchiveCleanup($client));
+}
+
+#
+# Cleanup and update the archive status
+#
+sub ArchiveCleanup
+{
+ my($client) = @_;
+
+ $stat{xferOK} = 0 if ( $stat{hostError} || $stat{hostAbort} );
+
+ if ( !$stat{xferOK} ) {
+ #
+ # kill off the tranfer program, first nicely then forcefully
+ #
+ if ( @xferPid ) {
+ kill(2, @xferPid);
+ sleep(1);
+ kill(9, @xferPid);
+ }
+ }
+
+ my $lastNum = -1;
+ my @Archives;
+
+ @Archives = $bpc->ArchiveInfoRead($client);
+ for ( my $i = 0 ; $i < @Archives ; $i++ ) {
+ $lastNum = $Archives[$i]{num} if ( $lastNum < $Archives[$i]{num} );
+ }
+ $lastNum++;
+
+ #
+ # Run an optional post-archive command
+ #
+ UserCommandRun("ArchivePostUserCmd") if ( $NeedPostCmd );
+
+ rename("$Dir/ArchiveLOG$fileExt", "$Dir/ArchiveLOG.$lastNum$fileExt");
+ rename("$Dir/$reqFileName", "$Dir/ArchiveInfo.$lastNum");
+ my $endTime = time();
+
+ #
+ # If the archive 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 "" );
+ sleep(2);
+ $stat{hostAbort} = 1;
+ $ArchiveLOG->write(\"Archive failed: $stat{hostError}\n")
+ if ( defined($ArchiveLOG) );
+ }
+
+ $ArchiveLOG->close() if ( defined($ArchiveLOG) );
+
+ #
+ # Add the new archive information to the archive file
+ #
+ @Archives = $bpc->ArchiveInfoRead($client);
+ my $i = @Archives;
+ $Archives[$i]{num} = $lastNum;
+ $Archives[$i]{startTime} = $startTime;
+ $Archives[$i]{endTime} = $endTime;
+ $Archives[$i]{result} = $stat{xferOK} ? "ok" : "failed";
+ $Archives[$i]{errorMsg} = $stat{hostError};
+
+ while ( @Archives > $Conf{ArchiveInfoKeepCnt} ) {
+ my $num = $Archives[0]{num};
+ unlink("$Dir/ArchiveLOG.$num.z");
+ unlink("$Dir/ArchiveLOG.$num");
+ unlink("$Dir/ArchiveInfo.$num");
+ shift(@Archives);
+ }
+ $bpc->ArchiveInfoWrite($client, @Archives);
+
+ if ( !$stat{xferOK} ) {
+ print(LOG $bpc->timeStamp, "Archive failed ($stat{hostError})\n");
+ print("archive failed: $stat{hostError}\n");
+ return 1;
+ } else {
+ print(LOG $bpc->timeStamp, "Archive Complete\n");
+ print("Archive Complete\n");
+ return;
+ }
+}
+
+#
+# The Xfer method might tell us from time to time about processes
+# it forks. We tell BackupPC about this (for status displays) and
+# keep track of the pids in case we cancel the backup
+#
+sub pidHandler
+{
+ @xferPid = @_;
+ @xferPid = grep(/./, @xferPid);
+ return if ( !@xferPid );
+ my @pids = @xferPid;
+ my $str = join(",", @pids);
+ $ArchiveLOG->write(\"Xfer PIDs are now $str\n") if ( defined($ArchiveLOG) );
+ print("xferPids $str\n");
+}
+
+#
+# Run an optional pre- or post-dump command
+#
+sub UserCommandRun
+{
+ my($type) = @_;
+
+ return if ( !defined($Conf{$type}) );
+ my $vars = {
+ xfer => $xfer,
+ client => $client,
+ host => $host,
+ user => $user,
+ share => $ArchiveReq{shareDest},
+ XferMethod => $Conf{XferMethod},
+ HostList => \@{$ArchiveReq{HostList}},
+ BackupList => \@{$ArchiveReq{BackupList}},
+ archiveloc => $ArchiveReq{archiveloc},
+ parfile => $ArchiveReq{parfile},
+ compression => $ArchiveReq{compression},
+ compext => $ArchiveReq{compext},
+ splitsize => $ArchiveReq{splitsize},
+ sshPath => $Conf{SshPath},
+ LOG => *LOG,
+ XferLOG => $ArchiveLOG,
+ stat => \%stat,
+ xferOK => $stat{xferOK} || 0,
+ type => $type,
+ };
+ my $cmd = $bpc->cmdVarSubstitute($Conf{$type}, $vars);
+ $ArchiveLOG->write(\"Executing $type: @$cmd\n");
+ #
+ # Run the user's command, dumping the stdout/stderr into the
+ # Xfer log file. Also supply the optional $vars and %Conf in
+ # case the command is really perl code instead of a shell
+ # command.
+ #
+ $bpc->cmdSystemOrEval($cmd,
+ sub {
+ $ArchiveLOG->write(\$_[0]);
+ },
+ $vars, \%Conf);
+}
diff --git a/bin/BackupPC_archivecd b/bin/BackupPC_archivecd
new file mode 100644
index 0000000..d9f4c0d
--- /dev/null
+++ b/bin/BackupPC_archivecd
@@ -0,0 +1,51 @@
+#!/bin/sh
+#=============================================================
+#
+# BackupPC_archivecd: Archive files to a cd host
+#
+# DESCRIPTION
+#
+# Usage: BackupPC_archivecd tarCreate splitpath parpath host backupnumber compression compext splitsize archiveloc parfile share
+#
+# AUTHOR
+# Craig Barratt
+#
+# 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.
+#
+#========================================================================
+
+tarCreate=$1
+splitpath=$2
+parpath=$3
+host=$4
+backupnumber=$5
+compression=$6
+compext=$7
+splitsize=$8
+archiveloc=$9
+parfile=${10}
+share=${11}
+
+$tarCreate -h $host -n $backupnumber -s $share $share | $compression | $splitpath -b $splitsize - $archiveloc/$host.$backupnumber.tar$compext.
+$parpath a -n $parfile $archiveloc/$host.$backupnumber.tar$compext.par $archiveloc/$host.$backupnumber.tar$compext.*
diff --git a/bin/BackupPC_archivetape b/bin/BackupPC_archivetape
new file mode 100644
index 0000000..18717ab
--- /dev/null
+++ b/bin/BackupPC_archivetape
@@ -0,0 +1,45 @@
+#!/bin/sh
+#=============================================================
+#
+# BackupPC_archivetape: Archive files to a tape host
+#
+# DESCRIPTION
+#
+# Usage: BackupPC_archivecd tarCreate host backupnumber compression archiveloc share
+#
+# AUTHOR
+# Craig Barratt
+#
+# 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.
+#
+#========================================================================
+
+tarCreate=$1
+host=$2
+backupnumber=$3
+compression=$4
+archiveloc=$5
+share=$6
+
+$tarCreate -h $host -n $backupnumber -s $share $share | $compression > $archiveloc
diff --git a/bin/BackupPC_dump b/bin/BackupPC_dump
index d1509b7..f59e38a 100755
--- a/bin/BackupPC_dump
+++ b/bin/BackupPC_dump
@@ -126,20 +126,19 @@ if ( $opts{d} ) {
#
$hostIP = $client;
if ( $bpc->CheckHostAlive($hostIP) < 0 ) {
- print("Exiting because CheckHostAlive($hostIP) failed\n")
+ print(STDERR "Exiting because CheckHostAlive($hostIP) failed\n")
if ( $opts{v} );
exit(1);
}
if ( $Conf{NmbLookupCmd} eq "" ) {
- print("Exiting because \$Conf{NmbLookupCmd} is empty\n")
+ print(STDERR "Exiting because \$Conf{NmbLookupCmd} is empty\n")
if ( $opts{v} );
exit(1);
}
($client, $user) = $bpc->NetBiosInfoGet($hostIP);
if ( $client !~ /^([\w\.\s-]+)$/ ) {
- print("Exiting because NetBiosInfoGet($hostIP) returned '$client',"
- . " an invalid host name\n")
- if ( $opts{v} );
+ print(STDERR "Exiting because NetBiosInfoGet($hostIP) returned"
+ . " '$client', an invalid host name\n") if ( $opts{v} );
exit(1)
}
$Hosts = $bpc->HostInfoRead($client);
@@ -148,8 +147,8 @@ if ( $opts{d} ) {
$Hosts = $bpc->HostInfoRead($client);
}
if ( !defined($Hosts->{$client}) ) {
- print("Exiting because host $client does not exist in the hosts file\n")
- if ( $opts{v} );
+ print(STDERR "Exiting because host $client does not exist in the"
+ . " hosts file\n") if ( $opts{v} );
exit(1)
}
@@ -200,6 +199,13 @@ if ( $opts{e} ) {
exit(0);
}
+#
+# For archive hosts we don't bother any further
+#
+if ($Conf{XferMethod} eq "archive" ) {
+ exit(0);
+}
+
if ( !$opts{d} ) {
#
# In the non-DHCP case, make sure the host can be looked up
@@ -215,7 +221,7 @@ if ( !$opts{d} ) {
# Ok, NS doesn't know about it. Maybe it is a NetBios name
# instead.
#
- print("Name server doesn't know about $host; trying NetBios\n")
+ print(STDERR "Name server doesn't know about $host; trying NetBios\n")
if ( $opts{v} );
if ( !defined($hostIP = $bpc->NetBiosHostIPFind($host)) ) {
print(LOG $bpc->timeStamp, "Can't find host $host via netbios\n");
@@ -253,7 +259,7 @@ $bpc->ServerDisconnect();
if ( $opts{d} ) {
if ( $StatusHost{activeJob} ) {
# oops, something is already running for this host
- print("Exiting because backup is already running for $client\n")
+ print(STDERR "Exiting because backup is already running for $client\n")
if ( $opts{v} );
exit(0);
}
diff --git a/cgi-bin/BackupPC_Admin b/cgi-bin/BackupPC_Admin
index c99ba4c..8dc2091 100755
--- a/cgi-bin/BackupPC_Admin
+++ b/cgi-bin/BackupPC_Admin
@@ -61,6 +61,7 @@ my %ActionDispatch = (
$Lang->{Start_Incr_Backup} => "StartStopBackup",
$Lang->{Start_Full_Backup} => "StartStopBackup",
$Lang->{Stop_Dequeue_Backup} => "StartStopBackup",
+ $Lang->{Stop_Dequeue_Archive} => "StartStopBackup",
"queue" => "Queue",
"view" => "View",
"LOGlist" => "LOGlist",
@@ -72,12 +73,21 @@ my %ActionDispatch = (
"hostInfo" => "HostInfo",
"generalInfo" => "GeneralInfo",
"restoreInfo" => "RestoreInfo",
+ "archiveInfo" => "ArchiveInfo",
+ $Lang->{Start_Archive} => "Archive",
+ "Archive" => "Archive",
+ "Reload" => "ReloadServer",
+ "startServer" => "StartServer",
+ "Stop" => "StopServer",
+ "adminOpts" => "AdminOptions",
);
#
# Set default actions, then call sub handler
#
$In{action} ||= "hostInfo" if ( defined($In{host}) );
+## rk default non admin users to pc summary for their hosts
+$In{action} = "summary" if ( !defined($ActionDispatch{$In{action}}) && !CheckPermission());
$In{action} = "generalInfo" if ( !defined($ActionDispatch{$In{action}}) );
my $action = $ActionDispatch{$In{action}};
require "BackupPC/CGI/$action.pm"
diff --git a/conf/config.pl b/conf/config.pl
index 2912fa3..8c58140 100644
--- a/conf/config.pl
+++ b/conf/config.pl
@@ -160,6 +160,16 @@ $Conf{DfPath} = '/bin/df';
#
$Conf{DfCmd} = '$dfPath $topDir';
+#
+# Full path to various commands for archiving
+#
+
+$Conf{SplitPath} = '/usr/bin/split';
+$Conf{ParPath} = '/usr/bin/par';
+$Conf{CatPath} = '/bin/cat';
+$Conf{GzipPath} = '/bin/gzip';
+$Conf{Bzip2Path} = '/usr/bin/bzip2';
+
#
# Maximum threshold for disk utilization on the __TOPDIR__ filesystem.
# If the output from $Conf{DfPath} reports a percentage larger than
@@ -422,6 +432,13 @@ $Conf{IncrFill} = 0;
#
$Conf{RestoreInfoKeepCnt} = 10;
+#
+# Number of archive logs to keep. BackupPC remembers information about
+# each archive request. This number per archive client will be kept around before
+# the oldest ones are pruned.
+#
+$Conf{ArchiveInfoKeepCnt} = 10;
+
#
# List of directories or files to backup. If this is defined, only these
# directories or files will be backed up.
@@ -855,6 +872,69 @@ $Conf{RsyncRestoreArgs} = [
#
$Conf{RsyncLogLevel} = 1;
+#
+# Archive Destination
+#
+# The Destination of the archive
+# e.g. /tmp for file archive or /dev/nst0 for device archive
+#
+$Conf{ArchiveDest} = '/tmp';
+
+#
+# Archive Compression type
+#
+# The valid values are:
+#
+# - 'none': No Compression
+#
+# - 'gzip': Medium Compression. Recommended.
+#
+# - 'bzip2': High Compression but takes longer.
+#
+$Conf{ArchiveComp} = 'gzip';
+
+#
+# Archive Parity Files
+#
+# The number of Parity Files to generate.
+# Uses the commandline par available from
+# http://parchive.sourceforge.net
+#
+# Only useful for file dumps.
+#
+# Set to 0 to disable this feature.
+#
+$Conf{ArchivePar} = 0;
+
+#
+# Archive Size Split
+#
+# Only for file archives. Splits the output into
+# the specified size * 1,000,000.
+# e.g. to split into 650,000,000 bytes, specify 650 below.
+#
+$Conf{ArchiveSplit} = 650;
+
+#
+# Archive Command
+#
+# This is the command that is called to actually run the archive process
+# The following variables are substituted at run-time:
+#
+# $Installdir The installation directory of BackupPC
+# $tarCreatePath The path to BackupPC_tarCreate
+# $splitpath The path to the split program
+# $parpath The path to the par program
+# $host The host to archive
+# $backupnumber The backup number of the host to archive
+# $compression The path to the compression program
+# $compext The extension assigned to the compression type
+# $splitsize The number of bytes to split archives into
+# $archiveloc The location to put the archive
+# $parfile The number of par files to create
+#
+$Conf{ArchiveClientCmd} = '$Installdir/bin/BackupPC_archivecd $tarCreatePath $splitpath $parpath $host $backupnumber $compression $compext $splitsize $archiveloc $parfile /';
+
#
# Full path for ssh. Security caution: normal users should not
# allowed to write to this file or directory.
@@ -942,6 +1022,25 @@ $Conf{PingPath} = '/bin/ping';
#
$Conf{PingCmd} = '$pingPath -c 1 $host';
+#
+# Path to init.d script and command to use that script to start the
+# server from the CGI interface. The following variables are substituted
+# at run-time:
+#
+# $sshPath path to ssh ($Conf{SshPath})
+# $serverHost same as $Conf{ServerHost}
+# $serverInitdPath path to init.d script ($Conf{ServerInitdPath})
+#
+# Example:
+#
+# $Conf{ServerInitdPath} = '/etc/init.d/backuppc';
+# $Conf{ServerInitdStartCmd} = '$sshPath -l root $serverHost'
+# . ' $serverInitdPath start'
+# . ' < /dev/null >& /dev/null';
+#
+$Conf{ServerInitdPath} = '';
+$Conf{ServerInitdStartCmd} = '';
+
#
# Compression level to use on files. 0 means no compression. Compression
# levels can be from 1 (least cpu time, slightly worse compression) to
@@ -1059,10 +1158,31 @@ $Conf{MaxOldPerPCLogFiles} = 12;
# $pathHdrDest common starting path of destination
# $fileList list of files being restored
#
+# The following variable substitutions are made at run time for
+# $Conf{ArchivePreUserCmd} and $Conf{ArchivePostUserCmd}:
+#
+# $client client name being backed up
+# $xferOK 1 if the archive succeeded, 0 if it didn't
+# $host Name of the archive host
+# $user user name from the hosts file
+# $share the first share name
+# $XferMethod value of $Conf{XferMethod} (eg: tar, rsync, smb)
+# $HostList list of hosts being archived
+# $BackupList list of backup numbers for the hosts being archived
+# $archiveloc location where the archive is sent to
+# $parfile number of par files being generated
+# $compression compression program being used (eg: cat, gzip, bzip2)
+# $compext extension used for compression type (eg: raw, gz, bz2)
+# $splitsize size of the files that the archive creates
+# $sshPath value of $Conf{SshPath},
+# $type set to "archive"
+#
$Conf{DumpPreUserCmd} = undef;
$Conf{DumpPostUserCmd} = undef;
$Conf{RestorePreUserCmd} = undef;
$Conf{RestorePostUserCmd} = undef;
+$Conf{ArchivePreUserCmd} = undef;
+$Conf{ArchivePostUserCmd} = undef;
#
# Override the client's host name. This allows multiple clients
@@ -1299,20 +1419,9 @@ $Conf{CgiDateFormatMMDD} = 1;
$Conf{CgiNavBarAdminAllHosts} = 0;
#
-# Header font and size for CGI interface
-#
-$Conf{CgiHeaderFontType} = 'arial';
-$Conf{CgiHeaderFontSize} = '3';
-
-#
-# Color scheme for CGI interface. Default values give a very light blue
-# for the background navigation color, green for the header background,
-# and white for the body background. (You call tell I should stick to
-# programming and not graphical design.)
+# Color scheme for CGI interface.
#
-$Conf{CgiNavBarBgColor} = '#ddeeee';
$Conf{CgiHeaderBgColor} = '#99cc33';
-$Conf{CgiBodyBgColor} = '#ffffff';
#
# Hilight colors based on status that are used in the PC summary page.
@@ -1363,3 +1472,179 @@ $Conf{CgiExt2ContentType} = { };
# $Conf{CgiImageDirURL} = '/BackupPC';
#
$Conf{CgiImageDirURL} = '';
+
+#
+# CSS stylesheet for the CGI interface.
+#
+$Conf{CSSstylesheet} = <<'EOF';
+
+EOF
diff --git a/configure.pl b/configure.pl
index 0abc9a7..7fdea71 100755
--- a/configure.pl
+++ b/configure.pl
@@ -131,6 +131,11 @@ my %Programs = (
'ssh/ssh2' => "SshPath",
sendmail => "SendmailPath",
hostname => "HostnamePath",
+ split => "SplitPath",
+ par => "ParPath",
+ cat => "CatPath",
+ gzip => "GzipPath",
+ bzip2 => "Bzip2Path",
);
foreach my $prog ( sort(keys(%Programs)) ) {
@@ -406,6 +411,7 @@ printf("Installing binaries in $Conf{InstallDir}/bin\n");
foreach my $prog ( qw(BackupPC BackupPC_dump BackupPC_link BackupPC_nightly
BackupPC_sendEmail BackupPC_tarCreate BackupPC_trashClean
BackupPC_tarExtract BackupPC_compressPool BackupPC_zcat
+ BackupPC_archive BackupPC_archivecd BackupPC_archivetape
BackupPC_restore BackupPC_serverMesg BackupPC_zipCreate ) ) {
InstallFile("bin/$prog", "$Conf{InstallDir}/bin/$prog", 0555);
}
@@ -422,6 +428,7 @@ foreach my $lib ( qw(
BackupPC/Attrib.pm
BackupPC/PoolWrite.pm
BackupPC/View.pm
+ BackupPC/Xfer/Archive.pm
BackupPC/Xfer/Tar.pm
BackupPC/Xfer/Smb.pm
BackupPC/Xfer/Rsync.pm
@@ -431,6 +438,9 @@ foreach my $lib ( qw(
BackupPC/Lang/fr.pm
BackupPC/Lang/es.pm
BackupPC/Lang/de.pm
+ BackupPC/CGI/AdminOptions.pm
+ BackupPC/CGI/Archive.pm
+ BackupPC/CGI/ArchiveInfo.pm
BackupPC/CGI/Browse.pm
BackupPC/CGI/DirHistory.pm
BackupPC/CGI/EmailSummary.pm
@@ -439,10 +449,13 @@ foreach my $lib ( qw(
BackupPC/CGI/Lib.pm
BackupPC/CGI/LOGlist.pm
BackupPC/CGI/Queue.pm
+ BackupPC/CGI/ReloadServer.pm
BackupPC/CGI/RestoreFile.pm
BackupPC/CGI/RestoreInfo.pm
BackupPC/CGI/Restore.pm
+ BackupPC/CGI/StartServer.pm
BackupPC/CGI/StartStopBackup.pm
+ BackupPC/CGI/StopServer.pm
BackupPC/CGI/Summary.pm
BackupPC/CGI/View.pm
) ) {
@@ -623,7 +636,9 @@ will need to do:
- BackupPC should be ready to start. Don't forget to run it
as user $Conf{BackupPCUser}! The installation also contains an
init.d/backuppc script that can be copied to /etc/init.d
- so that BackupPC can auto-start on boot. See init.d/README.
+ so that BackupPC can auto-start on boot. This will also enable
+ administrative users to start the server from the CGI interface.
+ See init.d/README.
Enjoy!
EOF
@@ -716,8 +731,9 @@ sub ConfigParse
my($out, @conf, $var);
my $comment = 1;
my $allVars = {};
+ my $endLine = undef;
while ( ) {
- if ( /^#/ ) {
+ if ( /^#/ && !defined($endLine) ) {
if ( $comment ) {
$out .= $_;
} else {
@@ -745,7 +761,10 @@ sub ConfigParse
$out .= $_;
}
$var = $1;
+ $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<(.*);/ );
+ $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<'(.*)';/ );
} else {
+ $endLine = undef if ( defined($endLine) && /^\Q$endLine[\n\r]*$/ );
$out .= $_;
}
}
diff --git a/doc-src/BackupPC.pod b/doc-src/BackupPC.pod
index e8e8c0a..ef114b8 100644
--- a/doc-src/BackupPC.pod
+++ b/doc-src/BackupPC.pod
@@ -141,9 +141,7 @@ full support for special file types and unix attributes in v1.4.0
likely means an exact image of a linux/unix file system can be made.
BackupPC saves backups onto disk. Because of pooling you can relatively
-economically keep several weeks of old backups. But BackupPC does not
-provide permanent storage to tape. Other Open Source applications can do
-this by backing up BackupPC's pool directories to tape.
+economically keep several weeks of old backups.
At some sites the disk-based backup will be adequate, without a
secondary tape backup. This system is robust to any single failure: if a
@@ -153,8 +151,8 @@ fresh file system, and create new backups from the clients. The chance
of the server disk failing can be made very small by spending more money
on increasingly better RAID systems.
-At other sites a secondary tape backup will be required. This tape
-backup can be done perhaps weekly from the BackupPC pool file system.
+At other sites a secondary tape backup or cd/dvd will be required. This
+backup can be done perhaps weekly using the archive function of BackupPC.
=back
@@ -2032,6 +2030,47 @@ in a location different from their original location.
Each of these programs reside in __INSTALLDIR__/bin.
+=head1 Archive functions
+
+BackupPC supports archiving to removable media. For users that require
+offsite backups, BackupPC can create archives that stream to tape
+devices, or create files of specified sizes to fit onto cd or dvd media.
+
+Each archive type is specified by a BackupPC host with its XferMethod
+set to 'archive'. This allows for multiple configurations at sites where
+there might be a combination of tape and cd/dvd backups being made.
+
+=head2 Configuring an Archive Host
+
+To create an Archive Host, add it to the hosts file just as any other host
+and call it a name that best describes the type of archive, e.g. ArchiveDLT
+
+To tell BackupPC that the Host is for Archives, create a config.pl file in
+the Archive Hosts's pc directory, adding the following line:
+
+$Conf{XferMethod} = 'archive';
+
+To further customise the archive's parameters you can adding the changed
+parameters in the host's config.pl file. The parameters are explained in the config.pl
+file.
+
+The example archive programs included with BackupPC are for a CD and
+Tape archive. The programs are called BackupPC_archivecd and
+BackupPC_archivetape. These are specified by the ArchiveClientCmd configuration
+parameter.
+
+=head2 Starting an Archive
+
+In the web interface, click on the Archive Host you wish to use. You will see a
+list of previous archives and a summary on each. By clicking the "Start Archive"
+button you are presented with the list of hosts and the approximate backup size
+(note this is raw size, not projected compressed size) Select the hosts you wish
+to archive and press the "Archive Selected Hosts" button.
+
+The next screen allows you to adjust the parameters for this archive run.
+Press the "Start the Archive" to start archiving the selected hosts with the
+parameters displayed.
+
=head1 BackupPC Design
=head2 Some design issues
diff --git a/images/icon-dir.gif b/images/icon-dir.gif
new file mode 100644
index 0000000000000000000000000000000000000000..dafa818460de25702dd31c08ed7d81e3ba6f315b
GIT binary patch
literal 426
zcmZ?wbhEHblxL7;xT?UwP&A{yzJCAy{Q?343_fY|=g(JAP%tnsV5nK@;NZYu>64I<
zz#yx}pk{pj{CNg0UWWL32It84@893Qf4`uhARr*1zrUX$vxh-ga{c=C3{6o0ZXGB7AG=zweh`H6w;xWj}34;`ug6HAIt=2*?Ypb_{;
zLd>SE%Qaz-oKEPHgO4qBc*I#;4t`M4n8}&JutP(RjcdEdyK1|J1{nqx-irE04nYZK
zMi=(Fj>gIISyLJ~~Y~sS^h+d)jegy
l6P_deayy<}bh|A0gkiC}5R*i=%Z3HknjFGfQ-oL;tO1|La&G_t
literal 0
HcmV?d00001
diff --git a/images/icon-file.gif b/images/icon-file.gif
new file mode 100644
index 0000000000000000000000000000000000000000..95a1145af951da1c4426a6452b727dc8cdeffdb2
GIT binary patch
literal 395
zcmZ?wbhEHblxL7;xT?U=(2&;O-@kwV3M+2PHQ5x0v^=u`u9ai&`7k(JR-RXurJP){~o|xw$U0!GpQ2
zt;4;xJ6^1}VnP-ZyJv04Y&j-*Cf1o#GZ%Prh%b&?>cKj1WsIbt=h~P#A@dkmHm_U1
zbF;|$n0+2B3+Z^fkBHw2V?@s
zPYi6&9i|p|=t%XSP-HopV>SOwV9-;?4xyE6%1-NgPGl8GZGJRs`z)qQO{+|#o_>~`
z>XOL!W5*nCcQ>zwhU&Chch%vvJYlMVi90
zo+=EpqnH?1u3n?LZbNlIK)ma!g-cX5)DIlwKd7?PML==e!Gml(2adWkGMzfDt|or|
znDeD82U*nAxYaMX-PyPOpb*ysH8z$fu8i_mnBP3$dVkAFxxHvV-vgBzZgao+Ty>{j
s@iL?-Id4-|-tfaZ@I2#&H2z)@g@YRxACJGdvh{V&8w@b6@T*PEc_CWneQf3IYF>
zc=f@=+&iPuC>D!h7;bwoXSG^O+9p5{)a&&EfdGOaI-Raot4Bsgcs!o4a(MCmiclzA
zUio6NSQH9H*V9+^{WIy>CwYxy{S%9q?o6t?r$?sW%q}jkuC9JH{l1)og%!f^K(|tJP3k~$NaaY~>4+wN%Xs6Np{0y&t_d4SQ>h%-M&Zw$a;XVs^4uH9
zk%Hmu&jU8Ljzpk9g16o0LOPduzLcMnCsCH8ct}^dJWEj#?Mx`I2J#CqQ72TY8+I@&$kE=D*!P>`uMO#3-LaEc7o-L0^+=(#
z%N;3qx?jL;7`MKayW&3LJf^UoFOcMyu}T`g%y&?MIRg~WU%0QY>e=qLNHHH5Pj{S$
zke)dlfI>=G!zy;a6Oh|`YKmdKDBx6=AtfQ+Lu`Zgp^E79tVfY@BxsdNlNkej+dOdD
z;TQem2HWeO*7B+&oQ$cvc-|}oc~4<$K)H@(aKF>@~>Vl1=2_~a@h!?LgIIlB|j;wHHQSFJOfSJ)ZdofJ4ovZGcY|R
zly%ET_kH>MlmiCzCqXyWkOu9z&8{BQMdv(b{o{>n3Xv6nr8X2Z!-;CuezjYQT
zyo&qS9CK@dKOjc;NFxh5>1LGGpv8+OI(aLN!&1nmstZJaD0hbTw*A$v=$9X|nEY{R
zFdBmm9lPOh%(Xy4Ux*P`23|{e$c8G_4O7U+^MXH*$2^HMMjlC#mSfCPo*!#q7V_$y4bw!C}1G%1U
zb%C*yLj7QoPb@_Pp0lSfQ0wN?7N~@-2C5Fq2wF>;y%CMpb|%qJ_#g$X0b9)ge;3LT
zX9MfCsT+1@7UdQur|KPEtS%X#aDf}<>Fd2q+JX}8@s8W1eOC<{x0!jSBzndugPR)?
zb)$6)i{LLD88hZBmflkQI+$lC)9w(KUmAD5`Mg$|#5jVPqY{j0c2ZX&r9RiFp-|V5
zQn1{q^{@OI558!k5CR3Qq)j_;zau^oC0?kCrA+DW5L;zTD{HZYHe4|=ZfH6O7v*1n
zG7;IA*Za?;D=y_W>z(l0C}%*xje?DJTkf*AG%`ZfVr0&qtinH%ncI7}{^ZLv6}e3Y
zVYx#t-9LVFZm#IiD~6Ya>BFZZD!V=M|iKiBm>cP1PGa|k2`Lrl5_DD8ICMIy!1wNE3zdIF+ldw
+#
+# COPYRIGHT
+# Copyright (C) 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::CGI::AdminOptions;
+
+use strict;
+use BackupPC::CGI::Lib qw(:all);
+
+sub action
+{
+ unless ( CheckPermission() ) {
+ ErrorExit($Lang->{Only_privileged_users_can_view_admin_options});
+ }
+ my $content = eval("qq{$Lang->{Admin_Options_Page}}");
+ Header(eval("qq{$Lang->{H_Admin_Options}}"), $content);
+ Trailer();
+}
+
+1;
diff --git a/lib/BackupPC/CGI/Archive.pm b/lib/BackupPC/CGI/Archive.pm
new file mode 100644
index 0000000..43a9b8e
--- /dev/null
+++ b/lib/BackupPC/CGI/Archive.pm
@@ -0,0 +1,235 @@
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::Archive package
+#
+# DESCRIPTION
+#
+# This module implements the Archive action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt
+#
+# COPYRIGHT
+# Copyright (C) 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::CGI::Archive;
+
+use strict;
+use BackupPC::CGI::Lib qw(:all);
+use Data::Dumper;
+
+sub action
+{
+ if ( $In{type} == 0 ) {
+ my($fullTot, $fullSizeTot, $incrTot, $incrSizeTot, $str,
+ $strNone, $strGood, $hostCntGood, $hostCntNone, $checkBoxCnt,
+ $backupnumber);
+
+ $hostCntGood = $hostCntNone = $checkBoxCnt = $fullSizeTot = 0;
+ GetStatusInfo("hosts");
+ my $Privileged = CheckPermission();
+
+ if ( !$Privileged ) {
+ ErrorExit($Lang->{Only_privileged_users_can_archive} );
+ }
+ foreach my $host ( sort(keys(%Status)) ) {
+ my($fullDur, $incrCnt, $fullSize, $fullRate);
+ my @Backups = $bpc->BackupInfoRead($host);
+ my $fullCnt = $incrCnt = 0;
+ for ( my $i = 0 ; $i < @Backups ; $i++ ) {
+ if ( $Backups[$i]{type} eq "full" ) {
+ $fullSize = $Backups[$i]{size} / (1024 * 1024);
+ $incrSizeTot = 0;
+ } else {
+ $incrSizeTot = $Backups[$i]{size} / (1024 * 1024);
+ }
+ $backupnumber = $Backups[$i]{num};
+ }
+ $fullSizeTot += $fullSize + $incrSizeTot;
+ $fullSize = sprintf("%.2f", ($fullSize + $incrSizeTot) / 1000);
+ $str = <
+
EOF
}
- Header($Lang->{BackupPC__Queue_Summary});
-
- print ( eval ( "qq{$Lang->{Backup_Queue_Summary}}") );
-
+ my $content = eval ( "qq{$Lang->{Backup_Queue_Summary}}");
+ Header($Lang->{BackupPC__Queue_Summary}, $content);
Trailer();
}
diff --git a/lib/BackupPC/CGI/ReloadServer.pm b/lib/BackupPC/CGI/ReloadServer.pm
new file mode 100644
index 0000000..13b66b2
--- /dev/null
+++ b/lib/BackupPC/CGI/ReloadServer.pm
@@ -0,0 +1,51 @@
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::ReloadServer package
+#
+# DESCRIPTION
+#
+# This module implements the ReloadServer action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt
+#
+# COPYRIGHT
+# Copyright (C) 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::CGI::ReloadServer;
+
+use strict;
+use BackupPC::CGI::Lib qw(:all);
+
+sub action
+{
+ if ( defined($bpc) ) {
+ $bpc->ServerMesg("log User $User requested server configuration reload");
+ $bpc->ServerMesg("server reload");
+ }
+ print $Cgi->redirect($MyURL);
+}
+
+1;
diff --git a/lib/BackupPC/CGI/Restore.pm b/lib/BackupPC/CGI/Restore.pm
index f236e1e..2a6d683 100644
--- a/lib/BackupPC/CGI/Restore.pm
+++ b/lib/BackupPC/CGI/Restore.pm
@@ -42,7 +42,7 @@ use Data::Dumper;
sub action
{
- my($str, $reply);
+ my($str, $reply, $content);
my $Privileged = CheckPermission($In{host});
if ( !$Privileged ) {
ErrorExit(eval("qq{$Lang->{Only_privileged_users_can_restore_backup_files}}"));
@@ -101,19 +101,19 @@ EOF
#
# Tell the user what options they have
#
- Header(eval("qq{$Lang->{Restore_Options_for__host}}"));
- print(eval("qq{$Lang->{Restore_Options_for__host2}}"));
+ $content .= eval("qq{$Lang->{Restore_Options_for__host2}}");
#
# Verify that Archive::Zip is available before showing the
# zip restore option
#
if ( eval { require Archive::Zip } ) {
- print (eval("qq{$Lang->{Option_2__Download_Zip_archive}}"));
+ $content .= eval("qq{$Lang->{Option_2__Download_Zip_archive}}");
} else {
- print (eval("qq{$Lang->{Option_2__Download_Zip_archive2}}"));
+ $content .= eval("qq{$Lang->{Option_2__Download_Zip_archive2}}");
}
- print (eval("qq{$Lang->{Option_3__Download_Zip_archive}}"));
+ $content .= eval("qq{$Lang->{Option_3__Download_Zip_archive}}");
+ Header(eval("qq{$Lang->{Restore_Options_for__host}}"), $content);
Trailer();
} elsif ( $In{type} == 1 ) {
#
@@ -209,8 +209,8 @@ EOF
EOF
}
-
- Header(eval("qq{$Lang->{Restore___num_details_for__host}}"));
- print(eval("qq{$Lang->{Restore___num_details_for__host2 }}"));
+ my $content = eval("qq{$Lang->{Restore___num_details_for__host2 }}");
+ Header(eval("qq{$Lang->{Restore___num_details_for__host}}"),$content);
Trailer();
}
diff --git a/lib/BackupPC/CGI/StartServer.pm b/lib/BackupPC/CGI/StartServer.pm
new file mode 100644
index 0000000..d0cb973
--- /dev/null
+++ b/lib/BackupPC/CGI/StartServer.pm
@@ -0,0 +1,63 @@
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::StartServer package
+#
+# DESCRIPTION
+#
+# This module implements the StartServer action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt
+#
+# COPYRIGHT
+# Copyright (C) 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::CGI::StartServer;
+
+use strict;
+use BackupPC::CGI::Lib qw(:all);
+
+sub action
+{
+ if ( -f $Conf{ServerInitdPath}
+ && $bpc->{Conf}{ServerInitdStartCmd} ne ""
+ && !$bpc->ServerOK() ) {
+ my $args = {
+ serverInitdPath => $bpc->{Conf}{ServerInitdPath},
+ sshPath => $bpc->{Conf}{SshPath},
+ serverHost => $bpc->{Conf}{ServerHost},
+ };
+ my $serverInitdStartCmd = $bpc->cmdVarSubstitute($bpc->{Conf}{ServerInitdStartCmd}, $args);
+ $bpc->cmdSystemOrEval($serverInitdStartCmd, undef, $args);
+ for ( my $i = 0; $i < 10; $i++ ) {
+ last unless ( $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort}) );
+ sleep(1);
+ }
+ $bpc->ServerDisconnect();
+ }
+ print $Cgi->redirect($MyURL);
+}
+
+1;
diff --git a/lib/BackupPC/CGI/StartStopBackup.pm b/lib/BackupPC/CGI/StartStopBackup.pm
index 38b7f6f..e62ced2 100644
--- a/lib/BackupPC/CGI/StartStopBackup.pm
+++ b/lib/BackupPC/CGI/StartStopBackup.pm
@@ -70,17 +70,15 @@ sub action
$reply = $bpc->ServerMesg("stop ${EscURI($host)} $User $In{backoff}");
$str = eval("qq{$Lang->{Backup_stopped_dequeued_on__host_by__User}}");
}
-
- Header(eval ("qq{$Lang->{BackupPC__Backup_Requested_on__host}}") );
- print (eval ("qq{$Lang->{REPLY_FROM_SERVER}}"));
+ my $content = eval ("qq{$Lang->{REPLY_FROM_SERVER}}");
+ Header(eval ("qq{$Lang->{BackupPC__Backup_Requested_on__host}}"),$content);
Trailer();
} else {
if ( $start ) {
my $ipAddr = ConfirmIPAddress($host);
-
- Header(eval("qq{$Lang->{BackupPC__Start_Backup_Confirm_on__host}}"));
- print (eval("qq{$Lang->{Are_you_sure_start}}"));
+ my $content = eval("qq{$Lang->{Are_you_sure_start}}");
+ Header(eval("qq{$Lang->{BackupPC__Start_Backup_Confirm_on__host}}"),$content);
} else {
my $backoff = "";
GetStatusInfo("host(${EscURI($host)})");
@@ -88,8 +86,8 @@ sub action
$backoff = sprintf("%.1f",
($StatusHost{backoffTime} - time) / 3600);
}
- Header($Lang->{BackupPC__Stop_Backup_Confirm_on__host});
- print (eval ("qq{$Lang->{Are_you_sure_stop}}"));
+ my $content = eval ("qq{$Lang->{Are_you_sure_stop}}");
+ Header($Lang->{BackupPC__Stop_Backup_Confirm_on__host},$content);
}
Trailer();
}
diff --git a/lib/BackupPC/CGI/StopServer.pm b/lib/BackupPC/CGI/StopServer.pm
new file mode 100644
index 0000000..f73f4b8
--- /dev/null
+++ b/lib/BackupPC/CGI/StopServer.pm
@@ -0,0 +1,56 @@
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::StopServer package
+#
+# DESCRIPTION
+#
+# This module implements the StopServer action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt
+#
+# COPYRIGHT
+# Copyright (C) 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::CGI::StopServer;
+
+use strict;
+use BackupPC::CGI::Lib qw(:all);
+
+sub action
+{
+ if ( defined($bpc) && $bpc->ServerOK() ) {
+ $bpc->ServerMesg("log User $User requested server shutdown");
+ $bpc->ServerMesg("server shutdown");
+ for ( my $i = 0; $i < 10; $i++ ) {
+ last unless $bpc->ServerOK();
+ sleep(1);
+ }
+ sleep(2);
+ }
+ print $Cgi->redirect($MyURL);
+}
+
+1;
diff --git a/lib/BackupPC/CGI/Summary.pm b/lib/BackupPC/CGI/Summary.pm
index 0706b62..50e730b 100644
--- a/lib/BackupPC/CGI/Summary.pm
+++ b/lib/BackupPC/CGI/Summary.pm
@@ -48,15 +48,24 @@ sub action
GetStatusInfo("hosts");
my $Privileged = CheckPermission();
- if ( !$Privileged ) {
- ErrorExit($Lang->{Only_privileged_users_can_view_PC_summaries} );
- }
- foreach my $host ( sort(keys(%Status)) ) {
+ foreach my $host ( GetUserHosts() ) { ## give access to users hosts only
+ ## foreach my $host ( sort(keys(%Status)) ) {
my($fullDur, $incrCnt, $incrAge, $fullSize, $fullRate, $reasonHilite);
my($shortErr);
my @Backups = $bpc->BackupInfoRead($host);
my $fullCnt = $incrCnt = 0;
my $fullAge = $incrAge = -1;
+
+ if ( defined(my $error = $bpc->ConfigRead($host)) ) {
+ print("dump failed: Can't read PC's config file: $error\n");
+ exit(1);
+ }
+ %Conf = $bpc->Conf();
+
+ if ($Conf{XferMethod} eq "archive" ) {
+ next;
+ }
+
for ( my $i = 0 ; $i < @Backups ; $i++ ) {
if ( $Backups[$i]{type} eq "full" ) {
$fullCnt++;
@@ -102,17 +111,17 @@ sub action
}
$str = <
+EOF
+$Lang{Unable_to_connect_to_BackupPC_server} = "Unable to connect to BackupPC server",
+ "This CGI script (\$MyURL) is unable to connect to the BackupPC"
+ . " server on \$Conf{ServerHost} port \$Conf{ServerPort}. The error"
+ . " was: \$err.",
+ "Perhaps the BackupPC server is not running or there is a "
+ . " configuration error. Please report this to your Sys Admin.";
+$Lang{Admin_Start_Server} = <
+The BackupPC server at \$Conf{ServerHost} port \$Conf{ServerPort}
+is not currently running (maybe you just stopped it, or haven't yet started it).
+Do you want to start it?
+
+
+
+EOF
+
+# -----
+
$Lang{H_BackupPC_Server_Status} = "BackupPC Server Status";
$Lang{BackupPC_Server_Status}= < The servers PID is \$Info{pid}, on host \$Conf{ServerHost},
version \$Info{Version}, started at \$serverStartTime.
This status was generated at \$now.
+
The configuration was last loaded at \$configLoadTime.
@@ -69,12 +109,13 @@ EOF
# --------------------------------
$Lang{BackupPC__Server_Summary} = "BackupPC: Server Summary";
+$Lang{BackupPC__Archive} = "BackupPC: Archive";
$Lang{BackupPC_Summary}=<
This status was generated at \$now.
-
+
\${h2("Hosts with good Backups")}
@@ -85,8 +126,9 @@ There are \$hostCntGood hosts that have been backed up, for a total of:
\$incrTot incr backups of total size \${incrSizeTot}GB
(prior to pooling and compression).
-
-
Host
+
+
+
Host
User
#Full
Full Age/days
@@ -98,14 +140,13 @@ There are \$hostCntGood hosts that have been backed up, for a total of:
Last attempt
\$strGood
-
-
+
\${h2("Hosts with no Backups")}
There are \$hostCntNone hosts with no backups.
-
-
Host
+
+
Host
User
#Full
Full Age/days
@@ -119,6 +160,91 @@ There are \$hostCntNone hosts with no backups.
EOF
+$Lang{BackupPC_Archive}=<
+
+
+
+There are \$hostCntGood hosts that have been backed up for a total size of \${fullSizeTot}GB
+
@@ -269,25 +399,26 @@ $Lang{Browse_backup__num_for__host} = "BackupPC: Browse backup \$num for \$host"
# ------------------------------
$Lang{Restore_Options_for__host} = "BackupPC: Restore Options for \$host";
$Lang{Restore_Options_for__host2} = <
You have selected the following files/directories from
share \$share, backup number #\$num:
\$fileListStr
-
+
You have three choices for restoring these files/directories.
Please select one of the following options.
-
+
\${h2("Option 1: Direct Restore")}
You can start a restore that will restore these files directly onto
\$host.
-
+
Warning: any existing files that match the ones you have
selected will be overwritten!
-
-
+
+
@@ -296,8 +427,17 @@ selected will be overwritten!
Warning: depending upon which files/directories you have selected,
this archive might be very very large. It might take many minutes to
create and transfer the archive, and you will need enough local disk
space to store it.
-
+
@@ -352,7 +492,7 @@ 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
www.cpan.org.
-
Warning: depending upon which files/directories you have selected,
this archive might be very very large. It might take many minutes to
create and transfer the archive, and you will need enough local disk
space to store it.
-
+
@@ -424,6 +564,13 @@ Reply from server was: \$reply
Go back to \$hostDest home page.
EOF
+$Lang{BackupPC_Archive_Reply_from_server} = <
+Reply from server was: \$reply
+EOF
+
+
# -------------------------
$Lang{Host__host_Backup_Summary} = "BackupPC: Host \$host Backup Summary";
@@ -434,7 +581,7 @@ $Lang{Host__host_Backup_Summary2} = <
\$statusStr
-
+
\${h2("User Actions")}
Click on the backup number to browse and restore backup files.
-
-
Backup#
+
+
+
Backup#
Type
Filled
Start Date
@@ -461,11 +609,12 @@ Click on the backup number to browse and restore backup files.
\$restoreStr
-
+
+
\${h2("Xfer Error Summary")}
-
-
-
Backup#
+
+
+
Backup#
Type
View
#Xfer errs
@@ -475,20 +624,21 @@ Click on the backup number to browse and restore backup files.
\$errStr
-
+
\${h2("File Size/Count Reuse Summary")}
Existing files are those already in the pool; new files are those added
to the pool.
Empty files and SMB errors aren\'t counted in the reuse and new counts.
-
-
+
+
+
Totals
Existing Files
New Files
-
+
Backup#
Type
#Files
@@ -501,18 +651,19 @@ Empty files and SMB errors aren\'t counted in the reuse and new counts.
\$sizeStr
-
+
\${h2("Compression Summary")}
Compression performance for files already in the pool and newly
compressed files.
-
+
+
+\$ArchiveStr
+
EOF
# -------------------------
@@ -577,10 +751,10 @@ $Lang{Backup_browse_for__host} = < You are browsing backup #\$num, which started around \$backupTime
(\$backupAge days ago),
\$filledBackup
+
Enter directory:
Click on a directory below to navigate into that directory,
Click on a file below to restore that file,
You can view the backup history of the current directory.
-
Enter directory:
@@ -592,18 +766,15 @@ $Lang{Backup_browse_for__host} = <
-
EOF
@@ -706,7 +904,7 @@ $Lang{BackupPC__Lib__new_failed__check_apache_error_log} = "BackupPC::Lib->new f
$Lang{Wrong_user__my_userid_is___} =
"Wrong user: my userid is \$>, instead of \$uid"
. "(\$Conf{BackupPCUser})\n";
-$Lang{Only_privileged_users_can_view_PC_summaries} = "Only privileged users can view PC summaries.";
+# $Lang{Only_privileged_users_can_view_PC_summaries} = "Only privileged users can view PC summaries.";
$Lang{Only_privileged_users_can_stop_or_start_backups} =
"Only privileged users can stop or start backups on"
. " \${EscHTML(\$host)}.";
@@ -727,6 +925,8 @@ $Lang{Only_privileged_users_can_restore_backup_files} = "Only privileged users c
$Lang{Bad_host_name} = "Bad host name \${EscHTML(\$host)}";
$Lang{You_haven_t_selected_any_files__please_go_Back_to} = "You haven\'t selected any files; please go Back to"
. " select some files.";
+$Lang{You_haven_t_selected_any_hosts} = "You haven\'t selected any hosts; please go Back to"
+ . " select some hosts.";
$Lang{Nice_try__but_you_can_t_put} = "Nice try, but you can\'t put \'..\' in any of the file names";
$Lang{Host__doesn_t_exist} = "Host \${EscHTML(\$In{hostDest})} doesn\'t exist";
$Lang{You_don_t_have_permission_to_restore_onto_host} = "You don\'t have permission to restore onto host"
@@ -739,17 +939,12 @@ $Lang{Empty_host_name} = "Empty host name";
$Lang{Unknown_host_or_user} = "Unknown host or user \${EscHTML(\$host)}";
$Lang{Only_privileged_users_can_view_information_about} = "Only privileged users can view information about"
. " host \${EscHTML(\$host)}." ;
+$Lang{Only_privileged_users_can_view_archive_information} = "Only privileged users can view archive information.";
$Lang{Only_privileged_users_can_view_restore_information} = "Only privileged users can view restore information.";
$Lang{Restore_number__num_for_host__does_not_exist} = "Restore number \$num for host \${EscHTML(\$host)} does"
. " not exist.";
-
-$Lang{Unable_to_connect_to_BackupPC_server} = "Unable to connect to BackupPC server",
- "This CGI script (\$MyURL) is unable to connect to the BackupPC"
- . " server on \$Conf{ServerHost} port \$Conf{ServerPort}. The error"
- . " was: \$err.",
- "Perhaps the BackupPC server is not running or there is a "
- . " configuration error. Please report this to your Sys Admin.";
-
+$Lang{Archive_number__num_for_host__does_not_exist} = "Archive number \$num for host \${EscHTML(\$host)} does"
+ . " not exist.";
$Lang{Can_t_find_IP_address_for} = "Can\'t find IP address for \${EscHTML(\$host)}";
$Lang{host_is_a_DHCP_host} = <Host or User name:";
$Lang{Go} = "Go";
$Lang{Hosts} = "Hosts";
+$Lang{There_have_been_no_archives} = "
There have been no archives
\n";
$Lang{This_PC_has_never_been_backed_up} = "
This PC has never been backed up!!
\n";
$Lang{This_PC_is_used_by} = "
This PC is used by \${UserLink(\$user)}";
@@ -858,23 +1056,31 @@ EOF
$Lang{tryIP} = " and \$StatusHost{dhcpHostIP}";
-$Lang{Host_Inhost} = "Host \$In{host}";
+# $Lang{Host_Inhost} = "Host \$In{host}";
$Lang{checkAll} = <
+
Select all
-
+
EOF
+$Lang{checkAllHosts} = <
+ Select all
+
+
+
+EOF
+
$Lang{fileHeader} = <
Name
+
Name
Type
Mode
#
Size
-
Mod time
+
Date modified
EOF
@@ -887,15 +1093,15 @@ $Lang{This_display_is_merged_with_backup} = < Visit this directory in backup #\$otherDirs.
+
Select the backup you wish to view:
EOF
$Lang{Restore_Summary} = <
Click on the restore number for more details.
-
-
Restore#
+
+
Restore#
Result
Start Date
Dur/mins
@@ -909,6 +1115,21 @@ Click on the restore number for more details.
EOF
+$Lang{Archive_Summary} = <
+Click on the archive number for more details.
+
+
Archive#
+
Result
+
Start Date
+
Dur/mins
+
+\$ArchiveStr
+
+
+EOF
+
$Lang{BackupPC__Documentation} = "BackupPC: Documentation";
$Lang{No} = "no";
diff --git a/lib/BackupPC/Lib.pm b/lib/BackupPC/Lib.pm
index cf99f4b..cef6d9c 100644
--- a/lib/BackupPC/Lib.pm
+++ b/lib/BackupPC/Lib.pm
@@ -70,6 +70,9 @@ sub new
num startTime endTime result errorMsg nFiles size
tarCreateErrs xferErrs
)],
+ ArchiveFields => [qw(
+ num startTime endTime result errorMsg
+ )],
}, $class;
$bpc->{BinDir} .= "/bin";
$bpc->{LibDir} .= "/lib";
@@ -255,6 +258,51 @@ sub RestoreInfoWrite
close(LOCK);
}
+sub ArchiveInfoRead
+{
+ my($bpc, $host) = @_;
+ local(*ARCHIVE_INFO, *LOCK);
+ my(@Archives);
+
+ flock(LOCK, LOCK_EX) if open(LOCK, "$bpc->{TopDir}/pc/$host/LOCK");
+ if ( open(ARCHIVE_INFO, "$bpc->{TopDir}/pc/$host/archives") ) {
+ binmode(ARCHIVE_INFO);
+ while ( ) {
+ s/[\n\r]+//;
+ next if ( !/^(\d+.*)/ );
+ $_ = $1;
+ @{$Archives[@Archives]}{@{$bpc->{ArchiveFields}}} = split(/\t/);
+ }
+ close(ARCHIVE_INFO);
+ }
+ close(LOCK);
+ return @Archives;
+}
+
+sub ArchiveInfoWrite
+{
+ my($bpc, $host, @Archives) = @_;
+ local(*ARCHIVE_INFO, *LOCK);
+ my($i);
+
+ flock(LOCK, LOCK_EX) if open(LOCK, "$bpc->{TopDir}/pc/$host/LOCK");
+ unlink("$bpc->{TopDir}/pc/$host/archives.old")
+ if ( -f "$bpc->{TopDir}/pc/$host/archives.old" );
+ rename("$bpc->{TopDir}/pc/$host/archives",
+ "$bpc->{TopDir}/pc/$host/archives.old")
+ if ( -f "$bpc->{TopDir}/pc/$host/archives" );
+ if ( open(ARCHIVE_INFO, ">$bpc->{TopDir}/pc/$host/archives") ) {
+ binmode(ARCHIVE_INFO);
+ for ( $i = 0 ; $i < @Archives ; $i++ ) {
+ my %b = %{$Archives[$i]};
+ printf(ARCHIVE_INFO "%s\n",
+ join("\t", @b{@{$bpc->{ArchiveFields}}}));
+ }
+ close(ARCHIVE_INFO);
+ }
+ close(LOCK);
+}
+
sub ConfigRead
{
my($bpc, $host) = @_;
diff --git a/makeDist b/makeDist
index 712ca05..8c547a4 100755
--- a/makeDist
+++ b/makeDist
@@ -47,6 +47,9 @@ my $DistDir = "dist/BackupPC-$Version";
my @PerlSrc = qw(
bin/BackupPC
+ bin/BackupPC_archive
+ bin/BackupPC_archivecd
+ bin/BackupPC_archivetape
bin/BackupPC_dump
bin/BackupPC_link
bin/BackupPC_nightly
@@ -64,6 +67,9 @@ my @PerlSrc = qw(
lib/BackupPC/Lib.pm
lib/BackupPC/PoolWrite.pm
lib/BackupPC/View.pm
+ lib/BackupPC/CGI/AdminOptions.pm
+ lib/BackupPC/CGI/Archive.pm
+ lib/BackupPC/CGI/ArchiveInfo.pm
lib/BackupPC/CGI/Browse.pm
lib/BackupPC/CGI/DirHistory.pm
lib/BackupPC/CGI/EmailSummary.pm
@@ -72,16 +78,20 @@ my @PerlSrc = qw(
lib/BackupPC/CGI/Lib.pm
lib/BackupPC/CGI/LOGlist.pm
lib/BackupPC/CGI/Queue.pm
+ lib/BackupPC/CGI/ReloadServer.pm
lib/BackupPC/CGI/RestoreFile.pm
lib/BackupPC/CGI/RestoreInfo.pm
lib/BackupPC/CGI/Restore.pm
+ lib/BackupPC/CGI/StartServer.pm
lib/BackupPC/CGI/StartStopBackup.pm
+ lib/BackupPC/CGI/StopServer.pm
lib/BackupPC/CGI/Summary.pm
lib/BackupPC/CGI/View.pm
lib/BackupPC/Lang/de.pm
lib/BackupPC/Lang/en.pm
lib/BackupPC/Lang/es.pm
lib/BackupPC/Lang/fr.pm
+ lib/BackupPC/Xfer/Archive.pm
lib/BackupPC/Xfer/Smb.pm
lib/BackupPC/Xfer/Tar.pm
lib/BackupPC/Xfer/Rsync.pm
@@ -107,6 +117,7 @@ foreach my $file ( @PerlSrc ) {
$errCnt += CheckLangUsage();
exit(1) if ( $errCnt );
+$errCnt = 0;
foreach my $var ( sort(keys(%$ConfVars) ) ) {
next if ( $ConfVars->{$var} >= 2 || $var =~ /^\$/ );
printf("Unused config parameter $var\n");
@@ -335,7 +346,11 @@ sub CheckLangUsage
}
close(F);
}
- foreach my $f ( ) {
+ # CB: disable other lang checks for now
+ #
+ # foreach my $f ( ) {
+ #
+ foreach my $f ( ) {
my $done = {};
open(F, $f) || die("can't open $f\n");
binmode(F);
@@ -343,7 +358,7 @@ sub CheckLangUsage
s/#.*//g;
s/\$Lang{([^}]*)}/
my $var = $1;
- next if ( $var =~ m{^(Reason_|Status_)} );
+ next if ( $var =~ m{^(Reason_|Status_|backupType_)} );
if ( !defined($vars->{$var}) ) {
print("Unexpected Lang var $var in $f\n");
$errors++;
--
2.20.1