/[BackupPC]/upstream/2.1.0/bin/BackupPC_archive
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/2.1.0/bin/BackupPC_archive

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Jun 22 19:12:04 2005 UTC (18 years, 10 months ago) by dpavlin
File size: 10278 byte(s)
import of version 2.1.0

1 dpavlin 1 #!/bin/perl
2     #============================================================= -*-perl-*-
3     #
4     # BackupPC_archive: Archive files for an archive client.
5     #
6     # DESCRIPTION
7     #
8     # Usage: BackupPC_archive <user> <archiveclient> <reqFileName>
9     #
10     # AUTHOR
11     # Josh Marshall
12     #
13     # COPYRIGHT
14     # Copyright (C) 2001-2004 Craig Barratt
15     #
16     # This program is free software; you can redistribute it and/or modify
17     # it under the terms of the GNU General Public License as published by
18     # the Free Software Foundation; either version 2 of the License, or
19     # (at your option) any later version.
20     #
21     # This program is distributed in the hope that it will be useful,
22     # but WITHOUT ANY WARRANTY; without even the implied warranty of
23     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24     # GNU General Public License for more details.
25     #
26     # You should have received a copy of the GNU General Public License
27     # along with this program; if not, write to the Free Software
28     # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29     #
30     #========================================================================
31     #
32     # Version 2.1.0, released 20 Jun 2004.
33     #
34     # See http://backuppc.sourceforge.net.
35     #
36     #========================================================================
37    
38     use strict;
39     no utf8;
40     use lib "__INSTALLDIR__/lib";
41     use BackupPC::Lib;
42     use BackupPC::FileZIO;
43     use BackupPC::Xfer::Archive;
44    
45     use vars qw( %ArchiveReq );
46    
47     ###########################################################################
48     # Initialize
49     ###########################################################################
50    
51     die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
52     my $TopDir = $bpc->TopDir();
53     my $BinDir = $bpc->BinDir();
54     my %Conf = $bpc->Conf();
55     my $NeedPostCmd;
56    
57     my($user, $host, $client, $reqFileName, %stat);
58    
59     $bpc->ChildInit();
60    
61     if ( @ARGV != 3 ) {
62     print("usage: $0 <user> <archiveclient> <reqFileName>\n");
63     exit(1);
64     }
65     $user = $1 if ( $ARGV[0] =~ /(.+)/ );
66     $client = $1 if ( $ARGV[1] =~ /(.+)/ );
67     if ( $ARGV[2] !~ /^([\w.]+)$/ ) {
68     print("$0: bad reqFileName (arg #3): $ARGV[2]\n");
69     exit(1);
70     }
71     $reqFileName = $1;
72    
73     my $startTime = time();
74    
75     my $Dir = "$TopDir/pc/$client";
76     my @xferPid = ();
77    
78     #
79     # Catch various signals
80     #
81     $SIG{INT} = \&catch_signal;
82     $SIG{ALRM} = \&catch_signal;
83     $SIG{TERM} = \&catch_signal;
84     $SIG{PIPE} = \&catch_signal;
85     $SIG{STOP} = \&catch_signal;
86     $SIG{TSTP} = \&catch_signal;
87     $SIG{TTIN} = \&catch_signal;
88     my $Pid = $$;
89    
90     mkpath($Dir, 0, 0777) if ( !-d $Dir );
91     if ( !-f "$Dir/LOCK" ) {
92     open(LOCK, ">", "$Dir/LOCK") && close(LOCK);
93     }
94     open(LOG, ">>", "$Dir/LOG");
95     select(LOG); $| = 1; select(STDOUT);
96    
97    
98     #
99     # Read the request file
100     #
101    
102     if ( !(my $ret = do "$Dir/$reqFileName") ) {
103     my $err;
104     if ( $@ ) {
105     $err = "couldn't parse $Dir/$reqFileName: $@";
106     } elsif ( !defined($ret) ) {
107     $err = "couldn't do $Dir/$reqFileName: $!";
108     } else {
109     $err = "couldn't run $Dir/$reqFileName";
110     }
111     $stat{hostError} = $err;
112     exit(ArchiveCleanup($client));
113     }
114    
115     #
116     # Re-read config file, so we can include the PC-specific config
117     #
118     if ( defined(my $error = $bpc->ConfigRead($client)) ) {
119     $stat{hostError} = "Can't read PC's config file: $error";
120     exit(ArchiveCleanup($client));
121     }
122     %Conf = $bpc->Conf();
123    
124     #
125     # Make sure we eventually timeout if there is no activity from
126     # the data transport program.
127     #
128     alarm($Conf{ClientTimeout});
129    
130     #
131     # See if the host name is aliased
132     #
133     if ( $Conf{ClientNameAlias} ne "" ) {
134     $host = $Conf{ClientNameAlias};
135     } else {
136     $host = $client;
137     }
138    
139     #
140     # Setup file extension for compression and open ArchiveLOG output file
141     #
142     $Conf{CompressLevel} = 0 if ( !BackupPC::FileZIO->compOk );
143     my $fileExt = $Conf{CompressLevel} > 0 ? ".z" : "";
144     my $ArchiveLOG = BackupPC::FileZIO->open("$Dir/ArchiveLOG$fileExt", 1,
145     $Conf{CompressLevel});
146     my($logMsg, $xfer);
147    
148     $stat{xferOK} = 1;
149     $stat{hostAbort} = undef;
150     $stat{hostError} = $stat{lastOutputLine} = undef;
151     local(*RH, *WH);
152    
153     #
154     # Run an optional pre-archive command
155     #
156     UserCommandRun("ArchivePreUserCmd");
157     $NeedPostCmd = 1;
158    
159     $xfer = BackupPC::Xfer::Archive->new($bpc);
160    
161     #
162     # Run the transport program
163     #
164    
165     my $xferArgs = {
166     client => $client,
167     host => $host,
168     user => $ArchiveReq{user},
169     type => "archive",
170     XferLOG => $ArchiveLOG,
171     XferMethod => $Conf{XferMethod},
172     pathHdrSrc => $ArchiveReq{pathHdrSrc},
173     pathHdrDest => $ArchiveReq{pathHdrDest},
174     HostList => \@{$ArchiveReq{HostList}},
175     BackupList => \@{$ArchiveReq{BackupList}},
176     archiveloc => $ArchiveReq{archiveloc},
177     parfile => $ArchiveReq{parfile},
178     compression => $ArchiveReq{compression},
179     compext => $ArchiveReq{compext},
180     splitsize => $ArchiveReq{splitsize},
181     pidHandler => \&pidHandler,
182     };
183    
184     $xfer->args($xferArgs);
185    
186     if ( !defined($logMsg = $xfer->start()) ) {
187     UserCommandRun("ArchivePostUserCmd") if ( $NeedPostCmd );
188     $stat{hostError} = "xfer start failed: ", $xfer->errStr;
189     exit(ArchiveCleanup($client));
190     }
191    
192     print(LOG $bpc->timeStamp, "Starting archive\n");
193     print("started_archive\n");
194     $xfer->run();
195     $stat{xferOK} = 0 if ( defined($stat{hostError} = $xfer->errStr) );
196     alarm(0);
197    
198     exit(ArchiveCleanup($client));
199    
200     ###########################################################################
201     # Subroutines
202     ###########################################################################
203    
204     sub catch_signal
205     {
206     my $signame = shift;
207    
208     #
209     # Children quit quietly on ALRM
210     #
211     exit(1) if ( $Pid != $$ && $signame eq "ALRM" );
212    
213     #
214     # Ignore signals in children
215     #
216     return if ( $Pid != $$ );
217    
218     #
219     # Note: needs to be tested for each kind of XferMethod
220     #
221     print(LOG $bpc->timeStamp, "cleaning up after signal $signame\n");
222     $SIG{$signame} = 'IGNORE';
223     $ArchiveLOG->write(\"exiting after signal $signame\n");
224     $stat{xferOK} = 0;
225     if ( $signame eq "INT" ) {
226     $stat{hostError} = "aborted by user (signal=$signame)";
227     } else {
228     $stat{hostError} = "aborted by signal=$signame";
229     }
230     exit(ArchiveCleanup($client));
231     }
232    
233     #
234     # Cleanup and update the archive status
235     #
236     sub ArchiveCleanup
237     {
238     my($client) = @_;
239    
240     $stat{xferOK} = 0 if ( $stat{hostError} || $stat{hostAbort} );
241    
242     if ( !$stat{xferOK} ) {
243     #
244     # Kill off the tranfer program, first nicely then forcefully.
245     # We use negative PIDs to make sure all processes in each
246     # group get the signal.
247     #
248     if ( @xferPid ) {
249     foreach my $pid ( @xferPid ) {
250     kill($bpc->sigName2num("INT"), -$pid);
251     }
252     sleep(1);
253     foreach my $pid ( @xferPid ) {
254     kill($bpc->sigName2num("KILL"), -$pid);
255     }
256     }
257     }
258    
259     my $lastNum = -1;
260     my @Archives;
261    
262     @Archives = $bpc->ArchiveInfoRead($client);
263     for ( my $i = 0 ; $i < @Archives ; $i++ ) {
264     $lastNum = $Archives[$i]{num} if ( $lastNum < $Archives[$i]{num} );
265     }
266     $lastNum++;
267    
268     #
269     # Run an optional post-archive command
270     #
271     UserCommandRun("ArchivePostUserCmd") if ( $NeedPostCmd );
272    
273     rename("$Dir/ArchiveLOG$fileExt", "$Dir/ArchiveLOG.$lastNum$fileExt");
274     rename("$Dir/$reqFileName", "$Dir/ArchiveInfo.$lastNum");
275     my $endTime = time();
276    
277     #
278     # If the archive failed, clean up
279     #
280     if ( !$stat{xferOK} ) {
281     $stat{hostError} = $stat{lastOutputLine} if ( $stat{hostError} eq "" );
282     $stat{hostAbort} = 1;
283     $ArchiveLOG->write(\"Archive failed: $stat{hostError}")
284     if ( defined($ArchiveLOG) );
285     }
286    
287     $ArchiveLOG->close() if ( defined($ArchiveLOG) );
288    
289     #
290     # Add the new archive information to the archive file
291     #
292     @Archives = $bpc->ArchiveInfoRead($client);
293     my $i = @Archives;
294     $Archives[$i]{num} = $lastNum;
295     $Archives[$i]{startTime} = $startTime;
296     $Archives[$i]{endTime} = $endTime;
297     $Archives[$i]{result} = $stat{xferOK} ? "ok" : "failed";
298     $Archives[$i]{errorMsg} = $stat{hostError};
299    
300     while ( @Archives > $Conf{ArchiveInfoKeepCnt} ) {
301     my $num = $Archives[0]{num};
302     unlink("$Dir/ArchiveLOG.$num.z");
303     unlink("$Dir/ArchiveLOG.$num");
304     unlink("$Dir/ArchiveInfo.$num");
305     shift(@Archives);
306     }
307     $bpc->ArchiveInfoWrite($client, @Archives);
308    
309     if ( !$stat{xferOK} ) {
310     print(LOG $bpc->timeStamp, "Archive failed ($stat{hostError})\n");
311     print("archive failed: $stat{hostError}\n");
312     return 1;
313     } else {
314     print(LOG $bpc->timeStamp, "Archive Complete\n");
315     print("archive complete\n");
316     return;
317     }
318     }
319    
320     #
321     # The Xfer method might tell us from time to time about processes
322     # it forks. We tell BackupPC about this (for status displays) and
323     # keep track of the pids in case we cancel the backup
324     #
325     sub pidHandler
326     {
327     @xferPid = @_;
328     @xferPid = grep(/./, @xferPid);
329     return if ( !@xferPid );
330     my @pids = @xferPid;
331     my $str = join(",", @pids);
332     $ArchiveLOG->write(\"Xfer PIDs are now $str\n") if ( defined($ArchiveLOG) );
333     print("xferPids $str\n");
334     }
335    
336     #
337     # Run an optional pre- or post-dump command
338     #
339     sub UserCommandRun
340     {
341     my($cmdType) = @_;
342    
343     return if ( !defined($Conf{$cmdType}) );
344     my $vars = {
345     xfer => $xfer,
346     client => $client,
347     host => $host,
348     user => $user,
349     share => $ArchiveReq{shareDest},
350     XferMethod => $Conf{XferMethod},
351     HostList => \@{$ArchiveReq{HostList}},
352     BackupList => \@{$ArchiveReq{BackupList}},
353     archiveloc => $ArchiveReq{archiveloc},
354     parfile => $ArchiveReq{parfile},
355     compression => $ArchiveReq{compression},
356     compext => $ArchiveReq{compext},
357     splitsize => $ArchiveReq{splitsize},
358     sshPath => $Conf{SshPath},
359     LOG => *LOG,
360     XferLOG => $ArchiveLOG,
361     stat => \%stat,
362     xferOK => $stat{xferOK} || 0,
363     type => "archive",
364     cmdType => $cmdType,
365     };
366     my $cmd = $bpc->cmdVarSubstitute($Conf{$cmdType}, $vars);
367     $ArchiveLOG->write(\"Executing $cmdType: @$cmd\n");
368     #
369     # Run the user's command, dumping the stdout/stderr into the
370     # Xfer log file. Also supply the optional $vars and %Conf in
371     # case the command is really perl code instead of a shell
372     # command.
373     #
374     $bpc->cmdSystemOrEval($cmd,
375     sub {
376     $ArchiveLOG->write(\$_[0]);
377     },
378     $vars, \%Conf);
379     }

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26