# 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.
$Info{ConfigModTime} = $bpc->ConfigMTime();
$Info{pid} = $$;
$Info{startTime} = time;
+ $Info{ConfigLTime} = time;
$Info{Version} = $bpc->{Version};
#
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)
$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";
= 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]} ) {
# 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 = "";
}
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";
$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;
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;
$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);
+}
+
--- /dev/null
+#!/bin/perl -T
+#============================================================= -*-perl-*-
+#
+# BackupPC_archive: Archive files for an archive client.
+#
+# DESCRIPTION
+#
+# Usage: BackupPC_archive <user> <archiveclient> <reqFileName>
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# COPYRIGHT
+# Copyright (C) 2001-2003 Craig Barratt
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+#========================================================================
+#
+# Version 2.1.0_CVS, released 3 Jul 2003.
+#
+# See http://backuppc.sourceforge.net.
+#
+#========================================================================
+
+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 <user> <archiveclient> <reqFileName>\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);
+}
--- /dev/null
+#!/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 <cbarratt@users.sourceforge.net>
+#
+# COPYRIGHT
+# Copyright (C) 2001-2003 Craig Barratt
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+#========================================================================
+#
+# Version 2.1.0_CVS, released 3 Jul 2003.
+#
+# See http://backuppc.sourceforge.net.
+#
+#========================================================================
+
+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.*
--- /dev/null
+#!/bin/sh
+#=============================================================
+#
+# BackupPC_archivetape: Archive files to a tape host
+#
+# DESCRIPTION
+#
+# Usage: BackupPC_archivecd tarCreate host backupnumber compression archiveloc share
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# COPYRIGHT
+# Copyright (C) 2001-2003 Craig Barratt
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+#========================================================================
+#
+# Version 2.1.0_CVS, released 3 Jul 2003.
+#
+# See http://backuppc.sourceforge.net.
+#
+#========================================================================
+
+tarCreate=$1
+host=$2
+backupnumber=$3
+compression=$4
+archiveloc=$5
+share=$6
+
+$tarCreate -h $host -n $backupnumber -s $share $share | $compression > $archiveloc
#
$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);
$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)
}
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
# 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");
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);
}
$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",
"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"
#
$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
#
$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.
#
$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.
#
$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
# $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
$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.
# $Conf{CgiImageDirURL} = '/BackupPC';
#
$Conf{CgiImageDirURL} = '';
+
+#
+# CSS stylesheet for the CGI interface.
+#
+$Conf{CSSstylesheet} = <<'EOF';
+<style type="text/css">
+body {
+ font-family:arial,sans-serif;
+ font-size:1em;
+ background-color:#ffffff;
+ margin:2px 5px 0px 2px;
+ height:100%
+}
+
+h1 {
+ font-family:arial,sans-serif;
+ font-size:1.5em;
+ color:#000000
+}
+
+h2 {
+ font-family:arial,sans-serif;
+ font-size:1em;
+ color:#000000
+}
+
+p {
+ font-family:arial,sans-serif;
+ font-size:.8em
+}
+
+a {
+ font-family:arial,sans-serif;
+ font-size:1em;
+ color:#3333ff
+}
+
+a:hover {
+ color:#cc0000;
+ text-decoration:none
+}
+
+a.NavCurrent {
+ font-weight:bold;
+ padding-left:5px;
+ padding-right:5px;
+}
+
+a.navbar {
+ padding-left:5px;
+ padding-right:5px;
+}
+
+.h1 {
+ font-family:arial,sans-serif;
+ font-size:1.5em;
+ color:#000000;
+ font-weight:bold;
+ background-color:#99cc33;
+ padding:3px;
+ padding-left:10px
+}
+
+.h2 {
+ font-family:arial,sans-serif;
+ font-size:1em;
+ color:#000000;
+ font-weight:bold;
+ background-color:#ddeeee;
+ padding:3px;
+ padding-left:10px
+}
+
+.border {
+ border-bottom:1px solid #000000;
+ border-left:1px dotted #666666
+}
+
+.tableheader {
+ font-weight:bold;
+ background-color:#cccccc
+}
+
+.fviewheader {
+ font-weight:bold;
+ color:#ffffff;
+ background-color:#999999
+}
+
+.fviewborder {
+ border-bottom:1px solid #000000;
+ border-left:1px dotted #666666;
+ background-color:#dddddd
+}
+
+.fviewon {
+ background-color:#cccccc
+}
+
+.fviewoff {
+ background-color:#ffffff
+}
+
+.fview {
+ font-size:13px;
+ font-family:arial,sans-serif;
+ text-decoration:none;
+ line-height:15px
+}
+
+.fviewbold {
+ font-size:13px;
+ font-family:arial,sans-serif;
+ text-decoration:none;
+ line-height:15px;
+ font-weight:bold
+}
+
+.histView {
+ border-bottom:1px solid #000000;
+ border-left:2px solid #ffffff;
+ background-color:#dddddd
+}
+
+.histViewMis {
+ border-bottom:1px solid #000000;
+ background-color:#ffdddd
+}
+
+div.NavMenu {
+ width:18%;
+ margin:0px;
+ background-color:#ddeeee;
+}
+
+div.NavMenu a {
+ font-size:.8em;
+ display:block;
+ margin-left:8px;
+ padding:3px;
+}
+
+div.NavTitle {
+ padding-left:10px;
+ background-color:#99cc33;
+ font-family:arial,sans-serif;
+ color:#000000;
+ font-weight:bold
+}
+
+div.HostOn {
+ width:18%;
+ background-color:#ddeeee;
+ padding:3px;
+ padding-left:10px;
+}
+
+div.HostOnContent {
+ background-color:#ddeeee;
+ padding:5px;
+}
+
+div.HostOnContent a {
+ font-size:.8em;
+ display:block;
+}
+
+#Content {
+ float:right;
+ width:80%;
+ left:20%;
+ top:10px;
+ position:absolute;
+}
+</style>
+EOF
'ssh/ssh2' => "SshPath",
sendmail => "SendmailPath",
hostname => "HostnamePath",
+ split => "SplitPath",
+ par => "ParPath",
+ cat => "CatPath",
+ gzip => "GzipPath",
+ bzip2 => "Bzip2Path",
);
foreach my $prog ( sort(keys(%Programs)) ) {
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);
}
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
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
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
) ) {
- 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
my($out, @conf, $var);
my $comment = 1;
my $allVars = {};
+ my $endLine = undef;
while ( <C> ) {
- if ( /^#/ ) {
+ if ( /^#/ && !defined($endLine) ) {
if ( $comment ) {
$out .= $_;
} else {
$out .= $_;
}
$var = $1;
+ $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<(.*);/ );
+ $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<'(.*)';/ );
} else {
+ $endLine = undef if ( defined($endLine) && /^\Q$endLine[\n\r]*$/ );
$out .= $_;
}
}
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
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
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
echo -n "Shutting down BackupPC: "
killproc __INSTALLDIR__/bin/BackupPC
RETVAL=$?
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/backupcpc
+ [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/backuppc
echo ""
return $RETVAL
}
--- /dev/null
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::AdminOptions package
+#
+# DESCRIPTION
+#
+# This module implements the AdminOptions action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# 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;
--- /dev/null
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::Archive package
+#
+# DESCRIPTION
+#
+# This module implements the Archive action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# 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;
+<tr bgcolor="#ffffcc">
+<td><input type="hidden" name="backup$checkBoxCnt" value="$backupnumber"><input type="checkbox" name="fcb$checkBoxCnt" value="$host"> ${HostLink($host)} </td>
+<td align="center"> ${UserLink($Hosts->{$host}{user})} </td>
+<td align="center"> $fullSize </td>
+EOF
+ $checkBoxCnt++;
+ if ( @Backups == 0 ) {
+ $hostCntNone++;
+ $strNone .= $str;
+ } else {
+ $hostCntGood++;
+ $strGood .= $str;
+ }
+ }
+ $fullSizeTot = sprintf("%.2f", $fullSizeTot / 1000);
+ my $now = timeStamp2(time);
+ my $checkAllHosts = $Lang->{checkAllHosts};
+ $strGood .= <<EOF;
+<input type="hidden" name="archivehost" value="$In{'archivehost'}">
+EOF
+ Header($Lang->{BackupPC__Archive});
+ print eval ("qq{$Lang->{BackupPC_Archive}}");
+
+ Trailer();
+ } else {
+
+ my(@HostList, @BackupList, $HostListStr, $hiddenStr, $pathHdr, $badFileCnt, $reply, $str);
+
+ my $Privileged = CheckPermission();
+ my $args = {
+ SplitPath => $bpc->{Conf}{SplitPath},
+ ParPath => $bpc->{Conf}{ParPath},
+ CatPath => $bpc->{Conf}{CatPath},
+ GzipPath => $bpc->{Conf}{GzipPath},
+ Bzip2Path => $bpc->{Conf}{Bzip2Path},
+ ArchiveDest => $bpc->{Conf}{ArchiveDest},
+ ArchiveComp => $bpc->{Conf}{ArchiveComp},
+ ArchivePar => $bpc->{Conf}{ArchivePar},
+ ArchiveSplit => $bpc->{Conf}{ArchiveSplit},
+ topDir => $bpc->{TopDir},
+ };
+
+ if ( !$Privileged ) {
+ ErrorExit($Lang->{Only_privileged_users_can_archive} );
+ }
+ ServerConnect();
+
+ for ( my $i = 0 ; $i < $In{fcbMax} ; $i++ ) {
+ next if ( !defined($In{"fcb$i"}) );
+ my $name = $In{"fcb$i"};
+ my $backupno = $In{"backup$i"};
+ push(@HostList, $name);
+ push(@BackupList, $backupno);
+ $hiddenStr .= <<EOF;
+<input type="hidden" name="fcb$i" value="$In{'fcb' . $i}">
+<input type="hidden" name="backup$i" value="$In{'backup' . $i}">
+EOF
+ $HostListStr .= <<EOF;
+<li> ${EscHTML($name)}
+EOF
+ }
+ $hiddenStr .= <<EOF;
+<input type="hidden" name="archivehost" value="$In{'archivehost'}">
+EOF
+ $hiddenStr .= "<input type=\"hidden\" name=\"fcbMax\" value=\"$In{fcbMax}\">\n";
+ if ( @HostList == 0 ) {
+ ErrorExit($Lang->{You_haven_t_selected_any_hosts});
+ }
+ my ($ArchiveDest, $ArchiveCompNone, $ArchiveCompGzip, $ArchiveCompBzip2, $ArchivePar, $ArchiveSplit);
+ $ArchiveDest = $bpc->{Conf}{ArchiveDest};
+ if ( $bpc->{Conf}{ArchiveComp} eq "none" ) {
+ $ArchiveCompNone = "checked";
+ } else {
+ $ArchiveCompNone = "";
+ }
+ if ( $bpc->{Conf}{ArchiveComp} eq "gzip" ) {
+ $ArchiveCompGzip = "checked";
+ } else {
+ $ArchiveCompGzip = "";
+ }
+ if ( $bpc->{Conf}{ArchiveComp} eq "bzip2" ) {
+ $ArchiveCompBzip2 = "checked";
+ } else {
+ $ArchiveCompBzip2 = "";
+ }
+ $ArchivePar = $bpc->{Conf}{ArchivePar};
+ $ArchiveSplit = $bpc->{Conf}{ArchiveSplit};
+
+ if ( $In{type} == 1 ) {
+ #
+ # Tell the user what options they have
+ #
+
+ Header($Lang->{BackupPC__Archive});
+ print eval ("qq{$Lang->{BackupPC_Archive2}}");
+ Trailer();
+ } elsif ( $In{type} == 2 ) {
+ my $reqFileName;
+ my $archivehost = $1 if ( $In{archivehost} =~ /(.+)/ );
+ for ( my $i = 0 ; ; $i++ ) {
+ $reqFileName = "archiveReq.$$.$i";
+ last if ( !-f "$TopDir/pc/$archivehost/$reqFileName" );
+ }
+ my $compname;
+ if ( $In{compression} == 2 ) { # bzip2 compression
+ $compname = $Conf{Bzip2Path};
+ } elsif ( $In{compression} == 1 ) { # gzip compression
+ $compname = $Conf{GzipPath};
+ } else { # No Compression
+ $compname = $Conf{CatPath};
+ }
+ my $compext;
+ if ( $In{compression} == 2 ) { # bzip2 compression
+ $compext = '.bz2';
+ } elsif ( $In{compression} == 1 ) { # gzip compression
+ $compext = '.gz';
+ } else { # No Compression
+ $compext = '.raw';
+ }
+ my $fullsplitsize = $In{splitsize} . '000000';
+ my %ArchiveReq = (
+ # parameters for the archive
+ archiveloc => $In{archive_device},
+ archtype => $In{archive_type},
+ compression => $compname,
+ compext => $compext,
+ parfile => $In{par},
+ splitsize => $fullsplitsize,
+ host => $archivehost,
+
+
+ # list of hosts to restore
+ HostList => \@HostList,
+ BackupList => \@BackupList,
+
+ # other info
+ user => $User,
+ reqTime => time,
+ );
+ my($archive) = Data::Dumper->new(
+ [ \%ArchiveReq],
+ [qw(*ArchiveReq)]);
+ $archive->Indent(1);
+ if ( open(REQ, ">$TopDir/pc/$archivehost/$reqFileName") ) {
+ binmode(REQ);
+ print(REQ $archive->Dump);
+ close(REQ);
+ } else {
+ ErrorExit($Lang->{Can_t_open_create} );
+ }
+ $reply = $bpc->ServerMesg("archive $User $archivehost $reqFileName");
+
+ $str = eval("qq{$Lang->{Archive_requested}}");
+ Header($Lang->{BackupPC__Archive});
+ print eval ("qq{$Lang->{BackupPC_Archive_Reply_from_server}}");
+ Trailer();
+ }
+
+ }
+
+}
+
+1;
--- /dev/null
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::ArchiveInfo package
+#
+# DESCRIPTION
+#
+# This module implements the ArchiveInfo action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# 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::ArchiveInfo;
+
+use strict;
+use BackupPC::CGI::Lib qw(:all);
+
+sub action
+{
+ my $Privileged = CheckPermission($In{host});
+ my $host = $1 if ( $In{host} =~ /(.*)/ );
+ my $num = $In{num};
+ my $i;
+
+ if ( !$Privileged ) {
+ ErrorExit($Lang->{Only_privileged_users_can_view_archive_information});
+ }
+ #
+ # Find the requested archive
+ #
+ my @Archives = $bpc->ArchiveInfoRead($host);
+ for ( $i = 0 ; $i < @Archives ; $i++ ) {
+ last if ( $Archives[$i]{num} == $num );
+ }
+ if ( $i >= @Archives ) {
+ ErrorExit(eval("qq{$Lang->{Archive_number__num_for_host__does_not_exist}}"));
+ }
+
+ %ArchiveReq = ();
+ do "$TopDir/pc/$host/ArchiveInfo.$Archives[$i]{num}"
+ if ( -f "$TopDir/pc/$host/ArchiveInfo.$Archives[$i]{num}" );
+
+ my $startTime = timeStamp2($Archives[$i]{startTime});
+ my $reqTime = timeStamp2($ArchiveReq{reqTime});
+ my $dur = $Archives[$i]{endTime} - $Archives[$i]{startTime};
+ $dur = 1 if ( $dur <= 0 );
+ my $duration = sprintf("%.1f", $dur / 60);
+
+ my $HostListStr = "";
+ my $counter=0;
+ foreach my $f ( @{$ArchiveReq{HostList}} ) {
+ $HostListStr .= <<EOF;
+<tr><td>$f</td><td>@{$ArchiveReq{BackupList}}[$counter]</td></tr>
+EOF
+ $counter++;
+ }
+
+ Header(eval("qq{$Lang->{Archive___num_details_for__host}}"));
+ print(eval("qq{$Lang->{Archive___num_details_for__host2 }}"));
+ Trailer();
+}
+
+1;
# Find the requested backup and the previous filled backup
#
my @Backups = $bpc->BackupInfoRead($host);
+
+ #
+ # default to the newest backup
+ #
+ if ( !defined($In{num}) && defined(@Backups) ) {
+ $i = @Backups - 1;
+ $num = $Backups[$i]{num};
+ }
+
for ( $i = 0 ; $i < @Backups ; $i++ ) {
last if ( $Backups[$i]{num} == $num );
}
# Display directory if it exists in current backup.
# First find out if there are subdirs
#
- my($bold, $unbold, $BGcolor);
+ my $tdStyle;
+ my $linkStyle = "fview";
$img |= 1 << 6;
$img |= 1 << 5 if ( $attr->{$f}{nlink} > 2 );
if ( $dirOpen ) {
- $bold = "<b>";
- $unbold = "</b>";
+ $linkStyle = "fviewbold";
$img |= 1 << 2;
$img |= 1 << 3 if ( $attr->{$f}{nlink} > 2 );
}
my $imgFileName = sprintf("%07b.gif", $img);
$imgStr = "<img src=\"$Conf{CgiImageDirURL}/$imgFileName\" align=\"absmiddle\" width=\"9\" height=\"19\" border=\"0\">";
if ( "$relDir/$f" eq $dir ) {
- $BGcolor = " bgcolor=\"$Conf{CgiHeaderBgColor}\"";
+ $tdStyle = "fviewon";
} else {
- $BGcolor = "";
+ $tdStyle = "fviewoff";
}
my $dirName = $f;
$dirName =~ s/ / /g;
push(@DirStr, {needTick => 1,
- tdArgs => $BGcolor,
+ tdArgs => " class=\"$tdStyle\"",
link => <<EOF});
-<a href="$MyURL?action=browse&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path">$imgStr</a><a href="$MyURL?action=browse&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path" style="font-size:13px;font-family:arial;text-decoration:none;line-height:15px"> $bold$dirName$unbold</a></td></tr>
+<a href="$MyURL?action=browse&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path">$imgStr</a><a href="$MyURL?action=browse&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path" class="$linkStyle"> $dirName</a></td></tr>
EOF
$fileCnt++;
$gotDir = 1;
#
# This is the selected directory, so display all the files
#
- my $attrStr;
+ my ($attrStr, $iconStr);
if ( defined($a = $attr->{$f}) ) {
my $mtimeStr = $bpc->timeStamp($a->{mtime});
# UGH -> fix this
my $typeStr = BackupPC::Attrib::fileType2Text(undef,
$a->{type});
my $modeStr = sprintf("0%o", $a->{mode} & 07777);
+ $iconStr = <<EOF;
+<img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" align="center">
+EOF
$attrStr .= <<EOF;
- <td align="center">$typeStr</td>
- <td align="center">$modeStr</td>
- <td align="center">$a->{backupNum}</td>
- <td align="right">$a->{size}</td>
- <td align="right">$mtimeStr</td>
+ <td align="center" class="fviewborder">$typeStr</td>
+ <td align="center" class="fviewborder">$modeStr</td>
+ <td align="center" class="fviewborder">$a->{backupNum}</td>
+ <td align="right" class="fviewborder">$a->{size}</td>
+ <td align="right" class="fviewborder">$mtimeStr</td>
</tr>
EOF
} else {
- $attrStr .= "<td colspan=\"5\" align=\"center\"> </td>\n";
+ $attrStr .= "<td colspan=\"5\" align=\"center\" class=\"fviewborder\"> </td>\n";
}
(my $fDisp = "${EscHTML($f)}") =~ s/ / /g;
if ( $gotDir ) {
$fileStr .= <<EOF;
-<tr bgcolor="#ffffcc"><td><input type="checkbox" name="fcb$checkBoxCnt" value="$path"> <a href="$MyURL?action=browse&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path">$fDisp</a></td>
+<tr><td class="fviewborder">
+ <table cellpadding="0" cellspacing="0" border="0"><tr><td>
+ <input type="checkbox" name="fcb$checkBoxCnt" value="$path"> $iconStr
+ </td><td>
+ <a href="$MyURL?action=browse&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path">$fDisp</a>
+ </td></tr></table>
+</td>
$attrStr
</tr>
EOF
} else {
$fileStr .= <<EOF;
-<tr bgcolor="#ffffcc"><td><input type="checkbox" name="fcb$checkBoxCnt" value="$path"> <a href="$MyURL?action=RestoreFile&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path">$fDisp</a></td>
+<tr><td class="fviewborder">
+ <table cellpadding="0" cellspacing="0" border="0"><tr><td>
+ <input type="checkbox" name="fcb$checkBoxCnt" value="$path"> $iconStr
+ </td><td>
+ <a href="$MyURL?action=RestoreFile&host=${EscURI($host)}&num=$num&share=$shareURI&dir=$path">$fDisp</a>
+ </td></tr></table>
+</td>
$attrStr
</tr>
EOF
my $numF = join(", #", @mergeNums);
$filledBackup = eval("qq{$Lang->{This_display_is_merged_with_backup}}");
}
- Header(eval("qq{$Lang->{Browse_backup__num_for__host}}"));
foreach my $d ( @DirStrPrev ) {
$dirStr .= "<tr><td$d->{tdArgs}>$d->{link}\n";
$pathURI =~ s/([^\w.\/-])/uc sprintf("%%%02x", ord($1))/eg;
$shareURI =~ s/([^\w.\/-])/uc sprintf("%%%02x", ord($1))/eg;
foreach my $i ( $view->backupList($share, $dir) ) {
- push(@otherDirs, "<a href=\"$MyURL?action=browse&host=${EscURI($host)}"
- . "&num=$i&share=$shareURI&dir=$pathURI\">$i</a>");
+ push(@otherDirs, $i);
}
if ( @otherDirs ) {
my $otherDirs = join(",\n", @otherDirs);
+ my $inc = 0;
+ foreach my $value (@otherDirs) {
+ my $selected = undef;
+ my $showDate = timeStamp2($Backups[$inc]{startTime});
+ $selected = " selected" if ($value == $num);
+ $otherDirs .= "<option value=\"$MyURL?action=browse&host=${EscURI($host)}&num=$value\"$selected>#$value - ($showDate)</option>\n";
+ $inc++;
+ }
$filledBackup .= eval("qq{$Lang->{Visit_this_directory_in_backup}}");
}
- print (eval("qq{$Lang->{Backup_browse_for__host}}"));
+ my $content = eval("qq{$Lang->{Backup_browse_for__host}}");
+ Header(eval("qq{$Lang->{Browse_backup__num_for__host}}"), $content);
Trailer();
}
my %inode2name;
my $nameCnt = 0;
(my $fDisp = "${EscHTML($f)}") =~ s/ / /g;
- $fileStr .= "<tr><td align=left>$fDisp</td>";
- my($colSpan, $url, $inode, $type, $tdColor);
+ $fileStr .= "<tr><td align=\"left\" class=\"histView\">$fDisp</td>";\r
+ my($colSpan, $url, $inode, $type);\r
+ my $tdClass = ' class="histView"';\r
for ( $i = 0 ; $i < @Backups ; $i++ ) {
my($path);
if ( $colSpan > 0 ) {
$colSpan++;
next;
}
- $fileStr .= "<td align=center colspan=$colSpan$tdColor>"
+ $fileStr .= "<td align=center colspan=$colSpan$tdClass>"\r
. "$url</td>";
$colSpan = 0;
- $tdColor = "";
+ $tdClass = ' class="histView"';\r
}
if ( !defined($hist->{$f}[$i]) ) {
$colSpan = 1;
$url = " ";
$inode = -3; # special value for missing
- $tdColor = ' bgcolor="#ffffaa"';
+ $tdClass = ' class="histViewMis"';\r
next;
}
if ( $dir eq "" ) {
$colSpan = 1;
}
if ( $colSpan > 0 ) {
- $fileStr .= "<td align=center colspan=$colSpan$tdColor>$url</td>";
+ $fileStr .= "<td align=center colspan=$colSpan$tdClass>$url</td>";\r
$colSpan = 0;
}
$fileStr .= "</tr>\n";
$dirDisplay =~ s{//+}{/}g;
$dirDisplay =~ s{/+$}{}g;
$dirDisplay = "/" if ( $dirDisplay eq "" );
-
- Header(eval("qq{$Lang->{DirHistory_backup_for__host}}"));
-
- print (eval("qq{$Lang->{DirHistory_for__host}}"));
-
+ my $content = eval("qq{$Lang->{DirHistory_for__host}}");\r
+ Header(eval("qq{$Lang->{DirHistory_backup_for__host}}"), $content);\r
Trailer();
}
foreach my $t ( sort({$b <=> $a} keys(%EmailStr)) ) {
$str .= $EmailStr{$t};
}
- Header($Lang->{Email_Summary});
- print (eval("qq{$Lang->{Recent_Email_Summary}}"));
+ my $content = eval("qq{$Lang->{Recent_Email_Summary}}");
+ Header($Lang->{Email_Summary}, $content);
Trailer();
}
(my $cmd = $Jobs{$host}{cmd}) =~ s/$BinDir\///g;
(my $xferPid = $Jobs{$host}{xferPid}) =~ s/,/, /g;
$jobStr .= <<EOF;
-<tr><td> ${HostLink($host)} </td>
- <td align="center"> $Jobs{$host}{type} </td>
- <td align="center"> ${UserLink(defined($Hosts->{$host})
+<tr><td class="border"> ${HostLink($host)} </td>
+ <td align="center" class="border"> $Jobs{$host}{type} </td>
+ <td align="center" class="border"> ${UserLink(defined($Hosts->{$host})
? $Hosts->{$host}{user} : "")} </td>
- <td> $startTime </td>
- <td> $cmd </td>
- <td align="center"> $Jobs{$host}{pid} </td>
- <td align="center"> $xferPid </td>
+ <td class="border"> $startTime </td>
+ <td class="border"> $cmd </td>
+ <td align="center" class="border"> $Jobs{$host}{pid} </td>
+ <td align="center" class="border"> $xferPid </td>
EOF
$jobStr .= "</tr>\n";
}
}
(my $shortErr = $Status{$host}{error}) =~ s/(.{48}).*/$1.../;
$statusStr .= <<EOF;
-<tr><td> ${HostLink($host)} </td>
- <td align="center"> $Status{$host}{type} </td>
- <td align="center"> ${UserLink(defined($Hosts->{$host})
+<tr><td class="border"> ${HostLink($host)} </td>
+ <td align="center" class="border"> $Status{$host}{type} </td>
+ <td align="center" class="border"> ${UserLink(defined($Hosts->{$host})
? $Hosts->{$host}{user} : "")} </td>
- <td align="right"> $startTime </td>
- <td> $XferViewStr </td>
- <td align="right"> $errorTime </td>
- <td> ${EscHTML($shortErr)} </td></tr>
+ <td align="right" class="border"> $startTime </td>
+ <td class="border"> $XferViewStr </td>
+ <td align="right" class="border"> $errorTime </td>
+ <td class="border"> ${EscHTML($shortErr)} </td></tr>
EOF
}
my $now = timeStamp2(time);
my $numUserQueue = $QueueLen{UserQueue};
my $numCmdQueue = $QueueLen{CmdQueue};
my $serverStartTime = timeStamp2($Info{startTime});
+ my $configLoadTime = timeStamp2($Info{ConfigLTime});
my $poolInfo = genPoolInfo("pool", \%Info);
my $cpoolInfo = genPoolInfo("cpool", \%Info);
if ( $Info{poolFileCnt} > 0 && $Info{cpoolFileCnt} > 0 ) {
} elsif ( $Info{cpoolFileCnt} > 0 ) {
$poolInfo = $cpoolInfo;
}
-
- Header($Lang->{H_BackupPC_Server_Status});
- print (eval ("qq{$Lang->{BackupPC_Server_Status}}"));
+ my $content = eval ("qq{$Lang->{BackupPC_Server_Status}}");
+ Header($Lang->{H_BackupPC_Server_Status}, $content);
Trailer();
}
}
ReadUserEmailInfo();
+ if ($Conf{XferMethod} eq "archive" ) {
+ my @Archives = $bpc->ArchiveInfoRead($host);
+ my ($ArchiveStr,$warnStr);
+
+ for ( my $i = 0 ; $i < @Archives ; $i++ ) {
+ my $startTime = timeStamp2($Archives[$i]{startTime});
+ my $dur = $Archives[$i]{endTime} - $Archives[$i]{startTime};
+ $dur = 1 if ( $dur <= 0 );
+ my $duration = sprintf("%.1f", $dur / 60);
+ my $Archives_Result = $Lang->{failed};
+ if ($Archives[$i]{result} ne "failed") { $Archives_Result = $Lang->{success}; }
+ $ArchiveStr .= <<EOF;
+<tr><td align="center"><a href="$MyURL?action=archiveInfo&num=$Archives[$i]{num}&host=${EscURI($host)}">$Archives[$i]{num}</a> </td>
+ <td align="center"> $Archives_Result </td>
+ <td align="right"> $startTime </td>
+ <td align="right"> $duration </td>
+</tr>
+EOF
+ }
+ if ( $ArchiveStr ne "" ) {
+ $ArchiveStr = eval("qq{$Lang->{Archive_Summary}}");
+ }
+ if ( @Archives == 0 ) {
+ $warnStr = $Lang->{There_have_been_no_archives};
+ }
+ if ( $StatusHost{BgQueueOn} ) {
+ $statusStr .= eval("qq{$Lang->{Host_host_is_queued_on_the_background_queue_will_be_backed_up_soon}}");
+ }
+ if ( $StatusHost{UserQueueOn} ) {
+ $statusStr .= eval("qq{$Lang->{Host_host_is_queued_on_the_user_queue__will_be_backed_up_soon}}");
+ }
+ if ( $StatusHost{CmdQueueOn} ) {
+ $statusStr .= eval("qq{$Lang->{A_command_for_host_is_on_the_command_queue_will_run_soon}}");
+ }
+
+ my $content = eval("qq{$Lang->{Host__host_Archive_Summary2}}");
+ Header(eval("qq{$Lang->{Host__host_Archive_Summary}}"), $content);
+ Trailer();
+ return;
+ }
+
+ #
+ # Normal, non-archive case
+ #
my @Backups = $bpc->BackupInfoRead($host);
my($str, $sizeStr, $compStr, $errStr, $warnStr);
for ( my $i = 0 ; $i < @Backups ; $i++ ) {
my $filled = $Backups[$i]{noFill} ? $Lang->{No} : $Lang->{Yes};
$filled .= " ($Backups[$i]{fillFromNum}) "
if ( $Backups[$i]{fillFromNum} ne "" );
- my $ltype = $Lang->{"backupType_$Backups[$i]{type}"};
+ my $ltype = $Lang->{"backupType_$Backups[$i]{type}"};
$str .= <<EOF;
-<tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
- <td align="center"> $ltype </td>
- <td align="center"> $filled </td>
- <td align="right"> $startTime </td>
- <td align="right"> $duration </td>
- <td align="right"> $age </td>
- <td align="left"> <tt>$TopDir/pc/$host/$Backups[$i]{num}</tt> </td></tr>
+<tr><td align="center" class="border"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
+ <td align="center" class="border"> $ltype </td>
+ <td align="center" class="border"> $filled </td>
+ <td align="right" class="border"> $startTime </td>
+ <td align="right" class="border"> $duration </td>
+ <td align="right" class="border"> $age </td>
+ <td align="left" class="border"> <tt>$TopDir/pc/$host/$Backups[$i]{num}</tt> </td></tr>
EOF
$sizeStr .= <<EOF;
-<tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
- <td align="center"> $ltype </td>
- <td align="right"> $Backups[$i]{nFiles} </td>
- <td align="right"> $MB </td>
- <td align="right"> $MBperSec </td>
- <td align="right"> $Backups[$i]{nFilesExist} </td>
- <td align="right"> $MBExist </td>
- <td align="right"> $Backups[$i]{nFilesNew} </td>
- <td align="right"> $MBNew </td>
+<tr><td align="center" class="border"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
+ <td align="center" class="border"> $ltype </td>
+ <td align="right" class="border"> $Backups[$i]{nFiles} </td>
+ <td align="right" class="border"> $MB </td>
+ <td align="right" class="border"> $MBperSec </td>
+ <td align="right" class="border"> $Backups[$i]{nFilesExist} </td>
+ <td align="right" class="border"> $MBExist </td>
+ <td align="right" class="border"> $Backups[$i]{nFilesNew} </td>
+ <td align="right" class="border"> $MBNew </td>
</tr>
EOF
- my $is_compress = $Backups[$i]{compress} || $Lang->{off};
- if (! $ExistComp) { $ExistComp = " "; }
- if (! $MBExistComp) { $MBExistComp = " "; }
+ my $is_compress = $Backups[$i]{compress} || $Lang->{off};
+ if (! $ExistComp) { $ExistComp = " "; }
+ if (! $MBExistComp) { $MBExistComp = " "; }
$compStr .= <<EOF;
-<tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
- <td align="center"> $ltype </td>
- <td align="center"> $is_compress </td>
- <td align="right"> $MBExist </td>
- <td align="right"> $MBExistComp </td>
- <td align="right"> $ExistComp </td>
- <td align="right"> $MBNew </td>
- <td align="right"> $MBNewComp </td>
- <td align="right"> $NewComp </td>
+<tr><td align="center" class="border"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
+ <td align="center" class="border"> $ltype </td>
+ <td align="center" class="border"> $is_compress </td>
+ <td align="right" class="border"> $MBExist </td>
+ <td align="right" class="border"> $MBExistComp </td>
+ <td align="right" class="border"> $ExistComp </td>
+ <td align="right" class="border"> $MBNew </td>
+ <td align="right" class="border"> $MBNewComp </td>
+ <td align="right" class="border"> $NewComp </td>
</tr>
EOF
$errStr .= <<EOF;
-<tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
- <td align="center"> $ltype </td>
- <td align="center"> <a href="$MyURL?action=view&type=XferLOG&num=$Backups[$i]{num}&host=${EscURI($host)}">$Lang->{XferLOG}</a>,
+<tr><td align="center" class="border"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
+ <td align="center" class="border"> $ltype </td>
+ <td align="center" class="border"> <a href="$MyURL?action=view&type=XferLOG&num=$Backups[$i]{num}&host=${EscURI($host)}">$Lang->{XferLOG}</a>,
<a href="$MyURL?action=view&type=XferErr&num=$Backups[$i]{num}&host=${EscURI($host)}">$Lang->{Errors}</a> </td>
- <td align="right"> $Backups[$i]{xferErrs} </td>
- <td align="right"> $Backups[$i]{xferBadFile} </td>
- <td align="right"> $Backups[$i]{xferBadShare} </td>
- <td align="right"> $Backups[$i]{tarErrs} </td></tr>
+ <td align="right" class="border"> $Backups[$i]{xferErrs} </td>
+ <td align="right" class="border"> $Backups[$i]{xferBadFile} </td>
+ <td align="right" class="border"> $Backups[$i]{xferBadShare} </td>
+ <td align="right" class="border"> $Backups[$i]{tarErrs} </td></tr>
EOF
}
my $duration = sprintf("%.1f", $dur / 60);
my $MB = sprintf("%.1f", $Restores[$i]{size} / (1024*1024));
my $MBperSec = sprintf("%.2f", $Restores[$i]{size} / (1024*1024*$dur));
- my $Restores_Result = $Lang->{failed};
- if ($Restores[$i]{result} ne "failed") { $Restores_Result = $Lang->{success}; }
- $restoreStr .= <<EOF;
-<tr><td align="center"><a href="$MyURL?action=restoreInfo&num=$Restores[$i]{num}&host=${EscURI($host)}">$Restores[$i]{num}</a> </td>
- <td align="center"> $Restores_Result </td>
- <td align="right"> $startTime </td>
- <td align="right"> $duration </td>
- <td align="right"> $Restores[$i]{nFiles} </td>
- <td align="right"> $MB </td>
- <td align="right"> $Restores[$i]{tarCreateErrs} </td>
- <td align="right"> $Restores[$i]{xferErrs} </td>
+ my $Restores_Result = $Lang->{failed};
+ if ($Restores[$i]{result} ne "failed") { $Restores_Result = $Lang->{success}; }
+ $restoreStr .= <<EOF;
+<tr><td align="center" class="border"><a href="$MyURL?action=restoreInfo&num=$Restores[$i]{num}&host=${EscURI($host)}">$Restores[$i]{num}</a> </td>
+ <td align="center" class="border"> $Restores_Result </td>
+ <td align="right" class="border"> $startTime </td>
+ <td align="right" class="border"> $duration </td>
+ <td align="right" class="border"> $Restores[$i]{nFiles} </td>
+ <td align="right" class="border"> $MB </td>
+ <td align="right" class="border"> $Restores[$i]{tarCreateErrs} </td>
+ <td align="right" class="border"> $Restores[$i]{xferErrs} </td>
</tr>
EOF
}
if ( $restoreStr ne "" ) {
- $restoreStr = eval("qq{$Lang->{Restore_Summary}}");
+ $restoreStr = eval("qq{$Lang->{Restore_Summary}}");
}
if ( @Backups == 0 ) {
$warnStr = $Lang->{This_PC_has_never_been_backed_up};
}
if ( defined($Hosts->{$host}) ) {
my $user = $Hosts->{$host}{user};
- my @moreUsers = sort(keys(%{$Hosts->{$host}{moreUsers}}));
- my $moreUserStr;
- foreach my $u ( sort(keys(%{$Hosts->{$host}{moreUsers}})) ) {
- $moreUserStr .= ", " if ( $moreUserStr ne "" );
- $moreUserStr .= "${UserLink($u)}";
- }
- if ( $moreUserStr ne "" ) {
- $moreUserStr = " ($Lang->{and} $moreUserStr).\n";
- } else {
- $moreUserStr = ".\n";
- }
+ my @moreUsers = sort(keys(%{$Hosts->{$host}{moreUsers}}));
+ my $moreUserStr;
+ foreach my $u ( sort(keys(%{$Hosts->{$host}{moreUsers}})) ) {
+ $moreUserStr .= ", " if ( $moreUserStr ne "" );
+ $moreUserStr .= "${UserLink($u)}";
+ }
+ if ( $moreUserStr ne "" ) {
+ $moreUserStr = " ($Lang->{and} $moreUserStr).\n";
+ } else {
+ $moreUserStr = ".\n";
+ }
if ( $user ne "" ) {
$statusStr .= eval("qq{$Lang->{This_PC_is_used_by}$moreUserStr}");
}
$statusStr .= eval("qq{$Lang->{Last_status_is_state_StatusHost_state_reason_as_of_startTime}}");
if ( $StatusHost{state} ne "Status_backup_in_progress"
- && $StatusHost{state} ne "Status_restore_in_progress"
- && $StatusHost{error} ne "" ) {
+ && $StatusHost{state} ne "Status_restore_in_progress"
+ && $StatusHost{error} ne "" ) {
$statusStr .= eval("qq{$Lang->{Last_error_is____EscHTML_StatusHost_error}}");
}
my $priorStr = "Pings";
$statusStr .= eval("qq{$Lang->{priorStr_to_host_have_succeeded_StatusHostaliveCnt_consecutive_times}}");
if ( $StatusHost{aliveCnt} >= $Conf{BlackoutGoodCnt}
- && $Conf{BlackoutGoodCnt} >= 0 && $Conf{BlackoutHourBegin} >= 0
- && $Conf{BlackoutHourEnd} >= 0 ) {
+ && $Conf{BlackoutGoodCnt} >= 0 && $Conf{BlackoutHourBegin} >= 0
+ && $Conf{BlackoutHourEnd} >= 0 ) {
my(@days) = qw(Sun Mon Tue Wed Thu Fri Sat);
my($days) = join(", ", @days[@{$Conf{BlackoutWeekDays}}]);
my($t0) = sprintf("%d:%02d", $Conf{BlackoutHourBegin},
}
$startIncrStr = eval ("qq{$startIncrStr}");
-
- Header(eval("qq{$Lang->{Host__host_Backup_Summary}}"));
- print(eval("qq{$Lang->{Host__host_Backup_Summary2}}"));
+ my $content = eval("qq{$Lang->{Host__host_Backup_Summary2}}");
+ Header(eval("qq{$Lang->{Host__host_Backup_Summary}}"), $content);
Trailer();
}
<td> $mtimeStr </td></tr>
EOF
}
- Header($Lang->{BackupPC__Log_File_History});
- print (eval("qq{$Lang->{Log_File_History__hdr}}"));
+ my $content = eval("qq{$Lang->{Log_File_History__hdr}}");
+ Header($Lang->{BackupPC__Log_File_History}, $content);
Trailer();
}
use vars qw(%Status %Info %Jobs @BgQueue @UserQueue @CmdQueue
%QueueLen %StatusHost);
use vars qw($Hosts $HostsMTime $ConfigMTime $PrivAdmin);
-use vars qw(%UserEmailInfo $UserEmailInfoMTime %RestoreReq);
+use vars qw(%UserEmailInfo $UserEmailInfoMTime %RestoreReq %ArchiveReq);
use vars qw($Lang);
@ISA = qw(Exporter);
%Status %Info %Jobs @BgQueue @UserQueue @CmdQueue
%QueueLen %StatusHost
$Hosts $HostsMTime $ConfigMTime $PrivAdmin
- %UserEmailInfo $UserEmailInfoMTime %RestoreReq
+ %UserEmailInfo $UserEmailInfoMTime %RestoreReq %ArchiveReq
$Lang
);
$Lang = $bpc->Lang();
$ConfigMTime = $bpc->ConfigMTime();
} elsif ( $bpc->ConfigMTime() != $ConfigMTime ) {
- $bpc->ConfigRead();
- %Conf = $bpc->Conf();
- $ConfigMTime = $bpc->ConfigMTime();
- $Lang = $bpc->Lang();
+ $bpc->ServerMesg("log Re-read config file because mtime changed");
+ $bpc->ServerMesg("server reload");
}
#
my(@mesg) = @_;
my($head) = shift(@mesg);
my($mesg) = join("</p>\n<p>", @mesg);
- $Conf{CgiHeaderFontType} ||= "arial";
- $Conf{CgiHeaderFontSize} ||= "3";
- $Conf{CgiNavBarBgColor} ||= "#ddeeee";
- $Conf{CgiHeaderBgColor} ||= "#99cc33";
if ( !defined($ENV{REMOTE_USER}) ) {
$mesg .= <<EOF;
$bpc->ServerMesg("log User $User (host=$In{host}) got CGI error: $head")
if ( defined($bpc) );
if ( !defined($Lang->{Error}) ) {
- Header("BackupPC: Error");
$mesg = <<EOF if ( !defined($mesg) );
There is some problem with the BackupPC installation.
Please check the permissions on BackupPC_Admin.
EOF
- print <<EOF;
+ my $content = <<EOF;
${h1("Error: Unable to read config.pl or language strings!!")}
<p>$mesg</p>
EOF
+ Header("BackupPC: Error", $content);
Trailer();
} else {
- Header(eval("qq{$Lang->{Error}}"));
- print (eval("qq{$Lang->{Error____head}}"));
+ my $content = eval("qq{$Lang->{Error____head}}");
+ Header(eval("qq{$Lang->{Error}}"), $content);
Trailer();
}
exit(1);
return if ( $bpc->ServerOK() );
$bpc->ServerDisconnect();
if ( my $err = $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort}) ) {
- ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"));
+ if ( CheckPermission()
+ && -f $Conf{ServerInitdPath}
+ && $Conf{ServerInitdStartCmd} ne "" ) {
+ Header(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"));
+ print (eval("qq{$Lang->{Admin_Start_Server}}"));
+ Trailer();
+ exit(1);
+ } else {
+ ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"));
+ }
}
}
#
sub GetUserHosts
{
- if ( $Conf{CgiNavBarAdminAllHosts} && CheckPermission() ) {
- return sort keys %$Hosts;
- }
+ my($host) = @_;
+ my @hosts;
- return sort grep { $Hosts->{$_}{user} eq $User ||
+ if ( $Conf{CgiNavBarAdminAllHosts} && CheckPermission() ) {
+ @hosts = sort keys %$Hosts;
+ } else {
+ @hosts = sort grep { $Hosts->{$_}{user} eq $User ||
defined($Hosts->{$_}{moreUsers}{$User}) } keys(%$Hosts);
+ }
+ #
+ # return the selected host first (if present)
+ #
+ return @hosts if ( !defined($host) || !grep(/^$host$/, @hosts) );
+ return ($host, grep(!/^$host$/, @hosts));
}
#
sub Header
{
- my($title) = @_;
+ my($title, $content) = @_;
my @adminLinks = (
- { link => "", name => $Lang->{Status},
- priv => 1},
- { link => "?action=summary", name => $Lang->{PC_Summary} },
- { link => "?action=view&type=LOG", name => $Lang->{LOG_file} },
- { link => "?action=LOGlist", name => $Lang->{Old_LOGs} },
- { link => "?action=emailSummary", name => $Lang->{Email_summary} },
- { link => "?action=view&type=config", name => $Lang->{Config_file} },
- { link => "?action=view&type=hosts", name => $Lang->{Hosts_file} },
- { link => "?action=queue", name => $Lang->{Current_queues} },
- { link => "?action=view&type=docs", name => $Lang->{Documentation},
- priv => 1},
+ { link => "", name => $Lang->{Status},
+ priv => 1},
+ { link => "?action=adminOpts", name => $Lang->{Admin_Options} },
+ { link => "?action=summary", name => $Lang->{PC_Summary} },
+ { link => "?action=view&type=LOG", name => $Lang->{LOG_file} },
+ { link => "?action=LOGlist", name => $Lang->{Old_LOGs} },
+ { link => "?action=emailSummary", name => $Lang->{Email_summary} },
+ { link => "?action=view&type=config", name => $Lang->{Config_file} },
+ { link => "?action=view&type=hosts", name => $Lang->{Hosts_file} },
+ { link => "?action=queue", name => $Lang->{Current_queues} },
+ { link => "?action=view&type=docs", name => $Lang->{Documentation},
+ priv => 1},
{ link => "http://backuppc.sourceforge.net/faq", name => "FAQ",
- priv => 1},
+ priv => 1},
{ link => "http://backuppc.sourceforge.net", name => "SourceForge",
- priv => 1},
+ priv => 1},
);
print $Cgi->header();
print <<EOF;
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<title>$title</title>
+$Conf{CSSstylesheet}
$Conf{CgiHeaders}
-</head><body bgcolor="$Conf{CgiBodyBgColor}">
-<table cellpadding="0" cellspacing="0" border="0">
-<tr valign="top"><td valign="top" bgcolor="$Conf{CgiNavBarBgColor}" width="10%">
+</head><body onLoad="document.getElementById('NavMenu').style.height=document.body.scrollHeight">
+<img src="$Conf{CgiImageDirURL}/logo.gif" hspace="5" vspace="7"><br>
EOF
- NavSectionTitle("BackupPC");
- print " \n";
- if ( defined($In{host}) && defined($Hosts->{$In{host}}) ) {
- my $host = $In{host};
- NavSectionTitle( eval("qq{$Lang->{Host_Inhost}}") );
- NavSectionStart();
- NavLink("?host=${EscURI($host)}", $Lang->{Home});
- NavLink("?action=view&type=LOG&host=${EscURI($host)}", $Lang->{LOG_file});
- NavLink("?action=LOGlist&host=${EscURI($host)}", $Lang->{Old_LOGs});
- if ( -f "$TopDir/pc/$host/SmbLOG.bad"
- || -f "$TopDir/pc/$host/SmbLOG.bad.z"
- || -f "$TopDir/pc/$host/XferLOG.bad"
- || -f "$TopDir/pc/$host/XferLOG.bad.z" ) {
- NavLink("?action=view&type=XferLOGbad&host=${EscURI($host)}",
- $Lang->{Last_bad_XferLOG});
- NavLink("?action=view&type=XferErrbad&host=${EscURI($host)}",
- $Lang->{Last_bad_XferLOG_errors_only});
- }
- if ( -f "$TopDir/pc/$host/config.pl" ) {
- NavLink("?action=view&type=config&host=${EscURI($host)}", $Lang->{Config_file});
- }
- NavSectionEnd();
+ if (!defined($In{host})) {
+ print <<EOF;
+<div id="Content">
+$content
+<br><br><br>
+</div>
+<div class="NavMenu" id="NavMenu" style="height:100%">
+EOF
+ } else {
+ print "<div class=\"NavMenu\">";
}
- NavSectionTitle($Lang->{NavSectionTitle_});
- NavSectionStart();
- foreach my $l ( @adminLinks ) {
- if ( $PrivAdmin || $l->{priv} ) {
- NavLink($l->{link}, $l->{name});
- } else {
- NavLink(undef, $l->{name});
+ NavSectionTitle($Lang->{Hosts});
+ my $hostSelectbox = "<option value=\"#\">Select a host...</option>";
+ my @hosts;
+ if ( defined($Hosts) && %$Hosts > 0 ) {
+ @hosts = GetUserHosts($In{host});
+ foreach my $host ( @hosts ) {
+ if ($In{host} eq $host) {
+ print <<EOF;
+</div>
+<div class="HostOn"> <a href="?host=${EscURI($host)}">$host</a> <br>
+<div class="HostOnContent">
+EOF
+ NavLink("?host=${EscURI($host)}",
+ "$host $Lang->{Home}", " class=\"navbar\"");
+ NavLink("?action=browse&host=${EscURI($host)}",
+ "Browse backups", " class=\"navbar\"");
+ NavLink("?action=view&type=LOG&host=${EscURI($host)}",
+ $Lang->{LOG_file}, " class=\"navbar\"");
+ NavLink("?action=LOGlist&host=${EscURI($host)}",
+ $Lang->{LOG_files}, " class=\"navbar\"");
+ if ( -f "$TopDir/pc/$host/SmbLOG.bad"
+ || -f "$TopDir/pc/$host/SmbLOG.bad.z"
+ || -f "$TopDir/pc/$host/XferLOG.bad"
+ || -f "$TopDir/pc/$host/XferLOG.bad.z" ) {
+ NavLink("?action=view&type=XferLOGbad&host=${EscURI($host)}",
+ $Lang->{Last_bad_XferLOG}, " class=\"navbar\"");
+ NavLink("?action=view&type=XferErrbad&host=${EscURI($host)}",
+ $Lang->{Last_bad_XferLOG_errors_only},
+ " class=\"navbar\"");
+ }
+ if ( -f "$TopDir/pc/$host/config.pl" ) {
+ NavLink("?action=view&type=config&host=${EscURI($host)}",
+ $Lang->{Config_file}, " class=\"navbar\"");
+ }
+ print <<EOF;
+</div></div>
+<div id="Content">
+$content
+<br><br><br>
+</div>
+<div class="NavMenu" style="height:100%" id="NavMenu">
+EOF
+ } else {
+ NavLink("?host=${EscURI($host)}", $host) if ( @hosts < 6 );
+ $hostSelectbox .= "<option value=\"?host=${EscURI($host)}\">"
+ . "$host</option>";
+ }
}
}
- NavSectionEnd();
- NavSectionTitle($Lang->{Hosts});
+ if ( @hosts >= 6 ) {
+ print <<EOF;
+<br>
+<select onChange="document.location=this.value">
+$hostSelectbox
+</select>
+<br><br>
+EOF
+ }
+ NavSectionTitle($Lang->{Host_or_User_name});
print <<EOF;
-<table cellpadding="2" cellspacing="0" border="0" width="100%">
- <tr><td>$Lang->{Host_or_User_name}</td>
- <tr><td><form action="$MyURL" method="get"><small>
+<form action="$MyURL" method="get">
<input type="text" name="host" size="10" maxlength="64">
<input type="hidden" name="action" value="hostInfo"><input type="submit" value="$Lang->{Go}" name="ignore">
- </small></form></td></tr>
-</table>
+ </form>
EOF
- if ( defined($Hosts) && %$Hosts > 0 ) {
- NavSectionStart(1);
- foreach my $host ( GetUserHosts() ) {
- NavLink("?host=${EscURI($host)}", $host);
- }
- NavSectionEnd();
+ NavSectionTitle($Lang->{NavSectionTitle_});
+ foreach my $l ( @adminLinks ) {
+ if ( $PrivAdmin || $l->{priv} ) {
+ NavLink($l->{link}, $l->{name});
}
- print <<EOF;
-</td><td valign="top" width="5"> </td>
-<td valign="top" width="90%">
+}
+
+print <<EOF;
+<br><br><br>
+</div>
EOF
}
sub Trailer
{
print <<EOF;
-</td></table>
</body></html>
EOF
}
{
my($head) = @_;
print <<EOF;
-<table cellpadding="2" cellspacing="0" border="0" width="100%">
-<tr><td bgcolor="$Conf{CgiHeaderBgColor}"><font face="$Conf{CgiHeaderFontType}"
-size="$Conf{CgiHeaderFontSize}"><b>$head</b>
-</font></td></tr>
-</table>
+<div class="NavTitle">
+$head
+</div>
EOF
}
sub NavSectionStart
{
- my($padding) = @_;
-
- $padding = 1 if ( !defined($padding) );
- print <<EOF;
-<table cellpadding="$padding" cellspacing="0" border="0" width="100%">
-EOF
}
sub NavSectionEnd
{
- print "</table>\n";
}
sub NavLink
{
my($link, $text) = @_;
- print "<tr><td width=\"2%\" valign=\"top\"><b>·</b></td>";
if ( defined($link) ) {
+ my($class);
+ $class = " class=\"NavCurrent\""
+ if ( length($link) && $ENV{REQUEST_URI} =~ /\Q$link\E$/
+ || $link eq "" && $ENV{REQUEST_URI} !~ /\?/ );
$link = "$MyURL$link" if ( $link eq "" || $link =~ /^\?/ );
print <<EOF;
-<td width="98%"><a href="$link"><small>$text</small></a></td></tr>
+<a href="$link"$class>$text</a>
EOF
} else {
print <<EOF;
-<td width="98%"><small>$text</small></td></tr>
+$text<br>
EOF
}
}
{
my($str) = @_;
return \<<EOF;
-<table cellpadding="2" cellspacing="0" border="0" width="100%">
-<tr>
-<td bgcolor="$Conf{CgiHeaderBgColor}"> <font face="$Conf{CgiHeaderFontType}"
- size="$Conf{CgiHeaderFontSize}"><b>$str</b></font>
-</td></tr>
-</table>
+<div class="h1">$str</div>
EOF
}
{
my($str) = @_;
return \<<EOF;
-<table cellpadding="2" cellspacing="0" border="0" width="100%">
-<tr>
-<td bgcolor="$Conf{CgiHeaderBgColor}"> <font face="$Conf{CgiHeaderFontType}"
- size="$Conf{CgiHeaderFontSize}"><b>$str</b></font>
-</td></tr>
-</table>
+<div class="h2">$str</div>
EOF
}
<td> $cmd $req->{cmd}[0] </td></tr>
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();
}
--- /dev/null
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::ReloadServer package
+#
+# DESCRIPTION
+#
+# This module implements the ReloadServer action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# 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;
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}}"));
#
# 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 ) {
#
<tr><td>$host:/$strippedShare$f</td><td>$In{hostDest}:/$strippedShareDest$targetFile</td></tr>
EOF
}
- Header(eval("qq{$Lang->{Restore_Confirm_on__host}}"));
- print(eval("qq{$Lang->{Are_you_sure}}"));
+ my $content = eval("qq{$Lang->{Are_you_sure}}");
+ Header(eval("qq{$Lang->{Restore_Confirm_on__host}}"), $content);
Trailer();
} elsif ( $In{type} == 4 ) {
if ( !defined($Hosts->{$In{hostDest}}) ) {
$reply = $bpc->ServerMesg("restore ${EscURI($ipAddr)}"
. " ${EscURI($hostDest)} $User $reqFileName");
$str = eval("qq{$Lang->{Restore_requested_to_host__hostDest__backup___num}}");
- Header(eval("qq{$Lang->{Restore_Requested_on__hostDest}}"));
- print (eval("qq{$Lang->{Reply_from_server_was___reply}}"));
+ my $content = eval("qq{$Lang->{Reply_from_server_was___reply}}");
+ Header(eval("qq{$Lang->{Restore_Requested_on__hostDest}}"), $content);
Trailer();
}
}
<tr><td>$RestoreReq{hostSrc}:/$strippedShareSrc$f</td><td>$RestoreReq{hostDest}:/$strippedShareDest$targetFile</td></tr>
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();
}
--- /dev/null
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::StartServer package
+#
+# DESCRIPTION
+#
+# This module implements the StartServer action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# 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;
$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)})");
$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();
}
--- /dev/null
+#============================================================= -*-perl-*-
+#
+# BackupPC::CGI::StopServer package
+#
+# DESCRIPTION
+#
+# This module implements the StopServer action for the CGI interface.
+#
+# AUTHOR
+# Craig Barratt <cbarratt@users.sourceforge.net>
+#
+# 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;
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++;
}
$str = <<EOF;
-<tr$reasonHilite><td> ${HostLink($host)} </td>
- <td align="center"> ${UserLink(defined($Hosts->{$host})
+<tr$reasonHilite><td class="border"> ${HostLink($host)} </td>
+ <td align="center" class="border"> ${UserLink(defined($Hosts->{$host})
? $Hosts->{$host}{user} : "")} </td>
- <td align="center"> $fullCnt </td>
- <td align="center"> $fullAge </td>
- <td align="center"> $fullSize </td>
- <td align="center"> $fullRate </td>
- <td align="center"> $incrCnt </td>
- <td align="center"> $incrAge </td>
- <td align="center"> $Lang->{$Status{$host}{state}} </td>
- <td> $Lang->{$Status{$host}{reason}}$shortErr </td></tr>
+ <td align="center" class="border"> $fullCnt </td>
+ <td align="center" class="border"> $fullAge </td>
+ <td align="center" class="border"> $fullSize </td>
+ <td align="center" class="border"> $fullRate </td>
+ <td align="center" class="border"> $incrCnt </td>
+ <td align="center" class="border"> $incrAge </td>
+ <td align="center" class="border"> $Lang->{$Status{$host}{state}} </td>
+ <td class="border"> $Lang->{$Status{$host}{reason}}$shortErr </td></tr>
EOF
if ( @Backups == 0 ) {
$hostCntNone++;
$incrSizeTot = sprintf("%.2f", $incrSizeTot / 1000);
my $now = timeStamp2(time);
- Header($Lang->{BackupPC__Server_Summary});
- print eval ("qq{$Lang->{BackupPC_Summary}}");
-
+ my $content = eval ("qq{$Lang->{BackupPC_Summary}}");
+ Header($Lang->{BackupPC__Server_Summary}, $content);
Trailer();
}
} elsif ( $type eq "RestoreErr" ) {
$file = "$TopDir/pc/$host/RestoreLOG$ext";
$comment = $Lang->{Extracting_only_Errors};
+ } elsif ( $type eq "ArchiveLOG" ) {
+ $file = "$TopDir/pc/$host/ArchiveLOG$ext";
+ } elsif ( $type eq "ArchiveErr" ) {
+ $file = "$TopDir/pc/$host/ArchiveLOG$ext";
+ $comment = $Lang->{Extracting_only_Errors};
} elsif ( $host ne "" && $type eq "config" ) {
$file = "$TopDir/pc/$host/config.pl";
$file = "$TopDir/conf/$host.pl"
$file = "$BinDir/../doc/BackupPC.html";
if ( open(LOG, $file) ) {
binmode(LOG);
- Header($Lang->{BackupPC__Documentation});
- print while ( <LOG> );
+ my $content;
+ $content .= $_ while ( <LOG> );
close(LOG);
+ Header($Lang->{BackupPC__Documentation}, $content);
Trailer();
} else {
ErrorExit(eval("qq{$Lang->{Unable_to_open__file__configuration_problem}}"));
$file .= ".z";
$compress = 1;
}
- Header(eval("qq{$Lang->{Backup_PC__Log_File__file}}") );
- print( eval ("qq{$Lang->{Log_File__file__comment}}"));
+ my $content;
+ $content .= eval ("qq{$Lang->{Log_File__file__comment}}");
if ( defined($fh = BackupPC::FileZIO->open($file, 0, $compress)) ) {
my $mtimeStr = $bpc->timeStamp((stat($file))[9], 1);
- print ( eval ("qq{$Lang->{Contents_of_log_file}}"));
+ $content .= ( eval ("qq{$Lang->{Contents_of_log_file}}"));
- print "<pre>";
+ $content .= "<pre>";
if ( $type eq "XferErr" || $type eq "XferErrbad"
|| $type eq "RestoreErr" ) {
my $skipped;
while ( 1 ) {
$_ = $fh->readLine();
if ( $_ eq "" ) {
- print(eval ("qq{$Lang->{skipped__skipped_lines}}"))
+ $content .= (eval ("qq{$Lang->{skipped__skipped_lines}}"))
if ( $skipped );
last;
}
$skipped++;
next;
}
- print(eval("qq{$Lang->{skipped__skipped_lines}}"))
+ $content .= (eval("qq{$Lang->{skipped__skipped_lines}}"))
if ( $skipped );
$skipped = 0;
- print ${EscHTML($_)};
+ $content .= ${EscHTML($_)};
}
} elsif ( $linkHosts ) {
while ( 1 ) {
my $s = ${EscHTML($_)};
$s =~ s/\b([\w-]+)\b/defined($Hosts->{$1})
? ${HostLink($1)} : $1/eg;
- print $s;
+ $content .= $s;
}
} elsif ( $type eq "config" ) {
while ( 1 ) {
s/(SmbShareUserName.*=.*['"]).*(['"])/$1$2/ig;
s/(RsyncdPasswd.*=.*['"]).*(['"])/$1$2/ig;
s/(ServerMesgSecret.*=.*['"]).*(['"])/$1$2/ig;
- print ${EscHTML($_)};
+ $content .= ${EscHTML($_)};
}
} else {
while ( 1 ) {
$_ = $fh->readLine();
last if ( $_ eq "" );
- print ${EscHTML($_)};
+ $content .= ${EscHTML($_)};
}
}
$fh->close();
} else {
- printf( eval("qq{$Lang->{_pre___Can_t_open_log_file__file}}"));
+ $content .= ( eval("qq{$Lang->{_pre___Can_t_open_log_file__file}}"));
}
- print <<EOF;
+ $content .= <<EOF;
</pre>
EOF
+ Header(eval("qq{$Lang->{Backup_PC__Log_File__file}}"), $content);
Trailer();
}
CgiNavBarAdminAllHosts => {struct => 'SCALAR',
type => 'BOOLEAN', },
- CgiHeaderFontType => {struct => 'SCALAR',
- type => 'STRING', },
-
- CgiHeaderFontSize => {struct => 'SCALAR',
- type => 'INT', },
-
- CgiNavBarBgColor => {struct => 'SCALAR',
- type => 'STRING', },
-
- CgiHeaderBgColor => {struct => 'SCALAR',
- type => 'STRING', },
-
CgiHeaders => {struct => 'SCALAR',
type => 'STRING', },
#!/bin/perl -T
#my %lang;
-
#use strict;
# --------------------------------
+$Lang{Start_Archive} = "Start Archive";
+$Lang{Stop_Dequeue_Archive} = "Stop/Dequeue Archive";
$Lang{Start_Full_Backup} = "Start Full Backup";
$Lang{Start_Incr_Backup} = "Start Incr Backup";
$Lang{Stop_Dequeue_Backup} = "Stop/Dequeue Backup";
# -----
+$Lang{Only_privileged_users_can_view_admin_options} = "Only privileged users can view admin options.";
+$Lang{H_Admin_Options} = "BackupPC Server: Admin Options";
+$Lang{Admin_Options} = "Admin Options";
+$Lang{Admin_Options_Page} = <<EOF;
+\${h1(qq{$Lang{Admin_Options}})}
+<br>
+\${h1("Server Control")}
+<form action="\$MyURL" method="get">
+<table>
+ <tr><td>Stop the server:<td><input type="submit" name="action" value="Stop">
+ <tr><td>Reload the server configuration:<td><input type="submit" name="action" value="Reload">
+</table>
+</form>
+\${h1("Server Configuration")}
+<ul>
+ <li><i>Other options can go here... e.g.,</i>
+ <li>Edit server configuration
+</ul>
+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} = <<EOF;
+\${h1(qq{$Lang{Unable_to_connect_to_BackupPC_server}})}
+<form action="\$MyURL" method="get">
+The BackupPC server at <tt>\$Conf{ServerHost}</tt> port <tt>\$Conf{ServerPort}</tt>
+is not currently running (maybe you just stopped it, or haven't yet started it).<br>
+Do you want to start it?
+<input type="hidden" name="action" value="startServer">
+<input type="submit" value="Start Server" name="ignore">
+</form>
+EOF
+
+# -----
+
$Lang{H_BackupPC_Server_Status} = "BackupPC Server Status";
$Lang{BackupPC_Server_Status}= <<EOF;
<li> The servers PID is \$Info{pid}, on host \$Conf{ServerHost},
version \$Info{Version}, started at \$serverStartTime.
<li> This status was generated at \$now.
+<li> The configuration was last loaded at \$configLoadTime.
<li> PCs will be next queued at \$nextWakeupTime.
<li> Other info:
<ul>
\${h2("Currently Running Jobs")}
<p>
-<table border>
-<tr><td> Host </td>
+<table cellspacing="1" cellpadding="3">
+<tr class="tableheader"><td> Host </td>
<td> Type </td>
<td> User </td>
<td> Start Time </td>
\${h2("Failures that need attention")}
<p>
-<table border>
-<tr><td align="center"> Host </td>
+<table cellspacing="1" cellpadding="3">
+<tr class="tableheader"><td align="center"> Host </td>
<td align="center"> Type </td>
<td align="center"> User </td>
<td align="center"> Last Try </td>
# --------------------------------
$Lang{BackupPC__Server_Summary} = "BackupPC: Server Summary";
+$Lang{BackupPC__Archive} = "BackupPC: Archive";
$Lang{BackupPC_Summary}=<<EOF;
\${h1(qq{$Lang{BackupPC__Server_Summary}})}
<p>
This status was generated at \$now.
-<p>
+</p>
\${h2("Hosts with good Backups")}
<p>
<li> \$incrTot incr backups of total size \${incrSizeTot}GB
(prior to pooling and compression).
</ul>
-<table border>
-<tr><td> Host </td>
+</p>
+<table cellpadding="3" cellspacing="1">
+<tr class="tableheader"><td> Host </td>
<td align="center"> User </td>
<td align="center"> #Full </td>
<td align="center"> Full Age/days </td>
<td align="center"> Last attempt </td></tr>
\$strGood
</table>
-<p>
-
+<br><br>
\${h2("Hosts with no Backups")}
<p>
There are \$hostCntNone hosts with no backups.
<p>
-<table border>
-<tr><td> Host </td>
+<table cellpadding="3" cellspacing="1">
+<tr class="tableheader"><td> Host </td>
<td align="center"> User </td>
<td align="center"> #Full </td>
<td align="center"> Full Age/days </td>
</table>
EOF
+$Lang{BackupPC_Archive}=<<EOF;
+
+\${h1(qq{$Lang{BackupPC__Archive}})}
+<script language="javascript" type="text/javascript">
+<!--
+
+ function checkAll(location)
+ {
+ for (var i=0;i<document.form1.elements.length;i++)
+ {
+ var e = document.form1.elements[i];
+ if ((e.checked || !e.checked) && e.name != \'all\') {
+ if (eval("document.form1."+location+".checked")) {
+ e.checked = true;
+ } else {
+ e.checked = false;
+ }
+ }
+ }
+ }
+
+ function toggleThis(checkbox)
+ {
+ var cb = eval("document.form1."+checkbox);
+ cb.checked = !cb.checked;
+ }
+
+//-->
+</script>
+
+There are \$hostCntGood hosts that have been backed up for a total size of \${fullSizeTot}GB
+<p>
+<form name="form1" method="post" action="\$MyURL">
+<input type="hidden" name="fcbMax" value="\$checkBoxCnt">
+<input type="hidden" name="type" value="1">
+<input type="hidden" name="action" value="Archive">
+<table cellpadding="0" cellspacing="0" bgcolor="#333333"><tr><td>
+<table border="0" width="100%" align="left" cellpadding="2" cellspacing="1">
+<tr bgcolor="#99cc33"><td align=center> Host</td>
+ <td align="center"> User </td>
+ <td align="center"> Backup Size </td>
+\$strGood
+\$checkAllHosts
+</table>
+</td></tr></table>
+<p>
+
+</table>
+EOF
+
+$Lang{BackupPC_Archive2}=<<EOF;
+\${h1(qq{$Lang{BackupPC__Archive}})}
+About to archive the following hosts
+<ul>
+\$HostListStr
+</ul>
+<form action="\$MyURL" method="post">
+\$hiddenStr
+<input type="hidden" name="action" value="Archive">
+<input type="hidden" name="type" value="2">
+<input type="hidden" value="0" name="archive_type">
+<table border="1">
+<tr>
+ <td>Archive Location/Device</td>
+ <td><input type="text" value="\$ArchiveDest" name="archive_device"></td>
+<tr>
+ <td>Compression</td>
+ <td><input type="radio" value="0" name="compression" \$ArchiveCompNone>None<br>
+ <input type="radio" value="1" name="compression" \$ArchiveCompGzip>gzip<br>
+ <input type="radio" value="2" name="compression" \$ArchiveCompBzip2>bzip2</tr>
+</tr>
+<tr>
+ <td>Number of Parity Files</td>
+ <td><input type="numeric" value="\$ArchivePar" name="par"></td>
+</tr>
+<tr>
+ <td>Split output into:</td>
+ <td><input type="numeric" value="\$ArchiveSplit" name="splitsize">Megabytes</td>
+</tr>
+<tr>
+ <td colspan=2><input type="submit" value="Start the Archive" name=""></td>
+</tr>
+</table>
+EOF
+
# -----------------------------------
$Lang{Pool_Stat} = <<EOF;
<li>Pool is \${poolSize}GB comprising \$info->{"\${name}FileCnt"} files
# --------------------------------
$Lang{Only_privileged_users_can_view_queues_} = "Only privileged users can view queues.";
# --------------------------------
+$Lang{Only_privileged_users_can_archive} = "Only privileged users can Archive.";
+# --------------------------------
$Lang{BackupPC__Queue_Summary} = "BackupPC: Queue Summary";
# --------------------------------
$Lang{Backup_Queue_Summary} = <<EOF;
\${h1("Backup Queue Summary")}
-<p>
+<br><br>
\${h2("User Queue Summary")}
<p>
The following user requests are currently queued:
-<table border>
-<tr><td> Host </td>
+</p>
+<table cellspacing="1" cellpadding="3" width="80%">
+<tr class="tableheader"><td> Host </td>
<td> Req Time </td>
<td> User </td></tr>
\$strUser
</table>
-<p>
+<br><br>
\${h2("Background Queue Summary")}
<p>
The following background requests are currently queued:
-<table border>
-<tr><td> Host </td>
+</p>
+<table cellspacing="1" cellpadding="3" width="80%">
+<tr class="tableheader"><td> Host </td>
<td> Req Time </td>
<td> User </td></tr>
\$strBg
</table>
-<p>
-
+<br><br>
\${h2("Command Queue Summary")}
<p>
The following command requests are currently queued:
-<table border>
-<tr><td> Host </td>
+</p>
+<table cellspacing="1" cellpadding="3" width="80%">
+<tr class="tableheader"><td> Host </td>
<td> Req Time </td>
<td> User </td>
<td> Command </td></tr>
$Lang{Log_File_History__hdr} = <<EOF;
\${h1("Log File History \$hdr")}
<p>
-<table border>
-<tr><td align="center"> File </td>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td align="center"> File </td>
<td align="center"> Size </td>
<td align="center"> Modification time </td></tr>
\$str
$Lang{Recent_Email_Summary} = <<EOF;
\${h1("Recent Email Summary (Reverse time order)")}
<p>
-<table border>
-<tr><td align="center"> Recipient </td>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td align="center"> Recipient </td>
<td align="center"> Host </td>
<td align="center"> Time </td>
<td align="center"> Subject </td></tr>
# ------------------------------
$Lang{Restore_Options_for__host} = "BackupPC: Restore Options for \$host";
$Lang{Restore_Options_for__host2} = <<EOF;
+\${h1("Restore Options for \$host")}
<p>
You have selected the following files/directories from
share \$share, backup number #\$num:
<ul>
\$fileListStr
</ul>
-<p>
+</p><p>
You have three choices for restoring these files/directories.
Please select one of the following options.
-<p>
+</p>
\${h2("Option 1: Direct Restore")}
<p>
You can start a restore that will restore these files directly onto
\$host.
-<p>
+</p><p>
<b>Warning:</b> any existing files that match the ones you have
selected will be overwritten!
-
-<form action="\$MyURL" method="post">
+</p>
+<form action="\$MyURL" method="post" name="direct">
<input type="hidden" name="host" value="\${EscHTML(\$host)}">
<input type="hidden" name="num" value="\$num">
<input type="hidden" name="type" value="3">
<table border="0">
<tr>
<td>Restore the files to host</td>
- <td><input type="text" size="40" value="\${EscHTML(\$host)}"
- name="hostDest"></td>
+ <td><!--<input type="text" size="40" value="\${EscHTML(\$host)}"
+ name="hostDest">-->
+ <select name="hostDest" onChange="document.direct.shareDest.value=''">
+ <!-- hostOpt -->
+ </select>
+ <script language="Javascript">
+ function myOpen(URL) {
+ window.open(URL,'','width=200,height=200');
+ }
+ </script>
+ <a href="javascript:myOpen('\$MyURL?action=findShares&host='+document.direct.hostDest.options.value)">Search for available shares</a></td>
</tr><tr>
<td>Restore the files to share</td>
<td><input type="text" size="40" value="\${EscHTML(\$share)}"
You can download a Zip archive containing all the files/directories you have
selected. You can then use a local application, such as WinZip,
to view or extract any of the files.
-<p>
+</p><p>
<b>Warning:</b> 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.
-<p>
+</p>
<form action="\$MyURL" method="post">
<input type="hidden" name="host" value="\${EscHTML(\$host)}">
<input type="hidden" name="num" value="\$num">
zip archive.
Please ask your system adminstrator to install Archive::Zip from
<a href="http://www.cpan.org">www.cpan.org</a>.
-<p>
+</p>
EOF
You can download a Tar archive containing all the files/directories you
have selected. You can then use a local application, such as tar or
WinZip to view or extract any of the files.
-<p>
+</p><p>
<b>Warning:</b> 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.
-<p>
+</p>
<form action="\$MyURL" method="post">
<input type="hidden" name="host" value="\${EscHTML(\$host)}">
<input type="hidden" name="num" value="\$num">
Go back to <a href="\$MyURL?host=\$hostDest">\$hostDest home page</a>.
EOF
+$Lang{BackupPC_Archive_Reply_from_server} = <<EOF;
+\${h1(\$str)}
+<p>
+Reply from server was: \$reply
+EOF
+
+
# -------------------------
$Lang{Host__host_Backup_Summary} = "BackupPC: Host \$host Backup Summary";
<ul>
\$statusStr
</ul>
-
+</p>
\${h2("User Actions")}
<p>
<form action="\$MyURL" method="get">
<input type="submit" value="$Lang{Start_Full_Backup}" name="action">
<input type="submit" value="$Lang{Stop_Dequeue_Backup}" name="action">
</form>
-
+</p>
\${h2("Backup Summary")}
<p>
Click on the backup number to browse and restore backup files.
-<table border>
-<tr><td align="center"> Backup# </td>
+</p>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td align="center"> Backup# </td>
<td align="center"> Type </td>
<td align="center"> Filled </td>
<td align="center"> Start Date </td>
<p>
\$restoreStr
-
+</p>
+<br><br>
\${h2("Xfer Error Summary")}
-<p>
-<table border>
-<tr><td align="center"> Backup# </td>
+<br><br>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td align="center"> Backup# </td>
<td align="center"> Type </td>
<td align="center"> View </td>
<td align="center"> #Xfer errs </td>
</tr>
\$errStr
</table>
-<p>
+<br><br>
\${h2("File Size/Count Reuse Summary")}
<p>
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.
-<table border>
-<tr><td colspan="2"></td>
+</p>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td colspan="2" bgcolor="#ffffff"></td>
<td align="center" colspan="3"> Totals </td>
<td align="center" colspan="2"> Existing Files </td>
<td align="center" colspan="2"> New Files </td>
</tr>
-<tr>
+<tr class="tableheader">
<td align="center"> Backup# </td>
<td align="center"> Type </td>
<td align="center"> #Files </td>
</tr>
\$sizeStr
</table>
-<p>
+<br><br>
\${h2("Compression Summary")}
<p>
Compression performance for files already in the pool and newly
compressed files.
-<table border>
-<tr><td colspan="3"></td>
+</p>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td colspan="3" bgcolor="#ffffff"></td>
<td align="center" colspan="3"> Existing Files </td>
<td align="center" colspan="3"> New Files </td>
</tr>
-<tr><td align="center"> Backup# </td>
+<tr class="tableheader"><td align="center"> Backup# </td>
<td align="center"> Type </td>
<td align="center"> Comp Level </td>
<td align="center"> Size/MB </td>
</tr>
\$compStr
</table>
+<br><br>
+EOF
+
+$Lang{Host__host_Archive_Summary} = "BackupPC: Host \$host Archive Summary";
+$Lang{Host__host_Archive_Summary2} = <<EOF;
+\${h1("Host \$host Archive Summary")}
<p>
+\$warnStr
+<ul>
+\$statusStr
+</ul>
+
+\${h2("User Actions")}
+<p>
+<form action="\$MyURL" method="get">
+<input type="hidden" name="archivehost" value="\$host">
+<input type="hidden" name="host" value="\$host">
+<input type="submit" value="$Lang{Start_Archive}" name="action">
+<input type="submit" value="$Lang{Stop_Dequeue_Archive}" name="action">
+</form>
+
+
+\$ArchiveStr
+
EOF
# -------------------------
<li> You are browsing backup #\$num, which started around \$backupTime
(\$backupAge days ago),
\$filledBackup
+<li> Enter directory: <input type="text" name="dir" size="50" maxlength="4096" value="\${EscHTML(\$dir)}"> <input type="submit" value="\$Lang->{Go}" name="Submit">
<li> Click on a directory below to navigate into that directory,
<li> Click on a file below to restore that file,
<li> You can view the backup <a href="\$MyURL?action=dirHistory&host=\${EscURI(\$host)}&share=\$shareURI&dir=\$pathURI">history</a> of the current directory.
-<li> Enter directory: <input type="text" name="dir" size="50" maxlength="4096" value="\${EscHTML(\$dir)}"> <input type="submit" value="\$Lang->{Go}" name="Submit">
</ul>
</form>
<input type="hidden" name="fcbMax" value="\$checkBoxCnt">
<input type="hidden" name="action" value="$Lang{Restore}">
<br>
-<table>
+<table width="100%">
<tr><td valign="top">
- <!--Navigate here:-->
<br><table align="center" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff">
\$dirStr
</table>
</td><td width="3%">
</td><td valign="top">
- <!--Restore files here:-->
<br>
- <table cellpadding="0" cellspacing="0" bgcolor="#333333"><tr><td>
- <table border="0" width="100%" align="left" cellpadding="2" cellspacing="1">
+ <table border="0" width="100%" align="left" cellpadding="3" cellspacing="1">
\$fileHeader
\$topCheckAll
\$fileStr
This is now in the checkAll row
<input type="submit" name="Submit" value="Restore selected files">
-->
-</td></tr></table>
</form>
EOF
\${h2("History of \${EscHTML(\$dirDisplay)}")}
<br>
-<table border bgcolor="#ffffcc">
-<tr bgcolor="\$Conf{CgiHeaderBgColor}"><td>Backup number</td>\$backupNumStr</tr>
-<tr bgcolor="\$Conf{CgiHeaderBgColor}"><td>Backup time</td>\$backupTimeStr</tr>
+<table cellspacing="2" cellpadding="3">
+<tr class="fviewheader"><td>Backup number</td>\$backupNumStr</tr>
+<tr class="fviewheader"><td>Backup time</td>\$backupTimeStr</tr>
\$fileStr
</table>
EOF
$Lang{Restore___num_details_for__host2 } = <<EOF;
\${h1("Restore #\$num Details for \$host")}
<p>
+<table cellspacing="1" cellpadding="3" width="50%">
+<tr><td class="tableheader"> Number </td><td class="border"> \$Restores[\$i]{num} </td></tr>
+<tr><td class="tableheader"> Requested by </td><td class="border"> \$RestoreReq{user} </td></tr>
+<tr><td class="tableheader"> Request time </td><td class="border"> \$reqTime </td></tr>
+<tr><td class="tableheader"> Result </td><td class="border"> \$Restores[\$i]{result} </td></tr>
+<tr><td class="tableheader"> Error Message </td><td class="border"> \$Restores[\$i]{errorMsg} </td></tr>
+<tr><td class="tableheader"> Source host </td><td class="border"> \$RestoreReq{hostSrc} </td></tr>
+<tr><td class="tableheader"> Source backup num </td><td class="border"> \$RestoreReq{num} </td></tr>
+<tr><td class="tableheader"> Source share </td><td class="border"> \$RestoreReq{shareSrc} </td></tr>
+<tr><td class="tableheader"> Destination host </td><td class="border"> \$RestoreReq{hostDest} </td></tr>
+<tr><td class="tableheader"> Destination share </td><td class="border"> \$RestoreReq{shareDest} </td></tr>
+<tr><td class="tableheader"> Start time </td><td class="border"> \$startTime </td></tr>
+<tr><td class="tableheader"> Duration </td><td class="border"> \$duration min </td></tr>
+<tr><td class="tableheader"> Number of files </td><td class="border"> \$Restores[\$i]{nFiles} </td></tr>
+<tr><td class="tableheader"> Total size </td><td class="border"> \${MB} MB </td></tr>
+<tr><td class="tableheader"> Transfer rate </td><td class="border"> \$MBperSec MB/sec </td></tr>
+<tr><td class="tableheader"> TarCreate errors </td><td class="border"> \$Restores[\$i]{tarCreateErrs} </td></tr>
+<tr><td class="tableheader"> Xfer errors </td><td class="border"> \$Restores[\$i]{xferErrs} </td></tr>
+<tr><td class="tableheader"> Xfer log file </td><td class="border">
+<a href="\$MyURL?action=view&type=RestoreLOG&num=\$Restores[\$i]{num}&host=\$host">View</a>,
+<a href="\$MyURL?action=view&type=RestoreErr&num=\$Restores[\$i]{num}&host=\$host">Errors</a>
+</tr></tr>
+</table>
+<p>
+\${h1("File/Directory list")}
+<p>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td>Original file/dir</td><td>Restored to</td></tr>
+\$fileListStr
+</table>
+EOF
+
+# ------------------------------
+$Lang{Archive___num_details_for__host} = "BackupPC: Archive #\$num details for \$host";
+
+$Lang{Archive___num_details_for__host2 } = <<EOF;
+\${h1("Archive #\$num Details for \$host")}
+<p>
<table border>
-<tr><td> Number </td><td> \$Restores[\$i]{num} </td></tr>
-<tr><td> Requested by </td><td> \$RestoreReq{user} </td></tr>
+<tr><td> Number </td><td> \$Archives[\$i]{num} </td></tr>
+<tr><td> Requested by </td><td> \$ArchiveReq{user} </td></tr>
<tr><td> Request time </td><td> \$reqTime </td></tr>
-<tr><td> Result </td><td> \$Restores[\$i]{result} </td></tr>
-<tr><td> Error Message </td><td> \$Restores[\$i]{errorMsg} </td></tr>
-<tr><td> Source host </td><td> \$RestoreReq{hostSrc} </td></tr>
-<tr><td> Source backup num </td><td> \$RestoreReq{num} </td></tr>
-<tr><td> Source share </td><td> \$RestoreReq{shareSrc} </td></tr>
-<tr><td> Destination host </td><td> \$RestoreReq{hostDest} </td></tr>
-<tr><td> Destination share </td><td> \$RestoreReq{shareDest} </td></tr>
+<tr><td> Result </td><td> \$Archives[\$i]{result} </td></tr>
+<tr><td> Error Message </td><td> \$Archives[\$i]{errorMsg} </td></tr>
<tr><td> Start time </td><td> \$startTime </td></tr>
<tr><td> Duration </td><td> \$duration min </td></tr>
-<tr><td> Number of files </td><td> \$Restores[\$i]{nFiles} </td></tr>
-<tr><td> Total size </td><td> \${MB} MB </td></tr>
-<tr><td> Transfer rate </td><td> \$MBperSec MB/sec </td></tr>
-<tr><td> TarCreate errors </td><td> \$Restores[\$i]{tarCreateErrs} </td></tr>
-<tr><td> Xfer errors </td><td> \$Restores[\$i]{xferErrs} </td></tr>
<tr><td> Xfer log file </td><td>
-<a href="\$MyURL?action=view&type=RestoreLOG&num=\$Restores[\$i]{num}&host=\$host">View</a>,
-<a href="\$MyURL?action=view&type=RestoreErr&num=\$Restores[\$i]{num}&host=\$host">Errors</a>
+<a href="\$MyURL?action=view&type=ArchiveLOG&num=\$Archives[\$i]{num}&host=\$host">View</a>,
+<a href="\$MyURL?action=view&type=ArchiveErr&num=\$Archives[\$i]{num}&host=\$host">Errors</a>
</tr></tr>
</table>
<p>
-\${h1("File/Directory list")}
+\${h1("Host list")}
<p>
<table border>
-<tr><td>Original file/dir</td><td>Restored to</td></tr>
-\$fileListStr
+<tr><td>Host</td><td>Backup Number</td></tr>
+\$HostListStr
</table>
EOF
$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)}.";
$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"
$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} = <<EOF;
\$host is a DHCP host, and I don\'t know its IP address. I checked the
$Lang{Restore_requested_to_host__hostDest__backup___num} = "Restore requested to host \$hostDest, backup #\$num,"
. " by \$User from \$ENV{REMOTE_ADDR}";
+$Lang{Archive_requested} = "Archive requested by \$User from \$ENV{REMOTE_ADDR}";
# -------------------------------------------------
# ------- Stuff that was forgotten ----------------
$Lang{Status} = "Status";
$Lang{PC_Summary} = "PC Summary";
$Lang{LOG_file} = "LOG file";
+$Lang{LOG_files} = "LOG files";
$Lang{Old_LOGs} = "Old LOGs";
$Lang{Email_summary} = "Email summary";
$Lang{Config_file} = "Config file";
$Lang{Go} = "Go";
$Lang{Hosts} = "Hosts";
+$Lang{There_have_been_no_archives} = "<h2> There have been no archives </h2>\n";
$Lang{This_PC_has_never_been_backed_up} = "<h2> This PC has never been backed up!! </h2>\n";
$Lang{This_PC_is_used_by} = "<li>This PC is used by \${UserLink(\$user)}";
$Lang{tryIP} = " and \$StatusHost{dhcpHostIP}";
-$Lang{Host_Inhost} = "Host \$In{host}";
+# $Lang{Host_Inhost} = "Host \$In{host}";
$Lang{checkAll} = <<EOF;
-<tr bgcolor="#ffffcc"><td>
+<tr><td class="fviewborder">
<input type="checkbox" name="allFiles" onClick="return checkAll('allFiles');"> Select all
-</td><td colspan="5" align="center">
+</td><td colspan="5" align="center" class="fviewborder">
<input type="submit" name="Submit" value="Restore selected files">
</td></tr>
EOF
+$Lang{checkAllHosts} = <<EOF;
+<tr bgcolor="#ffffcc"><td>
+<input type="checkbox" name="allFiles" onClick="return checkAll('allFiles');"> Select all
+</td><td colspan="2" align="center">
+<input type="submit" name="Submit" value="Archive selected hosts">
+</td></tr>
+EOF
+
$Lang{fileHeader} = <<EOF;
- <tr bgcolor="\$Conf{CgiHeaderBgColor}"><td align=center> Name</td>
+ <tr class="fviewheader"><td align=center> Name</td>
<td align="center"> Type</td>
<td align="center"> Mode</td>
<td align="center"> #</td>
<td align="center"> Size</td>
- <td align="center"> Mod time</td>
+ <td align="center"> Date modified</td>
</tr>
EOF
EOF
$Lang{Visit_this_directory_in_backup} = <<EOF;
-<li> Visit this directory in backup #\$otherDirs.
+<li> Select the backup you wish to view: <select onChange="window.location=this.value">\$otherDirs </select>
EOF
$Lang{Restore_Summary} = <<EOF;
\${h2("Restore Summary")}
<p>
Click on the restore number for more details.
-<table border>
-<tr><td align="center"> Restore# </td>
+<table cellspacing="1" cellpadding="3" width="100%">
+<tr class="tableheader"><td align="center"> Restore# </td>
<td align="center"> Result </td>
<td align="right"> Start Date</td>
<td align="right"> Dur/mins</td>
<p>
EOF
+$Lang{Archive_Summary} = <<EOF;
+\${h2("Archive Summary")}
+<p>
+Click on the archive number for more details.
+<table border>
+<tr><td align="center"> Archive# </td>
+ <td align="center"> Result </td>
+ <td align="right"> Start Date</td>
+ <td align="right"> Dur/mins</td>
+</tr>
+\$ArchiveStr
+</table>
+<p>
+EOF
+
$Lang{BackupPC__Documentation} = "BackupPC: Documentation";
$Lang{No} = "no";
num startTime endTime result errorMsg nFiles size
tarCreateErrs xferErrs
)],
+ ArchiveFields => [qw(
+ num startTime endTime result errorMsg
+ )],
}, $class;
$bpc->{BinDir} .= "/bin";
$bpc->{LibDir} .= "/lib";
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 ( <ARCHIVE_INFO> ) {
+ 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) = @_;
my @PerlSrc = qw(
bin/BackupPC
+ bin/BackupPC_archive
+ bin/BackupPC_archivecd
+ bin/BackupPC_archivetape
bin/BackupPC_dump
bin/BackupPC_link
bin/BackupPC_nightly
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
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
$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");
}
close(F);
}
- foreach my $f ( <lib/BackupPC/Lang/*.pm> ) {
+ # CB: disable other lang checks for now
+ #
+ # foreach my $f ( <lib/BackupPC/Lang/*.pm> ) {
+ #
+ foreach my $f ( <lib/BackupPC/Lang/en.pm> ) {
my $done = {};
open(F, $f) || die("can't open $f\n");
binmode(F);
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++;